Skip to content
GitHub
Chapters

Guide

Working with an agent

Tokens and modes covered the declaration and the layer every earlier chapter quietly relied on. This last chapter changes subject once more: the agent-facing half of Jig itself, each of the 6 agents it installs for, in its own section, where its skill and its slash command land; the Claude Code Stop hook that can hold an agent to its own unfinished work; and, in full, what an agent does and does not do when the owner asks it to check or confirm a spec or a mockup on their behalf. Nothing below differs by which agent you use or which of Getting started’s two setup paths you started on: every agent gets its own section, read in the same order regardless of which one brought you here.

One table compares all 6, README’s own order, for install and file locations:

AgentInstallProject scopeGlobal scope
Claude Codenpx jig-ui@latest install --agent claude.claude/skills/jig/SKILL.md~/.claude/skills/jig/SKILL.md
Codexnpx jig-ui@latest install --agent codex.agents/skills/jig/SKILL.md~/.agents/skills/jig/SKILL.md
Cursornpx jig-ui@latest install --agent cursor.cursor/skills/jig/SKILL.md~/.cursor/skills/jig/SKILL.md
opencodenpx jig-ui@latest install --agent opencode.opencode/skills/jig/SKILL.md~/.config/opencode/skills/jig/SKILL.md
Gemini CLInpx jig-ui@latest install --agent gemini.gemini/skills/jig/SKILL.md~/.gemini/skills/jig/SKILL.md
Any other agentnpx jig-ui@latest install --agent generic.agents/skills/jig/SKILL.md~/.agents/skills/jig/SKILL.md

Two facts hold for every row above, so neither is repeated per agent below: every agent reads a skills/jig/SKILL.md, so a new harness is a config change rather than a new code path; and --scope global installs once for every project instead of just this one, every agent supporting both, with a project-scope install warning rather than a second, contradicting skill when the same agent is already installed globally.

Claude Code

npx jig-ui@0.25.0 install --agent claude

At project scope the skill lands at .claude/skills/jig/SKILL.md; at global scope, ~/.claude/skills/jig/SKILL.md.

Claude Code alone also gets a slash-command file, .claude/commands/jig.md, at the same scope as the skill itself, project or global. It is also the one agent that can install an optional Stop hook: what it is, --hook, and waiving a warning are the Stop hook’s own subject, next.

Codex

npx jig-ui@0.25.0 install --agent codex

At project scope the skill lands at .agents/skills/jig/SKILL.md; at global scope, ~/.agents/skills/jig/SKILL.md, the cross-agent .agents/ directory, the same one Any other agent uses below.

Its slash command lands at global scope only, ~/.codex/prompts/jig.md: OpenAI documents custom prompts as loading from ~/.codex/prompts with no project-scoped equivalent, so a project-scope install writes no prompt file. The skill itself works either way, and OpenAI deprecates custom prompts in favour of skills for exactly that reason, since a skill can be shared through a repository while a prompt stays on one machine.

Codex additionally gets a short pointer block in AGENTS.md, read into every session already, so it names the skill rather than restating it.

Cursor

npx jig-ui@0.25.0 install --agent cursor

At project scope the skill lands at .cursor/skills/jig/SKILL.md; at global scope, ~/.cursor/skills/jig/SKILL.md.

Its own slash-command file, .cursor/commands/jig.md, sits at the same scope as the skill, project or global. Nothing else about it forks from the comparison above.

opencode

npx jig-ui@0.25.0 install --agent opencode

At project scope the skill lands at .opencode/skills/jig/SKILL.md; at global scope, ~/.config/opencode/skills/jig/SKILL.md.

Its own slash-command file, .opencode/command/jig.md, singular command, not commands, sits at the same scope as the skill.

Gemini CLI

npx jig-ui@0.25.0 install --agent gemini

At project scope the skill lands at .gemini/skills/jig/SKILL.md; at global scope, ~/.gemini/skills/jig/SKILL.md.

Its own slash-command file, .gemini/commands/jig.toml, sits at the same scope as the skill, the one agent among the six whose command file is .toml rather than .md.

Any other agent

npx jig-ui@0.25.0 install --agent generic

At project scope the skill lands at .agents/skills/jig/SKILL.md; at global scope, ~/.agents/skills/jig/SKILL.md, the same cross-agent .agents/ path Codex’s own skill uses, above.

It gets no slash-command file at all. .agents/skills/ is a cross-agent convention for skills, not a harness with a command system of its own, so there is no file to write and nothing that would read one: ask in plain language instead, and the skill still loads.

The Stop hook

One entry install can add to .claude/settings.json, Claude Code only: it runs gate whenever the agent tries to finish, and holds the agent there while the files it changed carry a check error or warning, or while the /jig command it just ran left its own work incomplete: a spec that is still prose, a critique with no verdict files, a review that never rendered the page.

It is off unless asked for: --hook at install time, or answering yes when an interactive install offers it, turns it on. --yes never adds it, because that is the path an agent takes with nobody there to consent.

Why it exists, README’s own words: “weak models skip any step they are merely asked to run: in live runs at the capability floor, builds shipped 53 mechanical errors, pages rendered with no styles at all, and four reviews in a row wrote no verdicts.”

The skill and the hook install separately. With Jig installed globally, install --agent claude --hook run in one project adds only that project’s hook: a global hook would run on every stop in every project on the machine.

A warning that is right as it stands is waived on its own line, in a comment reading jig-allow <ID>: <why>:

