ClaudeMods
☰
KO
● 0 명 접속 중 · 조회 0 회
후원프로젝트 제출
GitHub 저장소 · 작성자 EduardoIllanes

ratchet

프롬프트가 아니라 훅으로 강제하는 Claude Code 가드레일, 작업 보드, 사양 주도 에이전트 역할.

번역 완료

이 mod 소개

ratchet

작업 규칙을 에이전트가 건너뛸 수 없는 장치로 바꾸는 Claude Code 플러그인입니다. 모든 도구 호출 전에 가드레일이 실행되고, 체크리스트가 있는 작업 보드에서 작업하며, 에이전트 역할(사양 테스트 작성자, 구현자, 리뷰어)을 분리합니다. 모든 내용은 프롬프트 텍스트가 아니라 훅과 작은 바이너리 하나로 강제됩니다.

하는 일

  • 모든 도구 호출 전 가드레일. 기본 규칙은 4개입니다(venv 밖의 Python, 파괴적인 git, .env 파일, 메인 트리에 쓰기). 여기에 머신별 또는 저장소별 사용자 규칙을 더할 수 있습니다. 호출이 차단되면 이유와 대안이 한 줄로 표시됩니다.
  • 속일 수 없는 작업 보드. 작업에는 인수 체크리스트가 있고, 진행률은 체크리스트에서 계산되며 직접 선언할 수 없습니다. 모든 변경은 추가 전용 이벤트입니다.
  • 필수 인계. 기록이 하나도 없는 작업을 들고 세션을 닫으려 하면 남은 일을 한 번 작성하라는 요청을 받습니다.
  • 세션 레지스트리. 모든 Claude Code 세션은 훅이 등록합니다. 세션이 끝나면 해당 작업은 스스로 대기열로 돌아갑니다.
  • 세션 시작 브리핑. 저장소, 브랜치, 진행 중 작업과 마지막 인계, 고아 작업, 바로 가져갈 수 있는 작업을 최대 5개까지 보여 줍니다. 그 뒤에는 프롬프트마다 한 줄입니다.
  • 로컬 PDF 추출(ratchet pdf). liteparse CLI를 통해 실행하고 OCR을 자동으로 재시도하며 출력은 터미널 밖에 둡니다.
  • 컨텍스트 미터. 옵트인한 저장소에서는 상태 줄에 메인 컨텍스트 창의 사용량이 표시됩니다. 70%와 85%에서 토스트가 뜨고, /ctx는 범주별 내역, 각 서브에이전트 창, 자동 압축 전 남은 턴을 예측한 메인 창 추이, 가장 큰 도구 결과, 역할별 보류 작업 토큰을 보여 주는 패널을 엽니다. 함수 훅 모듈이며 함수 훅 모듈을 지원하는 Claude Code가 필요하고 2.1.288을 기준으로 테스트되었습니다.
  • 에이전트 역할, 스킬, 명령. 에이전트 프로필 7개, ratchet-tasks와 ratchet-pdf 스킬, /opsx:* OpenSpec 명령, /ratchet:init, /ratchet:map.

핫 패스 비용: 가드레일 훅 자체의 작업은 도구 호출마다 11-13 ms입니다(끝의 Latency 참조).

빠른 설치

claude plugin marketplace add EduardoIllanes/ratchet
claude plugin install ratchet@ratchet

이게 전부입니다. 훅이 처음 실행되면 릴리스에 고정된 플랫폼용 사전 빌드 ratchet 바이너리(macOS arm64/x64, Linux x64, Windows x64)를 내려받습니다. .claude-plugin/binary-version에 고정된 릴리스를 기준으로 하고, 릴리스의 SHA256SUMS.txt와 SHA-256을 확인한 뒤 플러그인의 bin/에 넣습니다. Rust도 PATH 변경도, 다른 곳에 설치하는 일도 없습니다.

플러그인 매니페스트에 버전이 없는 것은 의도적입니다. Claude Code가 marketplace 커밋을 추적하므로 claude plugin update ratchet@ratchet는 바이너리 릴리스를 기다리지 않고 에이전트, 스킬, 훅의 모든 변경을 가져옵니다. 업데이트마다 새 플러그인 디렉터리가 만들어지고, 그곳의 첫 훅이 고정된 바이너리를 다시 내려받습니다(몇 MB). 새 바이너리는 태그된 릴리스로 배포하며 Cargo.toml과 binary-version을 함께 올립니다.

그다음 저장소에서 옵트인합니다. 루트에서 Claude Code 세션을 열고 실행합니다.

