Hallmark
Agentic development · automated review · a full record

Hallmark

A workshop for coding agents that runs on your machine. You hand in a request, agents build it with you, an independent principal engineer reviews it, and fixers repair what it finds. Only work that earns its hallmark leaves for GitHub. Every handoff and message is filed, so you can always see what happened and why.

The word comes from Goldsmiths' Hall in London, where silver was tested and stamped before it could be sold.

hall the command item one piece of work, prompt to PR journal the item's full history assayer the principal-engineer reviewer fixer the agent that addresses findings hallmark approval bound to a commit

Inside the Hall

Picture Hallmark as a building seen from above. Requests come in at the Front Desk, get built in the Workshop and tested in the Assay Office. If the assayer finds problems, they go to the Repair Shop and back. Approved work is stamped and leaves from the Dispatch Dock for GitHub. Every handoff passes through the Post Room, which files a copy in Records. When an item closes, the Library keeps what it taught, and briefs the principal engineer before each review (the gold slips). The boxes are items and the figures are agents. Select a room to see what happens there.

you dev agent principal engineer fixer clerks shipper watchman an item, coloured by state

Setup

Hallmark ships as the hallmark package and installs one command, hall. Setup is once per machine plus once per repository.

  1. Install the binary

    Any of these puts hall on your PATH, on macOS, Linux or Windows.

    cargo install hallmark
    brew install hallmark
    nix profile install github:<you>/hallmark
  2. Connect Claude Code

    Installs the Hallmark plugin at user level: the skills, the reviewer and fixer agents, and the hooks. Every repo and every session gets them.

    hall setup claude
  3. Add a repository

    Run in the repo. It detects the gates, writes .hallmark.toml and a stub .hallmark/review.md for local review notes, adds a short Hallmark section to CLAUDE.md or AGENTS.md, and registers the repo.

    hall init
    git add .hallmark.toml .hallmark/ CLAUDE.md
    git commit -m "Adopt Hallmark"
  4. Start the daemon

    Runs the review loop for every registered repo. --at-login registers it with launchd, systemd or Task Scheduler.

    hall daemon start --at-login
  5. Check everything

    Each failed check names the command that fixes it.

    $ hall doctor
    ✓ git 2.51 · gh (logged in) · claude
    ✓ Claude Code plugin hallmark (user)
    ✓ hooks: SessionStart UserPromptSubmit PreToolUse
             PostToolUse Stop
    ✓ rindahq/platform: gates rig test, rig run build
    ✗ daemon not running  →  hall daemon start

Using it

You do three things: start work, send it to review, and check status and history. Agents do everything else. You can do all three by talking to Claude Code, or from the terminal.

In Claude Code
In the terminal
# open the app: board, journals, history
hall

# start work and open Claude in its worktree
hall new "Retry failed webhook deliveries" --open
hall new --issue 212 --open

# see where things are
hall status
hall log H-0042
hall history --rejected --since 7d

# decide
hall ready H-0042
hall pull-back H-0042
hall drop H-0041 --reason "superseded by H-0044"

On a terminal these print readable text. When an agent runs them, they print JSON.

When Hallmark needs you

Anything that needs you lands in Your Office as an inbox entry. It shows the item, what's being asked, the options and how long it has waited. Hallmark then tells you wherever you are, and keeps telling you until you answer. Only the item that's waiting stops; the rest of the building carries on.

Waiting for youExampleWhat waitsTells you by
Question"The issue says usage: billed usage or raw events?"That item. The agent's session is saved and picks up with your answerdesktop, phone
Escalated"Rejected 3 times for the same missing tenant check"That itemdesktop, phone
Session waitingYour Workshop session wants a permission or a replyThat sessiondesktop
Ready?"H-0042 looks done: retries with jitter, 14 tests"Nothing; it stays in developmentdesktop
Budget"H-0039 reached its 800k token cap"That itemdesktop
StuckThe watchman saw no event for 30 minutes, or the daemon stoppedWhatever was runningdesktop, phone
Learnings4 proposed learnings to approveNothingdaily digest

