Canonical definitions of Codemap terms. Disambiguates pairs that look similar (TS shape vs SQL table, recipe vs query, hub vs barrel) and pins the SQL-table names so cross-references are unambiguous.
When introducing a new domain noun in a PR, add or update its entry here per README § Rules for Agents (Rule 9).
Alphabetical, lowercase. Disambiguation pairs link to each other.
- TS shape = a TypeScript interface or type alias.
- SQLite table = an actual on-disk table in
.codemap/index.db. - Recipe = a cataloged SQL recipe loaded by
src/application/recipes-loader.tsfromtemplates/recipes/<id>.{sql,md}(bundled) or<state-dir>/recipes/<id>.{sql,md}(project-local; default.codemap/recipes/). Exposed viacodemap query --recipe <id>and thecodemap://recipesMCP resource. See § R recipe. - Query = any SQL run against the index (recipe or ad-hoc).
Repo-level directory holding rules (.agents/rules/<name>.md) and skills (.agents/skills/<name>/SKILL.md). Source of truth; IDE-agnostic. Mirrored to .cursor/rules/ via per-file symlinks per agents-first-convention.
See language adapter.
A .agents/rules/<name>.md file with YAML frontmatter. Distinct from a skill (longer, scenario-specific). Distinct from a bundled recipe (which is SQL, not Markdown).
Second apply transport for caller-supplied hunks — same {file_path, line_start, before_pattern, after_pattern} contract as codemap apply but no recipe policy gates (auto_fixable, apply.autoApplyRecipes, or --force). CLI: codemap apply --rows - (stdin JSON array) or codemap apply --rows path.json. MCP / HTTP: apply_rows with {rows, dry_run?, yes?}. Use when an agent or external codemod already materialised rows; use apply + a recipe id when the index should synthesise rows from SQL. Unified diffs: apply_diff_input. Writes still require non-TTY consent (--yes / yes: true). Distinct from query --format diff-json (read-only preview).
Third apply transport for caller-supplied unified diff text — parses git-style hunks into the row contract, same executor as apply_rows (no recipe policy gates). CLI: codemap apply --diff-input <file>. MCP / HTTP: apply_diff_input with {diff_text, dry_run?, yes?, commit_message?}. Optional commit_message runs git add + git commit on touched files after a clean apply (recipe apply supports the same).
Substrate-shaped fix executor — reads the same row contract --format diff-json emits and applies hunks to disk. Recipe SQL is the synthesis surface; codemap is the executor (Moat-A — verdict-shape "should we fix this?" stays on the recipe author). Three CLI input modes (mutually exclusive): (1) recipe — codemap apply <recipe-id> [--params k=v[,k=v]]; MCP/HTTP apply {recipe, params?, dry_run?, yes?, force?, until_empty?, max_passes?, commit_message?}. (2) rows — codemap apply --rows -|<file.json>; MCP/HTTP apply_rows. (3) diff — codemap apply --diff-input <unified-diff>; MCP/HTTP apply_diff_input. Shared flags: --dry-run (phase-1 only), --yes (skip TTY prompt; required for non-TTY writes), --json. Recipe-only flags: --force / MCP force (bypass auto_fixable + allowlist); --until-empty / until_empty + --max-passes / max_passes (fixpoint on recipe apply only). Git commit: --commit / commit_message on recipe apply and apply_diff_input. diff-json preview: each hunk includes ambiguity_count (extra before_pattern matches on the line; apply rewrites first match only). Policy (recipe mode only): recipes with auto_fixable: false in <id>.md frontmatter reject writes unless --force / MCP force: true; apply.autoApplyRecipes in user config allowlists recipe ids for non-interactive CLI without --yes (MCP/HTTP writes still need yes: true). Bundled diff-shape recipe ids: rename-preview, migrate-import-source, replace-marker-kind (auto_fixable: true); stale-imports, migrate-deprecated, deprecated-usages, add-jsdoc-deprecated, migrate-jsx-prop (force-gated unless allowlisted). rename-preview homonyms: pass define_in=<symbols.file_path> to scope the rename to one definition; omit to union all homonyms (use find-symbol-references to pick the anchor first). CLI shorthand: codemap rename <old> <new> [--define-in <file_path>] [--in-file <prefix>] [--kind <k>] → apply rename-preview (thin alias — same recipe + policy gates). --commit / commit_message: recipe apply and apply_diff_input only (not apply_rows); with --until-empty, commit only when terminated_by is empty. Phase 1 validates every row via actual.includes(before_pattern) (substring match); six conflict reasons (file missing / line out of range / line content drifted / path escapes project root / path is a symlink / duplicate edit on same line). Phase 2 (gated on !dryRun && zero conflicts) writes via sibling temp + renameSync per file; all-or-nothing across files on conflicts (no cross-file rollback on crash mid-phase-2). Q6 gate — TTY without --yes prompts Proceed? [y/N]; MCP/HTTP have no prompt path. Result envelope: {mode, applied, files, conflicts, summary} (+ optional passes, terminated_by). Re-apply on stale disk → line content drifted; re-index then vacuous zero-row pass (Q7). Engine: application/apply-engine.ts (applyDiffPayload); orchestration: application/apply-run.ts. Full transport matrix: architecture.md § Apply — input modes. Boundary kit: § Boundary verification — apply write path.
Two-snapshot structural-drift command: codemap audit diffs the live <state-dir>/index.db (default .codemap/index.db) against a base snapshot and emits {head, deltas} where each deltas[<key>] carries {base, added, removed}. v1 ships three deltas: files, dependencies, deprecated. Each delta pins a canonical SQL projection (in V1_DELTAS) and a required-columns list — projects baseline rows down to that subset before diffing so schema bumps that add columns don't break pre-bump baselines. Primary snapshot sources: --baseline <prefix> (auto-resolve <prefix>-files / <prefix>-dependencies / <prefix>-deprecated from query_baselines) and --base <ref> (git archive | tar -x + reindex — see audit --base <ref>) are mutually exclusive; --<delta>-baseline <name> per-delta overrides compose with either primary source. Distinct from codemap query --baseline (that's one query, one diff; audit composes multiple per-delta diffs into one envelope). Distinct from code-quality audit tools (e.g. knip for unused exports, jscpd for duplication, framework-specific complexity linters) — those produce verdicts on dead code / dupes / complexity, which are explicit non-goals per roadmap.md § Non-goals (v1); codemap audit stays structural.
Ad-hoc audit snapshot from any git committish (origin/main, HEAD~5, <sha>, tag, …). git archive --format=tar <sha> is piped through tar -x into <projectRoot>/.codemap/audit-cache/<sha>/ — a plain extracted tree with no .git artifact and no registered git worktree, so git clean -xdf and rm -rf both sweep it without flag escalation. Codemap reindexes into the cache's .codemap/index.db, then per-delta canonical SQL runs on that DB vs the live one. Cache key is the resolved sha (git rev-parse --verify), so --base origin/main and --base <sha> (when they point at the same commit) share one cache entry. Atomic populate — per-pid temp dir + POSIX rename; concurrent processes resolving the same sha race-safely without lock files. Eviction: hardcoded LRU 5 entries / 500 MiB. Per-delta base.source is "ref" (vs "baseline") and the delta carries base.ref (user-supplied string) + base.sha (resolved). Each added row carries attribution: introduced | inherited — finding key (requiredColumns → JSON.stringify) vs merge-base index; filter branch-only deltas with jq 'select(.attribution == "introduced")'. --summary adds added_introduced / added_inherited counts per delta. Mutually exclusive with --baseline <prefix>; composes orthogonally with per-delta --<delta>-baseline <name> overrides. Hard error on non-git projects (no graceful fallback — there's no meaningful "ref" without git). Both transports (MCP audit tool's base? arg, HTTP POST /tool/audit) call the same runAuditFromRef engine in application/audit-engine.ts.
Row metadata on deltas[<key>].added[] when base.source is "ref" (audit --base). introduced — finding key absent at merge base (branch-new drift). inherited — key present at merge base (e.g. multiset surplus on pre-existing debt). Not a verdict primitive (Moat A); baseline-prefix audits omit the field. Key helper: findingKey(row, spec) in audit-engine.ts.
One row per AwaitExpression. Captures awaited_expression source text, optional awaited_callee_name, and loop/try context flags (in_loop, in_try) from a visitor context stack. Joins scopes.local_id via scope_local_id. Powers find-await-in-loop.
In Codemap usage: a file whose exports are entirely re-exports with no local value symbols — surfaced as files.is_barrel = 1 (post-pass). find-barrel-files lists barrel files (is_barrel = 1); barrel-files ranks files by export count (hub detection). Distinct from hub below — barrel measures exports out, hub measures imports in.
The shared batchInsert<T>() helper in src/db.ts. Splits inserts into multi-row INSERT … VALUES (…),(…) statements sized by batchSizeForTuple() (cap MAX_ROWS_PER_BATCH = 5000), with pre-computed placeholder strings. Used by every insertX function.
Per-reference resolution to the originating symbol per [R.12]. One row per non-member-kind references row, with resolution_kind in {same-file, imported, re-exported, global, unresolved} and a nullable resolved_symbol_id joining symbols(id). Resolved in a single in-memory pass (src/application/bindings-engine.ts) after files/symbols/imports settle. Full-rebuild only — targeted reindex skips per [R.10]. Powers find-symbol-references and find-re-exported-bindings.
Architecture-boundary substrate. Users declare boundaries: [{name, from_glob, to_glob, action?}] in .codemap/config.ts; the resolver fills action to "deny" when omitted. Every index pass calls reconcileBoundaryRules (in src/db.ts) which clears boundary_rules and re-inserts from the resolved config — config is the single source of truth, the table is a denormalised lookup. Bundled boundary-violations recipe joins dependencies × boundary_rules via SQLite GLOB and surfaces forbidden import edges; --format sarif lights up automatically because the recipe row aliases dependencies.from_path to file_path. CHECK constraint pins action ∈ {'deny','allow'}. v1 only honours 'deny'; 'allow' reserves the slot for future whitelist semantics. See architecture.md § boundary_rules.
Bun's native SQLite binding. Codemap uses it on Bun; falls back to better-sqlite3 on Node. Both are wrapped by src/sqlite-db.ts so call sites are runtime-agnostic.
Synchronous Node.js SQLite binding. The Node-side counterpart to bun:sqlite. Allows one statement per prepare(), unlike bun:sqlite which accepts multiple — see packaging § Node vs Bun.
Function-scoped call edges, deduped per (caller_scope, callee_name, call_kind) per file (call vs new). caller_scope is dot-joined enclosing scope (e.g. UserService.run). Module-level calls are excluded. Columns include args_count (NULL when a spread argument is present), is_method_call, is_constructor_call, is_optional_chain, and provenance (NULL = parse-resolved; heuristic = callback-synthesis). After bindings, resolveCalls (src/application/call-resolver.ts) fills callee_symbol_id and callee_resolution_kind on ast-only rows; method calls (is_method_call = 1) stay NULL and are not queued. Moat-A recipes and walks filter NULL/ast; calls-including-heuristic lists heuristic rows only. Optional synthesis.heuristicCalls in config (default false) runs callback-synthesis after resolve. See architecture.md § calls, CallRow, unresolved_calls.
TS shape for one row of the calls table. Maps 1:1 to the SQLite columns, including optional provenance (null | 'heuristic').
The extraction path a file took during parsing. One of ts, css, or text. Stored on ParsedFile.category, not on a SQLite table. See ParsedFile.
The codemap state directory under <project_root> — holds index.db (+ WAL / SHM), project-local recipes/, config.{ts,js,json}, and the self-managed .gitignore (per plan §D7 + D11). Default name .codemap/; override via --state-dir <path> CLI or CODEMAP_STATE_DIR env (relative paths resolve against <project_root>). Resolved at bootstrap, not via the config file (chicken-and-egg). audit --base cache is always at <projectRoot>/.codemap/audit-cache/<sha>/ (hardcoded; does not follow --state-dir). Engine: src/application/state-dir.ts (resolveStateDir).
The on-disk SQLite database file at <state-dir>/index.db (default <project_root>/.codemap/index.db). Always accompanied by index.db-wal and index.db-shm while open (WAL mode). Gitignored by the self-managed <state-dir>/.gitignore written by ensureStateGitignore.
Codemap-managed .gitignore inside <state-dir>/ (blacklist of generated artifacts; tracked sources recipes/ + config.* default to tracked). Reconciled on every codemap boot by ensureStateGitignore (src/application/state-dir.ts) — read → compare to canonical → write only on drift. Bumping the canonical body in a future PR IS the migration: every consumer's project repairs itself on next codemap run. Same self-healing pattern (ensure* reconciler, idempotent, drift-detect) governs <state-dir>/config.json (ensureStateConfig in src/application/state-config.ts — prunes unknown keys, sorts keys, never touches user-authored TS/JS configs). Inspired by flowbite-react's setup-* shape; expressed in codemap's own conventions per plan §D11.
CLI subcommand emitting a JSON envelope (ContextEnvelope) with project metadata, top hubs (full bundled fan-in recipe limit), sample markers, recipe catalog, optional intent via --for "<intent>", and non-compact start_here shortcuts (index summary, intent-ranked recipe cards, budget-capped hub leaders with export signatures). --include-snippets adds optional one-line hub-leader snippets (no-op with --compact). --compact drops hubs, sample_markers, and start_here, emitting minified JSON; default mode pretty-prints with 2-space indent. Whitespace-only --for values are rejected.
CI-aggregate flag on codemap query and codemap audit. Aliases --format sarif + process.exitCode = 1 on findings (query) or delta additions (audit). On query only, also suppresses the no-locatable-rows stderr warning (CI templates would surface it as red noise; the row-set is the gating signal). Mutually exclusive with --json (different format aliases) and with --format <other> (contradicts the alias); --ci --format sarif redundant but accepted. Designed for the GitHub Marketplace Action's headline default (audit --base ${{ github.base_ref }} --ci); independently useful for any non-Action CI consumer.
CLI subcommand comparing on-disk SHA-256 against files.content_hash. Statuses: stale | missing | unindexed | rejected (rejected carries optional reason: path escapes project root | path escapes via symlink | path resolves outside project root; output path keys are always project-relative POSIX paths). Exits 1 on any drift.
Strongly-connected components of the import dependency graph computed via Tarjan after the full index pass. Only cyclic files appear (SCC size ≥ 2, or size-1 with a self-edge). Powers circular-imports recipe.
Materialised re-export resolution. One row per (from_file, from_name) walked through barrel files to the terminal definition site. Bounded at 10 hops with cycle detection. truncated = 1 flags chains that hit the cap or an unindexed file mid-walk. Powers barrel-chains recipe.
React components (PascalCase + JSX return or hook usage). PascalCase functions that neither return JSX nor call hooks stay in symbols only — never components. hooks_used is JSON-encoded. See ComponentRow.
Per-function decision-point count (REAL column on symbols). Computed by the parser walker per the McCabe formula: 1 + (decision points). Counted nodes: if, while, do…while, for, for…in, for…of, case X: (not default:), &&, ||, ??, ?:, catch. Function-shaped symbols only (top-level function, named arrow/const, class methods); non-functions get complexity = NULL. Joins to coverage for high-complexity-untested (cyclomatic ≥ 10 ⨯ coverage < 50%). See also symbols.cognitive_complexity.
SonarSource-inspired cognitive complexity (INTEGER on symbols) for the same function-shaped symbols as cyclomatic complexity. Penalizes nested control flow; computed in the same parser walk as McCabe. Recipes: high-cognitive-complexity (min_score default 15, Sonar rule threshold); high-complexity-untested includes the column while filtering on cyclomatic complexity.
SHA-256 hex of a canonicalized function body AST (not raw source). Normalization (v1): every identifier → $id; literals → kind only (Literal:string, …); absent returns (null, undefined, void 0, bare return) → Literal:nullish; template literals walked structurally. Populated for function-shaped symbols (function, method, getter, setter) when body_line_count >= 2; NULL for trivial one-liners and non-functions. Recipe duplicates groups rows sharing a hash. Distinct from token-level suffix-array / copy-paste clone detectors — catches rename-insensitive structural twins; may false-positive on shared control-flow skeletons (triage with snippet).
Opt-in FTS5 virtual table over file content (tokenize='porter unicode61'). Always created (near-zero space when empty); populated only when the resolved config has FTS5 enabled (.codemap/config.ts fts5: true OR --with-fts CLI flag at index time; CLI wins, logs stderr override). Demonstrates the FTS5 ⨯ symbols ⨯ coverage JOIN composability that ripgrep can't match — bundled recipe text-in-deprecated-functions exemplifies the JOIN. Toggle change auto-detects via meta.fts5_enabled and forces a full rebuild so source_fts is consistently populated. Stderr telemetry [fts5] source_fts populated: <N> files / <X> KB on first populate. Distinct from coverage — source_fts is an FTS5 virtual table; coverage is a regular STRICT, WITHOUT ROWID table. Default OFF preserves .codemap/index.db size for non-users (~30–50% growth on text-heavy projects).
Output mode rendering {from, to, label?, kind?} rows as a Mermaid flowchart LR diagram. Sibling of --format sarif / --format annotations in application/output-formatters.ts. Bounded-input contract (50-edge ceiling; MERMAID_MAX_EDGES) — unbounded inputs reject with a scope-suggestion error naming the recipe + count + scoping knobs (LIMIT / --via / WHERE). Auto-truncation explicitly out of scope (would be a verdict masquerading as output mode, violating the predicate-as-API moat). Recipes / ad-hoc SQL must alias columns to the {from, to} shape (e.g. SELECT from_path AS "from", to_path AS "to" FROM dependencies LIMIT 50).
Change Risk Anti-Patterns score per published formula: CC² × (1 - effective_coverage/100)³ + CC where CC = symbols.complexity. Bundled recipe high-crap-score ranks symbols at or above min_crap (default 30). effective_coverage_pct uses ingested coverage.coverage_pct when a row exists (coverage_source: measured), else graph-estimated tiers from test reachability (coverage_source: estimated: 85% direct test reference, 40% file reachable from tests via value-only dependencies, 0% otherwise). Heuristic only — not execution coverage; prefer codemap ingest-coverage before CI gates. Complements high-complexity-untested when coverage is not ingested.
Statement coverage ingested from Istanbul JSON, LCOV, or V8 runtime (NODE_V8_COVERAGE=... directory via --runtime) via codemap ingest-coverage <path>. Natural-key PK (file_path, name, line_start) — intentionally not a FK to symbols.id because symbols re-creates with fresh AUTOINCREMENT ids on every --full reindex; the natural-key approach lets coverage rows survive that churn (coverage is also intentionally absent from dropAll(), joins the query_baselines precedent). Columns: coverage_pct REAL (NULL when total_statements = 0 — "untested" and "no testable code" are different signals), hit_statements, total_statements. Orphan rows (file deleted from project) are cleaned by an explicit DELETE FROM coverage WHERE file_path NOT IN (SELECT path FROM files) at the end of every ingest. Three meta keys (coverage_last_ingested_at / _path / _format) record freshness — single ingest at a time, so format is meta-level not per-row.
codemap ingest-coverage <path> [--runtime] [--json] reads a coverage artifact and writes statement-level rows into the coverage table. MCP/HTTP twin: ingest_coverage ({path, runtime?}). Three formats:
- Istanbul JSON (
coverage-final.json) — emitted natively byc8,nyc,vitest --coverage --coverage.reporter=json,jest --coverage --coverageReporters=json. Parser readsstatementMap+s(per-statement hit counts). - LCOV (
lcov.info) — emitted bybun test --coverage,c8 --reporter=lcov, every legacy stack. Parser tokenisesSF:/DA:<line>,<count>/end_of_recordrecords; ignoresTN:/FN:/BRDA:/LF:/LH:(statement coverage only). - V8 runtime (with
--runtime) — opt-in directory mode readingNODE_V8_COVERAGE=...per-process dumps (coverage-<pid>-<ts>-<seq>.json). Each script's byte-offset ranges are converted to per-line hit counts (innermost-wins: smaller ranges override the function-as-a-whole count). Skips non-file://URLs (Node internals,evalmachine.<anonymous>); merges duplicate-URL scripts across dumps. Useful for "delete cold code with stronger evidence" agent flows. Local-only — SaaS aggregation explicitly out of scope (different product class).
Format auto-detected from extension (.json → istanbul, .info → lcov, directory → probe both, error if ambiguous); --runtime opts into V8 directory mode. Each statement projects onto the innermost enclosing symbol via JS-side (line_end - line_start) ASC tie-break — required because nested symbols (class methods inside classes, closures inside functions) would otherwise inflate total_statements. Statements that fall outside every symbol range (top-level expressions, side-effect imports) increment skipped.statements_no_symbol for observability. Three bundled recipes consume the table at first-class agent surface (no agent ever has to hand-compose the JOIN):
untested-and-dead— exported functions with no callers AND zero coverage (the killer recipe; ships with a name-collision mitigation guide in the recipe.md).coverage-confirmed-dead— same static dead predicate asuntested-and-deadwith explicitconfidence(highwhen ingestedcoverage_pct = 0,mediumwhen unmeasured) plusreasonandcaller_count— Moat A predicate columns for deletion triage afteringest-coverage.files-by-coverage— files ranked ascending by statement coverage (replaces a deferredfile_coveragerollup table; aggregates the symbol-level table via index-boundedGROUP BY).worst-covered-exports— top-20 worst-covered exported functions.
Engine: application/coverage-engine.ts — pure upsertCoverageRows({db, projectRoot, rows, format, sourcePath}) core consumed by ingestIstanbul, ingestLcov, and ingestV8. Transport orchestration (path resolution, artifact I/O, V8 directory merge) lives in application/ingest-coverage-run.ts (runIngestCoverageOnDb), shared by CLI, MCP ingest_coverage, and HTTP.
Column on the files table. Lowercase SHA-256 hex of file bytes computed by src/hash.ts. Drives incremental staleness detection (getChangedFiles) and powers the files-hashes recipe + codemap validate CLI.
TS shape for the JSON emitted by codemap context. Stable contract; agents can key off field names. Non-compact payloads include start_here: inline index_summary, intent-ranked recipe cards (tool: "query_recipe"), and hub_leaders (budget-capped top fan-in files with exported-symbol signatures; optional snippet / stale / missing when CLI --include-snippets or MCP/HTTP include_snippets: true). Legacy hubs keeps the bundled fan-in recipe default limit; prefer hub_leaders for signatures. start_here.classified_as is "default" when no user intent was supplied.
A SQLite index that includes every column needed by a query, so SQLite reads everything from the index B-tree without touching the main table. The query plan shows USING COVERING INDEX. Used heavily for AI agent query patterns — e.g. idx_symbols_name_covering for codemap show equality lookups. See architecture § Covering indexes.
CSS class names from selectors (no leading .). is_module = 1 for .module.css files. See CssClassRow.
@keyframes <name> declarations. See CssKeyframeRow.
CSS custom properties (--token: value). scope is :root, @theme (Tailwind v4), or the selector text. See CssVariableRow.
One row per @decorator site on classes, methods, properties, or accessors. target_symbol_id links to symbols(id) post-insert when resolvable. Powers find-decorator-usage.
Data Definition Language — the CREATE TABLE / CREATE INDEX strings in src/db.ts. Distinct from schema (the conceptual structure) and from SCHEMA_VERSION (the integer that triggers auto-rebuild on mismatch).
Resolved file-to-file edges derived from imports.resolved_path. Composite primary key (from_path, to_path). Self-edges and unresolved imports are excluded. STRICT, WITHOUT ROWID. See DependencyRow.
TS shape for one row of the dependencies table.
One row per import() expression. source_kind is literal / template / expression; resolved_path filled when literal and resolvable. in_async_fn flags dynamic imports inside async functions. Powers find-dynamic-imports.
The 4-criterion gate for whether a doc earns its place — see README § Existence test. Forces deletion of stale docs.
Named, default, and re-exports. kind is value / type / re-export; re_export_source is non-null only for re-export rows. See ExportRow.
TS shape for one row of the exports table.
Number of edges into a file in the dependencies table — COUNT(*) FROM dependencies WHERE to_path = ?. Surfaces as the fan-in recipe (top files by inbound edges, i.e. hubs). Hotspot ranker only — not an orphan/dead-code detector; N-file packs with sibling imports can all have non-zero fan-in yet be unreachable from a real entry point (plans/c9-plugin-layer.md closed-dead-subgraph caveat).
Number of edges out of a file — COUNT(*) FROM dependencies WHERE from_path = ?. Surfaces as the fan-out recipe.
Per-file git churn metrics refreshed on every index pass (incremental scoped recompute; idle HEAD cache). Git via ingestFileChurnFromGit; non-git via codemap ingest-churn or config churn.file (skips git when churn.file is set). MCP/HTTP twin: ingest_churn ({path}). Config: churn.halfLifeDays, churn.since / --churn-since. Column churn_trend: accelerating | stable | cooling when enough history exists. Powers churn-complexity-hotspots (file or symbol grain, normalized score) — distinct from outcome alias hotspots → fan-in. Empty table → context churn_hint on start_here.
Header row for every indexed file. path is the primary key; all other tables FK to it with ON DELETE CASCADE. Flags: is_barrel (100% re-exports, no local value symbols) and has_side_effects (module-level call/assignment seen at parse time). See FileRow.
TS shape for one row of the files table. Distinct from the files SQLite table itself (the table name is lowercase plural; the TS interface is PascalCase singular).
Hand-crafted source tree under fixtures/minimal/ used as the corpus for golden tests. Excluded from oxlint via ignorePatterns: ["fixtures"] so auto-fixes never mutate test corpora.
Index mode that drops every table and rebuilds from scratch — codemap --full or cm.index({ mode: "full" }). Triggers automatically when SCHEMA_VERSION mismatches or when no previous index exists. Optimized via worker threads, deferred index creation, and relaxed PRAGMAs.
Read/write helpers for the meta key-value table. Stores schema_version, last_indexed_commit, indexed_at, etc.
Include patterns (relative to project root) used to find indexable files. Defaults in DEFAULT_INCLUDE_PATTERNS. Implemented via tinyglobby on both Node and Bun (POSIX paths). Pre-2026-05 used Bun.Glob on Bun; switched to tinyglobby everywhere when the collectFiles refactor needed glob-side ignore (which Bun.Glob doesn't support) — see packaging.md § Node vs Bun.
A bun scripts/query-golden.ts regression that compares a query/recipe's output against a checked-in JSON snapshot. Tier A uses fixtures/minimal/; Tier B uses external trees via CODEMAP_*. See golden-queries.md.
::notice file=<path>,line=<n>::<message> — GitHub Actions workflow command that surfaces a finding inline on the PR diff without writing a custom Action wrapper. Codemap emits annotations via codemap query --format annotations (or format: "annotations" on the MCP query tools). One line per locatable row; rows without a location are skipped. Property values + message payload are percent-encoded per actions/toolkit so paths with : / , and messages with % round-trip safely. Default level notice; warning and error overrides supported via the level parameter (CLI exposes only the default for v1; per-recipe override comes with the same v1.x frontmatter that grants per-recipe SARIF severity).
SHA-256 hex computed over file bytes via src/hash.ts. Same algorithm on Bun and Node — Bun.hash is not used because it differs across runtimes.
A file with high fan-in — many other files import it. Surfaced by the fan-in recipe (which we historically also called hubs). Distinct from barrel file (high fan-out via exports).
Index mode that diffs against last_indexed_commit (git) and only re-indexes changed files. Default mode (no flag); falls back to full rebuild if commit history is incompatible.
Symbol or file blast-radius walker. CLI: codemap impact <target> [--in <path>] [--direction up|down|both] [--depth N] [--via dependencies|calls|imports|all] [--limit N] [--summary] [--json]. MCP: impact tool (in arg). HTTP: POST /tool/impact. Replaces hand-composed WITH RECURSIVE queries that agents struggle to write reliably. Walks compatible graphs based on resolved target kind: symbol targets walk calls (callers / callees by name); file targets walk dependencies + imports (resolved_path only). Homonym symbols: unscoped walks union per-defining-file call graphs; --in / MCP in disambiguates via show-engine prefix/exact rules — mismatch → empty matches + skipped_scope. Mismatched explicit --via choices land in skipped_backends instead of failing. Cycle-detected via path-string instr check inside the recursive CTE; bounded by --depth (default 3, 0 = unbounded but still cycle-detected and limit-capped) and --limit (default 500). Result envelope: {target, direction, via, depth_limit, matches: [{depth, direction, edge, kind, name?, file_path}], summary: {nodes, max_depth_reached, by_kind, terminated_by: 'depth'|'limit'|'exhausted'}, skipped_backends?, skipped_scope?}. --summary trims matches for cheap CI gate consumption (jq '.summary.nodes') but preserves the count. Pure transport-agnostic engine in application/impact-engine.ts; CLI / MCP / HTTP all dispatch the same findImpact function. sarif / annotations formats not supported (impact rows are graph traversals, not findings).
Per-specifier breakdown of the imports.specifiers JSON blob. One row per imported binding — or one kind='side-effect' row for bare import "mod". Columns include imported_name, local_name, kind in {named, default, namespace, side-effect}, is_type_only, column-precise position, and import_id FK to imports. Powers find-import-sites and find-side-effect-imports.
Raw import statements. specifiers is JSON-encoded; resolved_path is non-null only when the resolver could map source to an indexed file. See ImportRow and the resolved view dependencies.
TS shape for one row of the imports table.
TS shape emitted under IndexRunStats.performance when --performance is set. Eight per-phase timings (collect_ms, parse_ms, insert_ms, index_create_ms, bindings_ms, module_cycles_ms, re_export_chains_ms, heritage_ms) + total_ms + top-10 slowest files. Note: total_ms is indexFiles wall-clock (parse + insert + DDL + bindings + cycles + re_exports + heritage) and excludes collect_ms; end-to-end run wall is collect_ms + total_ms. Setting CODEMAP_PERFORMANCE_JSON=<path> dumps the report as JSON post-run.
Public TS shape returned from Codemap#index() and runCodemapIndex(). Wall-clock + row counts + optional performance report.
Structured JSDoc tags parsed from symbols.doc_comment — one row per tag per symbol (@param, @throws, @returns, …). FK symbol_id → symbols(id). Powers find-throws-jsdoc.
One row per JSX attribute on a jsx_elements row. value_kind in {string, expression, boolean, spread, element}. Join parent via element_id.
One row per JSX element or fragment in .tsx/.jsx files. parent_element_id linked in a per-file post-insert pass. is_fragment = 1 for <>…</>. Powers find-jsx-usages.
A LanguageAdapter registered in src/adapters/builtin.ts that maps file extensions to a parser (parse(ctx) → ParsedFilePayload). Currently three built-ins: builtin.ts-js (oxc), builtin.css (lightningcss), builtin.text (markers-only). Future community adapters can register additional ones.
meta key holding the HEAD SHA at the end of the previous successful index run. Used by getChangedFiles to compute the changed set.
Rust-based CSS parser (NAPI bindings). Codemap's src/css-parser.ts uses its visitor pattern to extract custom properties, classes, keyframes, and @import sources. Not a preprocessor — Sass / Less / SCSS are out of scope.
Stdio MCP (Model Context Protocol) server exposing codemap's structural-query surface to agent hosts (Claude Code, Cursor, Codex, generic MCP clients) as JSON-RPC tools — eliminates the bash round-trip on every agent invocation. 21 tools: query, query_batch, query_recipe, audit, save_baseline, list_baselines, drop_baseline, context, validate, show, snippet, impact, affected, trace, explore, node, apply, apply_rows, apply_diff_input, ingest_coverage, ingest_churn. Each has a CLI twin with the same JSON payload except transport-only MCP resources (codemap://mcp-instructions, initialize instructions). Subset via CODEMAP_MCP_TOOLS (agents.md § MCP tool allowlist). Resources: codemap://schema, codemap://skill, codemap://rule, codemap://mcp-instructions, codemap://recipes, codemap://recipes/{id}, codemap://files/{path}, codemap://symbols/{name}. Resource freshness is split by contract: schema / skill / rule / mcp-instructions are lazy-cached per server process; recipes, files, and symbols are live read-per-call so inline recency fields and index mutations under --watch don't freeze at first read. HTTP's GET /resources/{encoded-uri} uses the same resource handler. Baseline tools (save_baseline, list_baselines, drop_baseline) mirror query --save-baseline / --baselines / --drop-baseline; query / query_recipe also accept optional baseline for one-shot row diff vs saved snapshots (same envelope as CLI query --baseline). CLI twins: query batch, trace, explore, node, file, schema, symbols, context --include-snippets, ingest-coverage. Tool input/output keys are snake_case on MCP/HTTP — Codemap's convention; CLI stays kebab. Output shape matches each tool's CLI JSON payload; MCP wraps payloads in {content: [{type: "text", text: …}]}. Bootstrap once at server boot; tool handlers (in application/tool-handlers.ts) and resource handlers (in application/resource-handlers.ts) are pure transport-agnostic — the same handlers serve codemap serve (HTTP) via POST /tool/{name} and GET /resources/{encoded-uri}. Session lifecycle: exits on client disconnect (stdin EOF, stdout broken pipe, parent process exit, SIGINT/SIGTERM) via session-lifecycle.ts; no idle timeout — the process stays up while the pipe is open even without tool calls (see § Session lifecycle). With --watch, the watcher starts before connect and drains on exit. Implementation: src/cli/cmd-mcp.ts (CLI shell) + src/application/mcp-server.ts (engine). See architecture.md § MCP wiring.
MCP/HTTP tool and codemap query batch (--stdin / --file, optional --summary / --no-summary, --changed-since, --group-by, --compact) — runs N read-only SQL statements in one round-trip. Items are string | {sql, summary?, changed_since?, group_by?}: bare strings inherit batch-wide flag defaults; object form overrides on a per-key basis. Output is an N-element array; per-element shape mirrors single-query's output for that statement's effective flag set. Per-statement errors are isolated (failed statement returns {error} in its slot; siblings still execute). Distinct from making query accept ;-delimited batches (rejected — would need a SQL tokenizer and would diverge query's output shape from its CLI counterpart). SQL-only (no recipe polymorphism); query_recipe_batch is an additive future change if a real consumer asks.
Per-file aggregate metrics (one row per indexed TS/JS file): total_lines, code_lines, blank_lines, comment_lines, plus symbol-kind counts (function_count, class_count, interface_count, export_count, let_count, const_count, var_count, arrow_count). Line classification is regex-light per Tier 11 ship report.
First-class function parameters — one row per leaf parameter binding, ordered by position. Keyed by (file_path, owner_name, owner_kind) to disambiguate same-name function vs method. type_text is the stringified annotation; default_text is the raw default-expression source. Powers find-by-param-type recipe.
TODO / FIXME / HACK / NOTE comments extracted from any indexed file (TS, CSS, Markdown, JSON, YAML, …). Stored in the markers table; surfaced by the markers-by-kind recipe. See MarkerRow.
TS shape for one row of the markers table.
Key-value metadata table. Holds schema_version, last_indexed_commit, indexed_at, file_count, project_root. STRICT, WITHOUT ROWID.
Top-level CLI verbs that thin-wrap query --recipe <id>: dead-code → untested-and-dead, deprecated → deprecated-symbols, boundaries → boundary-violations, hotspots → fan-in, coverage-gaps → worst-covered-exports. For change-frequency × complexity refactor targets use recipe churn-complexity-hotspots (not the hotspots alias). Every query flag passes through (--json, --format, --ci, --summary, --changed-since, --group-by, --params, --save-baseline, --baseline). Mapping lives in src/cli/aliases.ts (OUTCOME_ALIASES). Capped at 5 to avoid alias-sprawl — promote a sixth only when the recipe becomes a headline outcome. Moat-A clean: the alias is a one-line rewrite, not a new primitive; the recipe IS the SQL. Write alias (distinct): codemap rename thin-wraps apply rename-preview (not query --recipe) — mapping in src/cli/rename-alias.ts; same Moat-A rule (no new write semantics).
Rust-based TypeScript / JavaScript parser (NAPI bindings). Codemap's src/parser.ts uses it to extract symbols, imports, exports, components, type members, calls, and markers from .ts / .tsx / .js / .jsx (and .mts / .cts / .mjs / .cjs).
Rust-based import-path resolver (NAPI bindings). Configured with tsconfig.json for alias resolution (~/utils/foo). Produces the dependencies table from imports.resolved_path.
Rust-based linter. Configured in .oxlintrc.json. Auto-fixes most violations via bun run lint:fix.
Rust-based formatter. Run via bun run format / format:check.
TS shape returned by parse workers and built up by language adapters. Header (relPath, fileRow, category, parseMs?) plus optional row arrays per category (TS / CSS / text). Subset that adapters populate is ParsedFilePayload.
Code that turns source bytes into structured rows. Three implementations: parser.ts (oxc), css-parser.ts (lightningcss), markers.ts (regex). Distinct from adapter — an adapter wires a parser to a set of file extensions.
A docs/plans/<feature-name>.md file tracking in-flight work. Created on commit; deleted when the feature ships per README § Rule 3.
Every identifier USE per [R.11], column-precise per [R.6]. kind in {value, type, jsx, member}; is_write distinguishes reads from writes per [R.13]; scope_local_id joins scopes in the same file. Native HTML JSX tags, attribute names, and long-hand object-literal keys are NOT emitted (they're not bindings). kind='member' rows DO emit for non-computed property access — they're skipped by the bindings resolver but available for consumers that want member-name positions.
Operational signals worth auditing: console.* calls, debugger statements, throw statements, process.env.X accesses. kind in {console, debugger, throw, process-env}; detail carries the qualifier (method name, env-var name, truncated throw expression). Powers find-leftover-console + env-var-audit recipes.
Markdown PR-summary renderer. codemap pr-comment <input> (or - for stdin) reads a codemap audit --json envelope or a codemap query --format sarif doc and emits a markdown comment suitable for gh pr comment <PR> -F -. Auto-detects shape via runs[] (SARIF) vs deltas (audit); --shape audit|sarif overrides. Audit-mode groups by delta with collapsed <details> for added + removed rows; SARIF-mode groups by ruleId. Lists >50 entries collapse to … and N more. --json envelope {markdown, findings_count, kind} is the structured form action.yml consumers read. Targets the surfaces SARIF → Code Scanning doesn't cover (private repos without GHAS, aggregate audit deltas without file:line anchors, bot-context seeding). v1.0 ships the (b) summary-comment shape; (c) inline-review comments deferred per Q4 of plans/github-marketplace-action.md. Engine: application/pr-comment-engine.ts (pure transport-agnostic).
A managed root-level file (CLAUDE.md, AGENTS.md, GEMINI.md, .github/copilot-instructions.md) with a <!-- codemap-pointer:begin --> / <!-- codemap-pointer:end --> section. Written by codemap agents init. See agents.md § Pointer files.
Any SQL run against .codemap/index.db — either a recipe (saved SQL by id — bundled or project-local) or ad-hoc. Bundled SQL lives in templates/recipes/; project-local in <state-dir>/recipes/. src/application/query-recipes.ts is the registry/loader shim over recipes-loader.ts.
A snapshot of a query result set saved by codemap query --save-baseline[=<name>] and replayed by codemap query --baseline[=<name>] for added/removed diffs. MCP/HTTP twin: optional baseline on query / query_recipe (explicit name string; incompatible with non-json format and group_by). Stored in the query_baselines table inside <state-dir>/index.db (default .codemap/index.db; no parallel JSON files; survives --full and SCHEMA_VERSION rebuilds because the table is intentionally absent from dropAll()). Default name = --recipe id; ad-hoc SQL must pass an explicit name. Diff identity is per-row JSON.stringify equality — exact match, no fuzzy "changed" category in v1.
See recipe.
A SQL file (plus optional sibling .md description) loaded into the catalog by src/application/recipes-loader.ts. Two sources, same shape:
- Bundled — ships in the npm package as
templates/recipes/<id>.{sql,md}. Examples:fan-in,deprecated-symbols,files-hashes. - Project-local — loaded from
<state-dir>/recipes/<id>.{sql,md}(default.codemap/recipes/; honors--state-dir/CODEMAP_STATE_DIR; root-only resolution; not gitignored — meant to be checked in for team review).
Run via codemap query --recipe <id> (alias -r). Project recipes win on id collision with bundled ones (entries carry shadows: true in the catalog so agents reading codemap://recipes at session start see when a recipe behaves differently from the documented bundled version). Per-row actions templates (kebab-case verb + description) live in YAML frontmatter on each <id>.md — uniform between bundled and project. Load-time validation rejects empty SQL and DML / DDL keywords; runtime PRAGMA query_only=1 on queryRows, executeQuery, and printQueryResult (ad-hoc CLI SQL) is the parser-proof backstop. Distinct from an ad-hoc query (any SQL string the agent composes itself; ad-hoc SQL never carries actions).
Boolean flag on a project-local recipe entry that has the same id as a bundled recipe — shadows: true means "this project recipe overrides what the bundled version would have done." Surfaces in --recipes-json, codemap://recipes, and codemap://recipes/{id} so agents can see overrides without parsing per-execution responses (per-execution shape stays unchanged for plan § 4 uniformity). Silent at runtime — the agent-facing skill prompt is the channel that tells agents to check the flag at session start.
Per-recipe last_run_at (epoch ms) + run_count for agent-host ranking — surfaces inline on every --recipes-json entry and the matching codemap://recipes / codemap://recipes/{id} resources (live read every call; the resource cache was dropped to avoid freezing recency at first-read for the server-process lifetime). Counts only successful recipe runs; failed runs / param-validation rejections / SQL errors don't write. Default ON; opt-out via .codemap/config recipeRecency: false (short-circuits before any DB write — no rows ever land). 90-day rolling window enforced eagerly on the write path (single transactional DELETE + INSERT … ON CONFLICT inside recordRecipeRun); reads filter at SELECT, never mutate. Local-only — no upload primitive (resists telemetry-creep PRs by construction). Write paths — handleQueryRecipe, handleAffected, handleTrace, handleExplore, and handleNode in application/tool-handlers.ts (MCP + HTTP) and runQueryCmd in cli/cmd-query.ts + runAffectedCmd in cli/cmd-affected.ts (CLI) — each calls tryRecordRecipeRun (the failure-isolated wrapper around recordRecipeRun) from application/recipe-recency.ts. Failure-isolated: a recency-write throw NEVER blocks the recipe response (warning to stderr unless quiet). Schema: see architecture.md § recipe_recency.
A snapshot-style note under docs/research/ capturing a competitive scan or evaluation. Closed per README § Closing research — default lift + delete; rejected-only keep with a status header.
oxc-resolver, configured by src/resolver.ts. Maps import specifiers to absolute file paths using tsconfig aliases.
TS shape after resolveCodemapConfig() fills defaults and absolutifies paths. Stored in process-global runtime by initCodemap. Distinct from CodemapUserConfig (the user-facing input shape with optional fields).
docs/roadmap.md. Forward-looking only; shipped items are removed (see README § Rule 2). Holds the canonical Non-goals (v1) list.
One record in a SQLite table. Each table has a corresponding TS interface (FileRow, SymbolRow, …) so reads via db.query<RowType>(sql).all() are typed.
Lexical scope graph per [R.11]. Composite PK (file_path, local_id) with module scope at local_id = 0 and nested scopes incrementing. Kinds: module / function / arrow / class / method / interface / type-alias / for / catch. parent_local_id walks the chain. Anonymous scopes (callbacks, catch, for) get owner*symbol_name=NULL; the tracker (createScopeTracker) emits $anon*<localId>segments inscopeStrso sibling anons don't collide oncalls.caller_scope. Foundation for bindings resolution.
Conceptually, the structure of the SQLite database — every table, column, constraint, and index. Defined by DDL in src/db.ts. Versioned by SCHEMA_VERSION. Documented in architecture § Schema.
Integer constant in src/db.ts. Bumped only for rebuild-forcing DDL changes; additive tables / columns / indexes can land through CREATE ... IF NOT EXISTS without a version bump. createSchema() reads meta.schema_version and triggers a full rebuild on mismatch.
Long-running transport shutdown rules in src/application/session-lifecycle.ts. MCP: createStdioDisconnectMonitor exits codemap mcp on client disconnect (stdin EOF, stdout EPIPE, boot parent PID gone, SIGINT/SIGTERM). No idle timeout — the process stays up while stdio is open even without tool calls; IDE hosts do not respawn MCP mid-session. HTTP: createManagedWatchSession refcount-gates chokidar per request (GET /health excluded); HTTP_WATCH_RELEASE_GRACE_MS (5s) stops the watcher between stateless requests without shutting down the HTTP listener — not an MCP-style idle kill. See architecture.md § Session lifecycle wiring.
codemap show <name> — one-step lookup that returns metadata (file_path:line_start-line_end + signature + kind) for symbol(s). Fast tier (equality index): positional <name> or lone name:Token with no %/_ wildcards and no other query fields — same rows as exact <name>. Slow tier: name:%pat% substring LIKE, multi-field --query, or free text (name LIKE / source_fts with --with-fts or fts5: true). Exact mode flags: --kind, --in (positional only). --print-sql prints Moat-A equivalent SQL. Output: {matches, disambiguation?, warning?} (warning when FTS was requested but source_fts is empty). MCP: show with {name} or {query, with_fts?}. Distinct from snippet (adds source text) and from hand-composed query SQL. See architecture.md § Show / snippet wiring.
codemap snippet <name> — same fast/slow lookup tiers as show (<name> + --kind / --in, or --query + --with-fts), but each match also carries source (file lines from disk at line_start..line_end), stale (true when content_hash drifted since last index), and missing (true when file is gone). Envelope: {matches, disambiguation?, warning?} with the same additive fields on each row. Stale-file behavior: source is always returned when the file exists; stale: true is metadata the agent reads (no auto-reindex). MCP: snippet with {name} or {query, with_fts?}. See architecture.md § Show / snippet wiring.
Opt-in substrate. Markers parser recognises // codemap-ignore-next-line <recipe-id> and // codemap-ignore-file <recipe-id> directives (also #, --, <!--, /* leaders for non-JS files) and writes to suppressions(file_path, line_number, recipe_id). Two scopes encoded by line_number: positive integer = next-line (the directive sits one line above; line_number points at the suppressed line), 0 = file scope. Recipe authors opt in by LEFT JOIN suppressions s ON s.file_path = … AND s.recipe_id = '<id>' AND (s.line_number = 0 OR s.line_number = <row's line>) WHERE s.id IS NULL; ad-hoc SQL is unaffected. Stays consistent with the "no opinionated rule engine" Floor — no severity, no suppression-by-default, no universal-honor; the suppression is consumer-chosen substrate. The leader regex requires the directive to start a line (modulo whitespace) so it never matches inside string literals — both this clone's tests and recipe .md examples use the directive in prose without polluting the index. Bundled recipes that opt in: untested-and-dead (next-line + file), unimported-exports (file scope only — exports table has no line_number column).
Long-running process that subscribes to filesystem changes via chokidar v5 and re-indexes only the changed files via runCodemapIndex({mode: 'files'}). Eliminates the "is the index stale?" friction every CLI / MCP / HTTP query rides on today: agents in long sessions or multi-step refactors can query immediately after editing without remembering to reindex. Debounced (default 250 ms) so a burst — git checkout, npm install, multi-file save — collapses to one reindex call. Filters event paths the same way the indexer does (TS / TSX / JS / JSX / CSS + project-local recipes; skips node_modules, .git, dist, etc.). SIGINT / SIGTERM drains pending edits before exit. Three shapes:
- Standalone:
codemap watch— foreground process; logsreindex N file(s) in Mmsper batch unless--quiet. - Combined with MCP:
codemap mcp— boots stdio MCP server + watcher in one process by default since 2026-05; agents never hit a stale index. Pass--no-watchto disable. Watcher starts before MCP connect; stops on client disconnect (not on idle silence — see § Session lifecycle). - Combined with HTTP:
codemap serve— boots HTTP server + watcher by default; CI scripts / IDE plugins read live data. Pass--no-watchto disable. Watcher is refcount-gated per request (GET /healthexcluded) with a 5s release grace between requests — stops chokidar, not the HTTP listener.
CODEMAP_WATCH=0 (or "false") is the env-shortcut for opting out of the default-ON watcher on codemap mcp / codemap serve — useful for IDE / CI launches that can't easily edit the spawn command. CODEMAP_WATCH=1 still parses for backwards-compat but is now a no-op (it matches the new default). When watch is active, the audit tool's incremental-index prelude becomes a no-op on both transports (the watcher already keeps the index fresh — saves the per-request reindex cost on every mcp audit and every POST /tool/audit). Implementation: src/cli/cmd-watch.ts (CLI shell) + src/application/watcher.ts (engine — pure debouncer + chokidar backend; injectable backend for tests). See architecture.md § Watch wiring.
Long-running HTTP server exposing the same tool taxonomy as codemap mcp over POST /tool/{name} for non-MCP consumers (CI scripts, simple curl, IDE plugins that don't speak MCP). Default bind 127.0.0.1:7878 (loopback only — refuse 0.0.0.0 unless explicitly opted in via --host 0.0.0.0; any 127.0.0.0/8 address counts as loopback for the token rule); --token <secret> is optional on loopback binds and required on non-loopback binds — when set, every request needs Authorization: Bearer <secret>. HTTP returns each tool's native JSON payload directly (NOT MCP's {content: [...]} wrapper); query / query_recipe match codemap query --json row arrays unless summary / group_by reshape the envelope, or baseline returns a diff envelope (incompatible with non-json format / group_by; save/list/drop remain separate tools); parity twins (query batch, trace, explore, node, file, schema, symbols, context, ingest-coverage, ingest-churn) always emit JSON on CLI without --json; other tools match their CLI --json payloads when that flag is set; format: "sarif" payloads ship as application/sarif+json, format: "annotations" / "mermaid" / "diff" / "badge" (markdown) as text/plain; charset=utf-8, format: "diff-json" / "codeclimate" / "badge" + badge_style: "json" as application/json; charset=utf-8. Routes: POST /tool/{name} (every MCP tool), GET /resources/{encoded-uri} (resource handler for codemap://recipes, codemap://recipes/{id}, codemap://schema, codemap://skill, codemap://rule, codemap://mcp-instructions, codemap://files/{path}, and codemap://symbols/{name}), GET /health (auth-exempt liveness probe — does not start the watcher), GET /tools / GET /resources (catalogs). With --watch, chokidar is refcount-gated per request and stops 5s after the last client (HTTP_WATCH_RELEASE_GRACE_MS) — distinct from MCP idle shutdown; the HTTP process keeps listening. Pure transport — same tool-handlers.ts / resource-handlers.ts MCP uses; no engine duplication. Errors → {"error": "..."} with HTTP status 400 / 401 / 403 / 404 / 500. SIGINT / SIGTERM → graceful drain. Every response carries X-Codemap-Version: <semver>. CSRF + DNS-rebinding guard: every request (including auth-exempt /health) is evaluated against Sec-Fetch-Site / Origin / Host when present — modern browsers send Sec-Fetch-Site and Origin on cross-origin fetches (header presence varies by request type, browser, and privacy settings), so the guard rejects browser-driven cross-origin requests like a malicious local webpage fetch-ing http://127.0.0.1:7878/tool/save_baseline to mutate .codemap/index.db. Host mismatch on a loopback bind blocks DNS rebinding (an attacker resolving evil.com to 127.0.0.1 post-load). Non-browser clients (curl, fetch from Node, MCP hosts, CI scripts) typically omit these headers and pass through. Implementation: src/cli/cmd-serve.ts (CLI shell) + src/application/http-server.ts (transport). See architecture.md § HTTP wiring.
GitLab Code Quality JSON array emitted by codemap query --format codeclimate (MCP/HTTP: format: "codeclimate"). One object per locatable row (file_path / path / to_path / from_path + optional line_start); flat severity: "minor" in v1; location.lines.begin defaults to 1 without line_start; stable SHA-256 fingerprints (recipe + path + line + check name + row message) for GitLab dedup. Aggregate recipes emit [] + stderr warning. Incompatible with --summary / --group-by / baseline.
Issue-count presentation derived from locatable-row count only — not a triage primitive. CLI: codemap query --format badge prints codemap: N issues / codemap: clean; --badge-style json emits codemap-badge/v1 ({schema, label, message, count, status}). MCP/HTTP: format: "badge" + optional badge_style. Agents should triage via JSON query rows or --summary, not badge stdout.
JSON schema for structured badge output (badge_style: "json"). Fields: schema, label ("codemap"), message, count, status (pass when count === 0). Intended for CI gates (jq -e '.status == "pass"').
SARIF 2.1.0 — Static Analysis Results Interchange Format. JSON envelope GitHub Code Scanning consumes natively. Codemap emits SARIF via codemap query --format sarif (or format: "sarif" on the MCP query / query_recipe tools). Rule id is codemap.<recipe-id> for --recipe; codemap.adhoc for ad-hoc SQL. Location columns auto-detected (file_path / path / to_path / from_path priority; line_start + optional line_end for region). Aggregate recipes (index-summary, markers-by-kind) emit results: [] + a stderr warning. Incompatible with --summary / --group-by / baseline (different output shapes). Default result.level is "note"; per-recipe override deferred to v1.x. See architecture.md § Output formatters.
A .agents/skills/<name>/SKILL.md file with YAML frontmatter. Longer than a rule; describes a complete agent workflow. Distinct from a rule (shorter, normative).
SQLite per-table option enforcing column types at insert time. Every Codemap table uses STRICT.
Functions / consts / classes / interfaces / types / enums, plus class members (method, property, getter, setter). Class members carry parent_name. Function-shaped rows may carry return_type, is_async, and is_generator. JSDoc tags in doc_comment power the deprecated-symbols and visibility-tags recipes; structured tags also land in jsdoc_tags. members is JSON for enums. See SymbolRow.
TS shape for one row of the symbols table.
One row per TryStatement. Heuristic flags include catch_logs_only (catch body only calls console.*) and catch_rethrows. Powers find-swallowed-errors.
Test metadata — describe / it / test / suite / context blocks with skip/only/todo flags and detected framework in {vitest, jest, bun-test, node-test, mocha, unknown}. Framework detection is per-file from imports (mixed-framework codebases handled automatically). parent_suite_id resolves nested describes. Powers find-skipped-tests + tests-by-file recipes.
Index mode that re-parses only the explicit file paths passed to --files. Skips git diff and the full glob. See targetedReindex in src/application/index-engine.ts.
The templates/agents/ directory shipped with the npm package. Source for codemap agents init, which copies (or symlinks, in interactive mode) the bundled rules and skills into the consumer's .agents/.
The glob implementation used on both Bun and Node (since the collectFiles refactor in PR #96 — Bun.Glob has no ignore option so the post-filter walked node_modules etc.; tinyglobby with ignore is ~12× faster). Returns POSIX-separated paths regardless of OS — why cmd-validate.ts normalises its inputs to POSIX.
A small end-to-end vertical slice (see .cursor/rules/tracer-bullets.mdc). Used in PRs to validate the critical path before expanding.
One row per extends / implements edge on a class or interface. Populated at parse from oxc AST; heritage-resolver (pass 2, after bindings) fills base_file_path / base_symbol_id and sets resolution_kind (same-file, imported, qualified-unresolved, unresolved). Non-simple expression bases use base_qualified_name = '(expression)' and stay out of recipe walks. Incremental --files re-resolves rows in changed files plus importers and consumers pointing at changed base files (including one-hop type re-export barrels). Powers type-ancestors and type-descendants recipes. file_path param: on type-ancestors it disambiguates the start symbol only; on type-descendants it also filters output to descendants in that file.
Properties and method signatures on interfaces and object-literal types. symbol_name references the parent symbols.name. type is null when the parser can't reconstruct the annotation. See TypeMemberRow.
TS shape for one row of the type_members table.
Staging queue for call sites that resolveCalls could not bind after the bindings pass. Rows carry file_path, caller_scope, callee_name, and call-site position; deleted when resolved or when the call row is removed. Bundled recipes: unresolved-call-sites, call-resolution-stats. See architecture § calls / unresolved_calls.
meta key (meta.unresolved_calls_residual) — global COUNT(*) on unresolved_calls after each resolve pass; surfaced by the call-resolution-stats recipe.
A JSDoc tag controlling export visibility — @public, @internal, @private, @alpha, @beta. Parsed from doc_comment at parse time (line-leading match) and stored in the symbols.visibility column (TEXT, NULL when no tag). The visibility-tags recipe filters on WHERE visibility IS NOT NULL. @deprecated is a related but separate JSDoc tag — surfaced via WHERE doc_comment LIKE '%@deprecated%' in the deprecated-symbols recipe (no dedicated column; deprecation is orthogonal to visibility, not a 6th value).
Write-Ahead Log mode. Set by PRAGMA journal_mode = WAL on every openDb(). Why .codemap/index.db-wal and .codemap/index.db-shm files exist alongside .codemap/index.db. Allows concurrent readers during writes.
SQLite per-table option that stores data directly in the primary key B-tree, eliminating a rowid lookup indirection. Used on dependencies (composite PK) and meta (single-column TEXT PK).
Parallel parse workers in src/worker-pool.ts. Bun Worker on Bun, Node worker_threads on Node. Used during indexing (full rebuild and incremental file batches).