/ratchet:init

ratchet는 셸의 PATH에 없습니다. 바이너리는 플러그인의 bin/에만 있고 Claude Code가 자체 세션의 PATH에 그 디렉터리를 추가합니다. 따라서 이 README의 모든 ratchet ... 명령은 세션 안에서 실행됩니다. ! 접두사(! ratchet task list)를 사용하거나 에이전트에게 실행하게 하면 됩니다. 터미널에서 사용하려면 해당 bin/을 PATH에 넣거나 바이너리를 링크합니다. 예: ln -s "<plugin dir>/bin/ratchet" ~/.local/bin/ratchet. 플러그인 디렉터리 이름이 marketplace 커밋을 따르므로 업데이트마다 링크가 끊깁니다.

다운로드할 수 없으면(오프라인, 지원하지 않는 플랫폼, 체크섬 불일치) 훅은 한 줄을 출력하고 0으로 종료합니다. 세션에는 영향이 없으며, 훅은 한 시간 동안 조용히 있다가 다시 시도합니다. 지금 다시 시도하려면 bash <plugin dir>/hooks/bootstrap.sh를 실행합니다. 수동 설치는 https://github.com/EduardoIllanes/ratchet/releases에서 플랫폼용 자산을 내려받고 SHA256SUMS.txt와 대조한 뒤 안에 있는 단일 파일을 <plugin dir>/bin/에 풀면 됩니다. 또는 RATCHET_BIN=<path to a binary you built>를 export하면 훅이 먼저 확인합니다. 플러그인 디렉터리는 ~/.claude/plugins/installed_plugins.json에 있는 ratchet@ratchet의 installPath입니다.

빠른 둘러보기

Claude Code 세션 안에서(! 접두사) 임시 저장소를 실행한 실제 출력입니다. 옵트인합니다.

$ ratchet config init
wrote /tmp/demo/ratchet.toml

도구 호출에 가드레일이 어떻게 반응하는지 묻습니다(저장소에 .venv가 있습니다. 종료 코드 2는 차단을 의미하며 훅이 Claude Code에 반환하는 값입니다).

$ ratchet guardrails test Bash '{"command":"python x.py"}'
[ratchet guardrail:python-venv] Python must run through the repo's virtualenv, not the global interpreter. Prefix the command with `uv run` (e.g. `uv run python scripts/x.py`) or call the venv interpreter (`.venv/Scripts/python` or `.venv/bin/python`).

인수 조건을 가진 작업을 만들고 진행합니다.

$ ratchet task new "Port the parser" -c "tests green" -c "docs updated"
T-0001  Port the parser  (backlog)

$ ratchet task list
T-0001  backlog      p3  Port the parser  (0/2)

$ ratchet task check T-0001 1
T-0001 [x] 1. tests green  (1/2)

$ ratchet task handoff T-0001 "parser ported; docs still pending"
T-0001 handoff recorded

$ ratchet task show T-0001
T-0001  Port the parser
status backlog · repo demo · priority p3
progress 1/2

  1. [x] tests green
  2. [ ] docs updated

last handoff (2026-09-17T13:15:38Z): parser ported; docs still pending

events:
  2026-09-17T13:15:38Z  task.created     checklist=2 priority=3 repo=demo tags=[] title=Port the parser
  2026-09-17T13:15:38Z  checklist.done   tests green
  2026-09-17T13:15:38Z  handoff          parser ported; docs still pending

Claude Code 세션 안에서는 훅이 나머지를 처리합니다. ratchet task claim T-0001은 작업을 세션에 연결하고, 다음 세션 시작 시 마지막 인계가 포함된 브리핑을 표시합니다. 아무것도 기록하지 않고 세션을 닫는 일은 한 번 거부됩니다.

저장소 옵트인

저장소 루트의 Claude Code 세션에서 /ratchet:init을 실행합니다(또는 바이너리가 PATH에 있을 때 ratchet config init을 실행합니다. 빠른 설치 참조). 주석이 있는 다음 파일을 씁니다.

[repo]
default_branch = "main"
worktrees_dir = ".worktrees"

[guardrails]
off = []

이 파일이 없으면 모든 훅은 아무것도 하지 않습니다.

Init은 저장소의 CLAUDE.md에 reader와 researcher 에이전트를 언제 디스패치할지 알려 주는 짧은 블록도 추가합니다. 한 번만 기록하며(<!-- ratchet agents: 줄이 이미 있으면 건너뜀), 직접 편집할 수 있습니다. 일반 파일이 아닌 CLAUDE.md는 그대로 둡니다.