/* jig-allow A-01: the brand is violet */

The reason is required. An error cannot be waived this way, and check lists every waiver it honoured, with its reason, on every run. What the hook holds an agent to once a critique session is already under way, how many refusals it allows, and the verdict-lock commit that follows, is The loop’s own subject, not repeated here.

Checking and recording the owner’s word

An owner can ask an agent to check a spec, or approve a mockup, on their own behalf rather than doing it themselves. Read every line to the letter before saying yes on someone else’s word: a sheet that makes checking quick does not replace checking it.

Checking a spec, before the owner is asked to confirm it:

  • Your words are yours. Every quotation it gives as yours is something you said, and nothing reads as your ruling that you did not give. What the agent worked out for itself is labelled as its own.
  • Every fact holds up at its source. Where the spec says how something works (your product, an API, an existing page, a tool you depend on), open the source and check. One habit of your project stated as a general rule is a fact nobody decided.
  • Words the page will show are words you would ship. Headings, labels and any copy the spec writes out are built as written. Read them as the person arriving would. A sentence about how the page works (what a control costs to use, where a choice is stored) is a note for the builder, not copy.
  • Conditions you gave are there, as you gave them. “Three columns from 1280 up” is written as 1280, not moved to a width that was easier to build.
  • V1 is small, and later: holds what you cut. Nothing you set aside has come back in.
  • Every size says what you expect to see. The phone is written in full, first. Each same-as: gives a reason that is true, and nav: at every size is the navigation you would expect there.
  • States cover what the page will meet. Empty, one, a lot, loading, failure: whichever the page can actually be in.
  • Everything that moves has a reason. Each line of motion: names what moves, what sets it off, and what it tells the reader. Cut any line that cannot say, and expect nothing on the page to move that the list leaves out.
  • Open questions were asked, not answered for you. A spec touching an item under Unresolved in DECISIONS.md carries your answer, and a field reading unspecified — make chooses one it can defend is one you can decide now.
  • A page that exists is described as built. Its regions are the ones on the page today, and anywhere it contradicts your decisions is said plainly.

Confirming a spec on the owner’s behalf, when asked to: You can ask your agent to check a spec and confirm it for you. It works from the same sheet and confirms only what it checked itself: it opens every source marked unchecked and any it doubts, reads the copy as the person arriving would, and holds each condition to your words. What it could not check, it names to you instead of confirming. An agent’s yes is still yours, so read what it says it did not check.

Checking a mockup, before the owner is asked to approve it:

  • Every size matches its line in the spec. The order of the regions, what comes first, what sits with what, where each one is. A region that is present but in the wrong place is not a match.
  • The navigation at each size is what the spec’s nav: says.
  • Nothing extra. No region the spec does not list, and nothing from later:.
  • The spec’s states are drawn where one changes the layout: empty, error, a lot.
  • What a drawing cannot show is named, from your spec. If your spec says a part stays in place on scroll, or opens and closes, the sheet names it so you approve that too. If your spec says nothing of the kind, there is nothing to name.
  • Now that you see it, the spec is still what you want. If it is not, the spec changes first and the drawing is redrawn from it, so the two never disagree.
  • A condition you attach is written into the spec, in your words, before the approval is recorded. make builds from the spec, not from the conversation.
  • You are not approving colour, type or exact spacing. Those come from the tokens; a grey drawing settles none of them.

Approving a mockup on the owner’s behalf, when asked to: It renders every frame, compares each with its line in the spec, confirms only what it checked, and names to you what it could not.

Either way, an agent’s yes is still the owner’s to stand behind.

Recording the owner’s word is one general rule covering five things: a spec confirmed, a drawing approved or skipped, a re-judge left for later, a tweak’s change, and a decision’s reason. Each is the owner’s own words, quoted as they said them, and words that say that thing: a remark about the layout is not a skip of the mockup, and a yes to one question is not a yes to the spec. Where the owner has not said it, ask. What an agent reads into the owner’s words carries its own label, **Why (inferred):**, never inside their quotation marks.

Where Jig has no field for something worth recording, it goes in prose, below a spec’s front matter or in a report, never an invented front-matter key, verdict id or JSON field, since nothing reads one that does not exist and what it says is lost to every check. If the same gap keeps recurring, that is worth telling the owner: Jig may simply be missing a field.

Attestation

Before finishing a task that generated or modified UI, an agent emits this line:

JIG_CHECK: version=<version> mode=<mode> mechanical=<pass|fail|skipped>:<n> warnings=<n> judgment=<ran|skipped>:<n> files=<n> styled=<n>

warnings= counts what check reported as warnings. mechanical=pass means no errors and nothing more: a page that is not usable on a phone can still carry pass:0 with several warnings, since the mobile detectors warn rather than fail CI: a record that says pass with warnings above zero is not a clean page, and should say what the warnings were. jig check itself emits the same line for the half it can do, with judgment=not-run.

The line an agent emits is its own, not a copy of the CLI’s. judgment=not-run is the CLI truthfully describing itself. It cannot judge. An agent that did the judgment work writes ran:<n>, with the number of rules it gave a verdict; one that did not writes skipped and says why. If check could not run at all, that is mechanical=skipped:0, never pass, which would report a clean result for a check that never inspected anything.

files= and styled= describe a scope that is not fixed: check defaults to files changed since HEAD and falls back to the whole repo only once that diff is empty, so two attestation lines are comparable only when both runs shared the same scope. check --all is what to run for a number that describes the whole project rather than one diff.