Where you hear about it

  • In Claude Code. In any session, in any repo, a hook tells Claude what's waiting, so it mentions it. The status line shows the count. Ask "what needs me?" and Claude runs hall inbox.
  • In the terminal app. Your Office sits at the top with a count in the title bar, and the terminal bell rings.
  • On the desktop. A notification on macOS, Linux or Windows. Clicking it opens the item in the terminal app.
  • On your phone. Through ntfy (open source, and you can host it yourself), Telegram or a Slack webhook. A question with options shows them as buttons.
  • A morning digest. One summary of what's waiting, what closed yesterday, and what it used.

Your Workshop sessions are covered too. Claude Code fires a Notification hook when a session needs a permission or has waited for you, and Hallmark files it under the session's item.

hall · your office⚑ 3 waitingexample data
questionH-0043"usage" in #212: billed usage or raw events? [a] billed [b] raw12m
escalatedH-0039rejected 3×: tenant check missing in export query1h 05m
ready?H-0042retries with jitter, 14 tests [r] ready [n] not yet3m
a b answerenter openw open worktrees snooze 1h
# the Claude Code status line
rindahq/platform · H-0041 development · ⚑ 2 need you

How a question travels

  1. The agent asks. hall ask "billed usage or raw events?" --options billed,raw --default billed --wait 4h. Its run ends with the status waiting, and Hallmark saves the session ID.
  2. You're told. The item moves to Your Office and the notifications go out. A reminder repeats every 2 hours until you answer.
  3. You answer anywhere. Tell Claude Code "answer H-0043: billed", run hall answer Q-12 a, press a in the terminal app, or tap the button on your phone.
  4. The agent resumes. The daemon runs claude -p --resume <session> with your answer, so the agent keeps its context. Answered within the hour, most of that context is still cached.
  5. It's on record. The question, the answer and who gave it go in the journal. Decisions worth keeping become learnings in the Library.

If a question has a default and a wait, and nobody answers in time, the agent goes ahead with the default and the journal says so. Escalations never use a default.

# .hallmark.toml (or your user config)
[notify]
desktop     = true
phone       = "ntfy://ntfy.sh/hallmark-7f3k2q"
quiet_hours = "22:00-07:30"   # phone waits, desktop still shows
remind      = "2h"
digest      = "08:30"

[notify.route]
question  = ["desktop", "phone"]
escalated = ["desktop", "phone"]
stuck     = ["desktop", "phone"]
ready     = ["desktop"]
budget    = ["desktop"]
learnings = ["digest"]

Anyone who knows the topic name can read a topic on the public ntfy.sh. Hallmark sends only the item, the question and the options, never code, and generates a random topic. You can also host ntfy yourself.

How Claude knows to use Hallmark

You don't need to mention Hallmark. Four things work together, from most explicit to the one that can't be skipped.

Explicit

/hallmark <request>

A slash command from the plugin's skill. Always starts a new item.

Context

Session start

A SessionStart hook tells Claude whether this worktree belongs to an item, what state it's in, and how to start one. hall init adds the same rule to CLAUDE.md.

Natural language

Skill description

The hallmark skill's description covers starting work, picking up issues and asking about status, so "pick up #212" or "what's in review?" loads it.

Guaranteed

Edit gate

A PreToolUse hook denies the first file edit or commit outside an item's worktree. The denial says exactly what to run, so Claude creates the item and carries on.

# .hallmark.toml
[capture]
mode = "gate"   # gate: edits need an item
                # ask:  Claude asks you first
                # off:  only /hallmark starts items
# added to CLAUDE.md by hall init
## Hallmark
Changes in this repo are tracked with Hallmark.
Start each change with `hall new`, or `hall adopt`
for an existing branch. Never push: work reaches
GitHub only through review. `hall help --json`
lists every command.