가드레일

기본 제공: python-venv, git-destructive, env-files, main-tree, big-read. 저장소별로 [guardrails] off = ["id"]를 사용해 끌 수 있습니다. 같은 스키마로 직접 추가할 수도 있습니다. 머신 전체 설정은 ~/.ratchet/config.toml → [guardrails] extra = "guardrails.toml", 저장소 설정은 ratchet.toml → [guardrails] extra = "ratchet/guardrails.toml"입니다. 기존 id를 가진 규칙은 교체됩니다. 다음은 데이터베이스를 읽기 전용으로 유지하는 사용자 정의 content 규칙 예입니다(pattern에는 사용하는 드라이버의 쓰기 메서드 이름을 사용).

[[rules]]
id = "db-readonly"
tools = ["Bash", "PowerShell", "Edit", "Write", "NotebookEdit", "MultiEdit"]
kind = "content"
pattern = '\.(write_rows|purge_all)\s*\('
message = "The database is read-only for agents."
alternative = "Read through the data layer; if a write is really needed, the owner does it by hand."

일회성 명령 규칙은 별도 파일 없이 ratchet.toml 안에 바로 둘 수도 있습니다. match는 각 명령 구간에 대한 정규식이며, message 자체가 대안(예: "use" 또는 "instead")을 밝혀야 합니다. 그렇지 않으면 파일 로드가 거부됩니다.

[[guardrails.rules]]
name = "no-curl"
match = '^\s*curl\b'
message = "Use the repo's fetch script instead."

인라인 규칙은 항상 명령 전용이므로 name은 기본 제공 id(python-venv, git-destructive, env-files, main-tree, big-read)와 같으면 안 됩니다. 그러면 절대 일치할 수 없는 명령 규칙으로 명령이 아닌 기본 규칙을 조용히 바꾸게 됩니다. id를 재사용하거나 명시적으로 빈 tools = []를 주면 규칙과 대안을 이름 붙여 로드가 거부됩니다(이름을 바꾸거나 off = [...]로 기본 규칙을 끕니다).

다음은 의도된 동작입니다. 명령 규칙은 따옴표 밖에서만 ;로 나누므로 따옴표 안의 "done; mypy clean"은 python-venv를 건드리지 않습니다. 하지만 content 규칙은 쓰일 내용을 검사하므로 문서에서 차단 패턴을 따옴표로 감싸도 쓰기가 차단됩니다.

big-read는 큰 파일 전체가 오케스트레이터의 컨텍스트에 들어오지 않게 합니다. 일반 파일이 [guardrails] big_read_lines 줄(기본 350줄)을 넘으면 offset/limit 없는 Read나 단독 cat/head/tail/less/more가 차단되고 세 가지 방법이 제시됩니다. 창을 지정한 Read, 필요한 줄을 찾는 grep, 파일과 질문을 넘기는 reader 에이전트(haiku, low effort)입니다. 저장소 worktrees 디렉터리 아래 파일(구현자가 의도적으로 전체를 읽는 곳), 존재하지 않는 파일, 파이프 명령(cat big.rs | grep fn은 기록에 도착하기 전에 이미 걸러짐)은 제외됩니다. 저장소별 임계값을 덮어쓸 수 있습니다.

[guardrails]
big_read_lines = 800

보드

작업은 작업에 담기며, 작업은 나중에 확인할 수 있는 방식으로만 이동합니다.

ratchet task list                       # 이 저장소의 보드, 작업마다 한 줄
ratchet task list --mine --status in_progress
ratchet task show T-0042                # 본문, 체크리스트, 마지막 인계, 최근 이벤트
ratchet task new "Port the parser" -c "tests green" -c "docs updated"
ratchet task claim T-0042               # 한 번 호출해 가져오고 in_progress로 전환
ratchet task check T-0042 1 2           # 한 번 호출해 조건 하나 이상을 순서대로 완료 처리
ratchet task note T-0042 "found X" "decided Y"    # 한 번 호출해 메모 하나 이상을 순서대로 기록
ratchet task handoff T-0042 "what is left and how to resume" --status review
ratchet task archive T-0042             # 검토가 끝난 done 작업을 보드에서 제거

claim은 같은 호출에서 작업을 in_progress로 만듭니다(backlog였다면 먼저 ready를 거침). check와 note는 하나 이상의 값을 받아 순서대로 적용하고 값마다 이벤트를 하나씩 만듭니다. check의 체크리스트 번호가 잘못되면 아무것도 표시하지 않고 호출 전체를 거부합니다. handoff의 --status <state>는 인계를 기록한 뒤 ratchet task status와 같은 전환(--why와 소유자의 --unreviewed 포함)을 적용합니다. 전환이 거부되어도 인계는 기록됩니다.

