@openthink/stamp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +429 -0
- package/dist/chunk-TTOMORIY.js +502 -0
- package/dist/chunk-TTOMORIY.js.map +1 -0
- package/dist/hooks/post-receive.cjs +7822 -0
- package/dist/hooks/post-receive.cjs.map +1 -0
- package/dist/hooks/pre-receive.cjs +7890 -0
- package/dist/hooks/pre-receive.cjs.map +1 -0
- package/dist/index.js +5385 -0
- package/dist/index.js.map +1 -0
- package/dist/ui-4V2HDHOS.js +349 -0
- package/dist/ui-4V2HDHOS.js.map +1 -0
- package/package.json +55 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-2026 OpenThinkAi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
# stamp-cli
|
|
2
|
+
|
|
3
|
+
Local, headless pull-request system for agent-to-agent code review workflows.
|
|
4
|
+
|
|
5
|
+
An author-agent opens a diff, reviewer-agents consume it and return structured
|
|
6
|
+
feedback, the author iterates until merge rules are satisfied, and the merge
|
|
7
|
+
is pushed to a remote that cryptographically rejects any push that wasn't
|
|
8
|
+
properly reviewed and signed.
|
|
9
|
+
|
|
10
|
+
**Not a GitHub replacement.** GitHub is for humans collaborating. stamp-cli
|
|
11
|
+
is for agent fleets cycling fast while keeping `main` clean. No web UI, no
|
|
12
|
+
PR dashboard, no human comment threads in core. Just a CLI + a git hook.
|
|
13
|
+
|
|
14
|
+
Part of the [OpenThink](https://openthink.dev) suite.
|
|
15
|
+
|
|
16
|
+
**Docs:** [server quickstart](./docs/quickstart-server.md) (from-zero project on a stamp server) · [DESIGN](./DESIGN.md) (spec) · [ROADMAP](./docs/ROADMAP.md) (what's shipped + what's next) · [personas](./docs/personas.md) (writing reviewer prompts) · [troubleshooting](./docs/troubleshooting.md) · [server](./server/README.md) (Railway deploy)
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
npm install -g @openthink/stamp
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Node 22.5+ required (we use `node:sqlite` and `node:crypto`'s Ed25519 APIs,
|
|
25
|
+
both of which are built-in but gated on 22.5+).
|
|
26
|
+
|
|
27
|
+
Published tarballs carry an SLSA build attestation via npm's Trusted
|
|
28
|
+
Publishing, so you can verify chain-of-custody against the GitHub Actions
|
|
29
|
+
run that produced the release:
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
npm audit signatures
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Quick start
|
|
36
|
+
|
|
37
|
+
**Pick your deployment shape first** — it determines which command you run and
|
|
38
|
+
what guarantees you actually get:
|
|
39
|
+
|
|
40
|
+
| Shape | Origin is… | Enforcement | Command to run |
|
|
41
|
+
|---|---|---|---|
|
|
42
|
+
| **Server-gated** (recommended) | A stamp server you deployed | The server's pre-receive hook rejects any push without a valid stamped merge | `stamp bootstrap` on a clone of a server-provisioned repo |
|
|
43
|
+
| **Local-only** (advisory) | GitHub / GitLab / etc. directly | None — direct `git push origin main` succeeds; the stamp config is documentation + a discipline aid | `stamp init --mode local-only` |
|
|
44
|
+
|
|
45
|
+
These are not interchangeable. Server-gated is the only shape where the gate
|
|
46
|
+
is actually enforced; local-only signs your merges with a verifiable
|
|
47
|
+
attestation but the remote does not reject anything. Pick deliberately.
|
|
48
|
+
|
|
49
|
+
### Server-gated path
|
|
50
|
+
|
|
51
|
+
If you've deployed the stamp server (see [`docs/quickstart-server.md`](./docs/quickstart-server.md)
|
|
52
|
+
for the full Railway walkthrough), the from-zero flow is three commands:
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
ssh stamp new-stamp-repo myproject # provision bare repo + hook
|
|
56
|
+
git clone ssh://stamp/srv/git/myproject.git
|
|
57
|
+
cd myproject && stamp bootstrap # install real reviewers + push
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
`stamp bootstrap` detects the freshly-provisioned placeholder state, scaffolds
|
|
61
|
+
the three starter reviewers (security, standards, product), and lands them on
|
|
62
|
+
`main` via a single signed merge that the server hook accepts. From there it's
|
|
63
|
+
the normal review/merge cycle.
|
|
64
|
+
|
|
65
|
+
### Local-only path
|
|
66
|
+
|
|
67
|
+
When origin is a public forge directly (GitHub etc.), `stamp init` defaults to
|
|
68
|
+
local-only and prints a prominent warning that the gate is unenforced. Pass
|
|
69
|
+
`--mode local-only` to acknowledge explicitly and silence the warning:
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
cd myproject
|
|
73
|
+
stamp init --mode local-only # scaffolds .stamp/ + AGENTS.md (advisory mode)
|
|
74
|
+
git add .stamp AGENTS.md && git commit -m "stamp: advisory config"
|
|
75
|
+
git push origin main
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
You can still run `stamp review` / `stamp merge` / `stamp verify` against this
|
|
79
|
+
repo — the merge commits carry signed attestations and `stamp verify <sha>`
|
|
80
|
+
validates them on any clone. What you don't get: server-side rejection of
|
|
81
|
+
unstamped pushes. Anyone with repo write access can `git push origin main`
|
|
82
|
+
of any commit, stamped or not.
|
|
83
|
+
|
|
84
|
+
### Local-test (no server, on-disk bare repo)
|
|
85
|
+
|
|
86
|
+
Run everything on one machine using a bare git repo on disk as the "remote".
|
|
87
|
+
Useful for learning the shape before deploying a real server.
|
|
88
|
+
|
|
89
|
+
```sh
|
|
90
|
+
# Install + initialize a fresh project
|
|
91
|
+
mkdir myproject && cd myproject
|
|
92
|
+
git init -b main
|
|
93
|
+
stamp init # scaffolds .stamp/ with three starter reviewers
|
|
94
|
+
# (security, standards, product) + keypair in
|
|
95
|
+
# ~/.stamp/keys/. Use --minimal to scaffold a
|
|
96
|
+
# single placeholder reviewer instead.
|
|
97
|
+
|
|
98
|
+
# Commit the scaffolded .stamp/ directory so the reviewers + trusted key are
|
|
99
|
+
# part of the repo's history before you start working.
|
|
100
|
+
git add .stamp && git commit -m "stamp: scaffold starter reviewers"
|
|
101
|
+
|
|
102
|
+
# Provision a bare "remote" with the verify hook
|
|
103
|
+
cd ..
|
|
104
|
+
./node_modules/@openthink/stamp/scripts/setup-repo.sh \
|
|
105
|
+
/tmp/myproject.git \
|
|
106
|
+
./node_modules/@openthink/stamp/dist/hooks/pre-receive.cjs \
|
|
107
|
+
~/.stamp/keys/ed25519.pub
|
|
108
|
+
|
|
109
|
+
# Wire up the remote
|
|
110
|
+
cd myproject
|
|
111
|
+
git remote add origin /tmp/myproject.git
|
|
112
|
+
|
|
113
|
+
# Work:
|
|
114
|
+
git checkout -b feature
|
|
115
|
+
# ...make changes, commit...
|
|
116
|
+
stamp review --diff main..feature # three reviewers run in parallel
|
|
117
|
+
stamp status --diff main..feature # gate status; exit 0 if open, 1 if closed
|
|
118
|
+
git checkout main
|
|
119
|
+
stamp merge feature --into main # signed merge commit
|
|
120
|
+
stamp push main # hook verifies; main advances on remote
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
The scaffolded reviewer prompts are generic starting points. Before relying
|
|
124
|
+
on them for real code review, edit them to match your project's stack,
|
|
125
|
+
conventions, and domain — see [`docs/personas.md`](./docs/personas.md).
|
|
126
|
+
|
|
127
|
+
Any push that isn't a properly signed stamped merge will be rejected by the
|
|
128
|
+
hook with a clear reason.
|
|
129
|
+
|
|
130
|
+
## Concepts
|
|
131
|
+
|
|
132
|
+
- **Reviewer** — a persona defined by a prompt file at
|
|
133
|
+
`.stamp/reviewers/<name>.md`. `stamp init` scaffolds three starter
|
|
134
|
+
reviewers (`security`, `standards`, `product`) calibrated for generic
|
|
135
|
+
TS/JS projects — edit them to fit your codebase. Use `--minimal` for
|
|
136
|
+
a single placeholder instead. Prompts must end with a `VERDICT:
|
|
137
|
+
approved|changes_requested|denied` line.
|
|
138
|
+
- **Verdict** — a reviewer's judgment on a specific diff. Recorded per
|
|
139
|
+
reviewer per `(base_sha, head_sha)` in `.git/stamp/state.db`.
|
|
140
|
+
- **Gate** — for each required reviewer, the latest verdict must be
|
|
141
|
+
`approved`. Config lives at `.stamp/config.yml`.
|
|
142
|
+
- **Attestation** — `stamp merge` signs a payload (base/head/target/approvals)
|
|
143
|
+
with Ed25519 and attaches it as `Stamp-Payload` + `Stamp-Verified`
|
|
144
|
+
commit-message trailers on the merge commit.
|
|
145
|
+
- **Hook** — `stamp-verify` runs server-side on pre-receive. Reads config
|
|
146
|
+
and trusted keys from the target branch's tree at push time, re-runs
|
|
147
|
+
every check the client ran.
|
|
148
|
+
|
|
149
|
+
See [`DESIGN.md`](./DESIGN.md) for the full spec and [`docs/ROADMAP.md`](./docs/ROADMAP.md) for current status + upcoming work.
|
|
150
|
+
|
|
151
|
+
## Commands
|
|
152
|
+
|
|
153
|
+
**Core review cycle:**
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
stamp init [--mode <shape>] # scaffold .stamp/ + keypair; idempotent. Also ensures
|
|
157
|
+
# AGENTS.md at repo root with deployment-shape-aware
|
|
158
|
+
# guidance. --mode is server-gated|local-only;
|
|
159
|
+
# auto-detected from origin if omitted (forge-direct
|
|
160
|
+
# origins default to local-only with a loud warning).
|
|
161
|
+
stamp bootstrap # one-shot: replace placeholder example reviewer
|
|
162
|
+
# with real reviewers on a fresh server-provisioned
|
|
163
|
+
# repo. See `stamp bootstrap --help`.
|
|
164
|
+
stamp review --diff <revspec> # run all configured reviewers in parallel
|
|
165
|
+
stamp review --diff <revspec> --only <name> # run a single reviewer
|
|
166
|
+
stamp status --diff <revspec> # gate check; exit 0 if open, 1 if closed
|
|
167
|
+
stamp merge <branch> --into <target> # run required_checks → sign merge commit
|
|
168
|
+
stamp push <target> # plain git push; hook stderr forwarded
|
|
169
|
+
stamp verify <sha> # verify a merge commit's attestation locally
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**Browsing history:**
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
stamp log # first-parent commit list w/ attestation summary
|
|
176
|
+
stamp log <sha> # drill-down: decoded attestation + review prose
|
|
177
|
+
stamp log --branch <name> # filter by branch
|
|
178
|
+
stamp log --reviews # raw DB-row view of every review invocation
|
|
179
|
+
stamp ui # interactive TUI: list → detail → review prose
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**Managing reviewers (persona development):**
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
stamp reviewers list # configured reviewers + prompt file status
|
|
186
|
+
stamp reviewers add <name> [--no-edit] # scaffold + register; --no-edit skips $EDITOR
|
|
187
|
+
stamp reviewers edit <name> # open existing reviewer's prompt
|
|
188
|
+
stamp reviewers test <name> --diff <revspec> # invoke reviewer w/o recording to DB
|
|
189
|
+
stamp reviewers show <name> [--limit <n>] # verdict history + stats for calibration
|
|
190
|
+
stamp reviewers remove <name> [--delete-file] # de-register; optional rm of .md
|
|
191
|
+
stamp reviewers fetch <name> --from <source@ref> # install + pin from canonical source
|
|
192
|
+
# add --expect-prompt-sha <hex> (or --expect-tools-sha / --expect-mcp-sha)
|
|
193
|
+
# to anchor first-fetch trust against an out-of-band published manifest
|
|
194
|
+
stamp reviewers verify [<name>] # check prompt/tool/mcp against lock; exit 3 on drift
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Key management:**
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
stamp keys generate # create ~/.stamp/keys/ed25519{,.pub}
|
|
201
|
+
stamp keys list # local + trusted keys in this repo
|
|
202
|
+
stamp keys export # print your public key
|
|
203
|
+
stamp keys trust <pub-file> # deposit a key into .stamp/trusted-keys/
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Maintenance:**
|
|
207
|
+
|
|
208
|
+
```
|
|
209
|
+
stamp update # upgrade stamp to the latest npm release
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Configuration
|
|
213
|
+
|
|
214
|
+
`.stamp/config.yml`:
|
|
215
|
+
|
|
216
|
+
```yaml
|
|
217
|
+
branches:
|
|
218
|
+
main:
|
|
219
|
+
required: [security, standards, product] # reviewers that must approve
|
|
220
|
+
required_checks: # mechanical checks run pre-merge
|
|
221
|
+
- name: build
|
|
222
|
+
run: npm run build
|
|
223
|
+
- name: typecheck
|
|
224
|
+
run: npx tsc --noEmit
|
|
225
|
+
develop:
|
|
226
|
+
required: [security]
|
|
227
|
+
|
|
228
|
+
reviewers:
|
|
229
|
+
security: { prompt: .stamp/reviewers/security.md }
|
|
230
|
+
standards: { prompt: .stamp/reviewers/standards.md }
|
|
231
|
+
product: { prompt: .stamp/reviewers/product.md }
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Reviewer names are arbitrary — pick whatever matches your team's review
|
|
235
|
+
dimensions. The prompt file is the reviewer's full system prompt; the only
|
|
236
|
+
contract is that it must end with a `VERDICT:` line. See
|
|
237
|
+
[`docs/personas.md`](./docs/personas.md) for how to write good reviewer prompts.
|
|
238
|
+
|
|
239
|
+
`required_checks` run on the **post-merge tree** before the commit is signed.
|
|
240
|
+
Any non-zero exit blocks the merge and rolls it back. Results are attested
|
|
241
|
+
into the commit's signed payload; the server hook verifies that attestation
|
|
242
|
+
matches the committed config.
|
|
243
|
+
|
|
244
|
+
> **Security note.** `required_checks[].run` values execute as shell commands
|
|
245
|
+
> on the merger's machine via `spawnSync(cmd, { shell: true })`. Anyone who
|
|
246
|
+
> can land a PR that touches `.stamp/config.yml` can introduce arbitrary
|
|
247
|
+
> code that will run on the next person to call `stamp merge`. The mitigation
|
|
248
|
+
> is the reviewer gate itself: `.stamp/config.yml` changes go through the
|
|
249
|
+
> same reviewers as any other code change, and your security reviewer prompt
|
|
250
|
+
> should treat `required_checks` edits as high-scrutiny. Unlike GitHub
|
|
251
|
+
> Actions, these commands are **not** sandboxed. See
|
|
252
|
+
> [`DESIGN.md`](./DESIGN.md#security-model) for the full threat model.
|
|
253
|
+
|
|
254
|
+
Optional: `.stamp/mirror.yml` enables GitHub mirroring via the post-receive
|
|
255
|
+
hook. See [`server/README.md`](./server/README.md).
|
|
256
|
+
|
|
257
|
+
## Deployment shapes
|
|
258
|
+
|
|
259
|
+
Three ways to run stamp-cli in a real setting, trading setup cost for
|
|
260
|
+
enforcement strength. Pick based on whether your remote can run a
|
|
261
|
+
pre-receive hook — GitHub can't, so the choice matters.
|
|
262
|
+
|
|
263
|
+
**1. Self-hosted remote — full enforcement (recommended).**
|
|
264
|
+
A server you control runs `git + sshd` with stamp-cli's pre-receive
|
|
265
|
+
hook installed. Every push is rejected at the server if it isn't a
|
|
266
|
+
properly signed stamped merge, so author-agents can't bypass the gate
|
|
267
|
+
even with working credentials.
|
|
268
|
+
Easiest path: deploy `server/Dockerfile` to Railway, Fly, or any
|
|
269
|
+
container host — see [`server/README.md`](./server/README.md) for the
|
|
270
|
+
Railway walkthrough. Minimalist alternative: any Linux host with `git +
|
|
271
|
+
sshd + Node 22.5+` — create a bare repo, drop
|
|
272
|
+
`dist/hooks/pre-receive.cjs` into `hooks/pre-receive` (chmod +x), done.
|
|
273
|
+
The hook is self-contained.
|
|
274
|
+
|
|
275
|
+
**2. Self-hosted remote + GitHub mirror — full enforcement + GitHub ecosystem.**
|
|
276
|
+
Run the stamp server as source-of-truth; commit `.stamp/mirror.yml` to
|
|
277
|
+
mirror verified commits to a GitHub repo via the post-receive hook.
|
|
278
|
+
Deploy pipelines (Actions, Vercel, Netlify) integrate with the GitHub
|
|
279
|
+
copy. GitHub branch protection restricts pushes on the mirror to the
|
|
280
|
+
bot identity, so the only way anything lands on GitHub's `main` is via
|
|
281
|
+
a verified push through your stamp server. Humans can still fork/PR on
|
|
282
|
+
GitHub, but those PRs can't merge. See
|
|
283
|
+
[`server/README.md`](./server/README.md)'s GitHub mirror section.
|
|
284
|
+
|
|
285
|
+
**3. Local-only — weakest enforcement, lowest setup.**
|
|
286
|
+
Skip the server entirely. stamp-cli still produces signed merge commits
|
|
287
|
+
locally, and `stamp verify <sha>` validates them anywhere — but anyone
|
|
288
|
+
with push access to your remote (e.g. GitHub `main` without branch
|
|
289
|
+
protection, or with protection that doesn't require the hook) can
|
|
290
|
+
bypass the gate. You get the attestation audit trail without running
|
|
291
|
+
infrastructure. Suitable for solo use or small trusted teams.
|
|
292
|
+
|
|
293
|
+
## For agent authors
|
|
294
|
+
|
|
295
|
+
stamp-cli is designed for agents as the primary user. What that means in
|
|
296
|
+
practice:
|
|
297
|
+
|
|
298
|
+
- **Output is prose**, not JSON. LLMs read prose natively. No `--json` flag.
|
|
299
|
+
- **Control flow is exit codes.** Agent loops branch on them.
|
|
300
|
+
- **State is files.** `.stamp/config.yml`, `.git/stamp/state.db` (chmoded
|
|
301
|
+
`0600`; parent `.git/stamp/` chmoded `0700`), git commit trailers. Easy
|
|
302
|
+
to inspect, hard to lose. To bound retention on long-lived repos, run
|
|
303
|
+
`stamp prune --older-than 30d` (use `--dry-run` first to preview).
|
|
304
|
+
- **Operations are idempotent.** `stamp init` is safe to re-run. `stamp
|
|
305
|
+
review` accumulates history; re-invoking doesn't corrupt anything.
|
|
306
|
+
|
|
307
|
+
The canonical unattended loop:
|
|
308
|
+
|
|
309
|
+
```sh
|
|
310
|
+
while :; do
|
|
311
|
+
stamp review --diff main..$BRANCH
|
|
312
|
+
if stamp status --diff main..$BRANCH; then
|
|
313
|
+
git checkout main
|
|
314
|
+
stamp merge "$BRANCH" --into main
|
|
315
|
+
stamp push main
|
|
316
|
+
break
|
|
317
|
+
fi
|
|
318
|
+
# author-agent reads review output, patches code, commits, loops
|
|
319
|
+
done
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
**Exit-code cheat sheet:**
|
|
323
|
+
|
|
324
|
+
| Command | 0 | non-zero (check stderr to disambiguate) |
|
|
325
|
+
|---|---|---|
|
|
326
|
+
| `stamp review` | reviewers ran and recorded | invocation failed (reviewer crash, DB error) — verdict may or may not be approved; always follow with `stamp status` to check the gate |
|
|
327
|
+
| `stamp status` | gate open (all required reviewers approved) | gate closed — at least one required reviewer missing or non-approved |
|
|
328
|
+
| `stamp merge` | merge signed, on main | stderr says which case: `gate CLOSED:` (need reviews), `pre-merge checks failed:` (merge rolled back, need fix), or a git-merge conflict message (working tree needs resolution) |
|
|
329
|
+
| `stamp push` | remote accepted | stderr has `remote: stamp-verify: rejecting ...` for hook rejections, or a standard git error for network/auth issues |
|
|
330
|
+
| `stamp verify` | attestation valid | stderr names the specific verification step that failed (signature invalid, untrusted signer, SHA mismatch, missing check, etc.) |
|
|
331
|
+
|
|
332
|
+
Distinct exit codes per failure mode are on the roadmap — for now, agents should regex on the stderr markers above to disambiguate.
|
|
333
|
+
|
|
334
|
+
**Tuning reviewer prompts.** Use `stamp reviewers test <name> --diff <revspec>`
|
|
335
|
+
when iterating on a prompt — it invokes the reviewer against a diff **without
|
|
336
|
+
recording to the DB**, so you can tweak the prompt, retest, and not pollute
|
|
337
|
+
history. Pattern:
|
|
338
|
+
|
|
339
|
+
```sh
|
|
340
|
+
$EDITOR .stamp/reviewers/my-reviewer.md
|
|
341
|
+
stamp reviewers test my-reviewer --diff main..test-violations
|
|
342
|
+
# read output, adjust prompt, repeat
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
See [`docs/personas.md`](./docs/personas.md) for reviewer-prompt guidance and
|
|
346
|
+
[`docs/troubleshooting.md`](./docs/troubleshooting.md) for common failures
|
|
347
|
+
with concrete fixes.
|
|
348
|
+
|
|
349
|
+
## Data flow / privacy
|
|
350
|
+
|
|
351
|
+
stamp-cli runs reviewers by sending the diff to Anthropic. Operators
|
|
352
|
+
working with sensitive content should know the data-flow contract before
|
|
353
|
+
running their first `stamp review`.
|
|
354
|
+
|
|
355
|
+
**What gets sent to Anthropic on every `stamp review`:**
|
|
356
|
+
|
|
357
|
+
- The full unified diff between `base_sha` and `head_sha`, including all
|
|
358
|
+
added and removed lines, comments, fixtures, and any strings or
|
|
359
|
+
credentials present in the changeset.
|
|
360
|
+
- The reviewer's prompt file (read from the merge-base tree).
|
|
361
|
+
- The configured tool allowlist + MCP server names for that reviewer.
|
|
362
|
+
|
|
363
|
+
**What stays local:**
|
|
364
|
+
|
|
365
|
+
- Reviewer prose, verdicts, and tool-call traces are persisted to
|
|
366
|
+
`.git/stamp/state.db` (a sqlite file under the repo's git common
|
|
367
|
+
dir; per-machine, not committed, not pushed). The DB is chmoded
|
|
368
|
+
`0600` and its parent directory `0700` on every open so peer users
|
|
369
|
+
on shared/dev machines can't read review prose. To bound retention
|
|
370
|
+
— long-lived repos accumulate every review's verbatim model output
|
|
371
|
+
indefinitely — use `stamp prune --older-than <duration>`
|
|
372
|
+
(e.g. `stamp prune --older-than 30d`; `--dry-run` previews without
|
|
373
|
+
deleting).
|
|
374
|
+
- Your Ed25519 signing key (`~/.stamp/keys/`) never leaves your machine.
|
|
375
|
+
|
|
376
|
+
**What gets attached to the merge commit and mirrored to GitHub:**
|
|
377
|
+
|
|
378
|
+
- The signed `Stamp-Payload` trailer carrying approvals, base/head
|
|
379
|
+
SHAs, signer key fingerprint, and a tool-call audit trace (tool
|
|
380
|
+
names + input hashes — not the diff content itself).
|
|
381
|
+
|
|
382
|
+
**Disclosure on first run.** The first `stamp review` in a repo prints
|
|
383
|
+
a short note (to stderr) pointing at this section. The notice is
|
|
384
|
+
recorded under `.git/stamp/llm-notice-shown` and not repeated. To
|
|
385
|
+
suppress it unconditionally — agent loops, CI workers, environments
|
|
386
|
+
where the disclosure has already been baked into team docs — set
|
|
387
|
+
`STAMP_SUPPRESS_LLM_NOTICE=1`.
|
|
388
|
+
|
|
389
|
+
**Anthropic's data handling.** Reviewer calls go through the Claude
|
|
390
|
+
Agent SDK, which inherits whatever auth + retention posture you have
|
|
391
|
+
configured for Claude Code on your machine (Anthropic API key, Zero
|
|
392
|
+
Data Retention contract, etc.). See Anthropic's
|
|
393
|
+
[privacy policy](https://www.anthropic.com/privacy) and
|
|
394
|
+
[usage policy](https://www.anthropic.com/legal/aup) for the
|
|
395
|
+
authoritative terms; configure accordingly before running stamp on
|
|
396
|
+
content you're not free to share.
|
|
397
|
+
|
|
398
|
+
## Security model
|
|
399
|
+
|
|
400
|
+
**What this protects against.** Author-agents cannot merge unreviewed code,
|
|
401
|
+
cannot forge merges (the signing key isn't on disk anywhere they can
|
|
402
|
+
exfiltrate without the operator's explicit consent), and cannot bypass the
|
|
403
|
+
remote's verification.
|
|
404
|
+
|
|
405
|
+
**What this doesn't protect against.** You, the human holding the signing
|
|
406
|
+
key, can still produce a valid signed merge for arbitrary content. That's
|
|
407
|
+
inherent to any local-first system. What signing gives you is
|
|
408
|
+
**non-repudiation** — every merge on `main` is permanently attributed to a
|
|
409
|
+
specific key's owner, provable from git history alone. For the
|
|
410
|
+
agent-can't-bypass threat model this is exactly right.
|
|
411
|
+
|
|
412
|
+
See [`DESIGN.md`](./DESIGN.md) for the full bootstrap, key-management, and
|
|
413
|
+
verification-rule details, including the security model around user-configured
|
|
414
|
+
pre-merge checks.
|
|
415
|
+
|
|
416
|
+
## License
|
|
417
|
+
|
|
418
|
+
stamp-cli itself is MIT-licensed.
|
|
419
|
+
|
|
420
|
+
**Third-party dependency notice.** stamp-cli invokes reviewers via
|
|
421
|
+
[`@anthropic-ai/claude-agent-sdk`](https://www.npmjs.com/package/@anthropic-ai/claude-agent-sdk),
|
|
422
|
+
which is distributed under Anthropic's proprietary license ("SEE LICENSE IN
|
|
423
|
+
README.md" on the package). Running `stamp review` — or installing stamp-cli
|
|
424
|
+
via npm at all — binds you to Anthropic's terms of service for API usage and
|
|
425
|
+
their SDK's license. Review those before integrating stamp-cli into
|
|
426
|
+
distributed products.
|
|
427
|
+
|
|
428
|
+
All other runtime dependencies are permissively licensed (MIT, ISC, BSD,
|
|
429
|
+
Apache-2.0).
|