@ray_of_goodness_/docmap
v0.10.2
Published
AI-agent-agnostic documentation-map generator for FE/BE codebases
Maintainers
Readme
docmap
AI-agent-agnostic documentation-map generator for FE/BE codebases.
docmap deterministically discovers the modules of a project (via a
framework adapter), then delegates writing each module's business-logic
description to a headless AI agent of your choice — Claude Code, Codex, or
Gemini CLI. The result is a .docmap/ tree that mirrors your project's
module structure: one root doc per module plus one doc per element, with a
top-level .docmap/index.md cross-module relationship graph.
Discovery (what exists, what depends on what) is always deterministic and free — no AI call is needed to preview it. Only the prose explaining why a module exists and what its business logic does is generated by an agent.
Supported stacks
- Magento 2 (PHP) — modules via
registration.php; elements fromController/,Model/,Observer/,Plugin/,Block/,Api/,Helper/,Setup/; cross-module relations fromdi.xml(preference/plugin),events.xml, and PHPusestatements. - Nuxt 4 — layers/top-level dirs as modules (
pages,components,composables,stores,server); relations from imports,$fetch(...)calls resolved against Nitro server routes, and Pinia store usage. - NestJS — every
*.module.tsdefines a module boundary (its directory, minus any nested directory that has its own*.module.ts); elements classified by filename suffix (.controller.,.service.,.guard.,.dto., ...); relations parsed straight from each@Module({ imports: [...] })— the actual DI graph, not a guess. - Vue 3 (standalone, no Nuxt) —
src/{views|pages, components, composables|hooks, stores|store, layouts, router}as modules; relations from imports,useXStore()usage, and each vue-router route'scomponent(static or() => import(...)) resolved to its view. - Generic fallback — any other stack. Top-level directories become modules, cross-module edges come from import-statement heuristics. Any file is documentable by default (code, markdown docs, yaml/shell deploy scripts, sql — whatever the project actually uses) except known binary/asset types (images, fonts, archives, lockfiles, ...); a directory with nothing but those isn't treated as a module. Always available so the tool works on day one of a new project or an unsupported language.
Install
npm install -g @ray_of_goodness_/docmap # global — gives you the `docmap` command everywhere
# or, without installing anything:
npx @ray_of_goodness_/docmap initThe package is scoped (@ray_of_goodness_/docmap) but the CLI binary is
always just docmap, regardless of how it's installed.
Quick start
docmap init # scaffold docmap.config.json + .docmap/, gitignore .docmap/
docmap scan # preview modules & relations, no AI calls
docmap generate --runner claude # write .docmap/ using Claude Code
docmap status # missing / up-to-date / stale, per moduleRe-running generate only calls the agent for modules whose source files
changed since the last run (tracked via a content fingerprint stored in
each doc's frontmatter) — safe and cheap to run repeatedly, e.g. in CI or
a pre-commit hook.
init adds a .docmap/ entry to the project's .gitignore (creating the
file if it doesn't exist yet) — generated docs aren't meant to be
versioned. Every command also respects the project's .gitignore: files
it ignores are never scanned or documented, no config needed. Use --dir
<path> on scan/generate/status to restrict discovery to one
subdirectory of the project — modules entirely outside it are dropped
from the output.
Commands
docmap init
Scaffolds a new project for docmap. Writes docmap.config.json (with
defaults — see Configuration) unless one already
exists, creates the (empty) .docmap/ output directory, and adds a
.docmap/ entry to .gitignore (creating that file too if it's
missing). Safe to re-run: an existing config is left untouched, the
.gitignore entry is only added once.
docmap init # defaults: framework auto-detect, language en
docmap init --lang uk # generated prose in Ukrainian
docmap init --framework nuxt4 # skip auto-detection, force an adapterdocmap scan
Runs discovery only — no AI agent is invoked, so this is instant and
free. Finds the framework adapter, lists every module it found with its
element count and cross-module relations (with each relation's
confidence: deterministic, from a framework-specific signal like
Magento's di.xml, or heuristic, from an import-statement guess). This
is what actually gets sent to the agent in generate, so it doubles as a
"preview what will be documented" step before spending any AI budget.
docmap scan # human-readable tree
docmap scan --json # same data as JSON, for scripting
docmap scan --dir app/pages # only look inside app/pages
docmap scan --framework magento2 # override auto-detectiondocmap generate
The full pipeline: discovery, then one AI agent call per module (not per
element — cheaper, and gives the agent the whole module's context at
once) to write the module's README.md and each element's .md file
under .docmap/. A module is skipped if its content fingerprint already
matches the doc on disk from a previous run, so re-running after a small
change only regenerates what actually changed.
A module with more elements than maxFilesPerPrompt is automatically
split into several agent calls (batches of maxFilesPerPrompt) instead
of one — every element ends up documented from its actual source, rather
than the agent being asked to write hundreds of blocks for files it was
never shown. Only the first batch writes the module overview; later
batches only write per-element blocks. The module-level relationship
summary sent in every prompt is deduplicated (distinct type + target
pairs, capped at 40 lines) — a module where 200 files all call the same
useCartStore() produces one summary line, not 200.
| Flag | Effect |
|---|---|
| --module <id> | Only generate this module (repeatable — pass it multiple times for several) |
| --runner <name> | claude | codex | gemini | mock — which agent CLI to shell out to |
| --lang <lang> | Override config.language for this run |
| --force | Ignore the fingerprint cache, regenerate every targeted module |
| --dry-run | Build the prompts and write them to .docmap/.cache/prompts/<module>.txt (or <module>.batch<N>.txt for a split module) with a rough token estimate — no agent is called, nothing under .docmap/ (besides the cache) is touched |
| --concurrency <n> | Max parallel agent calls (default 2, capped at 8) |
| --fail-fast | Stop after the first module that errors, instead of continuing through the rest |
| --model <model> | Passed straight through to the runner CLI (e.g. claude --model <model>) |
| --framework <name> | Override auto-detection |
| --dir <path> | Restrict discovery to one subdirectory — see Quick start |
| --skill <path> | A markdown file (a Claude Code SKILL.md works as-is — YAML frontmatter is stripped) whose content is folded into every prompt as project-specific documentation instructions: house style, tone, what to emphasize, conventions discovery can't infer on its own |
docmap generate --runner claude # generate/refresh everything
docmap generate --runner claude --module checkout # just one module
docmap generate --runner mock # zero-cost structural preview
docmap generate --dry-run # see the prompts without spending anything
docmap generate --runner claude --skill docs-style.md # follow custom house-style instructionsA module ends up with status: error in its report (not written to
disk) only if its first batch's response is missing the module-overview
block, even after one retry with a stricter prompt (config.maxRetries)
— the run continues past it rather than aborting, unless --fail-fast is
set. A later batch that comes back empty doesn't fail the module: its
elements get a placeholder doc and a warning is logged, but everything
else that did generate is still written.
docmap status
Cheap, no-AI check of where every module's docs stand: missing (never
generated), up-to-date (fingerprint matches source), or stale
(source changed since the doc was written). Good for CI — fail the build
if anything is stale or missing.
docmap status
docmap status --json
docmap status --dir server # only report on one subdirectorydocmap install-skills
Copies the thin agent-integration wrappers from the package's skills/
directory into the target project, so Claude Code / Codex / Gemini CLI
pick them up automatically in that project going forward (no logic in
them beyond "run docmap generate, then summarize the result" — see
Using it from an agent).
docmap install-skills # all three: claude, codex, gemini
docmap install-skills --agent claude # just .claude/skills/docmap/docmap clean
Deletes the entire .docmap/ directory. Requires --yes — without it,
the command refuses and exits non-zero, so it can't be fired by accident
(e.g. via a mistyped script or muscle memory from a different command).
docmap clean --yes--dry-run and --runner mock (on generate) both exist to let you
sanity-check cost/structure before spending anything: --dry-run shows
you the exact prompts that would be sent, mock runs the full pipeline
with a deterministic placeholder instead of a real agent call — useful
in CI or for previewing the module tree.
Configuration
docmap.config.json (or .docmaprc[.json], resolved via cosmiconfig):
| Key | Default | Notes |
|---|------------------------------------------------------|---|
| framework | "auto" | magento2 | nuxt4 | nestjs | vue3 | generic | auto |
| language | "en"/"ua" | Language code written into generated prose |
| runner | "claude" | claude | codex | gemini | mock |
| model | — | Passed through to the runner CLI, if set |
| concurrency | 2 | Parallel agent calls (max 8) |
| include / exclude | — / node_modules, vendor, .git, dist, build, .docmap | Glob-style path filters, matched per scanned subtree |
| scanDir | — | Same as --dir: restrict discovery to one subdirectory |
| skill | — | Same as --skill: path to project-specific documentation instructions |
| maxFilesPerPrompt | 20 | Source files included per module prompt |
| maxFileExcerptBytes | 4000 | Per-file excerpt cap |
| maxRetries | 1 | Retries when the agent's output is missing the required markers |
| timeoutMs | 120000 | Per-agent-call timeout |
| elementDocThreshold | 1 | Modules with this many elements or fewer get their docs folded into the module README instead of separate files |
Using it from an agent
docmap install-skills drops thin wrappers into the project so Claude
Code, Codex, and Gemini CLI can drive docmap generate themselves as part
of a conversation — the wrappers contain no logic beyond "run the CLI,
then summarize what changed." See skills/.
Doc format
Each module doc (.docmap/<modulePath>/README.md) and element doc share a
YAML frontmatter (docmap_version, id, status, fingerprint,
generated_by, elements/dependencies or relations, ...) plus a
fixed set of body sections: Purpose, Responsibilities,
Business Logic, Inputs / Outputs, Relationships. The format is
direction-agnostic by design: a future "interview mode" will write the
same files with status: planned (spec-first) before any code exists,
letting an agent build the implementation from the doc instead of the
other way around.
Development
npm install
npm run build # tsup -> dist/cli.js
npm test # vitest — all tests run against the mock runner, no live LLM calls
npm run typecheckLicense
MIT
