Doc index: README.md. Package layout: packaging.md (templates/ on npm). CLI layering: architecture.md § Key Files.
The published package ships two parallel directories under templates/:
| Directory | Role | Lifecycle |
|---|---|---|
templates/agents/ |
Consumer-disk targets — what codemap agents init copies into <project>/.agents/ |
Stable across releases; only changes when the pointer protocol shape changes |
templates/agent-content/ |
Server-side source served by codemap skill / codemap rule / codemap://skill / codemap://rule |
Updates every release as recipes / schema / narrative evolve |
The split exists so consumers can bun update @stainless-code/codemap and pick up today's reference content automatically — the file on their disk is a thin pointer that always fetches live. No agents init --force needed unless the pointer shape itself changes.
This repo also has .agents/ for Codemap development (CLI from source); after the v1 pointer rewrite it mirrors templates/agents/ (pointers, not fat content). Drift between the two should be zero — both regenerate from the same templates via bun src/index.ts agents init --force.
Maintenance discipline (post-pointer-protocol):
- Code, schema, recipe changes → auto-flow into the served skill via
*.gen.mdrenderers insrc/application/agent-content.ts. No template edit required. - Hand-written narrative changes (overview, recipes context, query patterns, maintenance, troubleshooting) → edit
templates/agent-content/skill/*.mddirectly. Single source of truth. - Pointer template shape changes (frontmatter schema, fetch instructions, marker comments) → edit
templates/agents/{rules/codemap,skills/codemap/SKILL}.mdAND bumpEXPECTED_POINTER_VERSIONinsrc/application/agent-content.tsso consumers see the staleness nag and re-runagents init --force.
Query examples in the bundled codemap rule and skill lead with codemap query --json (agents and automation). Omit --json when you want console.table in a terminal — see README.md § CLI.
codemap agents init
codemap agents init --force
codemap agents init --interactive # or -i; requires a TTY
codemap agents init --mcp # project MCP config (default project-local targets; Windsurf opt-in via -i)
codemap agents init --git-hooks # opt-in background index on git events
codemap agents init --no-git-hooks # remove codemap hook blocks--force— if.agents/already exists, delete only the same file paths that ship intemplates/agents(underrules/andskills/), then copy those files from the template. Any other files next to them (your custom rules, extra skill dirs, notes at.agents/root, etc.) are not removed. Use--interactive, not a bareinteractiveargument (unknown tokens are rejected).--interactive— multiselect which tools to wire (see below); choose symlink vs copy for integrations that mirror.agents/rules(and Cursor also.agents/skills). Uses @clack/prompts; non-TTY runs exit with an error.
Codemap maintains its own self-managed <state-dir>/.gitignore (default .codemap/.gitignore) — a blacklist of generated artifacts (index.db + WAL/SHM, audit-cache/ entry in the canonical list) reconciled to canonical on every codemap boot via ensureStateGitignore (src/application/state-dir.ts). audit --base cache physically lives at <projectRoot>/.codemap/audit-cache/ (hardcoded; does not follow --state-dir). Project-tracked sources (recipes/, config.{ts,js,json}) default to tracked.
The user's root .gitignore is no longer touched by codemap agents init. Future codemap versions can add new generated artifacts to the canonical blacklist; every consumer's project repairs itself on the next codemap invocation. The setup logic IS the migration (per plan §D11).
All integrations reuse the same bundled content under .agents/. Symlink-style rows use one link mode for the whole run (symlink or copy) when any of them is selected.
| Integration | What gets created | Notes |
|---|---|---|
| Cursor | .cursor/rules, .cursor/skills → .agents/ |
Per-file symlink or copy (each rule/skill file, not a directory link). |
| Windsurf | .windsurf/rules → .agents/rules |
Rules only. |
| Continue | .continue/rules → .agents/rules |
Continue rules. |
| Cline | .clinerules → .agents/rules |
Per-file symlink or copy. |
| Amazon Q | .amazonq/rules → .agents/rules |
AWS rules. |
| GitHub Copilot | .github/copilot-instructions.md |
Pointer + link to GitHub Docs. |
| Claude Code | CLAUDE.md |
Root onboarding pointer. |
| Zed / JetBrains / Aider (generic) | AGENTS.md |
Many tools read root AGENTS.md; JetBrains/Aider have no single mandated path — this file is the shared hook. |
| Gemini | GEMINI.md |
For integrations that load GEMINI.md. |
When the file watcher is off (WSL /mnt/* mounts, CODEMAP_WATCH=0, etc.), codemap agents init --git-hooks installs marker-delimited blocks in post-commit, post-merge, and post-checkout that run ( codemap >/dev/null 2>&1 & ) — non-blocking background incremental index. --no-git-hooks removes only codemap-marked blocks. Interactive init offers hooks automatically when watch-policy.ts would disable the watcher for the project root.
Concurrent indexers (CLI, MCP --watch, git hooks) coordinate via <state-dir>/index.lock. If indexing fails with “Index already running” after a crash, run codemap unlock. Per-file parse failures append to <state-dir>/errors.log.
Root / Copilot pointer files (CLAUDE.md, AGENTS.md, GEMINI.md, .github/copilot-instructions.md) use a managed section between <!-- codemap-pointer:begin --> and <!-- codemap-pointer:end --> (HTML comments — usually hidden in rendered Markdown):
| Situation | Behavior |
|---|---|
| File missing | Write that section (with markers). |
| File exists, section present | Replace only that section — idempotent re-runs, no duplicate blocks; template updates fix stale text. |
| File exists, no section, but content looks like an old Codemap-only file | Replace whole file with the managed section (one-time migration). |
| File exists with other content (e.g. your team intro) | Append the managed section once. |
--force |
Replace the entire file with the latest managed section. |
Append alone would duplicate on every run — markers + replace are what prevent duplicates and staleness.
Once agents init has written the pointer templates, the consumer's disk holds ~16-line SKILL + ~23-line rule. The actual content is served live:
| Surface | Skill | Rule |
|---|---|---|
| CLI | codemap skill |
codemap rule |
| MCP | resource codemap://skill |
resource codemap://rule |
HTTP (codemap serve) |
GET /resources/{encoded uri} against codemap://skill |
GET /resources/{encoded uri} against codemap://rule |
All three transports resolve to the same assembleAgentContent(kind) function in src/application/agent-content.ts — there is no MCP-only or HTTP-only path for skill/rule content. The MCP and HTTP paths share a lazy per-process cache via readResource() in src/application/resource-handlers.ts for schema/skill/rule/mcp-instructions; recipes, files, and symbols read live every call. The CLI re-assembles every call (cheap — markdown read + concat).
codemap mcp passes a tool-selection playbook in the MCP initialize response instructions field. MCP clients (Cursor, Claude Code, etc.) inject this into the agent system prompt — operational guidance only (which tool when, common chains, anti-patterns). Full schema and recipe catalog stay on codemap://skill / codemap://rule.
| Surface | URI / field |
|---|---|
| MCP initialize | instructions on handshake |
| MCP / HTTP resource | codemap://mcp-instructions |
| Source file | templates/agent-content/mcp-instructions.md (assembled by assembleMcpInstructions() in agent-content.ts) |
Recipe ids cited in the playbook are machine-validated in tests against the live catalog (extractMcpInstructionRecipeIds).
CODEMAP_MCP_TOOLS — comma-separated snake_case MCP tool names. When set, only listed tools register (stderr lists the active set). Unknown names are ignored with a warning. Unset = all tools (default). query_batch registers only when listed or when unset (eval ablation).
Example: CODEMAP_MCP_TOOLS=query,context,show codemap mcp --no-watch
Agent eval live arms — see benchmark § Agent eval harness for AGENT_EVAL_MODE=live, log comparison, and the minimal eval subset (query, query_recipe).
codemap agents init --mcp (or the interactive prompt) writes project MCP config without duplicating skill/rule markdown. Registry source of truth: src/agents-init-mcp-registry.ts (AGENTS_INIT_MCP_REGISTRY).
| Target | Files written |
|---|---|
| Cursor | .cursor/mcp.json — codemap mcp --watch --root ${workspaceFolder} |
| Claude Code | .mcp.json + .claude/settings.json — permissions.allow includes mcp__codemap__* |
| VS Code / Copilot | .vscode/mcp.json — servers.codemap with type: stdio |
| Continue | .continue/mcpServers/codemap-mcp.json (JSON mcpServers; also accepted from Cursor/Cline exports) |
| Amazon Q Developer | .amazonq/default.json (IDE canonical) + .amazonq/mcp.json (legacy workspace; still read when global useLegacyMcpJson is true — AWS default). AWS MCP IDE docs |
| Gemini CLI | .gemini/settings.json — top-level mcpServers.codemap |
| Cline | .cline/mcp.json (Cline CLI reference; global IDE settings may also use ~/.cline/data/settings/cline_mcp_settings.json) |
| Windsurf (Cascade) | ~/.codeium/windsurf/mcp_config.json (Windsurf docs — user-global only; written when Windsurf integration is selected) |
With --mcp and no --target filter, all project-local rows above are written except Windsurf, which has no documented workspace MCP path.
Merge is idempotent: foreign MCP servers and existing settings keys are preserved; only the codemap server entry and permission pattern are upserted. Requires codemap on PATH (global install or dev dependency binary).
Side-effect-only re-runs: When .agents/ already exists, codemap agents init --mcp or --git-hooks still applies MCP/hook changes without --force. codemap agents init --no-git-hooks --mcp uninstalls hook blocks and writes MCP even when .agents/ is absent. Template refresh still requires --force. Unparseable MCP JSON is rejected unless --force (which replaces the whole file and drops foreign entries — a warning is printed).
templates/agent-content/<kind>/ is a directory of section files concatenated in lexical name order (joined with a blank line). A numeric prefix (00-, 10-, …) controls section order so renumbering is a file-rename, never a code edit.
*.gen.md files have special semantics: if a renderer is registered for the path <kind>/<filename> in the RENDERERS map (in agent-content.ts), the renderer's output replaces the on-disk file body at assembly time. The on-disk file still controls section ordering and carries a hand-written fallback for environments where the renderer's data source is unreachable (today: none).
Current skill section layout:
| File | Source | Updates when |
|---|---|---|
00-overview.md |
Hand-written | Rare (intro / CLI usage / output contract) |
10-recipes-context.md |
Hand-written | Rare (flags, MCP/HTTP/Apply, tools, resources) |
20-recipes.gen.md |
Generated from listQueryRecipeCatalog() |
Every recipe added under templates/recipes/ or <state-dir>/recipes/ |
30-schema.gen.md |
Generated from createTables() DDL |
Every column / table added in src/db.ts |
40-query-patterns.md |
Hand-written | Rare (basic / dep / component / CSS / agg examples) |
50-maintenance.md |
Hand-written | Rare (re-indexing guidance) |
90-troubleshooting.md |
Hand-written | Rare (FAQ) |
Adding a new generated section: write a renderer, register it in RENDERERS, drop a placeholder XX-name.gen.md in the kind directory (the placeholder body is the offline-fallback prose). No assembler change.
Every consumer-disk template carries an HTML-comment stamp:
<!-- codemap-pointer-version: 1 -->On every codemap invocation the runtime scans <root>/.agents/{skills/codemap/SKILL,rules/codemap}.md once and prints a single stderr nag when:
- Stamp present and
< EXPECTED_POINTER_VERSION→ "v0, expected v1". - Stamp absent and file is "fat" (>50 lines) → treated as pre-pointer legacy.
- Stamp absent and file is short → silent (assumed user-managed override).
Cure: codemap agents init --force rewrites the bundled paths to current pointers. Should fire roughly once a year — only bump EXPECTED_POINTER_VERSION when the shape of the pointer file changes (frontmatter schema, fetch URI list, marker comments), not when the served content changes.
Warning goes to stderr only so codemap skill > file.md stays clean.
| Source | Role |
|---|---|
src/agents-template-path.ts |
resolveAgentsTemplateDir() — leaf bundled templates/agents/ resolver; shared by init and application/* live-fetch without import cycles. |
src/agents-init-targets.ts |
AgentsInitTarget + symlink-style integration ids — shared by init and MCP registry without import cycles. |
src/agents-init.ts |
runAgentsInit, upsertCodemapPointerFile, listRegularFilesRecursive, applyAgentsInitTargets (per-file copyFileSync / symlinkFilesGranular), ensureGitignoreCodemapPattern (writes <state-dir>/.gitignore), targetsNeedLinkMode. |
src/agents-init-mcp-registry.ts |
AGENTS_INIT_MCP_REGISTRY — paths, formats, defaults, docs URLs (source of truth for the MCP table below). |
src/agents-init-mcp.ts |
applyAgentsInitMcp, JSON merge + post-write verify; --mcp side effect. |
src/agents-init-interactive.ts |
@clack/prompts flow; calls runAgentsInit. |
src/cli/cmd-agents.ts |
Lazy-loaded from src/cli/main.ts. |
src/cli/cmd-skill.ts |
codemap skill / codemap rule verbs; thin wrapper over assembleAgentContent(kind). |
src/application/agent-content.ts |
assembleAgentContent, RENDERERS map, renderRecipesSection, renderSchemaSection, checkConsumerPointers, maybeWarnStalePointers, EXPECTED_POINTER_VERSION. |
src/application/resource-handlers.ts |
readSkill / readRule (MCP + HTTP resource handlers; both delegate to assembleAgentContent). |
Do not duplicate long IDE matrices, --force / pointer behavior, codemap-pointer details, section assembler shape, or pointer-version semantics in README.md or packaging.md — link here instead.
- architecture.md — CLI chunks, layering.
- .github/CONTRIBUTING.md —
.agents/+.cursor/wiring,main/ PR workflow. - why-codemap.md — why SQL + index for agents.