Skip to content
GitHub
Chapters

Guide

The CLI

Bringing Jig to an existing codebase covered adopting Jig, reading a first report and redesigning a page on purpose. This chapter changes register: it is not about a page or a project’s design loop at all, but about the CLI itself, run the way a linter or a formatter is run: from a terminal, with no agent reading a skill file, no /jig slash command, nothing that differs by which agent you use or which of the two setup paths you started on. Every command it names is the same binary, run the same way, whichever chapter brought you here.

Two kinds of command

Two kinds of command exist in this system, and only one of them has a terminal form at all. The 11 CLI-backed ones, install, update, init, check, explain, verdicts, gate, probe, seo, ship, checksum, run a real binary, the same whichever agent or none is asking. The 6 agent procedures, decide, spec, mockup, make, critique, tweak, have no binary behind them at all: judgment and authorship a CLI cannot perform, which is why every other chapter under /guide/ teaches them through an agent rather than a command line.

Every one of them but gate also has a /jig form: an agent runs the same command, the way it runs any other slash command. Some of those forms do more than the command they call. /jig check runs check and then applies the 120 judgment rules the CLI cannot. /jig critique runs verdicts and probe together, through readers that cannot see each other, and reports what none of the three alone would catch. /jig init runs init and then states the mode it chose and what it wired. gate has no slash form at all: nobody types it, since it is what the Stop hook runs on its own. The 6 agent procedures above have no CLI at all behind their /jig forms, whichever agent calls them, which is the whole reason this chapter does not cover them.

This chapter is the CLI-backed ones, in full. Four of them need no section of their own below: install and init, whose own depth already lives elsewhere (install in Working with an agent, init in Getting started), gate, which Working with an agent also covers, where the Stop hook that runs it lives, and checksum, which needs only its own line here: it prints a spec’s checksum, the value its .checked.json records as spec, so a spec’s reader never computes it by hand. The rest get their own section below, in the order a reader working from a terminal meets them: check, explain, seo, probe, verdicts, ship and update. A closing table gathers all 11, with their exact flags, to come back to.

check

check is the one you run without thinking: it reads the project and reports, with nothing to confirm and nothing to wait on.

npx jig-ui@0.25.0 check --all

Its 3 flags: --all scan every file in the repo, not just those changed since HEAD (same rules either way); --ci mechanical bucket only, so the run is deterministic; --json emit findings as JSON.

It reads CSS wherever it lives, not only in a stylesheet:

  • Stylesheets: .css, .scss, .less.
  • <style> blocks in HTML, Astro, Vue, Svelte, PHP, ERB, Twig, Handlebars, MDX, ASP/ASP.NET, Razor, JSP, Phoenix, EJS, Nunjucks, Liquid, Jinja, Velocity and FreeMarker, plus the indented style blocks Pug, Haml and Slim each use instead of a tag.
  • Style attributes written inline, CSS-in-JS such as styled.button, css, createGlobalStyle and keyframes, and Tailwind’s own arbitrary values and palette pairs.

Host files are reduced to their style regions before the detectors run, with character positions preserved, so a finding’s line points at the real line in your `.vue` or `.tsx` file. Application code outside a style region is never read as CSS.

This build’s own pinned corpus puts 27 rules in check’s mechanical bucket and 13 more in its hybrid bucket, out of 160 rules in total, including the ones a reader meets first: hard-coded values past the token layer (H-47), contrast below the floor (C-19), removed focus rings (E-29), gradient text (A-02), backdrop blur (A-04), and pure black and white (C-18). The violet-band hue check (A-01) sits in the hybrid bucket rather than the mechanical one, because it asks rather than fails.