Existing worktrees, such as the ones you already have, join with hall adopt, which turns the current branch into an item without moving it.

An item's states

The same journey as states, with the room each one happens in. An item starts in your Claude Code session and ends when its PR opens. You own the states on the left; the review loop on the right runs on its own. Select a state to see who acts, how it moves on and what the journal records.

YOUR SESSION REVIEW LOOP · RUNS ON ITS OWN OUT agent: done? not yet /hallmark ready ready /hallmark drop pass fail changes commit 3rd rejection you decide /hallmark pull-back approve ship command DevelopmentWorkshop Awaiting youYour Office DroppedRecords Room ChecksAssay · test bench ReviewAssay · principal FixingRepair Shop EscalatedYour Office HallmarkedStamping Room ClosedDispatch Dock
you decide agents and scripts on its way out where the replayed item is now

Replay one item

This is one item, H-0042, from first prompt to PR, as the terminal app would show it. Step through it, or select a point on the bar. Use the arrow keys when the controls are focused. The data is an example.

hall · rindahq/platform (1 of 3 repos)daemon ● running
Board
Findings
↑↓ itementer journalf findingsd diffr readyp pull backo open PR/ filterq quit

Usage and budgets

Every model run is measured and recorded in the journal. Each step has its own limits, and you can see totals by item, room, role, model or day. Only four places use a model: the Workshop, the Assay Office's review, the Repair Shop, and a little at the Front Desk. Everything else is a script.

Measured

Every run, every turn

  • Review and fix runs: claude -p --output-format json reports input, output and cache tokens, turns, duration and a cost per model. Hallmark writes all of it to the journal.
  • Your Workshop session: after each turn, the Stop hook reads the new usage from the session transcript, so development counts too.
  • Checks, Post Room, stamping, shipping: scripts, no tokens. Only their time is recorded.
Limited

Caps at four levels

[budget]
daily    = "4M"     # whole review loop
per_item = "800k"   # then it goes to you

[budget.review]
model = "opus";   effort = "high"
max_usd = 3.00      # per run
daily   = "2M"

[budget.fix]
model = "sonnet"; effort = "medium"
max_usd = 1.50

[budget.intake]
model = "haiku"
Reduced

Spend less per item

  • Checks first. A red build never reaches a model.
  • Incremental re-review. From round 2, the reviewer reads only the diff since the last round and the open findings.
  • The right model per role. Opus reviews, Sonnet fixes, Haiku summarises, and scripts handle routing.
  • Effort follows risk. A small diff gets a lighter review; paths marked sensitive in .hallmark/review.md get the deepest.
  • Fewer, larger runs. Each run starts with a fixed context cost, measured below.
LimitSet byWhen it's reached
Per runmax_usd, passed as --max-budget-usd, plus a time limitThe run stops, and the stop is recorded. The item is retried once, then goes to you.
Per itemper_itemThe item goes to Your Office marked "budget", with its spend so far.
Per room, per day[budget.review] dailyThat room closes for the day. Items wait in the Post Room, in order.
Daily totaldailyThe daemon pauses. Your Workshop session isn't blocked; a hook adds a note that the budget is spent.
Claude plan limitYour planWhen Claude reports a rate limit, the daemon pauses until it resets and records the pause.

Measured today

A one-word reply from Haiku through claude -p still loaded 29.7k tokens of context: 21.2k written to cache and 8.5k read from it. That's the fixed cost of any run before it does any work.

This design conversation, on Opus, has made 114 model calls: 18.1M tokens read from cache, 525k written to cache, and 399k output tokens. Long interactive sessions are where most tokens go, which is why the Workshop is metered too.

Costs are API list-price equivalents. They're a stable unit for comparison, not a bill. Claude plans count usage against limits rather than charging per token, and Hallmark can't read how much of your limit is left, so it enforces its own caps.

