Waypoints are distributed navigation markers for multi-file pipelines. Each file carries a compact comment block naming its ID, its role in the pipeline, its neighbors, and a pointer to the full map. One manifest per pipeline holds the complete topology. Grep any 8-character ID and the whole pipeline unfolds.
A single CLI does all the deterministic and token-heavy work. You bring the prose; the CLI brings the structure. Treat every step below as a call to that CLI.
The CLI
python3 <skill-path>/scripts/waypoint.py <subcommand> [args]
Every subcommand takes --json for machine-readable output. verify and
check-ids exit non-zero when they find drift.
| Subcommand | What it does |
|---|---|
id <path>... |
Print <id> <path> for each file (SHA-256 of the git-relative path, first 8 hex). |
scan |
Catalogue every map file and every block in the code, grouped by pipeline. Run this first to check for existing waypoints. |
manifest |
Write .ai/waypoints/<name>.md from a JSON spec on stdin. The rich map layout lives here. |
block |
Compose a source block from a JSON spec on stdin. --write --at <line> places or updates it in the file; --dry-run --at <line> previews the placement without writing. |
verify [pipeline] |
Detect drift: stale rows, orphaned blocks, and IDs that no longer match their path. |
check-ids |
Recompute IDs from paths and emit the exact correction list when files have moved. |
The JSON spec schemas for block and manifest, every flag, the comment-syntax
table, and worked examples live in references/cli.md. Read
it before composing your first spec.
Division of labor
The CLI owns structure so it is always right and never drifts: IDs, comment
syntax, block framing, layout, placement and update, manifest rendering, and
verification. You own prose, because judgment and warmth cannot be templated:
the role each file plays, what each neighbor does, and the manifest's opening
sentence. The voice guide at references/waypoint-voice.md
governs that writing — load it before you write any role or neighbor text.
You also make one placement judgment the CLI cannot: which line a brand-new
block belongs above. The CLI composes the text; you choose the anchor and pass
it as --at.
Mapping a pipeline
When asked to add waypoints, trace a process, or map a pipeline, work through these steps. Each is a CLI call wrapped around your own reading of the code.
-
Check what already exists. Run
waypoint scan. If the pipeline is already mapped, read its manifest and treat this as an update rather than a fresh placement — preserve the nodes that are still correct. -
Trace the process across files. Use your normal reading tools to follow the thread: imports, script calls, Dockerfile stages, shared env vars and version strings, CI step ordering. Identify two kinds of node:
- Flow (
from/into, shown as←/→): files in the execution chain. - Reference sinks (
reads/feeds, shown as◁/▷): files that consume a value at runtime without sitting in the build or deploy sequence.
Confirm the full path from entry to exit before placing anything. When a node's role is unclear, read the file.
- Flow (
-
Generate the IDs. Run
waypoint id <path>...for every file in one call. IDs are deterministic from the git-relative path — never invent them. -
Write the manifest. Compose a JSON spec (see
references/cli.md) with the pipeline name, the opening sentence, the ordered nodes, and the topology, then pipe it towaypoint manifest. Order nodes by execution; sinks go last. The CLI derives each node's ID from its path, so the manifest and the blocks always agree. -
Place a block in each file. For each node, compose a block spec and run
waypoint block --write --at <line>, choosing the anchor line yourself:- Top of file for configs, scripts, manifests, and pipeline-specific files.
- Directly above the relevant code section for source files where the pipeline touches a specific function or block.
Re-running
block --writeon a file that already carries this pipeline's own well-formed block updates it in place rather than duplicating it. When the nearby block has lost its closing legend line or belongs to a different pipeline, the write refuses to replace it: it inserts a fresh block instead, leaves the existing one untouched, and returns an advisory naming what to remove by hand. A write never deletes content it cannot prove is this pipeline's own block. Preview any placement first withblock --dry-run. -
Verify. Run
waypoint verify <pipeline>. Resolve any drift it reports before you report the work as done.
When a single source line participates in two or more pipelines, give that one
block multiple flows in its spec — the CLI stacks them under one ID. See the
multi-flow example in references/cli.md.
Reading and auditing waypoints
- List everything / find an entry point:
waypoint scan, then open the manifest's first row. - Check for drift:
waypoint verify(all pipelines) orwaypoint verify <pipeline>(one). It reports stale rows, orphaned blocks, and stale IDs. - A file moved:
waypoint check-idsnames every stale ID, its new value, and the neighbor references that must change. Apply the corrections — update the manifest row, recompose the moved file's block, and update each neighbor that pointed at the old ID — then re-runverify. - Trace from any node: grep its 8-char ID, or follow
→/←through the blocks and the manifest topology.
Block format
The CLI composes these; this section is the reference for what it produces and
why each part is there. The Waypoint <id> anchor and the symbol legend appear
in every block so a first-time reader can decode and grep it on sight.
A single-flow source block is compact. The reference path rides in the header, and one closing line carries both the grep hint and the legend:
── Waypoint a1b2c3d4 · sourcemap-upload · reference: .ai/waypoints/sourcemap-upload.md
uploads browser sourcemaps to Sentry so minified errors resolve to source
← 4263ae66 docker-compose.ci.yml — passes the release version into this build
→ 80e5dc26 browser.plugins.ts — uploads browser sourcemaps to Sentry
── grep any 8-char ID to trace this pipeline · ← from → into ◁ reads ▷ feeds
A multi-flow line — one source line that two or more pipelines touch — stacks the flows under one ID, each naming its own reference:
── Waypoint a1b2c3d4 · grep any 8-char ID to trace these pipelines ──
sourcemap-upload — uploads browser sourcemaps to Sentry
← 4263ae66 docker-compose.ci.yml — passes the release version in
reference: .ai/waypoints/sourcemap-upload.md
changeset-release — bumps versions and tags the release
→ 1a2b3c4d publish.yml — publishes the tagged packages to npm
reference: .ai/waypoints/changeset-release.md
── ← from → into ◁ reads ▷ feeds
The map file at .ai/waypoints/<name>.md keeps the rich layout: an opening
narrative sentence, a node table ordered by execution with sinks last, and a
## Topology graph. The opening sentence is the most important line in the
system — write it as one sentence that walks the pipeline's stages in order,
naming what happens at each and why. The CLI writes the file; you write the
sentence.
Each block is rendered in the file's native comment syntax. The CLI resolves
that from the extension; the comment-syntax table and the --comment override
are documented in references/cli.md.
Writing voice
Waypoint text is read by someone meeting the system for the first time. The
voice guide at references/waypoint-voice.md
defines the principles — concrete over abstract, active over passive, orient
first, purpose over mechanics, self-evident, warm over telegraphic. Load it
before writing or polishing any role description, neighbor description, or
manifest opening sentence.