⚠ A-139 a 4px coloured stripe on one side of : the shape of an alert on something that is not one  A-139.html:3   [hybrid]  (see rule A-139 in your installed jig skill's rules/)

  0 errors, 1 warning · 160 rules (+ 44 pattern and mode specs) · 1 file, 1 with styles, 1 fired
  JIG_CHECK: version=0.25.0 mode=unknown mechanical=pass:0 warnings=1 judgment=not-run files=1 styled=1

Captured live against A-139’s own example file: the shape of a hybrid finding, not a claim about your project.

It also reads the token layer itself: not application code, so no detector scans it, but where a mistake costs most, since every call site inherits it. It holds what is declared there to the floors the token layer claims: 4.5:1 for text roles and 3:1 for interface strokes, in both light and dark, plus --text-prose at 18px and --size-touch-target at 48px.

Two deliberate limits: a bare spacing utility is not a finding, since it resolves through a scale that is your project’s own decision; and a colour outside the framework’s default palette is not resolved rather than guessed at.

What a terminal-only check does not give you: the other 120 rules in this corpus are judgment, and a CLI cannot perform judgment. Reading them is The loop’s own subject, through critique.

And what no amount of check gives you at all: a small section of rules about what an interface does to itself, and nothing about sessions, rate limits, CORS, secrets, headers, dependencies or hosting. A clean check says nothing about any of them and should never be read as if it did.

explain

Given an id, explain prints the rule in full: what it forbids, what to do instead, the version it arrived in, and who checks it.

npx jig-ui@0.25.0 explain C-19

It resolves a P- pattern or an M- mode spec too, printed marked as a specification rather than a rule, with no wrong-and-right example pair and no detector: that is correct, not a gap. Given a word instead of an id, it searches every title and body and lists what matches, for finding a rule you cannot name.

npx jig-ui@0.25.0 explain contrast

Its flags: --list list every rule id and title, or one section with a section letter; --layer name the six layers, or list one of them by name.

Two different misses, on purpose. A well-formed id that does not exist errors, naming every id in that section, so a typo still lands you close. A word that matches nothing errors differently, suggesting --list: a search with no hits, not a typo.

seo

seo audits what a search engine and a link preview read, across the whole project, from one command: a route whose metadata says noindex sitting in the sitemap anyway, two pages claiming the same title, and a sitemap that lists nothing or lists paths instead of full URLs.

npx jig-ui@0.25.0 seo

It counts the pages it found (a dynamic route once, and an endpoint not at all, since it serves no page), and counts whether a sitemap and a robots file exist without judging either. No rule asks for them, and a project with no domain yet cannot write an honest sitemap. It needs no config, no decisions and no spec, so it is safe to run on the first day, or on somebody else’s codebase, before anything else in this chapter applies.

Its flag: --json emit findings as JSON (default: false).

probe

With no flag at all, probe prints one JavaScript expression, the render probe, that a critique’s screen arm evaluates in a browser at each width. It changes nothing on its own.

npx jig-ui@0.25.0 probe

--run <page> renders that page itself, at 360, 768, 1280 and 1600, and either side of each --breakpoint-* the project declares, finding a headless browser itself. It needs --save <surface> alongside it, to record what it measures under .jig/critique/<surface>/. --serve <dir> serves a directory over local HTTP first and loads --run from it, so a built static site’s root-relative links resolve.

npx jig-ui@0.25.0 probe --run <page> --save <surface>

A reader with no agent at all can run this by hand: it is real output, not only something a critique’s reader calls internally.

verdicts

verdicts verifies a critique’s two passes: every rule judged exactly once, no id that does not exist, no rule answered by the wrong arm, and no verdict the render probe itself contradicts. It computes a critique’s own counts, so nobody writes them by hand.

npx jig-ui@0.25.0 verdicts <surface>

Its flag: --reprobe re-take every probe that is missing or was taken on an older version of the page, first (needs a browser).

What comes back on a failure is an error naming the arm to re-run: never a verdict file edited until it passes, which would record nothing about the page. The same discipline gate holds a critique session to.

ship

ship says whether the project is ready to ship, by everything Jig checks: check --all --ci and seo with no errors, and every confirmed page critiqued as it stands with no finding left unruled. It takes no flags.

npx jig-ui@0.25.0 ship

It names, page by page, every reason a page is not yet clear, all six the binary itself reports, not a shortened list:

  • Never critiqued at all.
  • Changed since its last critique.
  • A tweak that deferred its re-judge.
  • A critique whose verdict files are incomplete.
  • A critique judged against a stale render, whose probes need retaking (jig verdicts <surface> --reprobe).
  • And the one a reader meets most often: findings the owner has not yet ruled on.

Exactly the shape verdicts, above, exists to compute rather than assert. It exits non-zero until the project is ready, and its own report closes by naming what Jig does not check, every run: security, performance, deployment, what a real screen reader does. It does not deploy anything and is not a security review.

update

update is the one command whose job is to move the version pin every other command holds fixed, so it is the one run unpinned:

npx jig-ui@latest update

Pinned, it would refresh to the version already installed and report success for a no-op. It reports what moved and what was left alone; a file reported skipped was edited locally and stays yours, never overwritten.

Upgrading across an older install, update performs none of the three migrations the pinned corpus names. init alone detects, reports and, with consent, acts on all three, every time: the function that does this work is called only from inside init, never from check or update.

  1. 1.

    A pre-0.4.0 install vendored Jig’s rules into the project’s own .jig/. Since 0.4.0 they live beside the agent’s own skill file instead, so running init again finds the leftover files, reports them, and, with consent, removes only the ones untouched since: a file you edited is named and left alone, never removed automatically.

  2. 2.

    A pre-0.7.0 project keeps a legacy .jig/tokens/ layout. init offers to move it to the location your project’s own structure suggests, all four parts together or none: write the new imports, remove the old files, strip the stale import, and update jig.config.json.

  3. 3.

    A Cursor install from before its skill moved keeps .cursor/rules/jig.mdc. init finds it and offers the same treatment, to .cursor/skills/jig/SKILL.md. The corpus dates the first two migrations by version and does not date this one at all, so this chapter says so rather than inventing one.

A reader whose only symptom is an update that reports nothing to do should re-run init, not update, to see any of the three.

One command left unnamed above: gate is not one you type. It is what Claude Code’s own Stop hook runs, and Working with an agent is where the hook itself, --hook, and waiving a warning are taught in full.

Every command, in full

All 11, gathered here to come back to: generated from the pinned binary’s own --help, not copied from this chapter by hand, so a flag it gains or drops between this build and a later release still pinned to the same version cannot go stale against it.

CommandFlagsWhat it does
check--all, --ci, ‑‑jsonCheck the repo against Jig's mechanical + hybrid rules.
explain [query]--list, ‑‑layerExplain a rule, or find the rules you cannot name.
seo‑‑jsonAudit what a search engine and a link preview read, across the whole project.
probe--save <surface>, --run <page>, ‑‑serve <dir>Print the render probe. With --save, read what it returned on stdin and record it for jig verdicts.
verdicts <surface>‑‑reprobeVerify a critique's verdict files and compute its counts.
shipNo flags.Say whether the project is ready to ship: no mechanical or seo errors, and every confirmed page judged as it stands with nothing open.
updateNo flags.Update vendored Jig rules, skipping files you have edited.
install--agent <name>, --scope <scope>, --hook, --no-hook, ‑‑yesInstall Jig rules and the agent skill file into a repository.
init‑‑yesSet the project up to use Jig: a brand file, jig.config.json, and a baseline check.
checksum <spec>No flags.Print a spec's checksum, the value its .checked.json records as spec.
gateNo flags.Run by the Claude Code Stop hook: block stopping while check or a critique fails.