Skip to main content
sightmap validate checks whether the corpus loads and follows the CLI’s structural rules. sightmap lint reports selector and naming problems. sightmap stats counts what the corpus holds. sightmap search searches component definitions offline. sightmap discover classifies same-host links from the current page against the corpus.
validate, lint, stats, and search are fully offline — no browser needed. discover reads links from a live page, so it needs a running session (see Browser). For scoring how well the corpus covers a page, see Coverage; for the normative YAML format, see the spec.

sightmap validate

Loads the YAML and checks the resulting corpus. It verifies required fields (a view’s name and route, a component’s name and selector), that every $ref resolves, component selector syntax, stability: and access: values, and duplicate name-plus-selector pairs within a scope. It reports two kinds of finding: errors, which fail validation (exit 1) — including a missing required field or an unresolved $ref, both of which the loader previously dropped silently — and warnings, which are advisory and do not (exit 0). Run it after YAML edits and in CI. Warnings flag corpus conflicts — two definitions that collide on identity where only one can win and a fallback rule (declaration order) silently resolves it: duplicate view name (merge-collision-view), two views sharing a route (route-conflict), and duplicate root-level global component names with different selectors (merge-collision-component). The corpus still loads; the warning tells you which definition is shadowing another. Warnings also flag unknown fields (unknown-field) — a key the spec doesn’t define at its position, such as a typo (memroy:) or an experimental field. These warn rather than fail, so you can stash work-in-progress fields during development; recognized fields (including the reserved tooling fields access and snapshots) are never flagged. The command also rejects selector syntax outside Sightmap’s supported subset. For example, :nth-child() produces a parse error; the supported pseudo-classes are :not(), :is(), :where(), and :has(). Flags:
On a broken corpus, each error prints as one error: line and the command exits 1; warnings print as warning: lines and do not affect the exit code:
When only warnings are present the command prints ✓ no errors (N warning(s)) and exits 0.

sightmap lint

Runs static style and maintainability checks without a browser. The five main rules are: Three other checks run with them. name-case flags component names that do not start with an uppercase letter. comma-in-selector flags a top-level comma and expects separate selector entries instead. The validation rule re-emits each validate error as a warning. By default, lint exits 1 when it finds a warning. Pass --warn-only to print warnings and exit 0. Snapshot data refines multi-instance-no-property. --snapshot FILE counts selector matches in one capture; --all-snapshots reads .sightmap/snapshots/**/*.snap.tree.json. A count of 1 suppresses the warning. A count of 0 adds (0 matches in snapshot — selector may be broken), while a higher count adds (matched N times in snapshot). When you pass no snapshot flag, lint auto-reconciles against any captures under .sightmap/snapshots/ — so a container-ish selector that actually matches a single node is not falsely flagged. With no captures present it runs the static heuristics unchanged. Pass --snapshot/--all-snapshots to control the set explicitly. Flags:
Property extraction (properties: on components) is implemented by the CLI as a draft extension — it is not part of spec v1 and may change. The multi-instance-no-property rule reflects the CLI’s behavior, not a spec requirement.

sightmap stats

Counts what the corpus holds: corpus-wide totals for views, components, requests, properties, and memory entries, followed by a per-view component and request table. The counts describe the corpus after loading$refs expanded, component hierarchies flattened — so they match what every other command sees. Flags:
What each total counts: Per-view rows need not sum to the Components total, in either direction. A global component that three views $ref appears in three rows but counts once in the total, which pushes the sum above it — the summary line prints both numbers so the gap is visible rather than surprising. A global component no view references counts in the total but appears in no row, which pushes the sum below it. Components deduplicates by name, but Properties and Memory sum over distinct definitions, because two views may legally define different components under the same local name (only global name collisions are rejected). Deduplicating those by name would silently drop the second view’s properties and memory. A $ref expanded at a view’s top level is a byte-identical copy of the global and counts once; a $ref expanded under a parent is scoped to that parent, so it is a separate extraction site and counts again. --json is a published contract. It prints one JSON object on stdout and nothing else — no banner to strip. The field names are consumed by CI outside this repo, so they are stable: views, components, requests, properties, memory, and per_view, whose rows carry name, route, components, and requests.
A corpus that holds only memory: entries is legal, and --json reports it with zero counts and "per_view": []. In table mode a corpus with nothing at all in it is an error that prints the views: schema instead of an all-zero table. stats refuses counts it cannot trust. The loader is lenient: an unresolved $ref, or a component missing its name or selector, drops that definition and records an error. Counting such a corpus would under-report with a zero exit, so stats runs the same checks as validate first and refuses any error-severity finding. Warnings are advisory and do not block.
Under --json the refusal is still one JSON object on stdout, so a consumer that parses stdout unconditionally always has something to parse. The envelope carries error and diagnostics (each with code, file, component, selector, and message) and never carries counts. An error key is present only on failure. The exit code is 1 either way.

Searches component definitions and $ref entries in .yaml and .yml files under .sightmap/. Each match includes a breadcrumb with the file, view and route when applicable, parent components, and matching component. PATTERN is a Go regular expression. Matching is case-insensitive unless you pass --case. Restrict the search with --field: name, selector, description, memory, or all (the default). These fields apply to component definitions; the command does not search view or request fields.
search currently reads scalar selector: values. If a file contains a selector array, it prints a parse warning and skips that file.
Flags:
When nothing matches, the command prints no matches for PATTERN to stderr and still exits 0.

sightmap discover

Reads unique same-host paths linked from the current page, replaces dynamic path segments with *, and classifies each resulting pattern against the corpus. Dynamic segments include numeric IDs, UUIDs, and digit-bearing slugs of at least eight characters.
  • ? unseen: no view route matches. Sorted by the number of distinct paths that normalize to the pattern.
  • mapped: the pattern matches a view’s route:.
  • surveyed: the pattern matches an entry in .sightmap/survey.yaml. Hidden unless you pass --all.
Run it on pages that link to major sections of the app, then add views for relevant unseen patterns or record surveyed patterns in .sightmap/survey.yaml. Flags:
Each ? line is unmatched among the links on the current page. Add a view or add the pattern and a reason to survey.yaml.

Typical flow

1

Validate after every edit

Run sightmap validate after changing corpus YAML. It works offline and exits 1 on load or validation errors, so it can run as a required CI check.
2

Lint for style

Run sightmap lint --warn-only and read the warnings as a review checklist. Add --all-snapshots once you have captures, so match counts separate real problems from false positives.
3

Search before you add

Before naming a component, search for its proposed name and selector. Reuse or promote an existing definition when it already represents the same UI.
4

Discover the uncovered URL space

From a live session, run sightmap discover on pages that link to the app’s main sections. Classify each relevant ? pattern as a view or a survey.yaml entry.