Review that isn't self‑assessment
A separate principal-engineer agent reviews a frozen commit against your base branch, headless, with fresh context. It never edits code, so it has no stake in what it's grading.
Agentic development · automated review · a full record
A local review loop for Claude Code. Agents build your change, an independent principal‑engineer agent reviews the exact commit, a fixer repairs what it finds, and only work that earns a hallmark leaves your machine. You step in only when a decision is truly yours.
$ hall log H-0042H-0042 Retry failed webhook deliveries 10:02 you prompt "retry failed deliveries"10:31 dev commit 7c2d018 retries, 14 tests10:32 you ready round 1, sha frozen10:33 assayer checks ✓ fmt ✓ lint ✓ test10:36 principal verdict changes requested major correctness · retry.rs:48 a 410 is retried forever: the loop has no cap10:41 fixer commit a19be3e cap at 6, stop on 4xx10:42 assayer checks ✓ all gates10:44 principal verdict approved · read the delta10:44 ⚒ hallmark struck on a19be3e10:45 shipper PR #318 opened 2 rounds · 1 finding fixed · 0 interruptions
The problem
A coding agent can produce a change in minutes. Deciding whether that change should ship is still on you, and it has quietly become the slowest, most draining part of the job.
The agent that wrote the code is the one telling you it works. Same context, same blind spots, grading its own homework.
Run the tests, paste the failure back, re-prompt, re-read the whole diff, repeat. The agent waits on you, and you wait on the agent.
Prompts, rejected attempts and decisions vanish with the session. Weeks later, nobody can say why the code looks the way it does.
An agent that keeps trying keeps spending. A red build can burn review tokens, and the bill is a surprise at the end of the month.
More agents don't fix this. They make it worse: every extra agent is another stream of diffs waiting on the same person.
The shift
Hallmark turns "the agent says it's done" into a loop that holds up, so your day stops revolving around someone else's diffs.
How it works
You start work and say when it's ready. Between that moment and a pull request, a script, not an agent, decides when to stop: the loop ends when a hallmark exists or the round limit is reached, never because a model printed "done".
A prompt, a GitHub issue or an existing branch becomes H-0042, with its own branch and worktree.
You and the dev agent iterate in Claude Code. Hooks record every prompt, turn and commit.
The commit is frozen and your tests, lint and build run first. A red build never spends review tokens.
Seven lenses, fresh context, your repo's rules. It reports only what it can show is broken.
Addresses findings or disputes them with a reason, and goes back to checks. Re-reviews read only what changed.
Rebased onto the latest base, stamped, and opened as a PR, then watched until it merges.
What changes for you
Agents do the building, the checking and the fixing. You keep the decisions that need judgement, and a record that lets you trust the rest.
A separate principal-engineer agent reviews a frozen commit against your base branch, headless, with fresh context. It never edits code, so it has no stake in what it's grading.
The approval is a git note on that exact SHA. A push gate in Claude Code blocks anything without one, so "approved" can't drift from what actually ships.
Failing checks and findings go to a fixer and back to review until the commit is approved. Three rejections escalate to you, with the evidence attached. Independent parts of a larger request run as parallel items.
Questions, escalations and holds land in your office, and reach you in Claude Code, the terminal app, the desktop or your phone. Only that item waits. The rest of the building keeps working.
Every model run is measured. Caps per run, per item, per role and per day stop the loop before it runs away, and checks run before any review tokens are spent.
Every prompt, commit, check, verdict, fix and decision is appended to a journal. See what was rejected, what was fixed and why, and export any item as Markdown.
When an item closes, the Library keeps what it taught and briefs the principal engineer before the next review. The same mistake gets cheaper to catch.
Gates, worktree and ship commands come from .hallmark.toml, with defaults for plain git and gh. Gates can run inside nix develop, devbox, mise or direnv.
No server, no account. Model runs go through your own Claude Code. The journal lives in your git directory and is never committed, because it contains your prompts.
The terminal app
Run hall with no arguments and watch work move live: your office, the board, each item's journal and findings, and what the daemon is doing. Closing it never stops work.
Why "Hallmark"
At Goldsmiths' Hall in London, silver was tested and stamped before it could be sold. The stamp didn't say the smith was good. It said this piece had passed. Hallmark works the same way, and is laid out like the building: requests arrive at the Front Desk, get built in the Workshop, tested in the Assay Office, repaired in the Repair Shop, stamped, and sent from the Dispatch Dock.
Built for agents
Ask for a change as usual, or be explicit with /hallmark <request>. A session hook tells Claude whether it's working in an item, and an edit gate makes sure it is.
next, the commands that make sense now.hall schema prints the JSON Schema of any output.$ hall ready H-0042 { "error": { "code": "ITEM_IN_REVIEW", "message": "H-0042 is in review, round 2.", "next": ["hall pull-back H-0042"] } } exit 4
Get started
You need git and Claude Code. gh is used for issues and pull requests by the default ship command.
hallOne Rust binary for macOS, Linux and Windows. Needs Rust 1.88 or newer.
cargo install --git https://github.com/tiagocolombo/hallmark --locked
Installs the Claude Code plugin, detects your gates, starts the review daemon and runs hall doctor. Safe to run again.
cd your-repo hall setup
Restart Claude Code and work as usual. Claude opens an item, builds it with you, and sends it to review when you say it's ready. The daemon takes it from there.
claude > retry failed webhook deliveries
Change budgets later with hall budget --set daily=4M, and every other setting in .hallmark.toml.
Prefer Nix or a prebuilt binary? See the installation guide for every option, upgrading with hall update, and notes for Windows.
Early and moving fast. Hallmark is at 0.1, and the full loop runs today: items and the journal, gates, checks, review, fixes, shipping, delivery tracking, parallel parts, budgets, notifications, the Library and the terminal app. Expect the configuration and CLI to change before 1.0. Every model run goes through claude -p and counts toward your Claude plan or API usage.
Read more
.hallmark.toml key and its default.
DecisionsWhy things are the way they are, one ADR at a time.
ContributingBug reports, docs and code are all welcome.