hall · usage · todayexample data
roomrunstokens≈ $budget
Workshop5 items3.42M41.20not capped
Assay Office91.21M14.80██████░░░░ 61%
Repair Shop60.48M3.10██░░░░░░░░ 24%
Front Desk40.02M0.03—
total5.13M59.13loop 1.71M / 4M
Most expensive items
H-00394 rounds1.40M17.60over item cap · with you
H-00423 rounds0.61M7.30closed · PR #191
b by roomi by itemm by modeld by daye edit budgets

The principal engineer

Yes, it's something you define, once, in the plugin. The role is split into a Claude Code agent (who it is and which tools it may use), a skill (how it reviews), and a schema (the exact shape of its verdict). Each repo can add local knowledge without changing the role.

hallmark plugin
├─ agents/
│  ├─ principal-engineer.md   role, read-only tools, model
│  └─ fixer.md                edits code, can't approve
├─ skills/
│  ├─ hallmark/               your session: new, ready, status
│  ├─ principal-review/       lenses, severity, evidence rules
│  └─ hallmark-fix/           address findings, dispute with reason
├─ schemas/verdict.json       enforced output shape
└─ hooks/hooks.json           every hook calls: hall hook <event>

your repo
└─ .hallmark/review.md        local knowledge, read from base
---
name: principal-engineer
description: Independent reviewer for Hallmark
  items. Reviews one frozen commit against its
  base branch and never edits code.
tools: Read, Grep, Glob, Bash(git diff:*),
  Bash(git log:*), Bash(git show:*), Bash(hall log:*),
  Bash(hall library search:*)
model: opus
---
You are a principal engineer reviewing a change
you did not write. Use the principal-review skill.
Report only what you can show breaks, with the
scenario. Approve when nothing blocks.

The daemon runs it headless with a fresh context. --json-schema makes Claude Code return a verdict that always matches the schema, so the daemon never has to parse prose.

claude -p --plugin-dir "$HALLMARK_PLUGIN" --agent principal-engineer \
  --json-schema "$HALLMARK_PLUGIN/schemas/verdict.json" --output-format json \
  "Review H-0042 round 2: commit b81f3e4 against main"

This is a sketch; the exact flags will be checked when it's built. Everything the reviewer reads comes from the base branch, so a change can't edit its own review rules.

The Library: what the principal engineer remembers

Each review starts with a fresh context on purpose. A long-lived reviewer would carry the biases of earlier reviews, and its growing context would be re-read on every call; this conversation alone has read 18M tokens from cache. Instead, the reviewer starts clean and gets a short briefing from the Library, a growing body of what reviews of this repository have taught. Fresh eyes, long memory.

How it learns

  1. An item closes or escalates. Its journal holds what the reviewer found, what was disputed and how it was settled, and your decisions with reasons.
  2. The librarian distils it. A small Haiku run turns the journal into proposed learnings. It updates existing entries rather than adding duplicates. Each costs a few thousand tokens.
  3. You approve the learnings. Proposed learnings wait in your inbox until you accept or reject them with hall library review. They live in a local store next to the journal, never in the repository, so no branch can change what its review is told.
  4. The reviewer is briefed. Before each review, Hallmark picks the learnings scoped to the changed paths and searches the rest using the diff. It sends the best of them within a set token limit.
  5. Learnings earn their place. Each verdict says which learnings it used and whether they held. Contradicted or unused ones are retired.

What a learning looks like

---
id: L-0017
kind: rule      # rule · false-positive · map · decision
scope: ["apps/api/src/webhooks/**"]
lens: correctness
source: [H-0042/F1]
status: accepted
used: 4         # reviews it informed
last_used: 2026-10-09
---
A retry must check that the endpoint still exists
before each attempt. A deleted endpoint keeps its
queued deliveries until the job notices.
  • Rules come from findings that turned out right.
  • False positives record what not to flag, and why. They cut repeat noise and wasted fix rounds.
  • Maps describe what a module does, so the reviewer stops re-exploring the same code. That saves tokens on every review.
  • Decisions are your rulings on escalations, with your reasons.