식별자는 번호를 재사용하지 않는 연속열의 T-0001, T-0002, …입니다. 작업에는 제목, 본문, 1부터 4까지의 우선순위, 태그, 선택적 부모, 인수 조건인 체크리스트가 들어 있습니다. 진행률은 계산됩니다. 읽을 때마다 완료 항목 수 / 전체 항목 수로 계산합니다. 어디에서도 "약 60 % 완료"를 받지 않으며 체크리스트가 없는 작업은 진행률을 전혀 보고하지 않습니다. 그래서 done으로 닫을 때 명시적인 --why가 필요합니다.

상태는 backlog → ready → in_progress → blocked → review → done입니다. 여기에 “대기열로 돌아가기”(in_progress, blocked 또는 review → ready)와 “처음으로 돌아가기”(무엇이든 → backlog)가 있습니다. 거부된 이동에서는 허용된 이동이 나열됩니다. 모든 변경은 사실마다 이벤트 하나(created、claimed、status、checklist、note、handoff、archived)를 추가하며 이벤트는 편집하거나 삭제하지 않습니다.

작업을 가져오면 세션에 연결됩니다. 살아 있는 세션이 보유한 작업은 가져가지 않으며, 종료된 세션이 보유한 작업은 이전 사실을 기록하고 넘겨받습니다. 종료된 세션의 작업은 스스로 되돌아옵니다(State and sessions 참조).

하네스는 요청하지 않아도 보드에 세 가지 일을 합니다.

  • *세션 시작 시

설치

먼저 작성자의 README에서 marketplace와 플러그인 이름을 확인하세요. 저장소 구조에 따라 명령어가 달라질 수 있습니다.

claude plugin marketplace add EduardoIllanes/ratchet
claude plugin install ratchet
원문 / README

ratchet

A Claude Code plugin that turns your working rules into things the agent cannot skip: a guardrail runs before every tool call, work lives on a task board with checklists and mandatory handoffs, and agent roles are kept separate (spec-test author, implementer, reviewer). Everything is enforced by hooks and one small binary, not by prompt text.

What it does

  • Guardrails before every tool call. Four built-in rules (Python outside the venv, destructive git, .env files, writes to the main tree) plus your own, per machine or per repo. A blocked call gets a one-line reason and the alternative.
  • A task board that cannot be faked. Tasks with acceptance checklists; progress is derived from the checklist, never declared. Every change is an append-only event.
  • Mandatory handoffs. A session that tries to close while holding a task with nothing recorded is asked, once, to write what is left.
  • Session registry. Every Claude Code session is registered by the hooks; when one dies, its tasks go back to the queue on their own.
  • A briefing at session start. Repo, branch, your tasks in progress with their last handoff, orphaned tasks, and up to five ready to take. One line per prompt after that.
  • Local PDF extraction (ratchet pdf) through the liteparse CLI, with automatic OCR retry and output kept out of the terminal.
  • A context meter. In a repo that opted in, the status line shows how full the main context window is, a toast fires at 70% and 85%, and /ctx opens a pane with the breakdown by category and every subagent's window, the main window's trend with a forecast of the turns left before auto-compaction, the heaviest tool results, and the held task's tokens by role. It is a function-hook module: it needs a Claude Code with function-hook modules and is tested against 2.1.288.
  • Agent roles, skills and commands. Seven agent profiles, the ratchet-tasks and ratchet-pdf skills, the /opsx:* OpenSpec commands, /ratchet:init and /ratchet:map.

Cost of the hot path: the guardrail hook does 11-13 ms of its own work per tool call (see Latency at the end).

Quick install

claude plugin marketplace add EduardoIllanes/ratchet
claude plugin install ratchet@ratchet

That is all. The first time a hook runs it downloads the prebuilt ratchet binary for your platform (macOS arm64/x64, Linux x64, Windows x64) from the release pinned in .claude-plugin/binary-version, verifies its SHA-256 against the release's SHA256SUMS.txt, and puts it in the plugin's bin/. No Rust, no PATH changes, nothing installed anywhere else.

The plugin manifest carries no version on purpose: Claude Code tracks the marketplace commit, so claude plugin update ratchet@ratchet picks up every change to agents, skills and hooks without waiting for a binary release. Each update lands in a fresh plugin dir, and the first hook there downloads the pinned binary again (a few MB). A new binary ships as a tagged release that bumps Cargo.toml and binary-version together.

