File content into the knowledge base as a single well-formed note, without creating a topic hub. Use when the user asks to write up a paper, save a conversation, or file content into the vault. For topic-hub filing with reciprocal links, use ai-wiki-full instead.
Installs into .claude/skills of the current project.
Are you the author of Ai Wiki?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/alfredzhang98-ai-wiki)
---
name: ai-wiki
description: File content into the knowledge base as a single well-formed note, without creating a topic hub. Use when the user asks to write up a paper, save a conversation, or file content into the vault. For topic-hub filing with reciprocal links, use ai-wiki-full instead.
---
# ai-wiki — file content into the knowledge base (lightweight, default)
Turns "write this up" into a correctly named, correctly linked note inside the AI-managed folder.
**This command does not create topics.** It produces one note and requires at least one `[[wikilink]]` to an **existing** note. To place a note under a topic hub with reciprocal links, use `/ai-wiki-full`.
> Why topics are off by default: when every paper gets its own hub, the hub organises nothing — it only gives the paper a longer name. A topic is a research direction, not a paper's subject. The test is in `references/note-specs.md` under "What qualifies as a topic".
## Where output goes
**Everything this skill files lands in the AI-managed folder.**
| Zone | How to treat it |
|---|---|
| AI-managed folder (`<AI_WIKI>/**`) | create / edit / move / rename / delete — free hand |
| The user's own note folders | read and search freely; additive edits fine; **ask before** deleting, renaming, moving, or overwriting |
| `.claude/rules/`, `CLAUDE.md` | static config — edit only when the user asks to change Claude's behaviour; bump `updated:`. The sole dynamic exception is `.claude/rules/active.md` |
| `.obsidian/`, `.trash/` | reachable but hands-off — editing Obsidian's config can break the vault |
Nothing is blocked at the permission layer, so the restraint above is judgement. A vault is usually not a git repo; a bad overwrite of a hand-written note is recoverable only from file-sync version history.
Reading *from* those zones and filing a summary into the AI-managed folder is exactly what this skill is for.
## Reference files — read the one you need, not all four
| File | Read it when |
|---|---|
| `references/vault-guide.md` | deciding **which folder** — routing table, example user phrasings, the tags/wikilinks model |
| `references/note-specs.md` | **writing** a paper note, learning note, or topic plan — filenames, frontmatter, section specs, wording rules |
| `references/figures-diagrams.md` | the note needs **figures** — extraction command, embedding format, mermaid rules |
| `references/tools.md` | choosing **which skill or CLI** handles the input, plus the end-to-end workflows |
Routine filing (one obvious folder, no figures) needs none of them — the procedure below is enough.
## When NOT to run this procedure
These requests need no note, and running the procedure on them is pure waste:
- **Just asking what a paper says** → answer it. The user will say when they want it kept.
- **Asking whether the vault already holds something, or what it holds** → grep `Research/paper-index.md` or read the hub's §0.5; produce no note.
- **Fixing one phrase or one number in an existing note** → `Edit` that spot. Do not re-run the flow, re-extract figures, or rebuild the index.
- **Packaging or exporting a direction** → `/ai-wiki-export`.
- **Content that belongs in the user's own hand-written area** → that is not this skill's output zone; ask first.
## Procedure
0. **Normalise the inputs, then check for duplicates — before downloading or reading anything.** Everything after this step is expensive: fetching the PDF, reading the full text, extracting figures. On a duplicate, all of that is wasted work.
**One command may carry several papers, and may mix their forms.** arXiv links or IDs, DOIs, and **local PDF paths** are all accepted, separated by spaces or newlines. Both commands take them; **there is no separate batch command** — a batch is not a different kind of filing, it is this procedure run N times plus one shared synthesis pass at the end (`/ai-wiki-full` step 6.6).
### 0.1 Turn every input into a stable identifier
| Input form | How to get the identifier |
|---|---|
| arXiv link or ID | Strip the version suffix and any query string (`?utm_source=...`) |
| DOI | As given |
| **Local PDF path** | **Do not trust the filename** — it may be `paper(3).pdf`, or renamed by whoever sent it. Read the **first page of text** and take the arXiv ID, DOI, or title from it; arXiv PDFs carry `arXiv:XXXX.XXXXX vN` stamped down the left margin. Use the interpreter the `paper-figures` skill was installed with (it already has pymupdf; the path is rendered by the installer into `~/.claude/skills/paper-figures/SKILL.md` — **never hard-code an absolute path into a note or a skill**) |
> **Always copy a local PDF into the scratchpad before touching it. Never edit in place, never move, never delete the user's file.** The copy on their desktop or in their downloads folder is theirs, and must still be there, unchanged, when the procedure finishes. The PDF itself **does not enter the vault** — the vault holds notes and the figures extracted under `_attachments/paper-figures/`.
### 0.2 Check every input for duplicates at once, before acting on any of them
Given N inputs, resolve all N first, report them as one table, **and only then fetch the first PDF**. Checking and reading one paper at a time means the third paper's duplicate surfaces after two papers' worth of cost has already been spent.
**Search the index at `Research/paper-index.md` first.** It is generated from every note's frontmatter and holds each slug, full title, first author, year, arXiv ID, DOI, topic, and status in one file — grepping one file scales, walking and opening a tree does not.
Look it up by stable identifier, stopping at the first hit. **Do not guess the filename** — the slug is a judgement call ("the 2-3 most distinctive keywords"), so the same paper read twice can produce different slugs, and a filename search will miss it.
| Order | How |
|---|---|
| 1 | **arXiv ID**, version suffix stripped: `Grep "2101\.09207" Research/paper-index.md` |
| 2 | **DOI**: `Grep "10\.1109/AIM65483" Research/paper-index.md` |
| 3 | **Neither exists** (common for older conference papers): scan the index by first-author surname + year, then confirm against the title |
| 4 | **Near-duplicates** (not the same paper but heavily overlapping: an earlier paper from the same group, a conference version of a journal paper): the index carries full titles, so scan by title keywords |
If the index is missing or visibly stale (the note count does not match), rebuild it before searching:
```bash
python .claude/skills/ai-wiki/scripts/build-paper-index.py <AI_WIKI>/Research/papers
```
**With several inputs, lead with a summary table** — one row per input: input → identifier → hit or miss → path and topic if it hit. **A partial hit does not stop the batch** — the misses proceed as usual, and each hit is raised separately under the rule below.
**On a hit, do not start rewriting.** Report these four things and stop for the user's decision:
- the **full path**, including the topic subfolder
- **`status` and `date_added`** — when it was read and how thoroughly
- the **Conclusion line from the quick card**, so the user recalls the earlier judgement
- **which topic** it is filed under
Then follow whichever the user wants:
- **Just wants to see it** → write nothing; surface the existing note
- **Add to or revise it** → edit the existing note in place; never create a second file
- **The arXiv version changed** (v1 was read, v3 supplied) → this is an **update, not a duplicate**: state what differs between versions, decide which sections that touches, and refresh `venue` / `year`
- **Genuinely wants a re-read** → ask why (a previous `status: skim` is a good reason), then run the full procedure and overwrite the note
**A `status: skim` note still counts as a hit** — it should be upgraded to `read`, not duplicated by a second file.
**Only on a miss do you continue to step 1.**
1. **Classify** — pick exactly one destination folder from the routing table in `references/vault-guide.md`. One piece of content, one folder; anything cross-cutting rides on `tags:` and `[[wikilinks]]`, never a duplicate copy.
- Uncommitted, exploratory, or batch hits go to `Inbox/`, not a real folder.
- Genuinely ambiguous between two folders: ask, do not guess and duplicate.
2. **Name** — per `references/note-specs.md` (lowercase kebab-case):
- paper → `Research/papers/<first-author-lastname>-<year>-<2-3-keyword-slug>.md` (**this command creates no topic, so the note goes at the root of `papers/`**; `/ai-wiki-full` places it in `papers/<topic-slug>/`)
- learning → `Research/learning/<topic-slug>-<YYYYMMDD>.md`
3. **Near-duplicate backstop** — step 0 covered exact identity; here scan the destination folder by *subject* (`Glob Research/papers/**/*.md`, noting the per-topic subfolders) for a note that is not the same paper but overlaps heavily: an earlier paper from the same group, a conference version of the same method. Prefer updating or cross-referencing that note over producing an isolated near-duplicate. The same applies to learning notes.
4. **Fill** — `Read` the matching skeleton in `Templates/` (`paper-note.md` / `learning-note.md`) and fill it **in place**; never rebuild the structure from memory. Section guidance is in `references/note-specs.md`, not in the skeleton's `{{...}}` prompts.
- The `> [!callout]` blocks are the emphasis system — keep them, do not add new types.
- The **quick card at the top is written last**: it compresses the finished note. If its six lines cannot be filled, the note below is not done.
- **S0 "What this paper does, in plain language" is mandatory**: 3-5 sentences for someone who knows the field basics but has not read this paper. Order: the situation they face, what they built, why it works, what they got. **If you cannot write this section you have not understood the paper — stop and reread rather than continuing.**
- A paper note answers, in order: S0 plain language → S1 background → **S2 what prior work could not do** → S3-S4 method and maths → S5 what was run → S6 what came out → S7 limitations and the authors' future work → **S8 my analysis and research opportunities**.
- **S2 and S8 are why the note exists** — neither may be filled with generic prose. S4's maths must be reconstructible from the note, not merely recognisable.
- Each S8 opportunity carries all four lines (opportunity → why still unsolved → first experiment → which topic it files under). "No opportunity worth taking — <why>" is valid; an invented one is not.
- **Professional wording**: no metaphorical labels ("this paper's cut", "the verdict", "strongest number"). See the wording table in `references/note-specs.md`. Every judgement must land on specific evidence.
- Read the paper before writing. Never fill a section from the abstract; if the PDF text for a section is unavailable, write `{{not available in source}}` rather than plausible filler.
5. **Figures** — per `references/figures-diagrams.md`: paper figures via the `paper-figures` skill into `_attachments/paper-figures/<paper-slug>/` (**the attachment tree stays flat, never mirrored into topic folders**), embedded **at the section where each figure does the work**.
- **The embed prefix depends on the note's depth**: `../../_attachments/...` at the `papers/` root, `../../../_attachments/...` inside `papers/<topic-slug>/`. This is the one thing that fails silently when a note moves — spot-check one image.
- Authored diagrams use a mermaid fence. ASCII art is banned.
6. **Link (mandatory, at least one)** — the note must carry at least one `[[wikilink]]` to an **existing** note: a hub in `Research/topics/`, another paper note, or a learning note.
- `Glob` `Research/topics/` and `Research/papers/` first, pick the nearest target, and state the relationship in a sentence rather than dropping a bare link.
- **This command does not create topics.** If there is genuinely nothing to link to, flag in `.claude/rules/active.md` that this opens a new area and tell the user that `/ai-wiki-full` is the command that builds a hub.
- When the note does fit an existing topic, add the forward link to that topic's S6 list — reciprocal links are what make the graph cluster.
7. **Rebuild the index — mandatory after writing, moving, or deleting a paper note.** The index is the entry point for the next duplicate check; leaving it stale is equivalent to switching that check off.
```bash
python .claude/skills/ai-wiki/scripts/build-paper-index.py <AI_WIKI>/Research/papers
```
It also reports three integrity checks: **duplicate identifiers** (usually the same paper written twice), **notes with neither arXiv nor DOI** (findable only by title), and **notes not filed under any topic**. The index is generated — **never hand-edit it**.
8. **Register** — if this opens a new direction or is in-flight work, add a one-line pointer to `.claude/rules/active.md` and bump its `updated:`. Do not mirror state there. `active.md` is the only rules file this workflow touches without an explicit request to change configuration.
9. **Run the checks — the last step before delivering:**
```bash
python .claude/skills/ai-wiki/scripts/check-vault.py <AI_WIKI>
```
It runs every **mechanical** item from the self-check below in one pass: whether image embeds resolve, residual `{{placeholder}}`, banned wording, stray tabs (the failure mode where a heredoc eats LaTeX escapes), `active.md` size, `subarea` against the hub's §2 rows, reciprocal links, and whether a paper map's count has gone stale. **Do not deliver while the hard count is non-zero**; the soft findings (wording, suspected letter labels) need a judgement call.
It is a script rather than a checklist because these are all deterministic greps, and re-typing them from memory does not hold: across one batch of six notes the wording check caught something in **all six**. A check that runs only when remembered does not run.
**When a note or hub gained references** — a new `doi:` / `arxiv:`, or new rows in a hub's S4 reading queue — also run:
```bash
python .claude/skills/ai-wiki/scripts/verify-refs.py <AI_WIKI>/Research/topics/<topic>.md
```
S4 entries are copied out of another paper's bibliography, which is exactly where author-order slips, wrong years and DOI mix-ups come from. The script checks cheapest and highest-yield first: one request to see whether the DOI resolves (a 404 means the DOI is wrong; a 200 whose title does not match means it belongs to a different paper), then the arXiv id, and only then a single Crossref query for entries that carry nothing but a title. `FAIL` means an identifier points at another paper and must be fixed; `CHECK` is for a human to read. Offline it skips itself rather than blocking delivery.
## Anti-patterns — each of these is wasted work
Every row happened in a real vault; none is hypothetical:
| Anti-pattern | Why it fails | Instead |
|---|---|---|
| Editing a file **already in context** through a shell or Python script | The harness treats the file as changed behind you and re-dumps the whole thing into the next tool result (100–220 lines, eight or nine times in one batch) | Use `Edit`; to change several places, send several `Edit` calls in one message |
| Writing content that contains LaTeX through a Python heredoc | `\t` and friends are read as escapes, `\\t` collapses to a literal tab all the same, and the maths is silently corrupted (fixed three times before the rule was written down) | Write it with `Edit`; `check-vault.py`'s tab check is the backstop |
| Opening every extracted crop to look at it | One image read each, and whether a crop is wrong was already decided exactly by `warnings` | Read `warnings` first, then look only at the figures you will actually embed |
| Running the closing scripts once per paper in a batch | The first N−1 runs are overwritten by the last one | Run them once, at the end |
| Checking one paper, reading it, then checking the next | The third paper's duplicate surfaces only after two papers' fetch + full read + figure extraction has been spent | Resolve and check all N before fetching any |
| Writing a deep note from the abstract | S2's gap and S8's judgement both need method and experiment detail, which an abstract does not carry | Declare the lower material level (see `note-specs.md`) instead of writing past what you have |
| Writing a hub as an appendix to the reader's own project | The review inherits a bias, and whole routes get excluded because of one application's constraints | Review the direction on its own terms (`note-specs.md`, "a hub is a neutral review") |
| Copying entries straight out of a bibliography into S4 | That is exactly where wrong years, author-order slips and DOI mix-ups come from | Run `verify-refs.py` |
## Script red lines
- **Do not substitute inline Python for the bundled scripts** (`prep-paper.py`, `build-paper-index.py`, `check-vault.py`, `verify-refs.py`). What they decide with — section line numbers, caption bounding boxes, the banned-term list, rate limits and caches — was accumulated; a throwaway script only produces something that looks like the same answer.
- **Do not patch those scripts during a normal filing run.** Say explicitly that you are changing the skill, then re-run the change against papers already read.
- **Do not invent what extraction could not give you.** A missing page number, figure number or reference is written as "not available from the supplied material", never filled in with a plausible value — a plausible number gets used as evidence by the next synthesis pass.
- **When a script fails, say so and fall back to checking its documented items by hand.** Do not write a replacement script to get past it.
## Exporting a bundle
When the user wants a whole direction packaged up — to send to a collaborator, read offline, or archive:
```bash
# list the topics with paper counts, figure counts, and size
python .claude/skills/ai-wiki/scripts/export-topic.py <AI_WIKI> --list
# export one: hub + every paper note under it + the figures those notes embed
python .claude/skills/ai-wiki/scripts/export-topic.py <AI_WIKI> <topic-slug>
python .claude/skills/ai-wiki/scripts/export-topic.py <AI_WIKI> --all # one zip per topic
python .claude/skills/ai-wiki/scripts/export-topic.py <AI_WIKI> <topic> --all-figures # include unembedded crops
```
The zip **preserves the vault's directory depths** (`Research/…` and `_attachments/…`), so the `../../../_attachments/` paths inside notes resolve unchanged and the images render in any markdown viewer after extraction. Only **embedded** figures ship by default — figure extraction is deliberately over-inclusive, so whole folders inflate a bundle several-fold. The bundle README lists any `[[wikilink]]` pointing outside it.
## Self-check before finishing
- [ ] **Step 0 duplicate check ran before any download or read** (grep `Research/paper-index.md`: arXiv → DOI → author+year → title near-duplicates), and on a hit the path was reported and the user decided
- [ ] **The index was rebuilt afterwards** with `build-paper-index.py`, and its integrity report was read
- [ ] `arxiv:` / `doi:` filled in frontmatter whenever the paper has one — they are the only reliable dedup key
- [ ] Every path written is inside the AI-managed folder
- [ ] Filename matches the spec for its note type; a paper note sits at the `papers/` root (this command creates no topic)
- [ ] **Embed prefix matches the note's depth**, and at least one image was spot-checked
- [ ] Frontmatter complete (`tags:` present and specific, not just `research/`)
- [ ] At least one `[[wikilink]]` to an **existing** note, with the relationship stated
- [ ] Built from the actual template file, section order and callouts intact
- [ ] **S0 plain-language summary filled**, without jargon dumping
- [ ] Quick card written last; all six lines are concrete statements and it stands alone
- [ ] No `{{placeholder}}` left in the delivered note
- [ ] **Wording passes the three tests** (see "Wording requirements" in `references/note-specs.md`): no images borrowed from other fields (ancestor / prescription / bar / niche / beat / collapsed / ceiling / load-bearing / landed...), no colloquialisms (figure out / good enough / just / the real trap), invented labels explain themselves
- [ ] **No metaphorical labels**
- [ ] Figures embedded inline, not dumped at the end
- [ ] **Paper note:** S2 names actual prior methods and their specific failure; S7 separates author-stated / mine / their future work; S8's conclusion cites evidence and each opportunity has all four lines
- [ ] **Learning note:** S1 is the user's question verbatim; S5 has a real numeric example
- [ ] Told the user the exact path(s) written
## Related
To create or find a topic hub with reciprocal links, use `/ai-wiki-full`.
Tool choice per input type: `references/tools.md`. Zone rules in full: `.claude/rules/permissions.md`.