| name | lit-library |
| description | Write side of the litman vault โ drives the `lit` CLI to change the library. Use when the user wants to add a paper to their **global** vault, browse/filter all papers, tag with controlled vocabulary, bind code repositories to a paper, export a BibTeX file for writing, manage the project registry (link/unlink papers to projects), govern the TAXONOMY, delete or restore a paper, or rebuild the vault's derived views. Triggers: 'add to lit library', 'ๅ ๅฐๆ็ฎๅบ', 'lit add', 'show me all my papers on X', 'tag/classify this paper', 'link this code repo to that paper'; export bib ('ๅฏผๅบ bib', 'export refs', 'thesis bib', 'ๅๅคๅผ็จ', 'refs.bib'); project lifecycle ('ๆฐๅปบ้กน็ฎ', 'register a project', 'rename/delete the project', 'the project moved', 'list my projects'); TAXONOMY governance ('ๅๅนถ่ฟไธคไธช topic', 'merge/rename a tag value', 'ๅ ๆ่ฟไธช topic/method'); restore a trashed paper ('ๆขๅคๅ ๆ็่ฎบๆ', 'restore from trash'); delete a paper ('ๆ่ฟ็ฏๅ ไบ', 'ๅ ๆ่ฟ็ฏ่ฎบๆ', 'delete/remove this paper', 'lit rm'); rebuild the vault's derived views ('views ไนฑไบ', '้ๅปบ่งๅพ/็ดขๅผ', 'refresh-views', 'rebuild my views'); unlink a paper from a project ('ๆ X ไป่ฟไธช้กน็ฎ้ๆฟๅบๆฅ/็งปๅบ', 'unlink this paper from the project'); clone/add a code repo to a paper ('ๆไปฃ็ clone ไธๆฅ', 'clone this repo', 'add the github repo', 'lit code add'). NOT for discussing/comparing/summarizing a paper you are reading โ that's the lit-reading skill. NOT for project-local References/ folders โ that's the ref-manager skill. |
lit-library โ Global Literature Vault Skill
Write side of litman. Read-side companion: lit-reading.
Architecture you must respect
- Two-root layout. Vault and code repo live in different filesystem locations. Discover the vault via
$LIT_LIBRARY env var or lit-config.yaml walk-up โ never assume a relative path.
- LLM never writes data files directly. Extract metadata as JSON to a temp file, then call
lit add --from-llm-json <path>. The CLI writes papers/<id>/metadata.yaml. Never write yaml/markdown into the vault yourself.
- TAXONOMY is mutated only via
lit taxonomy {add,rename,merge,rm} (and lit project for the projects dict). Never hand-edit TAXONOMY.md.
- Vault is NOT git-tracked. The CLI handles atomicity โ don't try to use git to roll back.
- Agent-writable free-form =
notes.md (overwrite) + discussion.md (append) only. Every other file in papers/<id>/ and codes/<name>/ is CLI-mediated. Drive only the forward paper-to-paper relation fields (related / extends / contradicts); the CLI auto-maintains the reverse pair (extended-by / contradicted-by) โ never set a reverse field by hand.
If a user request violates any of the above, push back and propose the CLI-mediated alternative.
PART A โ Autonomy, chaining, scope (read this first)
A1. Autonomy ladder
Classify every action before you take it.
| Tier | Operation class | Behavior | Examples |
|---|
| 1 | Read | Just do it, don't ask | lit list, lit show, scan a PDF, query INDEX via lit list --format json, lit project list, lit code list, lit trash list, lit health-check |
| 2 | Write, reversible, single-paper | Do it, then report | lit modify --set priority=A, lit modify --add-tag topics=X (only after Flow A/B โ [E]), lit read/skim/promote/drop/revisit, lit link/unlink (paperโproject, explicit request only โ [H]), lit code link, lit code unlink, lit modify --set relevance-<P>= |
| 3 | Write, multi-paper / structural / remote-IO | Ask once before acting | lit add (confirm โ [A]/[B]), lit code add (git clone), lit taxonomy add / lit project add (user types the new value), lit taxonomy merge + lit project rename/rm ([J]/[H]), lit export --force ([G]). (Exception โ lit taxonomy rename/rm of a value the user named explicitly: show the blast radius then act, do not re-ask โ rename just runs (no prompt), rm runs with --yes; see [J].) |
The CLI hard-rejects unregistered controlled-vocabulary values, so your job is to not invent values.
Execution ownership. lit-library runs every Tier-2 write inline โ it owns the write surface. lit-reading runs single-paper evaluation stamps inline (lit read/promote/skim/drop/revisit, lit modify --set priority=) and chains to lit-library for everything else.
A2. Chain hand-off contract
Inbound from lit-reading: when summoned mid-discussion, do the one write you were handed, report the result, and hand control back. Do NOT start a fresh interactive lit add session or swallow the conversation with a multi-step ingest. The hand-off carries: paper id, exact intent (e.g. "add extends=<other-id>"), any user instruction already given.
A2-out. Outbound hand-off to lit-reading
The chain is bidirectional: lit-reading hands writes in (A2), and lit-library hands reading/evaluation back out. lit-library owns the write surface but NOT the reading verdict โ the moment the conversation shifts from "change the library" to "read / discuss / evaluate this paper", switch to lit-reading and resume at its Phase 2 (with the paper id already in context).
Outbound triggers (most common right after an lit add, but any time mid-session):
- read-finished verdict โ "่ฏปๅฎไบ" / "่ฟ็ฏไธ่ฌ" / "ๆฒกไปทๅผ" / "done with this paper"
- discussion / comprehension โ "ๅฎ่ฎฒไบๅฅ" / "่ฟ็ฏๅ
ณไบ X ๆไน่ฏด" / "compare it to " / "ๆๆฒกๆ็ฑปไผผ็"
- resume reading / inbox triage / library health โ all lit-reading triggers
What to pass: paper id, PDF path, and whatever the user just said. Resume point: lit-reading Phase 2 (loaded context) โ B10 verdict ritual if the cue was read-finished. Do NOT try to run the status verdict, read-date stamp, or metadata self-check inside lit-library โ those are lit-reading B10's, by design (SOP-1). The failure mode this prevents: staying parked in lit-library after add, so a "่ฏปๅฎไบ๏ผไธ่ฌ" never reaches the verdict ritual and the paper rots at status: inbox.
A3. Scope discipline โ SOP vs maintenance, reversibility, active-vault confinement
(1) SOP vs maintenance. Operation Routing below covers high-frequency literature actions โ ingest, tag, link, bind code, export, govern vocab, restore. Low-frequency vault-maintenance (lit sync, lit vault use, lit config, lit refresh-views, lit init, lit install-skill, lit vault {add,info,remove}, lit code update/restore-all) has no SOP โ fall through to lit <cmd> --help.
- Read vs write within the no-SOP set. Pure-read no-SOP commands (
lit code list, lit vault info, lit vault list, lit config show) stay Tier 1: just run and report.
- "Teach, don't do" applies only to no-SOP writes / maintenance. Run
lit <cmd> --help, surface the command, let the user run it. Execute it yourself only when the user explicitly asks. Never guess a flag or invent a command from memory.
Destructive operations by reversibility:
- Soft-delete
lit rm (default โ moves papers/<id>/ into .trash/, recoverable via lit trash restore; [I]). Never initiate. May execute on explicit, confirmed request, and must relay lit rm's cascade report verbatim ("This paper is linked with N entriesโฆ") โ never silently delete, never summarize the link count away.
- Irreversible removal (
lit rm --purge, lit trash empty): NEVER execute these, even on explicit request. Surface the exact command and let the user run it. Delete-safety preview (read-only, you MAY run it): before surfacing a destructive command you may run lit rm <id> --dry-run (lists the paper + every link that would be cleared / unbound / orphaned) or lit trash empty --dry-run (lists every entry that would be permanently removed). The --dry-run flag writes nothing โ it belongs to the delete-safety family, NOT to retrieval; do not reach for rm --dry-run as a way to inspect a paper's links (use lit show / lit related for that).
lit code rm stays governed by [C.3] (confirm before execute; clone is re-cloneable).
(2) Write only in the active (primary) vault. Every write โ ingest, modify, link, code add, taxonomy, appends to notes.md / discussion.md โ targets the currently-active vault only. Cross-vault reading is fine; cross-vault writing is forbidden. If the user's intent requires writing into a different vault, tell the user to switch first (lit vault use <name>) and only then operate.
How to detect the vault
lit hello
echo $LIT_LIBRARY
lit list --format json | head -1
If lit is missing: tell the user pipx install -e /path/to/litman_dev/litman/ or activate the litman conda env. Do NOT try to install it yourself.
When to use lit-library vs other skills
| User intent | Skill |
|---|
| Add / tag / link / export / govern in the global vault | lit-library (this skill) |
| Discuss / compare / summarize a paper you are reading | lit-reading |
Add a paper to a project's References/ dir | ref-manager |
Cite in a .bib for a LaTeX manuscript | cite-retrieval |
| Review/critique manuscript text | paper-reviewer |
| Draft manuscript sections | academic-writing / paper-writer |
If the user has both a project References/ and a global vault, ask which one they mean before proceeding.
Operation Routing
- [A] Add paper from a PDF (LLM-augmented) โ PDF in hand and no DOI anywhere (not user-supplied AND none printed in the PDF), or the
--doi CrossRef fetch failed.
- [B] Add paper from a DOI (direct CrossRef) โ a DOI is available from any source (user-supplied OR read off the PDF); no LLM extraction. Preferred whenever a DOI exists.
- [C] Code repositories โ bind new clone, bind existing repo (1:N), retire/unbind.
- [D] Browse / search / inspect โ find a paper, list by filter, show metadata.
- [E] Modify metadata, tag, or apply an edge โ fields, Flow A/B tagging, confirmed edge.
- [G] Export bib for writing โ project vault โ
.bib.
- [H] Project operations โ register / link / unlink / list / rename / delete / set-path.
- [I] Restore a trashed paper โ execute the restore lit-reading B13 confirmed.
- [J] TAXONOMY governance โ merge / rename / remove a controlled value.
SOP-1 (hard rule for every branch): the agent does not proactively tag, edge-link, project-link, or code-bind a paper. Listing observations ("this touches tokenization, evaluation") is fine โ listing โ tagging. Always propose โ user decides โ you run the CLI. Never self-initiate a structural write.
[A] Add Paper from a PDF (LLM-augmented)
Use when the user has a PDF and no DOI, or explicitly says "add this paper with AI".
PDF-required precondition. lit add requires PDF_PATH as a positional argument. If the user gives only a DOI / URL with no local file, ask for the path ("litman ingests from a local PDF you've read").
Pipeline:
-
Read the PDF โ a must-achieve goal. Walk this ladder until one rung works:
- Claude Code
Read tool (default): Read(pdf_path, pages="1-3"). PDFs are natively handled via CC's multimodal pipeline.
- PDF-related MCP tool (for non-multimodal backends): scan your
available tools for any whose description mentions PDF / document / extract.
lit pdf-text โ deterministic fallback, no model / network / system tool: lit pdf-text <pdf> --pages 1-3 (omit --pages for the whole doc). litman ships pypdf as a hard dependency, so this works wherever lit runs โ it does NOT need poppler / pdftoppm. Exit code 3 means "no extractable text layer" (scanned / image-only PDF): go back up to a multimodal reader or OCR, don't retry here.
- Only if every rung above failed (no multimodal read, no PDF MCP, and
lit pdf-text returned no text): name the rung that failed and the exact gap, then surface OS-appropriate install commands for the user to run (brew install poppler / apt install poppler-utils / dnf install poppler-utils / scoop install poppler) or suggest a vision-capable model. Show these commands โ never execute an install yourself.
Extract: title (page 1 header), authors (page 1 list โ preserve "Family, Given" order), year, DOI (search first 1-2 pages), journal / venue, abstract.
DOI-found reroute (do this the moment a DOI surfaces). If you read a DOI off the PDF, abort the LLM-extraction path and switch to [B] โ run lit add <pdf> --doi <doi> instead. CrossRef returns authoritative metadata plus volume / issue / pages / publisher / venue-type, which the LLM-json schema cannot carry. Stay on [A] only when (a) no DOI appears anywhere in the PDF, or (b) the --doi CrossRef fetch fails โ then fall back here with the fields you already extracted. The up-front [A]/[B] split keys off "did the user hand a DOI"; this rule covers the other case ("a DOI turned up while reading the PDF").
Also harvest code-repo URLs into a side-buffer (NOT part of the metadata JSON โ feeds [C.1]). This is best-effort over the pages you already read โ do NOT read the whole PDF just to collect URLs. Full-text code-URL discovery is the CLI's job: lit add runs a full-text scan and emits the [code_candidates] block ([C.1] source 1). So harvest opportunistically from whatever pages you opened for metadata (Code Availability / Data Availability blocks, Acknowledgments, footnotes, first-page footer, inline "we release at https://โฆ" / "available at https://github.com/โฆ"); for each URL note one short context cue ("we present X" / "we use X" / "see also"). An empty side-buffer is expected and fine โ the CLI scan is the safety net.
-
Verify, do NOT hallucinate. If you cannot find a field, leave it as null rather than guessing.
-
Write metadata to a temp JSON file:
TMP_META=$(mktemp --suffix=.json /tmp/lit-llm-XXXX.json)
cat > $TMP_META <<'EOF'
{
"title": "<exact title from page 1>",
"authors": ["Family1, Given1", "Family2, Given2"],
"year": <int or null>,
"doi": "<10.xxx/yyy or null>",
"journal": "<venue or null>",
"arxiv-id": "<2401.12345 or null>",
"abstract": "<full abstract text or null>"
}
EOF
-
Call the CLI, then delete the temp file:
lit add <pdf-path> --from-llm-json "$TMP_META"
rm -f "$TMP_META"
On a platform without mktemp (e.g. Windows), you still wrote a JSON somewhere โ delete that exact path afterward. Never leave the extracted-metadata JSON lying in a temp dir.
-
Confirmation gate (mandatory โ human in the loop). lit add prints a success panel and runs a full-text code-URL scan. Run this as two separate messages โ never bundle them:
- 5a โ STOP and confirm the source. Report ONLY the derived
id and the title, then stop and wait for the user to confirm the source metadata is right. Surface only id + title โ do not self-judge title correctness. Do NOT attach the code-candidate table, a status offer, or anything else to this message. This is a hard gate: the next move waits on the user's word.
- 5b โ after the user confirms, in a fresh message: if either the CLI scan or your step-1 side-buffer surfaced a candidate โ present the merged table ([C.1]). A single CLI-only candidate still goes through the [C.1] three-state table โ no shortcut. If both are empty, stop here. Do NOT proactively enumerate tag / project / status / priority offers (SOP-1).
Post-ingest curation is lit-reading's, not yours. Status verdict (deep-read / skim / dropped), read-date, and the metadata completeness self-check all live in lit-reading B10 โ lit-library deliberately does not run them after add (SOP-1). If, right after confirming, the user starts reading or evaluating the paper ("่ฏปๅฎไบ" / "่ฟ็ฏไธ่ฌ" / "done with this" / "what does it say about X"), hand off to lit-reading (see A2-out) โ do not stop dead and do not absorb the reading verdict here.
Duplicate-add path. lit add prechecks the DOI and refuses with a DuplicateDOIError naming the existing id. Do not retry or force a second copy โ relay "already in your vault as <id>" and route to reading it (chain to lit-reading Phase 2 with that id).
JSON Schema Contract (LLMCandidateMeta)
| Field | Type | Required | Notes |
|---|
title | string (non-empty) | โ | Exactly as printed; no normalization |
authors | list[string] | โ (>=1) | "Family, Given" each; preserve order |
year | int | null | โ | Publication year |
doi | string | null | โ | Canonical DOI, no URL prefix |
journal | string | null | โ | Venue / journal / preprint server |
arxiv-id | string | null | โ | e.g. "2401.12345" |
abstract | string | null | โ | Currently informational |
Unknown keys are rejected. Topics/methods/data are NOT in this schema โ classification goes through Flow A ([E]) as a follow-up.
When lit add --from-llm-json errors
DuplicateDOIError / "DOI 'x' already registered" โ see Duplicate-add path above.
- "Metadata from LLM JSON has no year" โ re-read the PDF for a year, ask the user, or pass
--id 2024_Family_Keyword explicitly.
- "field 'title': String should have at least 1 character" โ re-extract.
Title / id rollback (when the confirm gate fails)
id and title are decoupled: lit modify --set title= changes the field without touching the id; lit rename changes the id handle (cascades every back-reference) without touching the title. Three branches:
- Title field wrong (almost only on
--from-llm-json; --doi is authoritative) โ lit modify <id> --set title=<correct>.
- Door-plate keyword unsatisfying (decoupled from title-correctness; possible on either path) โ
lit rename <old> <new>. Suggest a new id following <year>_<Family>_<Keyword>, label it "computed, confirm or change", let the user decide.
lit rm does NOT participate โ it is deletion semantics, would discard accumulated state and hit the reference safety net.
Standalone id rename (not a rollback). When the user names both handles outside any add flow ("ๆ <old> ็ id ๆนๆ <new>", "rename this paper to <new>", "ๆ่ฟ็ฏ็ id ๆนๆ X"): lit rename <old> <new>. Tier 3 โ cascades every back-reference (related / extends / contradicts edges, project links, INDEX). Same discipline as lit project rename ([H]) and lit taxonomy rename ([J]): for an explicitly named rename, show the cascade impact ("renames <old>โ<new>, updates the N papers referencing it") then run and report. Semantics-preserving (no data loss) โ the CLI has no prompt and no --yes; named โ show-then-act, do NOT insert a separate y/n confirmation. Map a bare "ๆ่ฟ็ฏ็ id ๆนๆ โฆ" straight to this โ do not stall asking which of rename / modify-title / binding the user means; the id-change wording is unambiguous.
[B] Add Paper from a DOI (direct, no LLM extraction)
Entered two ways: (1) the user hands a DOI up front, or (2) the [A] DOI-found reroute fired because a DOI surfaced while reading the PDF. Either way, skip LLM extraction:
lit add <pdf-path> --doi 10.1093/bioinformatics/btae364
Pipeline identical from id derivation onward; only the metadata source differs. Preferred whenever a DOI is available. PDF-required precondition still holds ([A]).
No --arxiv flag โ lit add accepts only --doi / --from-llm-json. If the user gives only an arxiv id, do NOT fabricate a DOI from it. A published/preprint PDF almost always prints its DOI on page 1 โ read it off the PDF and use --doi. If no DOI is printed anywhere, stay on [A] (LLM extraction) and leave doi: null; the arxiv-id goes into the [A] JSON's arxiv-id field. Never resolve an arxiv id to a DOI by guessing or by an unprompted external lookup.
Confirm gate. Title is authoritative on this path โ no re-confirm. But the door-plate keyword is still derived locally and can be unsatisfying. Read out the derived id and stop; if the user is unhappy with it, branch 2 of [A]'s rollback (lit rename).
[C] Code repositories โ bind, link, retire
A paper's code-clones field is a 1:N relationship: one repo under <vault>/codes/<name>/ can be cited by several papers.
[C.1] Bind a NEW clone โ reconcile CLI scan with agent re-read
Two sources:
- CLI scan โ
lit add prints candidates fenced by [code_candidates] / [/code_candidates], one per line as <url> (p<page>, ร<count>). Empty: no code repo URL found in full text.
- Agent side-buffer โ the URLs you harvested in [A] step 1.
Merge (lowercase scheme + host, strip trailing / and sentence punctuation, preserve path case), tag each [both] / [CLI only] / [agent only], present ONE table:
Code repo candidates for <id>:
[both] https://github.com/foo/bar CLI: p7 ร3 | agent: "Code Availability โ we release..."
[CLI only] https://github.com/baz/lib p12 ร1 | agent cue: appears as dependency citation
[agent only] https://github.com/qux/model | agent: footer p2
Pick which to bind: [1,3] / all / none
Tag rules:
[both] โ high confidence.
[CLI only] โ agent adds a one-line cue from PDF context when it can ("appears as dependency citation" / "deliverable in Methods"). Advisory; never silently drop a CLI candidate.
[agent only] โ note where in the PDF the agent saw it.
Both empty โ do not prompt.
Each selected item runs:
lit code add <url> --paper <current-id>
Tier 3 (git clone = remote IO). Binding one paper to multiple repos is not batch ingest โ ingest is still one paper.
Inspect with lit code list --paper <paper-id> (tier-1 read). Pull updates with lit code update <name>.
[C.2] Bind an EXISTING vault repo (the 2nd+ paper in a 1:N)
When the repo is already cloned in <vault>/codes/ and the user wants another paper bound:
lit code link <repo-name> --paper <id>
Tier 2 (pure bind, single-paper reversible). Trigger = explicit user request.
[C.3] Retire / unbind โ read the reverse list FIRST
Before unbinding, cat <vault>/codes/<repo>/repo-meta.yaml and read the papers: reverse list. Then branch:
[D] Browse / Search / Inspect
lit list
lit list --topic transformer --year 2023,2024
lit list --status deep-read --priority A
lit list --project pepforge --format json
lit show Pandi
lit show 2023_Pandi_Cell-free
lit show --paper-doi 10.1038/...
Every lit command that takes a paper id (show, open, modify, rm, rename, link, unlink, code link, code add --paper, code list --paper) accepts (a) the full id, (b) a unique case-insensitive substring, or (c) --paper-doi <DOI> (mutually exclusive with positional / --paper). Ambiguous substrings (2+ matches) print the candidate list and exit non-zero. lit rename <old> <new> is the one exception: no --paper-doi (two positionals would be ambiguous).
For "find a paper I read last month about X", filter by date with lit list --read-since YYYY-MM-DD (read-date lower-bound) or --added-since YYYY-MM-DD (created-at lower-bound), combined with --topic / --project. For large vaults filter via --topic / --project first. For author cues use lit list --author <cue> โ the JSON rows don't include authors.
[E] Modify Metadata, Tag, or Apply an Edge
SOP-1 โ never proactively tag (restated)
Every tag goes through Flow A or Flow B.
Flow A โ user says "tag this / classify it" (no specific value)
Propose candidates only from registered values โ user picks โ lit modify --add-tag. Sources:
topics / methods / data โ read the in-context TAXONOMY.md (or lit taxonomy list <dict>).
projects โ lit project list is canonical. A file read alone is incomplete; see [H].
lit modify <id> --add-tag topics=peptide-LM --add-tag methods=transformer
lit modify <id> --rm-tag topics=outdated-value
While enumerating candidates you MAY propose a TAXONOMY merge if you spot near-duplicates ("your topics dict has both tokenization and tokenisation โ merge them?") โ propose only; governance runs through [J].
Flow B โ user names a value ("add tokenization")
Check if it is registered. Registered โ apply. Not registered โ the CLI HARD-REJECTS (no escape hatch); say so and route registration by dict:
lit taxonomy add topics peptide-LM
lit modify <id> --add-tag topics=peptide-LM
lit project add pepforge --path /abs/path/to/pepforge
lit modify <id> --add-tag projects=pepforge
After the user registers, re-read TAXONOMY.md and then apply.
Register-first (MANDATORY for the four controlled dicts)
projects / topics / methods / data are controlled vocabularies. lit modify --add-tag <dict>=<value> HARD-REJECTS an unregistered value (no --register escape hatch). projects has its own group lit project {add,list,rename,set-path,rm} ([H]); lit taxonomy {add,rename,rm} projects is hard-deprecated โ it errors and redirects. (lit taxonomy list projects still works.) Never hand-edit lit-config.yaml's projects: map.
Not register-first checked: schemaless scalar fields (read-date, doi, year, custom scalars), reference fields (authors, related, contradicts, extends), fixed enums (type, status, priority). --rm-tag is never register-checked. (code-clones is not a tag target at all โ modify rejects it; bind/unbind via lit code link / lit code unlink.)
Sugar commands โ prefer over lit modify --set for known semantic fields
lit read <id> [--date YYYY-MM-DD]
lit revisit <id>
lit drop <id>
lit promote <id>
lit skim <id>
Same-day repeats are no-ops. For priority or an arbitrary scalar, fall back to lit modify <id> --set priority=A.
Apply a knowledge-graph edge (inbound from lit-reading B7)
When lit-reading hands off a user-confirmed edge, run the forward field only:
lit modify <id> --add-tag extends=<other-id>
The CLI mirrors the paired reverse field on the opposite paper automatically โ never run a second command for the reverse, never set extended-by / contradicted-by directly. You apply only an edge the user already confirmed; never originate edges here.
[G] Export bib for writing
The user expresses intent; you translate it to lit export flags.
| User says | Command |
|---|
| "็ปๆๅฏผๅบไธไธช bib" / "ๅฏผๅบๆ็ฎๅบ" / names no project | lit export --all -o refs.bib โ no project scope โ --all is the default; just run it (do not ask) |
| "ๅฏผๅบๅ pepforge ๆๅ
ณ็ๆ็ฎๅฐ่ฟ้" | lit export --project pepforge (defaults to ./refs.bib) |
| "ๅ thesis๏ผๆ priority A ็้ฝๅฏผๅบๆฅ" | lit export --all --priority A -o thesis.bib |
| "็ป PepCodec ๅๅค bib" | lit export --project pepcodec (canonicalize the project token first โ Flow B / [H]) |
| "ๆดๆฐไธไธ refs.bib" | infer current project โ lit export --project <inferred>; if not inferrable, lit export --all (do not ask) |
Flags: --project XOR --all (exactly one required), -o/--output (default ./refs.bib), --priority / --status / --year / --type / --topic / --method / --data / --author (comma-separated; within one flag OR, across flags AND), --force, --vault. Cite keys equal paper ids โ output drops into \cite{<paper-id>} directly. Re-running on the same file is the supported update path.
Four hard rules:
- Sentinel rejection โ NEVER auto-add
--force. When the CLI refuses to overwrite a target lacking the litman sentinel (typically a hand-edited references.bib), relay verbatim and let the user decide โ --force discards their hand edits.
- Path inference: "current dir" / "here" โ default
./refs.bib; a named directory ("thesis dir") โ ask for the path, do not guess.
- Project token: unregistered
--project gets deterministic canonicalization (case/whitespace) only, else present the registered set.
- Bare export โ
--all, act don't ask. When the request names no project and none is inferrable (common when no projects are registered), lit export --all -o refs.bib is the only sensible reading โ run it. Reserve a clarifying question for a named-but-unresolvable project token (rule 3) or the --force-over-sentinel decision (rule 1), never for "which scope?" when there is only one.
Tier: projection is Tier 2; --force-over-sentinel is a Tier-3 ask.
[H] Project operations
- Register โ
lit project add <name> --path <abs>. Tier 3. User supplies the path โ never guess it. Same register-first instance Flow B routes to.
- Link โ
lit link <paper-id> --project <name> [--relevance "..."]. Atomically adds the project to the paper's projects:, builds symlinks, regenerates <project>/REFERENCES.md. Trigger ownership = user (only on explicit request; never self-initiate). Tier 2. Unregistered --project โ Flow B routing (lit project add).
- Unlink โ
lit unlink <paper-id> --project <name>. Tier 2, reversible. (Not for code โ that's [C].)
- Update relevance after linking โ
lit modify <paper-id> --set relevance-<project>=โฆ sets/edits the per-project relevance note without re-linking. Tier 2. At link time prefer the inline lit link --relevance "...".
- List projects โ
lit project list. Tier 1 read, canonical source for the registered set AND each project's path. Three columns: name / path / status (drift marker โ / โ path-missing / โ config-only / โ taxonomy-only). Use this for both "what projects exist" and "where is <project> on disk". Do NOT hand-parse lit-config.yaml, do NOT use lit config show for project paths.
- List a project's literature โ
lit list --project <name> (Tier 1; supports --format json). Per-project view of papers, distinct from lit project list which lists the projects themselves.
- Rename โ
lit project rename <old> <new>. Tier 3 governance (cascades: TAXONOMY + config key + every referencing paper's projects: + INDEX). Reuse [J] discipline: never hand-edit; for an explicitly named rename ("ๆ <old> ๆนๅ <new>") show the impact ("renames <old>โ<new> across the N papers using it") then run and report (semantics-preserving โ the CLI has no prompt and no --yes; named โ show-then-act, don't re-ask); re-read TAXONOMY afterward.
- Delete โ
lit project rm <name>. Tier 3 + destructive (cascade-untags every paper). Treat like deletion: never initiate, show the impact + confirm before executing even on explicit request. Project-registry removal only โ trashes no paper.
- Set path โ
lit project set-path <name> <abs>. Tier 2. For when the project dir moved; user supplies the new path; no cascade.
Governance discipline (rename / rm) is shared with [J] โ cross-reference, don't duplicate.
[I] Restore a trashed paper
After lit-reading B13 hands off a user-confirmed paper id, execute the restore and relay the outcome:
lit trash restore <id>
Behavior:
- Accepts the paper id (must be unambiguous) or the full entry name
<id>-<UTC-timestamp>. If the same id was deleted more than once, the CLI raises with the list of entry names โ relay it and ask which timestamp, do not guess.
- id-slot collision: if
papers/<id>/ already holds a LIVE paper, restore REFUSES. Relay the error; tell the user to rename / remove the active paper first. Do not force.
- Edges with deleted opposites are silently dropped; surviving relations rebuild atomically.
- Re-clone is built INTO restore. If a repo was the paper's sole binder, it was hard-deleted at rm time with its upstream URL preserved. Restore re-clones it: prompted per repo (default Yes) interactively, or auto with
-y. On refuse / clone failure the binding code-clones:[X] is KEPT + a warning emitted; re-clone is never a precondition for restore success.
Agent behavior:
- Before running, you MAY
cat <vault>/.trash/<entry>.meta.yaml to surface the re-clone target(s) to the user up front (tier 1 read).
- TTY caveat: driving
lit trash restore <id> without -y hangs/aborts at the interactive re-clone confirm on a non-TTY stdin. Agent path: surface the re-clone target(s) โ get the user's nod โ run lit trash restore <id> -y. No --no-reclone flag today โ if the user wants restore but skip re-clone, relay that and let them run it themselves.
- Tier 2 (local, reversible, single-paper). Trigger = the user-confirmed identity from B13 โ never restore on your own initiative, never pick the candidate for the user.
- Relay the CLI's result summary verbatim (reverse edges rebuilt in N papers, re-bound to N repos, re-linked into N projects).
[J] TAXONOMY governance
Maintain the controlled vocabulary. Trigger keywords: "ๅๅนถ่ฟไธคไธช topic" / "merge X into Y", "ๆ X ๆนๅ" / "rename", "ๅ ๆ่ฟไธช topic/method/ๅผ" / "remove this value".
Commands (verify exact flag spelling with lit taxonomy <verb> --help):
lit taxonomy rename <dict> <old> <new> โ rename a value, ripples to every referencing paper.
lit taxonomy merge โ fold one or more near-duplicate sources into one destination, re-tags every referencing paper, drops the sources.
lit taxonomy rm <dict> <value> โ remove a value, strips it from every referencing paper.
Rules:
- NEVER hand-edit
TAXONOMY.md โ always the atomic CLI.
- Tier 3 (cascades to N papers): always show the blast radius first ("removing
diffusion strips it from the N papers tagged with it" / "merge folds tokenisation into tokenization and re-tags the N papers"). Then split by who owns the judgment:
rename of a value the user named explicitly ("ๆ X ๆนๅ Y") โ semantics-preserving (no data loss), so the CLI has no prompt and no --yes: show the impact, run, and report.
rm of a value the user named explicitly ("ๅ ๆ diffusion ่ฟไธช topic") โ the named value is the user's decision; show the blast radius then run with --yes / -y and report โ do not insert a separate confirmation question. The CLI's Continue? [y/N] is the safety gate for a human typing the command directly; an agent acting on an explicit, reversible instruction satisfies it with --yes. (taxonomy rm is atomic + reversible โ re-add the value, re-tag โ NOT the never-execute purge class; the real safety net is reversibility, not a relayed confirmation prompt.)
merge, or any consolidation YOU propose (which values "mean the same" is the user's vocabulary judgment), or genuinely ambiguous intent (the user is musing, not commanding), or a blast radius that contradicts the user's apparent expectation โ ask once before acting; merge then needs --yes / -y non-interactively (without it it aborts).
After running, re-read TAXONOMY.md.
- Never decide a consolidation yourself โ which values "mean the same thing" is a vocabulary judgment the user owns. You MAY propose a merge when you spot near-duplicates (e.g. in Flow A), but propose only.
- dict routing: these verbs operate on
topics / methods / data. The projects dict is governed through lit project ([H]), not lit taxonomy.
Architecture Invariants (do not violate)
- Never write
papers/<id>/metadata.yaml, TAXONOMY.md, INDEX.json, or codes/<name>/repo-meta.yaml directly. Always go through lit add / lit modify / lit taxonomy / lit project / lit code โฆ.
- Never suggest hand-editing
TAXONOMY.md or lit-config.yaml's projects: map. Use lit taxonomy {rm,rename,merge} for topics/methods/data ([J]) and lit project {add,rename,set-path,rm} for projects ([H]). Tagging requires the value registered first.
- Never assume the vault is git-tracked. It is deliberately not.
- Never store API keys in
lit-config.yaml. The CLI calls no LLM API โ that's the agent's job, via the JSON-file bridge.
- Never install / uninstall litman or modify its conda env. If
lit is missing, tell the user and stop.
- Cross-reference in-vault papers with
[[paper-id]] wikilinks, then verify each against the filesystem. When notes mention another paper in this vault, write it as a [[paper-id]] wikilink โ never backticks or plain text, which escape lit rm's (deleted) tagging and lit health-check's dangling detection, leaving a silent dead link when the target is removed. When you rewrite a notes.md / discussion.md, for each [[X]] you emit or preserve, check that papers/X/ exists (lit show X resolves, or it appears in lit list). If not, write it as [[X]] (deleted) โ never emit a bare [[X]] for a paper not in the vault.
- Never set a reverse relation field (
extended-by / contradicted-by) by hand โ drive only the forward field and let the CLI maintain the pair ([E]).
If unsure whether an operation respects these, run lit health-check after โ it surfaces vault drift and the user inspects before acting.
Staleness nudges. lit may append a dim tip: line after a command. Relay it and offer to run the named command โ never auto-run. Two variants: (1) tip: no lit health-check in 14+ days... โ offer lit health-check; (2) tip: no lit sync push in 7+ days... โ offer lit sync push (backs the vault up to the configured remote; appears only when a remote is configured).
Quick Reference
| Command | What it does |
|---|
lit init [--name <vault>] | Create a new vault skeleton |
lit add <pdf> --doi <doi> | Add via CrossRef ([B]) |
lit add <pdf> --from-llm-json <json> | Add via LLM-extracted JSON ([A]) |
lit pdf-text <pdf> [--pages 1-3] | Dump PDF text layer (deterministic read fallback, [A] step 1) |
lit list [filters] [--title <substr>] [--limit N] [--format json] | Browse ([D]); --title = title substring, --limit = top-N |
lit show <id-or-substring> [--format json] | Single-paper metadata (fuzzy substring OK; --paper-doi supported); --format json = full field set |
lit search <query> [--in notes,discussion] [--limit N] | Search free-form notes / discussion (read-only); --limit = first N hits; routes to lit-reading territory but usable here |
lit related <id> [--by edges|taxonomy] | Knowledge-graph neighbours (read-only); routes to lit-reading territory but usable here |
lit modify <id> --set k=v --add-tag list=v | Edit fields / tag ([E]) |
lit read / revisit / drop / promote / skim <id> | Status & date sugar ([E]) |
lit taxonomy {list,add,rename,merge,rm} <dict> [args] | Topics/methods/data vocab; merge/rm prompt โ pass --yes non-interactively ([J]) |
lit project {add,list,rename,set-path,rm} [args] | Project registry ([H]) |
lit link / unlink <id> --project <name> | Bind / unbind paperโproject ([H]) |
lit export (--project <p> | --all) [filters] [-o file] | Project vault โ .bib ([G]) |
lit code add <url> --paper <id> | Clone + bind a code repo ([C.1]) |
lit code link <repo> --paper <id> | Bind an existing vault repo (1:N โ [C.2]) |
lit code unlink <repo> --paper <id> | Unbind one paper, keep the clone ([C.3]) |
lit code list [--paper <id>] | Browse code repos |
lit code rm <repo> --cascade | Retire a repo (last citer only โ [C.3]) |
lit health-check | Vault consistency report |
lit rename <old> <new> | Atomic id rename with cascade |
lit rm <id> [--cascade] [--purge] | Soft-delete (trash) or purge |
lit trash {list,restore,empty} | Trash bin; restore rebuilds relations + re-clones ([I]) |
lit config show | Print parsed lit-config.yaml |