Records (the journal)Library (learnings)
HoldsWhat happenedWhat it taught
Source of truthAppend-only JSONL in .git/hallmark/. Local and private, since it includes your prompts; never committedMarkdown in .hallmark/knowledge/. Committed, reviewed, and read from the base branch
IndexSQLite, rebuilt from the files at any time with hall reindexBuilt-in SQLite full-text search, or qmd for hybrid semantic search when it's installed
QuestionsExact: by item, state, lens, room or dateFuzzy: "what do we know about retries in webhooks?"
Per repositoryOne journal per repoOne knowledge folder per repo, and one qmd collection per repo, hallmark-<repo>
Vectors?No. Every question has an exact answerHelpful once wording drifts from the code. Path scopes and keyword search cover a young library

Where qmd fits

qmd is a local search engine for Markdown, built for agents. It combines keyword search, vector search and reranking, with local models stored in SQLite. It has a JSON command line and an MCP server, and it's MIT-licensed. The Library is a folder of Markdown files, so qmd fits it without changes. It also runs locally, so searching the Library costs no Claude tokens.

It brings a Node 22 or Bun runtime, about 2 GB of local models, and on macOS a Homebrew SQLite. That's a lot to require of every install, so Hallmark makes it an option. Built-in search works everywhere; hall init offers qmd when it finds it. Hallmark always queries a single collection, because qmd ranks results from several collections in one shared pool.

# .hallmark.toml
[library]
search         = "qmd"     # or "builtin"
collection     = "hallmark-platform"
briefing_limit = "6k"      # tokens sent to each review
auto_accept    = ["map"]   # kinds that skip your approval
retire_after   = "90d"     # unused learnings
$ hall library search "webhook retries" --json
{"results": [{"id": "L-0017", "kind": "rule",
  "scope": ["apps/api/src/webhooks/**"],
  "score": 0.91, "used": 4}]}

CLAUDE.md stays for rules that are always true, because Claude reads it in full on every run. Situational knowledge belongs in the Library, where only the relevant entries are sent.

Built for agents

Agents are the main users of hall, so the command line is an API. These rules hold for every command.

  • JSON when it isn't a terminal. --json forces it; readable text appears only on a terminal.
  • Never prompts. Anything destructive needs an explicit flag, such as --reason.
  • Safe to repeat. Running hall ready twice returns the same review, not an error.
  • Says what to do next. Every reply has a next list of commands that make sense now.
  • Errors are data. A stable code, a message and next, plus a documented exit code.
  • Describes itself. hall help --json lists commands; hall schema <command> gives the output shape.
  • Knows where it is. Inside an item's worktree the ID is optional.
  • One worker per item. hall next --role fixer claims work with a lease, so two agents never take the same item.
$ hall ready
{"error": {
   "code": "ITEM_IN_REVIEW",
   "message": "H-0042 is in review, round 2.",
   "next": ["hall pull-back H-0042",
            "hall log H-0042 --kind review"]}}
$ echo $?
4
ExitMeaning
0Done
2Bad arguments
3No such item
4Not allowed in the item's current state
5Denied by the gate
6Checks failed
7Claimed by another agent

Commands