Then opt a repo in. Open a Claude Code session at its root and run:

/ratchet:init

ratchet is not on your shell's PATH: the binary lives only in the plugin's bin/, and Claude Code adds that directory to the PATH of its own sessions. So every ratchet ... command in this README runs inside a session, either through the ! prefix (! ratchet task list) or by letting the agent run it. To use it from a terminal, put that bin/ on your PATH or link the binary, for example ln -s "<plugin dir>/bin/ratchet" ~/.local/bin/ratchet; the link breaks on every plugin update, because the plugin dir is named after the marketplace commit.

If the download cannot happen (offline, unsupported platform, checksum mismatch), the hook prints one line and exits 0; the session is not affected, and the hooks stay quiet for an hour before retrying. To retry now: bash <plugin dir>/hooks/bootstrap.sh. To install by hand: download the asset for your platform from https://github.com/EduardoIllanes/ratchet/releases, verify it against SHA256SUMS.txt, and unpack the single file it contains into <plugin dir>/bin/; or export RATCHET_BIN=<path to a binary you built>, which the hooks check first. The plugin dir is the installPath for ratchet@ratchet in ~/.claude/plugins/installed_plugins.json.

Quick tour

Real output from a throwaway repo, run from inside a Claude Code session (! prefix). Opt it in:

$ ratchet config init
wrote /tmp/demo/ratchet.toml

Ask the guardrails what they would do with a tool call (the repo has a .venv; exit code 2 means blocked, which is what the hook returns to Claude Code):

$ ratchet guardrails test Bash '{"command":"python x.py"}'
[ratchet guardrail:python-venv] Python must run through the repo's virtualenv, not the global interpreter. Prefix the command with `uv run` (e.g. `uv run python scripts/x.py`) or call the venv interpreter (`.venv/Scripts/python` or `.venv/bin/python`).

Create a task with its acceptance criteria and work it:

$ ratchet task new "Port the parser" -c "tests green" -c "docs updated"
T-0001  Port the parser  (backlog)

$ ratchet task list
T-0001  backlog      p3  Port the parser  (0/2)

$ ratchet task check T-0001 1
T-0001 [x] 1. tests green  (1/2)

$ ratchet task handoff T-0001 "parser ported; docs still pending"
T-0001 handoff recorded

$ ratchet task show T-0001
T-0001  Port the parser
status backlog · repo demo · priority p3
progress 1/2

  1. [x] tests green
  2. [ ] docs updated

last handoff (2026-09-17T13:15:38Z): parser ported; docs still pending

events:
  2026-09-17T13:15:38Z  task.created     checklist=2 priority=3 repo=demo tags=[] title=Port the parser
  2026-09-17T13:15:38Z  checklist.done   tests green
  2026-09-17T13:15:38Z  handoff          parser ported; docs still pending

Inside a Claude Code session the hooks do the rest: ratchet task claim T-0001 ties the task to that session, the next session start prints the briefing with the last handoff, and closing the session without recording anything is refused once.

Opt a repo in

Run /ratchet:init from a Claude Code session at the repo root (or ratchet config init where the binary is on your PATH, see Quick install), which writes this file with comments:

[repo]
default_branch = "main"
worktrees_dir = ".worktrees"

[guardrails]
off = []

Without that file, every hook is a no-op.

Init also appends a short block to the repo's CLAUDE.md saying when to dispatch the reader and researcher agents. It is written once (skipped when a <!-- ratchet agents: line is already there) and is yours to edit; a CLAUDE.md that is not a regular file is left alone.

Guardrails

Built-in: python-venv, git-destructive, env-files, main-tree, big-read. Disable per repo with [guardrails] off = ["id"]. Add your own with the same schema, machine-wide in ~/.ratchet/config.toml → [guardrails] extra = "guardrails.toml", or per repo in ratchet.toml → [guardrails] extra = "ratchet/guardrails.toml". A rule with an existing id replaces it. Example of a custom content rule that keeps a database read-only (use the write-method names of your own driver in the pattern):

[[rules]]
id = "db-readonly"
tools = ["Bash", "PowerShell", "Edit", "Write", "NotebookEdit", "MultiEdit"]
kind = "content"
pattern = '\.(write_rows|purge_all)\s*\('
message = "The database is read-only for agents."
alternative = "Read through the data layer; if a write is really needed, the owner does it by hand."

A one-off command rule can also live right in ratchet.toml, without a separate file — match is a regex over each command segment, and the message must itself state the alternative (say "use" or "instead") or the file is refused on load:

