Ask your AI assistant to trace a feature through your codebase, and get back a markdown document and an interactive HTML page describing exactly how it works — the call chain, every function that participates, and where each one lives.
It installs into six assistant surfaces: Claude Code, GitHub Copilot, OpenAI Codex, Antigravity CLI, Antigravity IDE, and Gemini CLI (retired by Google for individual users on 2026-06-18 — its templates now install only where Gemini CLI is actually in use).
Two names, and which one you get depends on your host. The original command
and prompt files use a dot — /code-flow.map. The newer
Agent Skill form uses a hyphen — /code-flow-map —
because the skill format forbids dots in a name. Which one you get depends on
what your host reads — and GitHub Copilot is two hosts, not one:
| Host | Command / prompt file | Agent Skill |
|---|---|---|
| Claude Code | /code-flow.map |
/code-flow-map |
| GitHub Copilot (VS Code Chat) | /code-flow.map |
— |
| GitHub Copilot (CLI) | /code-flow.map |
/code-flow-map |
| Gemini CLI (legacy) | /code-flow.map |
/code-flow-map |
| OpenAI Codex | — | $code-flow-map, or the /skills menu |
| Antigravity CLI | — | /code-flow-map |
| Antigravity IDE | — | mention code-flow-map by name |
If a row shows only one form, that host reads only one file. Both forms read and
write the same Code_Flows/ artifacts, so a flow mapped by one is readable by the
other.
GitHub Copilot is two surfaces. VS Code Copilot Chat lists the prompt file and
not the skill — Agent Skills there are still an
experimental feature.
The Copilot CLI lists both, so you will see /code-flow.map and /code-flow-map
side by side: two commands doing the same job, one from each form, not a duplicate.
Observed 2026-08-17 on VS Code 1.132.0 with Copilot Chat 0.35.3, and Copilot CLI 1.0.10.
Everything below uses the dotted form when it means the command and the hyphenated form when it means the skill. Where only one exists for your host, the table above is the one to trust.
Given a feature or flow name (e.g. user login, password reset, checkout), the assistant will:
- Trace the repository statically, where a tracer applies — see Automated tracing. The rest of the steps then start from a call graph rather than from search.
- Discover the relevant files and functions using glob + grep searches.
- Trace the call chain from entry point to final output, following every function that participates in the flow.
- Docstring any undocumented functions encountered along the way, editing them in place.
- Generate
Code_Flows/<feature_name>.mdcontaining:- A plain-language description of the flow's purpose and trigger conditions.
- A MermaidJS flow/sequence diagram with every participating function as a named node.
- A bullet list of all functions in the diagram.
- A reference table with each function's description and exact
file:linelocation.
- Generate
Code_Flows/<feature_name>.html— an interactive, self-contained view of the same flow (see below). - Write
Code_Flows/<feature_name>.json— the same flow data as plain JSON — create or update the sharedCode_Flows/index.jsonregistry with an entry for this flow, and rebuildCode_Flows/index.htmlfrom that registry: the landing page listing every mapped flow, rewritten whenever the registry is. (Also written:Code_Flows/inventory.json— the function catalog — written by whole-codebase mode only; andCode_Flows/quality-report.json/Code_Flows/quality-report.md/Code_Flows/quality-report.html— written by/code-flow.quality, see Quality reporting below.) - Report the paths to the generated files.
If you invoke the skill with no argument, the assistant will survey the project and suggest 3–5 candidate flows to pick from.
Alongside the markdown, the assistant produces a single self-contained HTML file you can explore in a browser — no server, no build step, no internet required. Just double-click it. It renders the flow as a browsable graph where you can:
- Pan/zoom the layered call graph and Fit it to view.
- Click any function node to open a side panel with its description,
file:line, a code snippet, an "Open in VS Code" link, and clickable Called by / Calls lists to walk the flow. The panel needs a window at least 720px wide; below that it is hidden and the graph gets the whole width. - Search/filter functions by name, file, or description.
- Highlight a path — selecting a node lights up its full ancestor and descendant chain, answering "how did execution get here?" and "what happens next?".
- Toggle light/dark theme (persisted).
Node colors distinguish entry points, ordinary steps, external (third-party) boundaries, and io (DB/network/file) side effects. Edges distinguish plain calls, async calls (dashed), conditional branches (labeled), and back/cycle edges.
How it works: the installer drops a viewer scaffold at .code-flow/viewer.template.html. When you run the command, the assistant only has to emit a small JSON data block and inject it into that scaffold — so the interactive page is produced reliably, and the page self-validates (showing a clear error card, never a blank screen, if the data is malformed). If the scaffold is missing, the assistant falls back to a minimal Mermaid-based page.
By default /code-flow.map writes what it always has: Code_Flows/index.html, one page
per flow, and quality-report.html. Add --output both and it also writes
Code_Flows/code-flow.html — a single self-contained page carrying the index, every
mapped flow and the quality report. One file, no server, opens from file://. Use
--output bundle to write that page and no other HTML.
/code-flow.map user login --output both
/code-flow.map user login --output bundle
/code-flow.map --whole-code-base --output both
The first writes the loose pages and the bundle; the second writes the bundle alone;
the third bundles a whole-codebase map. Omit --output and you get files, exactly
what earlier versions wrote.
The bundle is rebuilt from Code_Flows/'s JSON artifacts every run, so it is never
stale — and no --output mode ever skips those artifacts, because /code-flow.quality
reads them.
It carries every flow, so it grows with your map. On a large repository that is a large
file, which is why files is still the default.
The installer writes .code-flow/theme.css listing every colour the pages use as a CSS
custom property, commented out at a current default value — the interactive viewer's,
where the four scaffolds disagree on the exact shade. Uncomment what you want to change:
:root {
--accent: #7c5cff;
}
[data-theme="light"] {
--accent: #5b3fd6;
}Your declarations are inlined into every generated page after the built-in styles, so they win. Leave the file alone and nothing changes.
Keep both blocks. :root is the dark palette and [data-theme="light"] is the light
one, and they have equal CSS specificity — set only :root and your colours apply in both
modes, making the theme toggle look broken.
Re-running the installer overwrites .code-flow/theme.css, along with the other
templates in that directory. Keep your edits in version control or a copy elsewhere.
npm i @htst/code-flow-skillThe postinstall script copies the Claude, Gemini, and Copilot templates into your project.
Skip the auto-install with either:
npm i @htst/code-flow-skill --code_flow_skip_install=true
# or
CODE_FLOW_SKIP_INSTALL=1 npm i @htst/code-flow-skillnpm i -g @htst/code-flow-skill
code-flow-skill --tool all --target .uvx htst-code-flow-skill --tool all --target .If neither npm nor uvx is available, you only need to copy a few small text files into your project. There is no code to build and no runtime dependency.
1. Get the templates. Pick whichever is easiest:
-
Download a release (recommended). Grab
code-flow-templates-*.zipfrom the latest release — it contains only thetemplates/directory, nothing else. Unzip it anywhere. -
Clone or download the repo:
git clone https://github.com/plearaj/code-flow-skill.git # or: download https://github.com/plearaj/code-flow-skill/archive/refs/heads/master.zip and unzip
You only need the templates/ directory. The rest of the repo (packaging, installer script, src/) can be ignored.
2. Copy the template(s) for the tool(s) you use into your target project.
From the project root where you want the skill available:
# Claude Code
mkdir -p .claude/commands
cp /path/to/code-flow-skill/templates/claude/code-flow.map.md .claude/commands/code-flow.map.md
cp /path/to/code-flow-skill/templates/claude/code-flow.quality.md .claude/commands/code-flow.quality.md
# Claude Code — the skill form; Claude Code does not read .agents/skills/
mkdir -p .claude/skills/code-flow-map .claude/skills/code-flow-quality
cp /path/to/code-flow-skill/templates/shared/code-flow-map/SKILL.md .claude/skills/code-flow-map/SKILL.md
cp /path/to/code-flow-skill/templates/shared/code-flow-quality/SKILL.md .claude/skills/code-flow-quality/SKILL.md
# Agent Skills — read by Copilot, both Antigravity surfaces, OpenAI Codex and
# Gemini CLI. The openai.yaml files carry Codex's invocation policy; the other
# hosts ignore them.
mkdir -p .agents/skills/code-flow-map/agents .agents/skills/code-flow-quality/agents
cp /path/to/code-flow-skill/templates/shared/code-flow-map/SKILL.md .agents/skills/code-flow-map/SKILL.md
cp /path/to/code-flow-skill/templates/shared/code-flow-map/agents/openai.yaml .agents/skills/code-flow-map/agents/openai.yaml
cp /path/to/code-flow-skill/templates/shared/code-flow-quality/SKILL.md .agents/skills/code-flow-quality/SKILL.md
cp /path/to/code-flow-skill/templates/shared/code-flow-quality/agents/openai.yaml .agents/skills/code-flow-quality/agents/openai.yaml
# Gemini CLI — only if you actually use it; see the note on --tool all above
mkdir -p .gemini/commands
cp /path/to/code-flow-skill/templates/gemini/code-flow.map.toml .gemini/commands/code-flow.map.toml
cp /path/to/code-flow-skill/templates/gemini/code-flow.quality.toml .gemini/commands/code-flow.quality.toml
# GitHub Copilot
mkdir -p .github/prompts
cp /path/to/code-flow-skill/templates/copilot/code-flow.map.prompt.md .github/prompts/code-flow.map.prompt.md
cp /path/to/code-flow-skill/templates/copilot/code-flow.quality.prompt.md .github/prompts/code-flow.quality.prompt.md
# Flow index, interactive viewer and quality report scaffolds (needed for all tools)
mkdir -p .code-flow
cp /path/to/code-flow-skill/templates/shared/viewer.template.html .code-flow/viewer.template.html
cp /path/to/code-flow-skill/templates/shared/report.template.html .code-flow/report.template.html
cp /path/to/code-flow-skill/templates/shared/index.template.html .code-flow/index.template.htmlOn Windows PowerShell, substitute New-Item -ItemType Directory -Force for mkdir -p and Copy-Item for cp.
If you skip the .code-flow/viewer.template.html step, the command still works — the assistant just falls back to a minimal Mermaid-based HTML page instead of the full interactive viewer. If you skip the .code-flow/report.template.html step, /code-flow.quality still works too, but there is no fallback page for it: the command says so and still writes quality-report.json and quality-report.md. Skipping .code-flow/index.template.html costs you only Code_Flows/index.html, the page that links the flows together — every individual flow page still opens on its own.
The .agents/skills/ step is not optional in the same way. It is the entirety of the OpenAI Codex and Antigravity integration — neither host reads a command or prompt file — so skipping it leaves those two with nothing installed at all.
3. Verify. Restart your assistant (or start a new session). In Claude Code, typing / should list four new entries — the commands /code-flow.map and /code-flow.quality, and the skills /code-flow-map and /code-flow-quality. In Gemini CLI, typing / should list the two commands; how it surfaces skills has not been checked here. For Copilot in VS Code, look for both prompts in the Prompts picker (or try /code-flow.map in chat), and both skills alongside them; on other Copilot surfaces, see the GitHub Copilot notes under Usage. On Codex the skills are $code-flow-map and $code-flow-quality, or the /skills menu, not a slash command; on Antigravity IDE, which documents no slash syntax, mention the skill by name.
That's it — no install step runs any code on your machine. If you later want to update the skill, just re-copy the template files.
Two commands, and every flag either one takes. Both read and write the same
Code_Flows/ artifacts, so anything mapped by one is available to the other. Use the
hyphenated names — /code-flow-map, /code-flow-quality — on the hosts whose row in
the table at the top says so.
| Command | Does |
|---|---|
/code-flow.map <flow name> |
Traces one flow and writes its markdown, HTML and JSON |
/code-flow.map (no argument) |
Surveys the project and suggests 3–5 flows to pick from |
/code-flow.quality |
Reports DRY, KISS and YAGNI findings from what the map recorded |
/code-flow.quality --rules auto |
The same, plus violations of the rules your project already wrote down |
| Flag | On | Default | Does |
|---|---|---|---|
--whole-code-base |
map | off | Catalogues every function, then discovers entry points and traces flows from them. Details |
--detail thin|standard|verbose |
map | standard |
How much evidence the function catalogue carries. Only affects whole-codebase mode. Details |
--output files|bundle|both |
map | files |
Which HTML gets written. both adds the single-file bundle; bundle writes only it. Never skips the JSON. Details |
--frontend auto|react|vue|angular|svelte|off |
map | auto |
Whether to map UI components as well as functions. Details |
--tracer auto|on|off |
map | auto |
Whether to run the installed static tracers before tracing anything. Details |
--read-code |
quality | off | Opens the files findings cite, drops the ones current source contradicts, and marks survivors verified. Details |
--rules [source ...] |
quality | off | Also checks the map against rules your project has already written down. Details |
/code-flow.map user login
/code-flow.map user login --output both
/code-flow.map --whole-code-base --detail verbose
/code-flow.map --whole-code-base --tracer on
/code-flow.quality --read-code
/code-flow.quality --rules auto
Flags work identically in the command and skill forms — see Skills and commands.
After installing (see below), invoke from inside your project:
Claude Code
/code-flow.map user login
Gemini CLI — retired for individual users on 2026-06-18, still supported on Gemini
Code Assist Standard/Enterprise licences and paid API keys. See --tool all and Gemini
CLI for when its templates install.
/code-flow.map password reset
GitHub Copilot
The installer writes an invocable prompt file to .github/prompts/code-flow.map.prompt.md.
Prompt files — .github/prompts/*.prompt.md with agent: agent frontmatter, which is what this one is — are a VS Code Copilot Chat feature. In VS Code, open Copilot Chat and select the prompt from the Prompts picker, or try:
/code-flow.map user login
Verified 2026-08-17 on VS Code 1.132.0 with Copilot Chat 0.35.3: /code-flow.map
appears in chat and runs. The dotted name follows the GitHub Spec Kit
prompt-file convention, and Copilot Chat does expose it as a /-command. That is one
observation on one machine, not a guarantee for every version — if the slash form
doesn't appear for you, use the Prompts picker.
The Copilot CLI lists both forms, so /code-flow.map and /code-flow-map appear
side by side there. They are two commands doing the same job — one from the prompt file,
one from the skill — not a duplicate entry. Either should work; this package installs
both because VS Code Chat has only the first and Codex, Antigravity and Gemini CLI have
only the second.
If you use neither Copilot surface — not VS Code Chat, not the CLI — assume the prompt file does nothing for you. Instead, paste the body of templates/copilot/code-flow.map.prompt.md — everything below the --- frontmatter — into .github/copilot-instructions.md under a ## Code Flow heading; that file is read across Copilot surfaces. Upgrading from 0.x, you already have such a section: keep it instead of deleting it.
In all three, the assistant writes its output to Code_Flows/<feature_name>.md, Code_Flows/<feature_name>.html, and Code_Flows/<feature_name>.json at the project root, creates or updates the shared Code_Flows/index.json registry, and rebuilds Code_Flows/index.html from it.
Instead of one feature, map the entire repository:
/code-flow.map --whole-code-base
This runs two passes. The first walks the repository and catalogues every function
it finds into Code_Flows/inventory.json, recording a file census — size and
content hash — in Code_Flows/index.json. The second discovers entry points (HTTP
routes, CLI commands, main(), event handlers, scheduled jobs, exported API) and
traces each one into its own markdown, HTML and JSON, registering it in the index.
The second pass is the expensive one, and on a large repository it may not finish in
a single session. That is expected and not an error: re-run the command and it skips
the flows already registered in index.json and continues. coverage in that file
always records what was actually done — if flowsTraced is below
entryPointsFound, the map is partial and says so.
Whole-codebase mode never edits your source. Feature mode adds docstrings to undocumented functions as it traces; at repository scale that would be a sweeping unrequested rewrite, so this mode only reads.
Control how much evidence the catalog carries with --detail:
| Level | Each catalogued function carries | Use when |
|---|---|---|
thin |
signature, purpose, line count — no code snippet | Very large repositories |
standard (default) |
the above plus a snippet capped at ~20 lines | The balanced default |
verbose |
the above plus the full function body | Small repositories, or when you want artifacts that stand alone without the source tree |
/code-flow.map --whole-code-base --detail verbose
Discovery is search and reading, not a compiler's view of your code. The artifacts say "catalogued", never "all", and they mean it.
Reading a repository function by function is what leaves a large map half-finished — the run gets to flow 10 of 118 and stops. Five static tracers install alongside the templates and do that reading in one pass:
| Language | Tracer | Needs |
|---|---|---|
| Python | .code-flow/tracers/trace_python.py |
any CPython 3.9+ |
| TypeScript, JavaScript, JSX/TSX, Vue, Svelte | .code-flow/tracers/trace_typescript.mjs |
any Node 18+ |
| Rust | .code-flow/tracers/trace_rust.py |
any CPython 3.9+ |
| Java | .code-flow/tracers/trace_java.py |
any CPython 3.9+ |
| C, C++, Objective-C, C# | .code-flow/tracers/trace_c_family.py |
any CPython 3.9+ |
Each writes one JSON document: every function with its file:line, signature,
purpose, role and export status; the resolved call graph between them; the entry
points execution arrives through; and, for the TypeScript one, the component tree
and the routes. The map then walks that graph instead of re-reading the
repository once per entry point, which is the difference between finishing a
large map in one pass and finishing it in four.
They are zero-dependency by design — no typescript package, no node_modules,
no compiler, no toolchain of any kind — because they run inside your repository,
not this one, and a tracer that needed a working build would be useless on
exactly the repository most in need of a map. Four of the five run under Python,
which is why a machine with one interpreter can trace most of a polyglot
codebase. They leave nothing behind in the tree they read, not even a
__pycache__.
--tracer auto (the default) runs each tracer whose language your repository
contains and whose interpreter your machine has, and falls back to reading source
where none applies. --tracer on says so and stops if none could run. --tracer off never runs one; everything still works, only slower.
A tracer is evidence, not the map. Every resolved call carries a confidence —
exact where an import, a self./this. receiver, a header a file includes or a
same-file definition made the target certain, heuristic where a unique name
match was the only evidence —
and calls it could not resolve are listed with their candidates rather than
guessed into edges. The map confirms heuristic edges against source before drawing
them. .code-flow/tracers/README.md documents the output and, just as important,
what static analysis cannot see: reflection, dependency injection by token,
registries populated at runtime, and entry points declared in configuration.
You can run one yourself, without the map:
python .code-flow/tracers/trace_python.py --root . --out trace.json
node .code-flow/tracers/trace_typescript.mjs --root . --out trace.json
python .code-flow/tracers/trace_rust.py --root . --out trace.json
python .code-flow/tracers/trace_java.py --root . --out trace.json
python .code-flow/tracers/trace_c_family.py --root . --out trace.jsonEach language brings its own way of hiding a call, and each tracer says which
one defeats it in the limits array it emits: trait dispatch in Rust, injected
interfaces in Java, the preprocessor in C, performSelector: in Objective-C.
None of them guesses past it.
A repository with a UI is two graphs, not one: functions call functions, and components render components. Mapping only the calls leaves the half of the system a user actually touches undocumented.
--frontend auto (the default) detects the frameworks your repository actually
uses — from package.json, then the config files present, then the file
extensions — and maps their components too. Name one to force it, or off to map
functions only.
| Framework | A component is | Its children come from |
|---|---|---|
| React, Preact, Solid | a capitalized function or class that returns markup | the JSX tags in its body, resolved through the file's imports |
| Vue | a .vue file, or an options object carrying a template |
the tags in its <template> block |
| Angular | a class decorated @Component |
the selectors its template uses, inline or in templateUrl |
| Svelte | a .svelte file |
the capitalized tags in its markup |
Each component is catalogued with its props and events, its lifecycle hooks and
effects, the hooks, composables, stores or services it depends on, the route that
reaches it, and the components it renders. Custom hooks, composables and injectable
services get their own kind — hook, service, store — rather than being filed
as components, because a hook filed as a component makes every component that uses
it look like its parent.
In a flow, a component is a node of kind component and the composition between
two of them is an edge of kind render, so the viewer paints and dashes them
distinctly. A UI flow traced from a route runs route → page → components → hooks
and handlers → services and requests, so one flow shows a click arriving at the
server.
Once a whole-codebase map exists, analyze it:
/code-flow.quality
/code-flow.quality --read-code
This reads Code_Flows/index.json, inventory.json and every <flow>.json, then
writes Code_Flows/quality-report.json, Code_Flows/quality-report.md and
Code_Flows/quality-report.html. The JSON is the data; the other two are
renderings of it, and none of the three may contradict another. The .html is a
single self-contained page — no server, no build step, no internet required —
that you open straight from disk, with the same coverage banner, the same
"catalogued, never all" wording, and filters by severity and principle. Four
detectors run, and a fifth when you pass --rules:
| Detector | Principle | Reports |
|---|---|---|
| duplicate-intent | DRY | The same work implemented in several places |
| repeated-sequence | DRY | Call chains repeated across flows |
| complexity-hotspot | KISS | High fan-out, deep nesting, very long functions |
| unreached | YAGNI | Catalogued functions no mapped flow reaches |
| rule-violation | RULES | Code contradicting a rule you pointed it at — only with --rules |
Severity is rule-based — thresholds, not impressions — so findings do not all drift toward "medium".
--read-code opens the files the candidate findings cite and confirms each
against current source, marking the survivors verified and dropping the rest;
without the flag every finding stays unverified. A candidate whose cited file
cannot be reopened at all — deleted, or unreadable — is neither: it stays
unverified and is then dropped as stale, which is why the dropped count is
usually, not always, zero under --read-code. It verifies candidates rather than
re-scanning the repository, so it costs far less than mapping. It requires the
source tree to be present and current, not just the artifacts.
The report never edits your code and never instructs deletion. Unreached findings are candidates: tracing here is search and reading, so it cannot see reflection, dependency injection, framework hooks or entry points declared in configuration. Anything exported is capped at low severity.
Coverage leads every report. If the trace pass mapped 14 of 17 entry points, the banner says so, and a clean section means clean within what was mapped — not a clean bill of health.
Three things stop the command rather than degrading it: no index.json (run
/code-flow.map first), no inventory.json (run /code-flow.map --whole-code-base first), and an index.json or inventory.json that does not
parse. A single unreadable <flow>.json does not stop it — that flow is skipped
and counted in the banner.
On a --detail thin map, duplicate-intent is skipped unless you pass
--read-code: a thin map carries no code snippets, so that detector has no
evidence to cite.
DRY, KISS and YAGNI are everybody's rules. --rules checks yours:
/code-flow.quality --rules auto
/code-flow.quality --rules .specify/memory/constitution.md
/code-flow.quality --rules CLAUDE.md,docs/style.md --read-code
/code-flow.quality --rules "Validation belongs in src/auth/ and nowhere else"
A source is a path to a document, the word auto, or a rule written inline.
auto looks for the files a project usually keeps its rules in: CLAUDE.md,
.claude/CLAUDE.md, AGENTS.md, GEMINI.md,
.github/copilot-instructions.md, .specify/memory/constitution.md (Spec Kit),
memory/constitution.md, CONVENTIONS.md and .code-flow/rules.md.
Each document is split into discrete rules, and each rule gets an id, its text
quoted rather than paraphrased, the file:line it came from, and a severity
taken from its own wording — must, never and always mean high; should and
prefer mean medium; consider and may mean low. The rule's words decide the
severity, not the report's opinion of them.
Findings look like every other finding — file:line sites, snippets, a
suggestion, an effort — plus the rule they rest on and where to read it. One rule
is one finding however many sites break it.
A rule the map has no evidence about is reported as not checked, never as passing. Naming, file placement, layering, duplication, function size, docstring presence, dependency direction and what may call what are all checkable against the map. Review process, commit messages, runtime behavior, dependency licences and CI configuration are not — the map holds no evidence about any of them, so those rules are listed in the banner with the reason they could not be checked. Silence about a rule you asked about would read exactly like a rule that passed, which is the one thing this must never imply.
quality-report.json carries the whole rule set it loaded — checkable or not — so
the banner's counts can be reconciled against the array behind them.
Back to /code-flow.map: Code_Flows/user_login.md will look roughly like:
# User Login — Flow
Brief description of what the flow does and when it runs.
## Diagram
```mermaid
flowchart TD
A[handle_login] --> B[validate_credentials]
B --> C[create_session]
C --> D[issue_token]
```
## Functions
- `handle_login`
- `validate_credentials`
- `create_session`
- `issue_token`
## Reference
| Function | Description | File |
|----------|-------------|------|
| `handle_login` | HTTP handler for POST /login | `src/auth/login.py:42` |
| `validate_credentials` | Verifies email + password against the user store | `src/auth/credentials.py:18` |
| ...A sibling Code_Flows/user_login.html is written at the same time — the interactive version of the same flow, ready to open in any browser. A Code_Flows/user_login.json sidecar (the same flow data as plain JSON) is written alongside it, and Code_Flows/index.json is created or updated to register the flow. Code_Flows/index.html is rebuilt from that registry at the same time — start there to browse every flow you have mapped.
Both commands now ship as Agent Skills
under .agents/skills/ (and .claude/skills/ for Claude Code) in addition to the
command and prompt files. Nothing was removed. If /code-flow.map works for you
today, it still works.
Three hosts get both forms; three get only the skill. Claude Code, Copilot and
the legacy Gemini CLI have command or prompt files and now also have skills. OpenAI
Codex, Antigravity CLI and Antigravity IDE have never had a command file and do not
get one — they read .agents/skills/ and nothing else, so for them the hyphenated
skill is not an alternative form, it is the whole integration. --tool codex and
--tool antigravity write exactly that directory and nothing else. See the
table at the top for which row you are in.
Where both forms exist, they differ in three ways worth knowing before you pick one.
The names differ, and they had to. The skill form is /code-flow-map and
/code-flow-quality, with hyphens; the command form keeps /code-flow.map and
/code-flow.quality, with dots. Only Copilot documents a character rule for skill
names — no dots, and an invalid name silently fails to load — but Copilot reads
the same .claude/skills/ directory Claude Code does, so there is no directory
where a laxer name would be safe. The dot is also spoken for: on Claude Code, a
skill and a command of the same name resolve in the skill's favour, so a dotted
skill would not sit beside /code-flow.map — it would replace it.
On Copilot, prefer the hyphenated skill. Skills are a documented Copilot feature
across surfaces; the dotted prompt file is a VS Code feature whose exposure as a
/-command this project has not verified. If you use Copilot,
/code-flow-map is the path with fewer unknowns.
Who can start them differs by host. Both skills set
disable-model-invocation: true, which asks the host to run them only when you
invoke them yourself. Not every host implements it:
| Host | Skill directory it reads | Can the assistant start the skill unasked? |
|---|---|---|
| Claude Code | .claude/skills/ |
No |
| GitHub Copilot | .github/skills/, .claude/skills/, .agents/skills/ |
No |
| Antigravity CLI | .agents/skills/ |
Yes — the field is not in its schema |
| Antigravity IDE | .agents/skills/ |
Yes — the field is not in its schema |
| OpenAI Codex | .agents/skills/ |
No — set in agents/openai.yaml, which ships beside each skill |
| Gemini CLI (legacy) | .agents/skills/ |
Yes, with a confirmation prompt |
Every row above comes from that host's own published documentation as of 2026-08-16, not from watching it happen: no row in this table has been observed on a running host in this repository, and no test here can observe one. Where a host ignores the field — or changes its mind about honouring it — what remains is the skills' own step of naming what they are about to do and waiting for you to confirm, which is why that step is in the skill body rather than in frontmatter.
On Copilot, the same skill lands in two directories it both scans. --tool all writes code-flow-map to both .claude/skills/ and .agents/skills/;
Copilot's docs list both as read locations but say nothing about precedence or
de-duplication when a name appears in both, so whether you see it once or
twice there is unverified here. --tool copilot writes the skill to .agents/skills/
only, so a Copilot-only install sidesteps the question entirely.
Codex reads that policy from its own metadata file rather than from SKILL.md,
so both files ship. On Codex, explicit invocation is $code-flow-map or the
/skills menu rather than a slash command.
On Antigravity there is no such setting to make. Both skills open by confirming what they are about to do before writing anything, which is the only gate available there — and the reason that paragraph is in the skill body rather than in frontmatter.
On the hosts in the "Yes" rows, code-flow-map can begin because the conversation
drifted near what it does, rather than because you asked. That matters more for
this command than most: it writes files under Code_Flows/ and adds docstrings
to source files that lack them. Its first instruction is therefore to name the
flow it is about to map and wait for you to confirm — a gate the assistant is free
to skip, which is why this table is here rather than buried. The edits are
additive, never rewrites or deletions. If that trade is not one you want, use the
command form on those hosts, or don't install the skill.
The flags work the same in both. --whole-code-base, --detail thin|standard|verbose, --output files|bundle|both and --read-code are read out
of what you type either way.
The skill format has no $ARGUMENTS substitution, so the skills advertise their
flags through argument-hint instead — your host shows them during autocomplete.
code-flow-skill [--target PATH] [--tool claude|copilot|codex|antigravity|gemini|all]
--tool names every supported host. claude writes .claude/ and the shared
scaffolds and nothing else — Claude Code does not read .agents/skills/, so a
Claude-only project no longer gets four files nothing there opens. codex and
antigravity write .agents/skills/, which is the whole of their integration.
copilot writes .agents/skills/ and .github/prompts/, because its two
surfaces read different files. gemini adds .gemini/commands/ on top.
If you upgraded from 1.0 and used --tool claude, re-running the installer will
not remove an .agents/skills/ directory that an earlier version created. Delete it
by hand if you want it gone; nothing on Claude Code reads it either way.
Defaults: --tool all, --target ..
--tool all installs the Claude and Copilot templates unconditionally, and the Gemini
CLI templates only if your project already has a .gemini/ directory.
Gemini CLI stopped serving free, Google AI Pro and Ultra, and individual Gemini Code
Assist users on 2026-06-18; its successor, Antigravity, does not read
.gemini/commands/ at all. The TOML commands still ship, because Gemini Code Assist
Standard and Enterprise licences and paid API keys keep Gemini CLI — but writing
them into every project would leave a dead directory in most of them.
The check looks at your project, not your home directory. Both Antigravity surfaces
keep workspace files under .agents/ and their global files under
~/.gemini/antigravity/ and ~/.gemini/antigravity-cli/, so a project-level
.gemini/ is a Gemini CLI signal in a way that ~/.gemini/ is not.
When the templates are skipped the installer says so and prints the flag that installs
them anyway. --tool gemini is an explicit request and always installs, regardless of
what is or is not in your project:
code-flow-skill --tool gemini| Tool | Command | Path |
|---|---|---|
| Claude Code | /code-flow.map |
.claude/commands/code-flow.map.md |
| Claude Code | /code-flow.quality |
.claude/commands/code-flow.quality.md |
| Claude Code | /code-flow-map |
.claude/skills/code-flow-map/SKILL.md |
| Claude Code | /code-flow-quality |
.claude/skills/code-flow-quality/SKILL.md |
| Gemini CLI | /code-flow.map |
.gemini/commands/code-flow.map.toml |
| Gemini CLI | /code-flow.quality |
.gemini/commands/code-flow.quality.toml |
| GitHub Copilot | /code-flow.map |
.github/prompts/code-flow.map.prompt.md |
| GitHub Copilot | /code-flow.quality |
.github/prompts/code-flow.quality.prompt.md |
| Copilot, Antigravity, Codex, Gemini CLI | /code-flow-map |
.agents/skills/code-flow-map/SKILL.md |
| Copilot, Antigravity, Codex, Gemini CLI | /code-flow-quality |
.agents/skills/code-flow-quality/SKILL.md |
| Codex | — | .agents/skills/code-flow-map/agents/openai.yaml (invocation policy) |
| Codex | — | .agents/skills/code-flow-quality/agents/openai.yaml (invocation policy) |
| All tools | — | .code-flow/viewer.template.html (interactive HTML scaffold) |
| All tools | — | .code-flow/report.template.html (quality report viewer scaffold) |
| All tools | — | .code-flow/index.template.html (flow index scaffold) |
| All tools | — | .code-flow/theme.css (your theme) |
| All tools | — | .code-flow/bundle.template.html (single-file bundled viewer scaffold) |
| All tools | — | .code-flow/tracers/_common.py (the discovery, id and envelope core the tracers share) |
| All tools | — | .code-flow/tracers/trace_python.py (Python call-graph tracer) |
| All tools | — | .code-flow/tracers/trace_typescript.mjs (TypeScript call-graph and component tracer) |
| All tools | — | .code-flow/tracers/trace_rust.py (Rust call-graph tracer) |
| All tools | — | .code-flow/tracers/trace_java.py (Java call-graph tracer) |
| All tools | — | .code-flow/tracers/trace_c_family.py (C, C++, Objective-C and C# call-graph tracer) |
| All tools | — | .code-flow/tracers/README.md (what the tracers emit, and what they cannot see) |
Every path this installer can write is listed above. The two .gemini/ rows are the
exception to "--tool all writes all of these" — see --tool all and Gemini
CLI. Every other row, the skills included, is written on
every --tool all install.
The .code-flow/viewer.template.html, .code-flow/report.template.html, .code-flow/index.template.html, .code-flow/bundle.template.html and .code-flow/theme.css files are tool-agnostic and are installed regardless of which --tool you select, since every command template references one of the scaffolds and every scaffold inlines the theme.
.agents/skills/ is not unconditional: it installs when your --tool selection
includes copilot, codex, antigravity, or gemini — the hosts that read it — and
is skipped for a bare --tool claude, which writes no .agents/ directory at all.
.claude/skills/ is the one directory only Claude Code reads, so it installs with the
claude selection — --tool gemini still leaves no .claude/ directory in your
project.
OpenAI Codex and Antigravity CLI each have their own --tool value, codex and
antigravity, and each writes only .agents/skills/ — the whole of what that host
reads.
The command was renamed and the Copilot integration changed. After upgrading:
/code-flowis now/code-flow.map. Delete the stale command file:.claude/commands/code-flow.mdor.gemini/commands/code-flow.toml.- Copilot now installs an invocable prompt at
.github/prompts/code-flow.map.prompt.md. The installer no longer edits.github/copilot-instructions.md.- If you use Copilot in VS Code, remove the old
## Code Flow — Documentation Generatorsection from.github/copilot-instructions.mdby hand — otherwise it lingers and contradicts the new prompt. - If you use Copilot anywhere else (github.com, JetBrains, Visual Studio, the CLI), keep that section. Prompt files are a documented VS Code feature; whether any other surface reads them has not been verified here, so assume the new prompt file does nothing for you. The instructions file is read across surfaces, and deleting it could leave you with no Code Flow skill at all. See the GitHub Copilot notes under Usage below.
- If you use Copilot in VS Code, remove the old
/code-flow.mapnow also writesCode_Flows/<feature_name>.jsonandCode_Flows/index.json. Flows mapped before 1.0 have no sidecar until re-mapped.
The skills are new in 1.0 and additive. You do not have to migrate to them.
They install alongside the command and prompt files, under different names
(/code-flow-map, not /code-flow.map), and both forms read the same
Code_Flows/ artifacts — a flow mapped by one is readable by the other. The
first thing you will notice is that your slash menu now lists four entries with
near-identical descriptions where it listed two: those are the same two commands
in both forms, and either one is fine to use. See
Skills and commands for which host gives which guarantee.
Everything 1.0 adds is listed in CHANGELOG.md.
- npm:
@htst/code-flow-skill - PyPI / uvx:
htst-code-flow-skill
No test in this repository executes any scaffold's rendering — templates/shared/viewer.template.html,
templates/shared/report.template.html, templates/shared/index.template.html and
templates/shared/bundle.template.html are checked for what their prompt-filled content says,
never for how a browser draws it. That gap is accepted (see
docs/superpowers/specs/2026-08-07-phase3b-report-viewer-design.md, Decision 1), on the
condition that a human closes it by hand before every release:
- Run
/code-flow.mapand/code-flow.qualityagainst any project and open the resultingCode_Flows/index.html,Code_Flows/<flow>.htmlandCode_Flows/quality-report.htmlin a browser. Confirm each renders its registry, diagram or findings instead of a blank page or a raw JSON dump, that every edge in a diagram ends in an arrowhead pointing at its target, and that the index's flow cards and the pages'Flowslinks actually navigate. Then run again with--output bothor--output bundle, open the resultingCode_Flows/code-flow.html, and confirm it does the same three things in one document: its landing view lists the same flows asindex.html, opening a flow shows its graph, and the quality report is reachable from the same page. - Corrupt one of the four files' embedded JSON (edit a character inside the
<script type="application/json">block so it no longer parses) and reload it. Confirm the page shows the red error card instead of a blank page or a silent failure. - Uncomment one property in a generated project's
.code-flow/theme.css, regenerate any page, and confirm the colour changed in both light and dark. A user's CSS is inlined verbatim and nothing in either suite validates it, so this is the only check theming ever gets. - Run every tracer against a real repository that is not this one and read the stats line. The
suites run them against fixtures this repository wrote, which prove the contract and prove
nothing about the heuristics — a resolver that resolves nothing still emits a valid,
well-shaped, empty-graph document. Confirm
entryPointsFoundis not zero,callEdgesis in the thousands rather than the dozens, andcomponentsFoundmatches roughly what the app has.
Do this for all four files, every release — a change to any scaffold's rendering re-opens the gap and the test suite will not tell you.
Add the release's entry to CHANGELOG.md before bumping the version.
tests/test_packaging.py fails if the changelog's leading ## [version] heading does not
match the version both packages declare, so a forgotten entry is caught rather than shipped.
npm publish enforces this. scripts/prepublish-check.js runs as prepublishOnly, prints
the checklist and fails the publish until you acknowledge it. To read the checklist
without publishing anything:
npm run release-checkCODE_FLOW_RELEASE_CHECKED=1 npm publish --access publicPowerShell has no inline VAR=value prefix, so that line fails there with
CommandNotFoundException. Set it, publish, then clear it — left set, the next
publish in the same session skips the gate without saying so:
$env:CODE_FLOW_RELEASE_CHECKED = "1"; npm publish --access public; Remove-Item Env:CODE_FLOW_RELEASE_CHECKEDuv publish has no equivalent hook, so the same checklist is on you here — run
npm run release-check first and work through it by hand.
uv build
uv publishLicensed under the Apache License, Version 2.0.
Commercial use is welcome. If you use, redistribute, or fork this project, you must:
- Keep the
LICENSEandNOTICEfiles intact. - Preserve the copyright and attribution notices (credit to Hightower Software Technologies) in any derivative work.
- State any significant changes you made to the files.
See the NOTICE file for the required attribution text.