CommandUsed byDoes
Start and decide
hallyouOpens the terminal app
hall new "<request>"you, your sessionCreates an item and its worktree. --issue 212 starts from a GitHub issue; --open opens Claude in the worktree
hall adoptyou, your sessionTurns the current branch and worktree into an item
hall readyyou, your sessionFreezes the commit and sends the item to review
hall pull-backyouStops review and returns the item to development
hall drop --reasonyouAbandons the item and keeps its journal
hall inboxyou, your sessionEverything waiting for you, oldest first
hall answer <q>you, your sessionAnswers a question; the asking agent resumes its session
See
hall statusyou, any agentItems by state, or one item in detail
hall log <id>you, any agentThe item's journal. --kind review filters it
hall historyyouClosed and dropped items. --rejected, --lens, --since
hall usageyou, any agentTokens and cost. --by room|item|role|model|day, --since
hall budgetyouShows or sets the caps in [budget]
hall library searchyou, any agentSearches the repo's learnings. Built-in search, or qmd when configured
hall library reviewyouApproves or rejects proposed learnings
hall library retire <id>you, librarianRetires a learning, keeping its history
hall export <id>you, shipperThe whole record as Markdown
Agents
hall propose-readydev agentSays the work looks done, with a summary. Moves the item to Awaiting you
hall askany agentAsks you a question with options, an optional default and a wait. Parks the item
hall next --roleassayer, fixerClaims the next piece of work for that role
hall findingsfixerOpen findings and failing checks for the claimed item
hall fixed <ids>fixerRecords which findings a commit addresses, or disputes one with --dispute
hall verdictassayerRecords a schema-checked verdict
Machinery and setup
hall hook <event>Claude Code hooksJournal entries, session context and the gate
hall daemonyou, oncestart, stop, status. Runs the checks, review, fixer, shipper and watchman
hall setup claudeyou, onceInstalls the Claude Code plugin
hall inityou, per repoWrites .hallmark.toml from what it detects
hall notify testyou, onceSends a test notification to every channel you configured
hall doctoryou, agentsChecks the install and names the fix for each problem
hall help --json · hall schemaagentsCommand list and output shapes

The terminal app

One Rust binary, hall, does everything. Run it with no arguments and it opens the terminal app, the human view of everything above. The subcommands are what agents, hooks and the daemon call. Because the hooks call the binary rather than shell scripts, it runs the same on macOS, Linux and Windows.

The app only reads the journal. Closing it never stops work; the loops run in hall daemon. Opening it on another terminal, or after a restart, shows the same state.

Views
  • Board. Items by state, with ones that need you flagged at the top.
  • Journal. The selected item's full history, newest at the bottom, with a scrubber to replay it as above.
  • Findings. Every finding with its lens, severity, file and line, the commit that claims to fix it and the review that verified it.
  • History. Closed and dropped items, filterable by outcome, lens or rejection reason. It answers "what got rejected this week, and why".
  • Live. The output of whatever the daemon is running now: a test run, or the reviewer's progress.
  • Usage. Tokens and API-equivalent cost by room, item, model or day, against your budgets.
  • Repos. Every repository on this machine that uses Hallmark, with counts of items needing you. tab switches between them.
Keys
↑ ↓select an item enteropen its journal ← →step through the journal ffindings for this item ddiff at the selected round rsend to review (same as /hallmark ready) ppull back to development xdrop, with a reason wopen the item's worktree oopen the PR hhistory view /filter uusage view tabnext repository
Built with
  • ratatui and crossterm for the interface. crossterm drives Windows consoles as well as Unix terminals.
  • notify to redraw when a journal file changes.
  • clap for subcommands, serde_json for the journal, fs4 for file locks.
  • cargo-dist to release binaries for all three systems, with Homebrew, an install script and a Nix flake.

The journal

Each item has an append-only file of events. Nothing is edited or deleted, so the history you read is the history that happened. Hooks write your session's events and the daemon writes the loop's. Every write goes through hall, which holds a file lock.

.git/hallmark/                  shared by every worktree
├─ items/H-0042/
│  ├─ item.json              title, branch, state
│  ├─ events.jsonl           the journal
│  ├─ reviews/r1.md          full review reports
│  └─ checks/r1.log          failing check output
└─ queue/                    tickets waiting for the assayer

A SQLite index, rebuilt from these files at any time, answers usage and history questions quickly. The journal lives in each repo's git directory, so it outlives worktrees and is never committed. A small registry in your user state directory lists which repos use Hallmark, so the terminal app can show them all. hall export H-0042 writes the whole record as Markdown, and the PR body links to it.

