i2y/ritsu/geas
Claude Code and agent skill by i2y/ritsu
- community
Checking that the SKILL.md file is still in the repository.
Hold code to claims a person has read, with geas. A `.geas` file holds claims about what a program does as anyone could observe it from outside (what a command prints and exits with, what an HTTP service answers, what a screen shows), and geas runs every claim against the real program, whatever language it is written in. Use when writing or changing code that a `.geas` claims file holds; when running the gate on a change (`ritsu geas check`, `drift`, `map` and `affected`); when a claim fails or a geas diagnostic (E001-E090, W060-W061, W901) has to be fixed; when the scenarios of an OpenSpec spec or change have to be held to claims (`ritsu geas scenarios`); or when behavior no claim covers has to be proposed to the person as new claims.
Install
npx vskill@latest install i2y/ritsu/geasSKILL.md
When this applies
The project keeps a claims file (*.geas) beside its code, or a person wants one. Each claim says what the program does as anyone could see it from outside: what a command prints and exits with, what an HTTP service answers, what a screen shows to a screen reader. The person reads and accepts the claims; you write the code; ritsu geas check runs every claim against the real program and says which hold.
It does not apply to tests of internal functions: a claim never names a file, a function, a class, a CSS selector or a line, and geas never reaches into the code. A library is claimed through a small command or service around it.
The files bundled with this skill are listed in §10. Read them when you need them, not all up front.
Working with geas
1. Who writes what
geas splits the work: the person reads about fifty lines of claims, you write the code, and geas holds the code to the claims. That split is the whole point, so keep to it.
- The claims file is the person's. Every line of it: the claims, the targets, the masks, the
pins. Do not change it to make the gate pass. Write a change you think it needs as text in your answer, and put it in the file once the person says yes. When there is no claims file yet, propose a first one the same way, from what the person asked for.
- A failing claim is fixed in the code, unless the person says the claim is wrong. A claim
that cannot be true of any sensible program is a question for the person, not something to loosen.
- A missing claim is proposed, not written. When
ritsu geas affectedlists changed code no claim
runs, when ritsu geas drift lists a change no claim covers, or when the person asks for behavior no claim states, write the claim you propose, say why, and let the person accept it. When the project has rules, gates, books or workflows, from-specs.md is how to propose many at once.
- A new baseline and a new mask are asked for.
ritsu geas snapchanges whatdriftcompares
against, and a mask line stops drift from looking at a field; both can hide a change, so the person decides.
- The files under `.geas/` are geas's. The journal, the baseline and the record are written
by geas; never edit them by hand.
- OpenSpec's scenarios are the person's too. In a project that keeps its behavior in OpenSpec,
each scenario (#### Scenario: under a requirement) is a case the person agreed on, and the claim that runs it carries the scenario's name exactly. ritsu geas scenarios <spec.geas> --openspec openspec/specs says which scenarios no claim answers; --openspec openspec/changes/<id> does the same for a change before it is archived. For each one, propose a claim (--draft writes the frame, with the scenario quoted above it; the steps are yours to propose and the person's to accept). Never rename a claim or a scenario to make the two meet: say which is wrong, and ask.
Run every command here as ritsu geas <command> (through a link to ritsu named geas, geas <command> is the same). Everything is reachable from the command line: ritsu geas --help lists the commands, ritsu geas explain <code> explains a diagnostic, and the commands that report take --json. There is no step where you have to read geas's source.
2. The loop
- Check:
ritsu geas check <spec.geas>runs every claim. Read eachnot ok(§4), fix the code,
and check again until every claim holds (exit 0).
- Snap, once the person accepts the behavior:
ritsu geas snap <spec.geas>runs the claims and
keeps every observation, not only what the checks look at, as the baseline in .geas/<stem>.baseline.jsonl. Ask before you snap.
- On every later change:
ritsu geas check <spec.geas>: every claim still holds.ritsu geas drift <spec.geas>: what changed since the baseline. A change marked[unclaimed]
is behavior no claim promises; tell the person, with a claim to add or a reason not to.
ritsu geas map <spec.geas>, thengit diff | ritsu geas affected <spec.geas> -: which claims the
change touches, and which changed lines no claim runs. map runs the claims with coverage on and records, for each claim, the lines it ran; affected reads the diff and that record and runs nothing. Run map on the changed code: added lines need a record of the code after the change (E063 otherwise). A file the change adds is in git diff only once git knows it, so git add -N <file> it first.
- Report what the person has to read: the claims the change touches, the changed code no
claim runs, and drift's unclaimed changes, each with the claim you propose or the reason it needs none.
check, snap, drift and map take several specs; --jobs N runs up to N claims at once (§8). Exit codes: 0 all held or nothing to report, 1 something failed or changed, 2 the spec, a file or the arguments are wrong. In a project that also holds the other languages' files, ritsu check runs the claims of every .geas with the rest (the ritsu skill).
3. The language on one page
A whole claims file, examples/greeter/greeter.geas:
A target says how to start the program. A claim is when steps, each an action on a target, and then checks of what the last when observed; and is another check of the same observation. Each claim starts its own instance of every service it touches, so claims do not see each other's state and can run in any order. # starts a comment. The forms, at a glance:
A role is a WAI-ARIA role name (button, textbox, heading, link, checkbox, listitem, dialog, …) or text, and the states are disabled, enabled, checked and unchecked. A pattern (matches, matching) is held against the whole value. In a string, \n, \t, \" and \\ are escapes, and a pattern keeps its backslashes as written ("\d+"). geas splits a command into words itself, never through a shell: '…' and "…" keep blanks inside a word, and a shell is named when one is wanted (run "sh -c 'cd tools && ./gen'").
A when on a command or a service can wait for an answer that comes later, such as a job's result after the service accepted it: with within <n> seconds after its call, geas calls again, 100 ms after each answer, until every check under that when holds on one answer, for up to n seconds from the first call. When the time runs out, the checks read the last answer. A call is made again as it is written, so a call that waits does what it does on every call: a post that creates something creates it again, and a put or a patch writes again. Wait on a read where there is one.
A handler that takes events, messages or webhooks from another system cannot choose the order they come in, and the same one can come twice. When the code you write is such a handler, propose a claim with in any order { … } around the deliveries and the state they should end in after it: geas runs the claim once for each order of the steps in the block, and a handler that writes each event as it comes fails in the orders that end on an older one. A delivery that comes twice is the same step written twice. The orders are fixed, so a failure comes back in every run. Its limit: geas makes one call at a time, so a handler that goes wrong only when two events are handled at the same time is not caught; say so when that is the risk. language.md has every form, with what each one means.
4. Reading the answers
ritsu geas check prints one line a claim, ok or not ok, then a summary. A failed check says what it expected and what came back, with the line of the spec and the run that gets there:
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/geas/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/i2y/ritsu/geas)