zotero-kb/CLAUDE.md
Saberlve aaafa78883 feat: Add multilingual support for project cards and attachments
- Introduced `card_language` attribute in ProjectRecord and Workspace classes to handle multiple languages for project cards.
- Updated project creation and renaming methods to accept and store the card language.
- Enhanced ZoteroReader to read and return attachment metadata, including language-specific summaries and claims.
- Modified LLM client to generate card content based on the specified language, supporting both English and Chinese.
- Updated tests to cover new functionality, ensuring correct handling of multilingual card generation and retrieval.
- Adjusted UI tests to verify the presence of language selection options and proper rendering of multilingual content.
2026-04-22 10:21:03 +08:00

5.9 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Zotero KB is a local FastAPI web service that reads from a Zotero SQLite database and generates structured Markdown knowledge cards for academic writing workflows. It provides project management, collection browsing, batch card generation via LLM (DeepSeek), and citation recommendation APIs.

Development Commands

Package manager is uv. All commands run through uv run.

# Install dependencies
UV_CACHE_DIR=/tmp/uv-cache uv sync --extra dev

# Run the server
UV_CACHE_DIR=/tmp/uv-cache uv run python main.py
# Serves on http://127.0.0.1:8000

# Run all tests
UV_CACHE_DIR=/tmp/uv-cache uv run pytest -q

# Run a single test file
UV_CACHE_DIR=/tmp/uv-cache uv run pytest tests/test_api.py -q

# Run a single test
UV_CACHE_DIR=/tmp/uv-cache uv run pytest tests/test_api.py::test_create_project_endpoint -q

Environment Variables

Variable Default Purpose
ZOTERO_DATA_DIR /mnt/c/Users/WSX/Zotero Path to Zotero data directory (must contain zotero.sqlite)
ZOTERO_KB_WORKSPACE workspace Workspace directory for projects, indexes, and cards
ZOTERO_BRIDGE_FILE workspace/bridge/selected-items.json Bridge file for Zotero-to-project item import
DEEPSEEK_API_KEY Required when projects use llm_provider=deepseek

Architecture

Layer Overview

api.py → FastAPI routes → Workspace / ProjectService / WritingService / ZoteroReader / CardBuilder

All business logic lives in src/zotero_kb/. There is no database migration system; the app creates directories on demand.

ZoteroReader (zotero_reader.py)

Reads directly from zotero.sqlite via sqlite3. Key capabilities:

  • read_items(item_keys) — full record with metadata, creators, tags, notes, attachment texts
  • get_collection_tree() / get_collection_items(collection_key) — browse collections hierarchically
  • search_items(query) — title/abstract substring search
  • PDF text extraction delegates to pdftotext CLI; other attachments read as plain text
  • Attachment paths resolve from storage:<key> relative to ZOTERO_DATA_DIR/storage/

Workspace & Project Model (workspace.py, projects.py)

A project is a JSON file plus two companion files under workspace/projects/<project_id>/:

  • project.json — metadata including llm.provider, llm.model, card_language
  • selected-items.json — ordered list of Zotero item keys belonging to the project
  • project-index.json — cached denormalized view rebuilt on every read

Workspace creates/renames/deletes projects. ProjectService manages item selection and rebuilds project-index.json by reading three shared indexes:

  • workspace/library/index/items.json — item metadata
  • workspace/library/index/cards.json — generated card data (supports per-language variants)
  • workspace/library/index/collections.json — collection metadata

Card Generation (cards.py, llm.py)

CardBuilder.build_or_update(item, language):

  1. Builds a source bundle from the item record (metadata + notes + attachment texts)
  2. Hashes and caches the bundle to library/cache/source-bundles/
  3. Calls llm_client.generate_card(source_bundle)
  4. Renders a Markdown file to library/collections/<collection_path>/<title> [<key>][<lang>].md
  5. Updates items.json, cards.json, and collections.json

The LLM layer supports two providers:

  • deepseek — calls DeepSeek Chat API, requires DEEPSEEK_API_KEY
  • deterministic (fallback) — derives card fields from abstract/notes without any API call

Cards support language variants: cards.json stores a map item_key -> {language -> card_data}. The project-index.json selects the variant matching the project's card_language.

Writing Support (writing.py)

  • recommend_citations(project_id, prompt) — simple term-overlap scoring across project cards
  • generate_plan(project_id, prompt) — returns a single-section plan using the top-scored card

Bridge Import (bridge.py)

The ZOTERO_BRIDGE_FILE (JSON with selected_keys array) is read by the /api/projects/{id}/imports/selected-items endpoint to import items that were pre-selected in Zotero. This is separate from the UI-driven /imports/item-keys endpoint.

Frontend

A single index.html (Jinja2 template rendered as static HTML) provides the full UI. It uses vanilla JS to call the REST API. No build step or JS bundler.

Testing

Tests use fastapi.testclient.TestClient with a FakeLlmClient injected via create_app(config, llm_client=...). The fixture builder (tests/fixtures/build_zotero_fixture.py) creates an in-memory Zotero SQLite schema with sample data. Most tests extract route handlers directly from the FastAPI app rather than using HTTP-level client calls.

Workspace Directory Layout

workspace/
  bridge/
    selected-items.json          # bridge file from Zotero
  library/
    index/
      items.json                 # item metadata index
      cards.json                 # card data index (language variants)
      collections.json           # collection metadata index
    collections/
      <collection_path>/
        <title> [<key>][<lang>].md   # generated Markdown cards
    cache/
      source-bundles/
        <key>.<lang>.json        # cached source bundles
  projects/
    <project_id>/
      project.json               # project config
      selected-items.json        # item keys in this project
      project-index.json         # denormalized project view
  • zotcard/ — Zotero plugin (separate JS project, not part of the Python service)
  • zotero-rag/ — Standalone RAG search service (separate project)
  • zotero-bridge/ — Zotero plugin bridge component
  • skills/zotero-citation-planner/ — Claude skill for reading project indexes and generating citation plans