Three lines from H-0042
{"t":"10:04:12","actor":"you","event":"ready",
 "sha":"7c2d018","note":"cap at 6 attempts done"}
{"t":"10:24:31","actor":"assayer","event":"review",
 "round":2,"sha":"b81f3e4","verdict":"changes",
 "findings":["F1","F2"],"report":"reviews/r2.md"}
{"t":"10:38:05","actor":"fixer","event":"commit",
 "sha":"2a9e771","fixes":["F1","F2"]}
What gets recorded
  • Your prompts and the agent's turn summaries, through Claude Code hooks
  • Every commit, and which findings it claims to fix
  • Every check run, with exit code, duration and failing output
  • Every verdict, with each finding's lens, severity, file, line and scenario
  • Every decision you make, with your reason
  • The hallmark, the PR link and the time spent in each state

The pieces

PieceWhat it doesDefined in
hallmark skillYour session's side: /hallmark, starting from an issue, ready, pull-back, status and "why was it rejected".skills/hallmark/
Session hooksTie the session to its item, add item context at start, record prompts, turns and commits, and gate edits and pushes.hooks/hooks.json → hall hook
AssayerRuns the gates at the frozen commit, then the principal-engineer agent with the principal-review skill.agents/principal-engineer.md
FixerAddresses open findings or failing checks in the item's worktree, commits and resubmits. It can dispute a finding, with a reason, but can't approve.agents/fixer.md
LibrarianDistils closed items into learnings, proposes them for your approval, and briefs each review from the Library.hall daemon → claude -p --model haiku
WatchmanFlags items with no new event for 30 minutes, and a daemon that stopped. The idea comes from Gas Town's Witness.hall daemon
ShipperChecks the hallmark, runs the ship command, writes the review summary and minor findings into the PR, links the issue, and closes the item.hall daemon
Terminal appBoard, journal, findings, history, live and repos views.hall

How the assayer reviews

Every review covers the same seven lenses. Each finding names its lens, a file and line, a severity, and the concrete case that breaks.

LensAsksTypical blocker
First principlesIs this the simplest change that solves the task? Does it belong in this layer?Patches a symptom; duplicates an existing mechanism
CorrectnessEdge cases, error paths, concurrency, idempotency, retriesA retry double-charges; two writers race
Security & tenancyAuthorization on every path, tenant isolation, secrets, injectionA query bypasses RLS; a secret in a log line
Data & migrationsIs the migration reversible and safe on live data?A locking ALTER on a hot table
EvidenceDo the tests prove the behaviour? Did the test count drop?A test asserts its own mock; a suite stopped compiling
OperabilityCan someone on call see it fail and recover?A swallowed error on a billing path
Repo rulesThe repo's CLAUDE.md or AGENTS.md and any rule files it listsBreaks a convention the repo wrote down
blockermajorminornit approve = 0 blockers and 0 majors

Rules come from main

The assayer loads its skill and lenses from the base branch, never from the branch under review, so a branch can't soften its own review.

Approval is bound to a commit

The hallmark is a git note on one SHA. Any later commit has none, so the gate blocks it until it is reviewed again.

A script decides when to stop

Loops end when the hallmark exists or the round limit is reached, never because an agent printed "done".

What exists already

Several tools cover parts of this. None follows one item from its first prompt to its PR with an independent reviewer and a complete record. Here is what Hallmark borrows from each and where it goes further.