[[guardrails.rules]]
name = "no-curl"
match = '^\s*curl\b'
message = "Use the repo's fetch script instead."

Inline rules are always command-only, so name must not equal a built-in id (python-venv, git-destructive, env-files, main-tree, big-read) — that would silently replace a non-command built-in with one that can never match. Reusing an id, or giving an explicit empty tools = [], is refused on load naming the rule and the alternative (rename it, or disable the built-in with off = [...]).

Known behaviour, by design: command rules split on ; only outside quotes, so a quoted "done; mypy clean" does not trip python-venv; but a content rule scans what will be written, so quoting a blocked pattern in documentation blocks that write too.

big-read keeps a whole big file out of the orchestrator's own context: a Read with no offset/limit, or a bare cat/head/tail/less/more, over a regular file of more than [guardrails] big_read_lines lines (default 350) is blocked, naming three ways out — Read with a window, grep for the lines wanted, or the reader agent (haiku, low effort) with the file and a question. It exempts a file under the repo's worktrees directory (that is where implementers read whole files on purpose), a file that does not exist, and a piped command (cat big.rs | grep fn already filters before anything reaches the transcript). Override the threshold per repo:

[guardrails]
big_read_lines = 800

The board

Work lives in tasks, and a task moves only in ways you can check afterwards.

ratchet task list                       # the board of this repo, one line per task
ratchet task list --mine --status in_progress
ratchet task show T-0042                # body, checklist, last handoff, last ten events
ratchet task new "Port the parser" -c "tests green" -c "docs updated"
ratchet task claim T-0042               # one call: takes it, already in_progress
ratchet task check T-0042 1 2           # one or more criteria met, in order, in one call
ratchet task note T-0042 "found X" "decided Y"    # one or more notes, in one call
ratchet task handoff T-0042 "what is left and how to resume" --status review
ratchet task archive T-0042             # a reviewed done task leaves the board

claim puts a task in in_progress in the same call (through ready first if it was in backlog). check and note each take one or more values and apply them in order, one event per value; a bad checklist number in a check call refuses the whole call before marking anything. handoff's --status <state> applies the same transition ratchet task status would — including --why and the owner's --unreviewed — after recording the handoff; a refused transition still leaves the handoff recorded.

Identifiers are T-0001, T-0002, … from a sequence that never reuses a number. A task carries a title, a body, a priority from 1 to 4, tags, an optional parent, and the checklist that is its acceptance criteria. Progress is derived: it is items done / items total, computed on every read. Nothing anywhere accepts "about 60 % done", and a task with no checklist reports no progress at all — which is also why closing one as done then needs an explicit --why.

Statuses are backlog → ready → in_progress → blocked → review → done, plus "back to the queue" (in_progress, blocked or review → ready) and "back to the start" (anything → backlog). A refused move lists the ones that were allowed. Every change appends one event per fact — created, claimed, status, checklist, note, handoff, archived — and events are never edited or deleted.

Claiming ties a task to your session. A task held by a session that is still alive is not taken from it; one held by a session that died is, with a note recording the transfer. Sessions that die give their work back on their own (see State and sessions).

Three things the harness does with the board, without being asked:

  • At session start it prints a briefing of at most 40 lines: the repo, the session and the branch; your tasks in progress with their last handoff; the repo's tasks held by dead sessions, with theirs; up to five ready to take; and where the full guide is. A repo with nothing pending gets one line. When the repo has an AGENTS.md at its root, a second line rules: AGENTS.md points at it — the briefing never restates what is in it.
  • On every prompt, if you hold a task, one line: [ratchet] T-0042 in_progress (2/5) · last handoff: "…".
  • When the session tries to close holding a task you recorded nothing about this turn, it is blocked once and asked for ratchet task handoff …. It never blocks twice, and never blocks a headless run, where nobody could answer.

Any command that would print more than 60 lines writes them to ~/.ratchet/out/<timestamp>-<name>.txt instead and prints the first 20 plus that path. --json gives the machine-readable form of any board, session or db command; --session <id> attributes a write explicitly and is accepted anywhere on the line, but it can never name a subagent (a value with / is refused) — a board write made from inside a subagent's own Bash call is attributed to that subagent automatically, by matching the call against the task id and subcommand, never by a flag.

State and sessions

Everything ratchet remembers lives in one SQLite file: ~/.ratchet/ratchet.db (override the directory with RATCHET_HOME). SQLite is compiled into the binary — nothing to install — and the schema is applied by embedded migrations. The session-start hook migrates automatically; everywhere else, an out-of-date database says so and asks for ratchet db migrate.

