Write annotations directly in source code; let Claude Code understand and execute them in batch — no more back-and-forth of "which file, which line, what do I want".
code-annotations-skill is a Claude Code skill that defines an @anno annotation syntax and three companion slash commands. You write your intent right next to the most relevant line of code:
# @anno-fix: avoid division by zero when items is empty
def average(items):
return sum(items) / len(items)Then run:
/anno-apply
Claude scans every annotation in the repo → shows you an execution plan → waits for your confirmation → modifies the code → appends each change to ANNOCHANGELOG.md → strips the applied annotations from source.
- Location is context: intent lives right next to the code, so conversations don't need wordy locators
- Batch execution: multiple changes across many files in a single pass
- Traceable: every applied change lands in
ANNOCHANGELOG.md, so your PR comes with a built-in change summary - Ask and answer:
@anno-q:lets you in-place ask questions; the agent answers in the changelog without touching code
Requires Claude Code already installed (~/.claude/ must exist).
One-step install. Both the skill and slash commands (/anno-apply, /anno-list, /anno-clear) are installed together.
/plugin marketplace add zlj-zz/code-annotations-skill
/plugin install code-annotations-skillRestart Claude Code (or start a new session), then type /anno- — you should see the three commands autocomplete.
git clone https://github.com/zlj-zz/code-annotations-skill.git
cd code-annotations-skill
bash scripts/install.shinstall.sh symlinks this repo into:
~/.claude/skills/code-annotations-skill/(so SKILL.md is recognized)~/.claude/commands/anno-apply.md,anno-list.md,anno-clear.md(so slash commands are available)
Prefer manual install? Copy
commands/anno-*.mdto~/.claude/commands/and put the whole repo at~/.claude/skills/code-annotations-skill/. Symlinks meangit pullupgrades are instant.
Use this if you want to share the skill across multiple AI agents (Claude Code, Cursor, Codex, etc.) via the skills.sh ecosystem.
npx skills add zlj-zz/code-annotations-skill --agent claude-codeNote: npx skills add only installs the skill (SKILL.md). The slash commands are Claude-Code-specific and require an extra step:
mkdir -p ~/.claude/commands
ln -s ~/.claude/skills/code-annotations-skill/commands/anno-apply.md ~/.claude/commands/
ln -s ~/.claude/skills/code-annotations-skill/commands/anno-list.md ~/.claude/commands/
ln -s ~/.claude/skills/code-annotations-skill/commands/anno-clear.md ~/.claude/commands/bash scripts/uninstall.shuninstall.sh will:
- Remove the skill and command symlinks from
~/.claude/ - Ask whether to remove
ANNOCHANGELOG.mdand.annoignorefrom the current project - Ask whether to remove the empty
~/.claude/commands/directory
Use --dry-run to preview what would be removed without making changes, or --yes to auto-confirm all prompts.
Want to type @anno-fix: from the keyboard with one tab? The repo ships a code-snippets file for VSCode (and forks: Cursor / VSCodium / Insiders / Windsurf / Trae).
Quickest — no clone needed (the script reuses your skill install when present, or downloads otherwise):
bash -c "$(curl -fsSL https://raw.githubusercontent.com/zlj-zz/code-annotations-skill/main/scripts/install-vscode.sh)"From a clone — same prompts, using local files:
bash scripts/install-vscode.sh # interactive prompt
bash scripts/install-vscode.sh --project # scripted: project-scoped to $PWD/.vscode/
bash scripts/install-vscode.sh --editor cursor # scripted: install into Cursor
bash scripts/install-vscode.sh --help # full optionsBoth flows ask the same four things: editor → user/project scope → symlink/copy → confirm.
Then in any .py / .ts / .go / .html file, type afix → Tab and you get a correctly-commented @anno-fix: annotation. Prefixes: anno, afix, atodo, aq, arefactor, afeat, adoc, aspc (with scope=), anext (next:N), ablock (multi-line). See vscode/README.md for the full cheat sheet.
Drop a line into any source file:
// @anno-feat: add retry, max 3 attempts, exponential backoff
async function fetchData(url: string) {
const res = await fetch(url);
return res.json();
}/anno-list
TYPE FILE:LINE SCOPE CONTENT
feat src/api.ts:1 line add retry, max 3 attempts, exponential backoff
Total 1 annotation (feat=1)
/anno-apply
Claude shows a plan → you reply y → Claude edits src/api.ts and writes ANNOCHANGELOG.md:
# ANNOCHANGELOG
## 2026-05-02 14:32 — /anno-apply
### ✅ feat — src/api.ts:1
**Annotation:** `@anno-feat: add retry, max 3 attempts, exponential backoff`
**Action:** extracted retryWithExponentialBackoff() utility and wrapped fetchData()
**Files:** src/api.ts (modified), src/utils/retry.ts (new)The annotation has been automatically removed from source.
| Command | What it does | Writes ANNOCHANGELOG? |
|---|---|---|
/anno-apply |
Apply annotations (scan → plan → confirm → execute → strip annotations) | Yes |
/anno-list |
Read-only listing of all annotations | No |
/anno-clear |
Delete annotations without executing them (double confirmation) | No |
Shared parameters:
- Path prefix:
/anno-apply src/api - Type filter:
/anno-apply --type=fix(valid:fix/todo/q/refactor/feat/doc)
The full spec is at references/syntax.md. The most common four forms:
# @anno: generic, applies to the next line
x = 1
# @anno-fix: typed, applies to the next line
y = 2
# @anno-refactor scope=function: explicit scope, affects the following function
def foo(): ...
# @anno-feat-start: multi-line block, for complex intent
# You can write several lines here
# e.g. enumerate requirements
def bar(): ...
# @anno-endSupported types: fix / todo / q / refactor / feat / doc.
Supported scopes: line / function / class / block / file / next:N.
Put a .annoignore at the repo root to skip specific directories or files (syntax identical to .gitignore). These are already excluded by default: .git/, node_modules/, vendor/, dist/, build/, target/, .venv/, etc.
See assets/annoignore.example.
code-annotations-skill/
├── SKILL.md # skill entry (loaded by ~/.claude/skills/)
├── commands/ # slash command definitions
│ ├── anno-apply.md
│ ├── anno-list.md
│ └── anno-clear.md
├── references/ # detailed specs (loaded on demand)
│ ├── syntax.md
│ ├── changelog-format.md
│ └── examples.md
├── assets/
│ ├── annochangelog.template.md
│ └── annoignore.example
├── examples/
│ └── before-after/ # end-to-end demo (ships with .vscode/ snippets)
├── vscode/
│ ├── anno.code-snippets # VSCode snippets (also works in Cursor / Codium / Insiders)
│ └── README.md
├── .claude-plugin/
│ └── plugin.json
├── scripts/
│ ├── install.sh
│ ├── install-vscode.sh # install vscode/anno.code-snippets into VSCode (or a fork); supports curl-pipe
│ └── uninstall.sh
├── LICENSE
└── README.md
@annoprefix, vendor-neutral — not@claudeor@ai, so the format is friendly to open-source collaboration- Strip annotations + write ANNOCHANGELOG — source stays clean, yet changes remain traceable (git-diff-friendly)
/anno-cleardoes not write ANNOCHANGELOG — clear is abandoning intent, not a change that happened; recording it would pollute the history@anno-q:does not change code — questions and answers are tracked in the changelog, so you don't need to context-switch back to chat- Double confirmation required — both
/anno-applyand/anno-clearrequire user sign-off, so code is never silently modified
v0.1.0 (current):
- ✅ Three core commands
- ✅ 6 types + 4 forms + 6 scopes
- ✅ Auto-generated ANNOCHANGELOG
- ✅ Multi-language support
- ✅ VSCode code snippets (autocomplete via
scripts/install-vscode.sh)
Future ideas:
- Full editor extension (syntax highlighting, tree view, in-editor
/anno-applybutton) - Annotation template library (common intent templates)
- CI integration (auto-run
/anno-listin PRs to remind about pending annotations) /anno-undorollback
Issues and PRs welcome. Before contributing:
- Run the end-to-end example in
examples/before-after/to confirm your environment is healthy - When changing syntax, update
references/syntax.mdfirst, then update the commands that reference it - Do not duplicate reference content inside
commands/*.md(single source of truth)