ToolWhat it isBorrowHallmark goes further
Claude SquadGo · AGPLTerminal app that runs many agents, each in its own worktree and tmux session, with a review before you pushA session list with a live preview pane; sessions that survive closing the terminalAn independent reviewer, fixed checks and a journal. Runs on Windows; Claude Squad runs on macOS and Linux.
Vibe Kanbanweb · community-maintained since April 2026Kanban board for agent tasks with a worktree per task and inline diff comments sent back to the agentColumns by state; feedback goes straight to the agent that will act on itTerminal-native. The reviewer is an agent, and your decision sits at "ready", not on every diff.
Gas TownSteve YeggeOrchestrator for 20–30 agents. A Refinery runs a merge queue with verification gates, Beads keeps state in git, and a Witness spots stuck agentsState in git; items that outlive the sessions working on them; a watch for stuck workFar smaller: a review line for work you start yourself, sized for one Claude plan rather than heavy API spend.
Ralph OrchestratorRust · MITLoop runner with "hats" (personas, including review) on an event bus, gates such as tests and lint, and an event historyAssayer and fixer as hats; checks before the model; the event historyIt stops when the agent prints a completion signal; Hallmark stops on a hallmark check. Adds your ready step.
CodeRabbit CLIpaid creditsLocal pre-PR review with JSON output meant for agentsFindings as structured data an agent can act onUses your Claude plan and your repo's rules, and binds approval to a commit.
githumanA review checkpoint at the staging area, with a handoff from you back to the agentThe explicit human handoffThe handoff is one step in a recorded lifecycle rather than the whole tool.

Before building

Why it's worth it

  • Parallel agents in many worktrees, across many repos, get one place to be seen.
  • It uses your Claude plan and your choice of model, with no API tokens and no Copilot seat.
  • The journal answers questions that are hard now: why something was rejected, what changed between rounds, how long review takes.

What to watch

  • Same model, same blind spots. Fixed lenses and checks help, but keep the final merge on GitHub with you.
  • Shared state. Test runs often share caches, coverage files and ports, so each repo's assayer takes one ticket at a time. Separate repos can run in parallel.
  • Usage. Every round is a test run plus a long review against your plan's limits. Three rejected reviews send the item to you.
  • The journal records your prompts. It stays in .git/hallmark/ on your machine and is exported only when you ask.

Works in any repository

Hallmark assumes only git and Claude Code. Everything specific to a project lives in one optional file at the repo root, and hall init writes a first version of it by looking at the repo.

Install once

The binary, the /hallmark and principal-review skills and the hooks ship as one Claude Code plugin. Hooks are installed at user level, so every repo and every session gets them.

hall init

Detects the stack and proposes the gates: package.json scripts, cargo test and clippy, go test and go vet, pytest, a Makefile, or a justfile. It also finds CLAUDE.md or AGENTS.md for the repo-rules lens.

Sensible defaults

With no config, worktrees use git worktree add, shipping uses git push and gh pr create, and the review uses all seven lenses. A repo on GitLab sets the ship command to glab mr create.

Defaults, used when a key is missing
# .hallmark.toml
base         = "main"
worktree     = "git worktree add ../{repo}-{id} -b {branch}"
ship         = "git push -u origin {branch} && gh pr create --fill"
gates        = []                  # hall init fills these
reviewer     = "claude -p"
max_rejects  = 3
stuck_after  = "30m"
lenses       = "all"
rules        = ["CLAUDE.md", "AGENTS.md"]

[budget]                           # no caps unless you set them
review_model = "opus"
fix_model    = "sonnet"
Example override: rindahq/platform
# .hallmark.toml
worktree = "rig wt new {branch}"
ship     = "rig submit --pr"
gates    = ["rig test", "rig run build"]
rules    = ["CLAUDE.md",
            "docs/plan/README.md#leave-alone"]

Every command is a setting, so a repo can use its own tooling without Hallmark knowing about it. The reviewer and fixer commands are settings too. Claude Code comes first because its hooks and skills make the session part of the record.

Build order

Stage 1

Journal and hooks

The hall binary with the agent contract, setup claude, init, doctor, items, the journal, the hallmark skill, the session hooks and the gate. Everything you do is recorded from day one.

Stage 2

The review loop

The daemon, the principal-engineer and fixer agents with their skills and verdict schema, hallmarks, pull-back and issue linking, then the Library with built-in search and the librarian.

Stage 3

Terminal app and plugin

The board, journal, findings, history, usage and live views, qmd as an optional Library search, then packaging as a plugin with cargo-dist releases for macOS, Linux and Windows.