Metadata-Version: 2.5
Name: htst-code-flow-skill
Version: 1.3.0
Summary: Installable Code Flow skill and command templates for Claude Code, GitHub Copilot, OpenAI Codex, Antigravity and Gemini CLI.
Author: Hightower Software Technologies
License: Apache-2.0
License-File: LICENSE
License-File: NOTICE
Keywords: claude,code-flow,copilot,documentation,gemini,skill
Classifier: Environment :: Console
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Requires-Python: >=3.11
Description-Content-Type: text/markdown

# Code Flow Skill

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](#--tool-all-and-gemini-cli) — 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](#skills-and-commands) 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](https://code.visualstudio.com/docs/agent-customization/agent-skills).
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.

## What the skill does

Given a feature or flow name (e.g. `user login`, `password reset`, `checkout`), the assistant will:

0. **Trace the repository statically**, where a tracer applies — see
   [Automated tracing](#automated-tracing). The rest of the steps then start from
   a call graph rather than from search.
1. **Discover** the relevant files and functions using glob + grep searches.
2. **Trace the call chain** from entry point to final output, following every function that participates in the flow.
3. **Docstring any undocumented functions** encountered along the way, editing them in place.
4. **Generate `Code_Flows/<feature_name>.md`** containing:
   - 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:line` location.
5. **Generate `Code_Flows/<feature_name>.html`** — an interactive, self-contained view of the same flow (see below).
6. **Write `Code_Flows/<feature_name>.json`** — the same flow data as plain JSON — create or update the shared `Code_Flows/index.json` registry with an entry for this flow, and rebuild `Code_Flows/index.html` from 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; and `Code_Flows/quality-report.json` / `Code_Flows/quality-report.md` / `Code_Flows/quality-report.html` — written by `/code-flow.quality`, see [Quality reporting](#quality-reporting) below. `/code-flow.qa` and `/code-flow.violations` write their own `qa-report.*` and `violations-report.*` trios from the same artifacts — see [QA walkthroughs](#qa-walkthroughs) and [Checking one violation you name](#checking-one-violation-you-name).)
7. **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.

## Interactive HTML view

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 `step`s, `external` (third-party) boundaries, and `io` (DB/network/file) side effects. Edges distinguish plain `call`s, `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.

## Output and appearance

### One file you can send someone

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.

```text
/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.

### Your own colours

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:

```css
: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.

## Install

### npm — local project (auto-installs templates)

```bash
npm i @htst/code-flow-skill
```

The `postinstall` script copies the Claude, Gemini, and Copilot templates into your project.

Skip the auto-install with either:

```bash
npm i @htst/code-flow-skill --code_flow_skip_install=true
# or
CODE_FLOW_SKIP_INSTALL=1 npm i @htst/code-flow-skill
```

### npm — global (manual install)

```bash
npm i -g @htst/code-flow-skill
code-flow-skill --tool all --target .
```

### uvx (Python)

```bash
uvx htst-code-flow-skill --tool all --target .
```

### Manual install (no npm, no uvx)

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-*.zip` from the [latest release](https://github.com/plearaj/code-flow-skill/releases/latest) — it contains only the `templates/` directory, nothing else. Unzip it anywhere.
- **Clone or download the repo:**

  ```bash
  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:

```bash
# 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
cp /path/to/code-flow-skill/templates/claude/code-flow.qa.md .claude/commands/code-flow.qa.md
cp /path/to/code-flow-skill/templates/claude/code-flow.violations.md .claude/commands/code-flow.violations.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 .claude/skills/code-flow-qa .claude/skills/code-flow-violations
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
cp /path/to/code-flow-skill/templates/shared/code-flow-qa/SKILL.md .claude/skills/code-flow-qa/SKILL.md
cp /path/to/code-flow-skill/templates/shared/code-flow-violations/SKILL.md .claude/skills/code-flow-violations/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 .agents/skills/code-flow-qa/agents .agents/skills/code-flow-violations/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-qa/SKILL.md .agents/skills/code-flow-qa/SKILL.md
cp /path/to/code-flow-skill/templates/shared/code-flow-violations/SKILL.md .agents/skills/code-flow-violations/SKILL.md
cp /path/to/code-flow-skill/templates/shared/code-flow-quality/agents/openai.yaml .agents/skills/code-flow-quality/agents/openai.yaml
cp /path/to/code-flow-skill/templates/shared/code-flow-qa/agents/openai.yaml .agents/skills/code-flow-qa/agents/openai.yaml
cp /path/to/code-flow-skill/templates/shared/code-flow-violations/agents/openai.yaml .agents/skills/code-flow-violations/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
cp /path/to/code-flow-skill/templates/gemini/code-flow.qa.toml .gemini/commands/code-flow.qa.toml
cp /path/to/code-flow-skill/templates/gemini/code-flow.violations.toml .gemini/commands/code-flow.violations.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
cp /path/to/code-flow-skill/templates/copilot/code-flow.qa.prompt.md .github/prompts/code-flow.qa.prompt.md
cp /path/to/code-flow-skill/templates/copilot/code-flow.violations.prompt.md .github/prompts/code-flow.violations.prompt.md

# Flow index, viewer, report, QA and bundle scaffolds, and your theme
# (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/qa.template.html .code-flow/qa.template.html
cp /path/to/code-flow-skill/templates/shared/index.template.html .code-flow/index.template.html
cp /path/to/code-flow-skill/templates/shared/bundle.template.html .code-flow/bundle.template.html
cp /path/to/code-flow-skill/templates/shared/theme.css .code-flow/theme.css

# The five static tracers (needed for --tracer, which every tool can use)
mkdir -p .code-flow/tracers
cp /path/to/code-flow-skill/templates/shared/tracers/* .code-flow/tracers/
```

On 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` and `/code-flow.violations` still work too, but there is no fallback page for either: they say so and still write their JSON and markdown. `.code-flow/qa.template.html` is the same story for `/code-flow.qa`. 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 **eight** new entries — the commands `/code-flow.map`, `/code-flow.quality`, `/code-flow.qa` and `/code-flow.violations`, and the skills `/code-flow-map`, `/code-flow-quality`, `/code-flow-qa` and `/code-flow-violations`. In Gemini CLI, typing `/` should list the four commands; how it surfaces skills has not been checked here. For Copilot in VS Code, look for all four prompts in the Prompts picker (or try `/code-flow.map` in chat), and all four skills alongside them; on other Copilot surfaces, see the **GitHub Copilot** notes under *Usage*. On Codex the skills are `$code-flow-map`, `$code-flow-quality`, `$code-flow-qa` and `$code-flow-violations`, 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.

## Usage

### Commands and flags

Four commands, and every flag any of them takes. All four read and write the same
`Code_Flows/` artifacts, so anything mapped by one is available to the rest. Use the
hyphenated names — `/code-flow-map`, `/code-flow-quality`, `/code-flow-qa`,
`/code-flow-violations` — on the hosts whose row in
[the table at the top](#code-flow-skill) says so.

`/code-flow.map` writes the map. The other three read it and ask different questions
of it: **is it good code** (quality), **does it still work** (QA), and **does it
follow the rule I care about** (violations).

| 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, YAGNI, SOLID and module-depth findings from what the map recorded |
| `/code-flow.quality --rules auto` | The same, plus violations of the rules your project already wrote down |
| `/code-flow.qa` | Walks every mapped flow, component and route and reports what still holds. [Details](#qa-walkthroughs) |
| `/code-flow.qa --live` | The same, and additionally starts the app and clicks through it |
| `/code-flow.violations "<rule>"` | Checks one rule you name, reading source to settle it. [Details](#checking-one-violation-you-name) |

| Flag | On | Default | Does |
|---|---|---|---|
| `--whole-code-base` | map | off | Catalogues every function, then discovers entry points and traces flows from them. [Details](#whole-codebase-mode) |
| `--detail thin\|standard\|verbose` | map | `standard` | How much evidence the function catalogue carries. Only affects whole-codebase mode. [Details](#whole-codebase-mode) |
| `--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](#one-file-you-can-send-someone) |
| `--frontend auto\|react\|vue\|angular\|svelte\|off` | map | `auto` | Whether to map UI components as well as functions. [Details](#frontend-component-mapping) |
| `--tracer auto\|on\|off` | map | `auto` | Whether to run the installed static tracers before tracing anything. [Details](#automated-tracing) |
| `--read-code` | quality | off | Opens the files findings cite, drops the ones current source contradicts, and marks survivors verified. Also unlocks the two SOLID detectors that read source rather than the map. [Details](#quality-reporting) |
| `--rules [source ...]` | quality | off | Also checks the map against rules your project has already written down. [Details](#checking-your-own-rules) |
| `--live` | qa | off | After the static walk, starts the application and exercises it through a browser. [Details](#qa-walkthroughs) |
| `--base-url <url>` | qa | — | Attaches to an app already running there instead of starting one. Implies `--live` |
| `--frontend off` | qa | off | Skips the component and route walk even where the map recorded a frontend |
| `--no-read-code` | violations | off | Settles rules from the map alone. Violations reads source **by default** — this is the one flag that turns it off. [Details](#checking-one-violation-you-name) |
| `--severity high\|medium\|low` | violations | `medium` | Severity for an inline rule whose wording carries no modal verb |

```text
/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
/code-flow.qa
/code-flow.qa user login --live
/code-flow.violations "Validation belongs in src/auth/ and nowhere else"
```

Flags work identically in the command and skill forms — see
[Skills and commands](#skills-and-commands).

### Invoking on your host

After installing (see below), invoke from inside your project:

**Claude Code**

```text
/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](#--tool-all-and-gemini-cli) for when its templates install.

```text
/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:

```text
/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](https://github.com/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.

### Whole-codebase mode

Instead of one feature, map the entire repository:

```text
/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 |

```text
/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.

### Automated tracing

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; how deeply control flow nests inside it; the
type that declares it and the supertype declarations it overrides; 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:

```bash
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.json
```

Each 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.

### Frontend component mapping

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.

### Quality reporting

Once a whole-codebase map exists, analyze it:

```text
/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. Ten
detectors run, two more when you pass `--read-code`, and one more with `--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 |
| single-responsibility | SOLID | A module reaching into many others — more than one reason to change |
| interface-segregation | SOLID | A wide export surface no single caller uses much of |
| dependency-cycle | SOLID | Modules that depend on each other in a ring |
| shallow-module | DEPTH | More interface than implementation behind it |
| pass-through | DEPTH | Functions that only hand their arguments to one other |
| internals-coupled-test | DEPTH | Tests reaching past a module's interface into its internals |
| open-closed | SOLID | A conditional chain that must be edited to add a variant — only with `--read-code` |
| liskov-substitution | SOLID | An override that refuses what its siblings promise — only with `--read-code` |
| 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".

**SOLID's five, split by where the evidence lives.** Three of them —
single-responsibility, interface-segregation and dependency-cycle — are settled by
the call graph. The other two are not, and they are not dropped for it:
open-closed and liskov-substitution locate candidates in the map and let
`--read-code` settle them against real source, so they run only under that flag
and every finding they produce is `verified`. Without it, both are reported as not
checked, by name, with `--read-code` named as the remedy.

That split is the point. A dispatch table, a registry and a polymorphic call are
all correct answers to the problem open-closed describes, and no call graph can
tell any of them from a conditional chain — so the map says where to look and the
source says whether it is a finding. Liskov gets the stricter treatment: a
candidate survives only if the family really shares a supertype, a caller really
holds one through it, and the member really weakens the contract.

**Where a Liskov family comes from.** The first of those three checks is the one
doing the most work — two unrelated `save` methods in unrelated classes are the
false positive this detector is most exposed to — and on a traced map it is
already settled before verification starts. Every tracer records `overrides` on
the functions it catalogues: the supertype declarations each one implements, read
off the relationship its language states outright (`impl Trait for Type`,
`extends`, `implements`, a base-class list) and named only where that supertype
really declares the member. A family is then the set of functions naming the same
declaration — a fact, not a guess.

Where `overrides` is absent — a map built without a tracer has none, and even a
traced map has none where the declaration lives outside the repository — the
detector falls back to matching an unqualified name and a parameter count, and
verification does all three checks. Both kinds can appear in one report, so every
finding carries `familyFrom`, `overrides` or `name`, and the viewers print it
beside the family: *stated by the source* or *matched by name*. A reader never has
to assume which one they are looking at.

**The DEPTH three** are Ousterhout's deep-module argument — a module earns its
keep when it hides more than it asks a caller to learn — including its test-side
corollary: a test that reaches around the interface into the internals freezes
the implementation that module was supposed to stay free to change.

Five of the nine new detectors read the call graph, so they need a map built with
a tracer. On a map without one, they are gated off and the banner names each with
its remedy; shallow-module reads only export counts and function lengths, so it
runs on any map that has an inventory.

`--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. On a map whose inventory carries no `calls` — one built with
`--tracer off`, or in a language no tracer covers — the five call-graph detectors
are skipped for the same kind of reason, and named in the banner rather than
quietly omitted. Without `--read-code`, open-closed and liskov-substitution are
skipped too: their evidence was never in the map to begin with.

#### Checking your own rules

DRY, KISS, YAGNI, SOLID and deep modules are everybody's rules. `--rules`
checks yours:

```text
/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.

### QA walkthroughs

A map is a claim about the code: *this function calls that one, execution arrives
here from there, this page renders that component.* `/code-flow.qa` checks the
claim against the code as it is now.

```text
/code-flow.qa
/code-flow.qa user login password reset
/code-flow.qa --live
/code-flow.qa --base-url http://localhost:5173
```

It walks every flow in the registry and runs five checks on each: the entry still
exists, every node still resolves to a definition, every edge is still a call the
caller makes, every node is still reachable from the entry, and the flow's files
have not changed since mapping. Where the map recorded a frontend it also walks
the components — each one still declared, its documented children still rendered,
its documented props still accepted — and every route, whose component must still
be in the catalog.

Everything checked gets exactly one status, and **`broken` outranks `drifted`
outranks `pass`**: a flow that works four steps out of five does not work.

| Status | Means | Remedy |
|---|---|---|
| `pass` | Every check that ran held | — |
| `drifted` | Still works; the map no longer describes it accurately | Re-map |
| `broken` | A check failed in a way that means it cannot work | Fix the code |
| `unchecked` | Nothing here could be settled | Named, with the reason |

Every status carries the checks that produced it, each named, each with its own
outcome — so a reader who disagrees with a verdict can see which check decided it
and go and look at the same line.

**`--live` additionally runs the application.** It finds the project's own way of
starting a dev server — a `package.json` script, a `Procfile`,
`docker-compose.yml`, `manage.py runserver`, a `Makefile` target — visits each
documented route in a browser, confirms the component the map says renders there
actually appeared, and records every console error and failed request. That last
one is the whole reason the mode exists: a page that renders nothing while every
function it needs is still sitting in the source is invisible to every static
check.

There is a hard line on what live checking may do. It navigates, reads, and clicks
things that only navigate or reveal — links, tabs, accordions, pagination. It
**never submits a form and never fires a mutating request on purpose**, and it
refuses to touch a `--base-url` that is not obviously local until you confirm the
environment is disposable. This is a report; a report is not worth one row written
to a real database.

A live pass that cannot start the app is not a failed QA run: those checks are
recorded as `unchecked` with the command that was tried, the static results stand,
and the report says on its face that the application was never run. That line
appears on every report, including the static ones — a static pass read as a live
one is the misreading it exists to prevent.

Output is `Code_Flows/qa-report.json`, `qa-report.md` and `qa-report.html`. The
markdown leads with the verdict and puts `broken` first, and closes with what was
*not* checked — flows you narrowed away, the component walk if you passed
`--frontend off`, the live pass if it did not run. That closing section is what
keeps a green report honest.

This command never edits source and never fixes what it finds. A QA pass that
quietly repaired things would be a QA pass nobody can reproduce.

### Checking one violation you name

`/code-flow.quality --rules` checks written-down rules as one detector among
thirteen, as part of a sweep. `/code-flow.violations` is for the other case: one
rule, or a few, that you want answered properly right now.

```text
/code-flow.violations "Validation belongs in src/auth/ and nowhere else"
/code-flow.violations "No handler may exceed 40 lines" "Every store is injected, never imported"
/code-flow.violations docs/style.md
/code-flow.violations auto --no-read-code
```

Three things make it different from the flag:

- **It reads source by default.** `--read-code` is off in the quality command
  because that sweep already has thirteen detectors' worth of results. Here you
  named one thing and want an answer about it, and "the map does not carry that
  evidence" is a poor answer when the files are right there. `--no-read-code`
  restores map-only checking.
- **Every rule gets a row**, violated or not. On a report that lists only
  violations, a rule that passed and a rule nobody looked at produce the same
  silence — and you asked specifically about these rules. The markdown leads with
  a rule ledger before any finding: "3 sites", "checked, clean", "not checked:
  needs source and `--no-read-code` was passed", "partially checked: 40 of 900
  files read".
- **It will not report a rule clean that it could not enumerate.** For a rule of
  the form "every X must Y", a site is an X that does not Y — so it has to be able
  to list every X. When it cannot, the rule is *not settled*, and it says which
  half it could not establish. Reporting zero violations there would be a claim it
  did not check.

It refuses to guess what you meant: with no violation named it stops and says what
it needs rather than falling back to `auto`. A rule is quoted, never paraphrased
and never sharpened — a report citing your own words is arguable, and one citing a
tightened version of them is not.

Output is `Code_Flows/violations-report.json`, `violations-report.md` and
`violations-report.html`. The findings use the same shape as the quality report's,
so both render through the same page and you learn one layout rather than two.

### Example map output

Back to `/code-flow.map`: `Code_Flows/user_login.md` will look roughly like:

````markdown
# 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.

## Skills and commands

Both commands now ship as [Agent Skills](https://code.visualstudio.com/docs/agent-customization/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](#code-flow-skill) 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](#github-copilot). 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.

## CLI options

```text
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` and Gemini CLI

`--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:

```bash
code-flow-skill --tool gemini
```

## Files written

| 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.qa` | `.claude/commands/code-flow.qa.md` |
| Claude Code | `/code-flow.violations` | `.claude/commands/code-flow.violations.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` |
| Claude Code | `/code-flow-qa` | `.claude/skills/code-flow-qa/SKILL.md` |
| Claude Code | `/code-flow-violations` | `.claude/skills/code-flow-violations/SKILL.md` |
| Gemini CLI | `/code-flow.map` | `.gemini/commands/code-flow.map.toml` |
| Gemini CLI | `/code-flow.quality` | `.gemini/commands/code-flow.quality.toml` |
| Gemini CLI | `/code-flow.qa` | `.gemini/commands/code-flow.qa.toml` |
| Gemini CLI | `/code-flow.violations` | `.gemini/commands/code-flow.violations.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` |
| GitHub Copilot | `/code-flow.qa` | `.github/prompts/code-flow.qa.prompt.md` |
| GitHub Copilot | `/code-flow.violations` | `.github/prompts/code-flow.violations.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` |
| Copilot, Antigravity, Codex, Gemini CLI | `/code-flow-qa` | `.agents/skills/code-flow-qa/SKILL.md` |
| Copilot, Antigravity, Codex, Gemini CLI | `/code-flow-violations` | `.agents/skills/code-flow-violations/SKILL.md` |
| Codex | — | `.agents/skills/code-flow-map/agents/openai.yaml` (invocation policy) |
| Codex | — | `.agents/skills/code-flow-quality/agents/openai.yaml` (invocation policy) |
| Codex | — | `.agents/skills/code-flow-qa/agents/openai.yaml` (invocation policy) |
| Codex | — | `.agents/skills/code-flow-violations/agents/openai.yaml` (invocation policy) |
| _All tools_ | — | `.code-flow/viewer.template.html` (interactive HTML scaffold) |
| _All tools_ | — | `.code-flow/report.template.html` (quality and violations report viewer scaffold) |
| _All tools_ | — | `.code-flow/qa.template.html` (QA walkthrough 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](#--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/qa.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.

## Upgrading from 0.x to 1.0

The command was renamed and the Copilot integration changed. After upgrading:

- `/code-flow` is now `/code-flow.map`. Delete the stale command file:
  `.claude/commands/code-flow.md` or `.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 Generator` section from
    `.github/copilot-instructions.md` by 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.
- `/code-flow.map` now also writes `Code_Flows/<feature_name>.json` and
  `Code_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](#skills-and-commands) for which host gives which guarantee.

Everything 1.0 adds is listed in [CHANGELOG.md](CHANGELOG.md).

## Packages

- npm: [`@htst/code-flow-skill`](https://www.npmjs.com/package/@htst/code-flow-skill)
- PyPI / uvx: `htst-code-flow-skill`

## Publishing

### Before publishing

No test in this repository executes any scaffold's rendering — `templates/shared/viewer.template.html`,
`templates/shared/report.template.html`, `templates/shared/qa.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:

1. Run `/code-flow.map`, `/code-flow.quality`, `/code-flow.qa` and `/code-flow.violations`
   against any project and open the resulting `Code_Flows/index.html`,
   `Code_Flows/<flow>.html`, `Code_Flows/quality-report.html`, `Code_Flows/qa-report.html` and
   `Code_Flows/violations-report.html` in a
   browser. Confirm each renders its registry, diagram, findings or checked flows 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' `Flows` links actually navigate.
   `violations-report.html` renders through the quality scaffold with `meta.kind` set to
   `violations`: confirm its heading reads **Violations** and that its banner names only
   `rule-violation` as having run clean, never the twelve quality detectors that never ran.
   Then run again with `--output both` or `--output bundle`, open the resulting
   `Code_Flows/code-flow.html`, and confirm it does the same three things in one document: its
   landing view lists the same flows as `index.html`, opening a flow shows its graph, and the
   quality report is reachable from the same page.
2. Corrupt one of the five 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.
3. 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.
4. 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 `entryPointsFound` is not zero, `callEdges` is in
   the thousands rather than the dozens, and `componentsFound` matches roughly what the app has.

Do this for all five files, every release — a change to any scaffold's rendering re-opens the
gap and the test suite will not tell you. The five are
`templates/shared/viewer.template.html`, `templates/shared/report.template.html`,
`templates/shared/index.template.html`, `templates/shared/bundle.template.html` and
`templates/shared/qa.template.html`.

Add the release's entry to [CHANGELOG.md](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:

```bash
npm run release-check
```

### npm

```bash
CODE_FLOW_RELEASE_CHECKED=1 npm publish --access public
```

PowerShell 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:

```powershell
$env:CODE_FLOW_RELEASE_CHECKED = "1"; npm publish --access public; Remove-Item Env:CODE_FLOW_RELEASE_CHECKED
```

### PyPI

`uv 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.

```bash
uv build
uv publish
```

## License

Licensed under the [Apache License, Version 2.0](LICENSE).

Commercial use is welcome. If you use, redistribute, or fork this project, you **must**:

- Keep the `LICENSE` and `NOTICE` files 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.