ratchet db path        # where the database is
ratchet db migrate     # apply pending migrations
ratchet session list   # one line per session: id, state, repo, branch, tasks, last signal
ratchet session list --live
ratchet session show   # the session covering this directory (or name one)

A session is registered by the hooks themselves, with the identifier Claude Code gives them — ratchet never invents one. It records the repo, the directory, the worktree and branch when there are any, the mode (interactive or headless), who launched it (user or platform), and its signals. State is derived, never stored: live while the last signal is under live_minutes, idle until idle_minutes, orphaned after that, ended once the session closed. Both thresholds come from [thresholds] in the repo's ratchet.toml (10 and 60 by default).

When a session dies, its work goes back: a task in_progress held by an ended or orphaned session returns to ready without a session, at the end of that session and, for sessions that died without a hook, at the next session start in that repo. The task keeps its whole history.

Two environment variables let a launcher place a headless session in the registry: RATCHET_SESSION_ID (the identity, also written to the session's shell through CLAUDE_ENV_FILE), RATCHET_SESSION_MODE and RATCHET_LAUNCHED_BY. RATCHET_NOW (RFC 3339) replaces the clock for one process and exists so the time-dependent behaviour above can be tested without sleeping.

The PreToolUse guardrail hook still opens no database at all: it is the hot path. Its own work is the ~11-13 ms measured above; the wall-clock ceiling it is tested against fails on this machine for the process-launch reasons given under Latency.

PDF

ratchet pdf <file> [--pages "1-8,12"] [--ocr] extracts text from a local PDF via the external liteparse CLI (npm i -g @llamaindex/liteparse) — no network code, no approval list, nothing web-related. The fast pass runs first; text under the configured minimum retries once with OCR automatically; --ocr forces OCR from the start. The extracted text is written to ~/.ratchet/out/pdf/<stem>[-p<pages>][-ocr].txt; the terminal prints only a short header (pages, whether OCR was used, characters extracted, the sink path) and never the body. Configure the extractor and its limits in ~/.ratchet/config.toml:

[pdf]
extractor = "liteparse"
timeout_s = 60
ocr_timeout_s = 600
ocr_min_chars = 200
ocr_language = "eng"
max_file_bytes = 209715200

The full audited web-fetch flow (approval lists, robots.txt, cache, forms) is not here and is not planned — it stays in ops, where it already runs daily (owner decision, 2026-09-16; see docs/superpowers/specs/2026-09-16-ratchet-plugin-design.md §2 D-pdf, §9).

Agents and skills

Eight agent profiles in agents/: analyst, spec-test-author, implementer, reviewer, refactorer, researcher, mapper, reader — see AGENTS.md for how they are meant to be combined. Two skills: ratchet-tasks (working the board, writing handoffs) and ratchet-pdf (extracting text from a local PDF). OpenSpec work is the six /opsx:* commands (propose, apply, update, sync, archive, explore) in commands/opsx/; they need the openspec CLI installed separately. Ratchet used to also ship the same six workflows a second time as openspec-* skills — that duplicate set is gone (T-0011); the /opsx:* commands carry every instruction the skills had. The standalone openspec plugin ships this same command set under its own name — do not install it alongside ratchet, it only doubles the listing every agent pays for on every turn.

Map

ratchet map derives .ratchet/map.md — the repo's layout, gate commands, and one sentence per source file — from git ls-files, file headers and manifests, deterministically, with no model involved. /ratchet:map runs it and offers to wire it into CLAUDE.md (--wire, run once, never automatic); /ratchet:map --deep describes header-less files by dispatching the mapper agent (haiku), which only ever records a sentence through ratchet map note — it edits no file directly. ratchet map status prints the map's freshness (map: current, map: N commits behind, or map: from another branch); the session-start briefing shows the same line when the map is not current, dropped first if the briefing's own 40-line cap is tight. A map never grows past 150 lines — over the cap, the deepest directories collapse into one summary line each. .ratchet/map.md and .ratchet/map.notes are local and untracked; --wire is what adds .ratchet/ to .gitignore, not ratchet map on its own. Configure [map] exclude and [map] gate in ratchet.toml when the defaults don't fit a repo.

Usage

ratchet usage reports token cost per task, role and model, read straight from the transcripts Claude Code already writes under ~/.claude/projects (or RATCHET_CLAUDE_PROJECTS) and joined with the sessions/task events ratchet already records — no extra tracking, nothing to opt into. Plain ratchet usage lists every task touched in the current repo's window, one line each (status, review rounds, abbreviated tokens, title, cost when weights are configured); a trailing skipped N partial N version X line appears only when the scan actually met something it couldn't fully read.

  • ratchet usage <id> shows one task in detail: tokens per role/model, orientation (the orchestrator's cost before the first claim), tokens per review round, orchestrator share, cache efficiency, and cost.
  • ratchet usage --by task|role|model|session aggregates across the whole window instead of listing tasks; --by role also adds review rounds per task and orientation per session.
  • --since 7d|30d|<RFC 3339 date> widens or narrows the window (default 7d); --all-repos drops the repo filter and reports across every repo ratchet knows about; --json prints the same data as JSON (raw, unabbreviated numbers) instead of the terminal text.

Cost is only ever shown when every bucket contributing to a number matched a configured weight. Configure weights in the machine config (~/.ratchet/config.toml), keyed by model name prefix and matched longest-prefix-first, so a more specific prefix overrides a shorter one:

[usage.weights]
"claude-sonnet" = { input = 3.0, cache_write = 3.75, cache_read = 0.3, output = 15.0 }
"claude-sonnet-5" = { input = 2.5, cache_write = 3.0, cache_read = 0.25, output = 12.0 }

ratchet usage <id> --note is the command's only write: it appends a task note starting with usage: that holds the same one-task summary paragraph the <id> detail view is built from (total tokens, rounds, orientation, cost), through the same services::tasks::note write ratchet task note uses — attributed to the same session, refused with the identical message on a task that doesn't exist. Without --note, ratchet usage never writes anything.

Build from source

With a Rust toolchain (1.79 or newer; on macOS also the Xcode Command Line Tools, on Windows the Visual Studio Build Tools, both for the bundled SQLite):

cargo build --release
cp target/release/ratchet <plugin dir>/bin/     # ratchet.exe on Windows

Latency

Measured pre-tool cost on Windows 11 (release build): about 11-13 ms of ratchet's own work above process-launch cost (full pre-tool runs ~53-56 ms in a direct harness against a ~40 ms do-nothing-binary floor on that machine). The check this replaces, in a Python harness, cost ~830 ms. cargo test -p ratchet --release --test latency -- --nocapture prints the figures for your machine; the 60 ms ceiling in that test is a local sanity check and fails on slow launchers, which is why CI reports it without gating on it.

Not here (yet)

Binaries are not code-signed or notarized; macOS Gatekeeper may ask once (xattr -d com.apple.quarantine bin/ratchet clears it). No Linux arm64 build. The audited web-fetch flow (approval lists, robots.txt, cache) that the original group 3 plan would have ported is deliberately not planned for ratchet — it stays in ops.

Status

v0.2.3 — a context meter, in repos that opted in: the status line shows how full the main context window is, its move since the last turn and a small bar per running subagent; a toast fires at 70% and 85%; and /ctx opens a pane with the breakdown by category, the trend with a forecast of the turns left before auto-compaction, the heaviest tool results still in the window, the held task's tokens by role and every subagent's window. It is a function-hook module tested against Claude Code 2.1.288. Also ratchet usage no longer double counts: Claude Code writes one transcript record per content block of a response, each repeating its usage, and every record was summed (totals were roughly twice the real ones); a response now counts once, by message.id.

v0.2.2 — ratchet config init also appends to the repo's CLAUDE.md a block saying when dispatching the reader and researcher agents pays off and when it does not (idempotent, never rewrites existing content, skips a CLAUDE.md that is not a regular file). Also since v0.2.1: on Windows the hook wrapper now propagates a blocking exit code, so guardrails block there too, and reviewer.md records verdicts with a bare ratchet task review.

v0.2.1 — Windows fixes: the big-read guardrail now sees whole-file Read calls (the PreToolUse matcher was missing Read), Git Bash drive paths (/c/..., /cygdrive/c/...) resolve for big-read and main-tree, ratchet config init prints a native repo root, and CI is green on Windows.

v0.2.0 — groups 0-7 of the design spec are shipped. New since v0.1.1: ratchet map, the big-read guardrail, subagent lifecycle on the board, ratchet usage (token cost per task, role and model), task review verdicts with a done gate that requires an independent approve (attributed per subagent, proven by its transcript), batched board commands, repo guardrail rules in ratchet.toml where every block names its alternative, and an invalid or unparseable config degrading to the built-in rules instead of turning guardrails off. Design: docs/superpowers/specs/2026-09-16-ratchet-plugin-design.md. Agent doctrine: AGENTS.md.

비슷한 프로젝트