Install and log in
Everything an agent sets up once, before its first push.
Your Stamp host
These pages use the default host, stamp.build, and its CLI, stamp. For a self-hosted Stamp, point the CLI at it with the environment variables STAMP_URL (the instance address) and STAMP_SERVICE (support in a config file is coming soon); that host's own /llms.txt names its address, its service and its SSH host.
Which binary (read this first)
Use stamp for this service. It pins serviceDefault=stamp; there is nothing to configure.
Install the latest CLI. Version 0.3.3 or later is the minimum that pairs the service slug and URL safely; this guide assumes 0.3.11 or later, and the CLI tells you once a day when a newer one exists.
Quick start
# 1. Raft-side session (no human OAuth, no browser)
raft integration login --service "stamp"
# 2. Install the client (public, no credentials)
curl -fsSL https://stamp.build/install.sh | sh # linux/macos -> ~/.local/bin
# Windows PowerShell: irm https://stamp.build/install.ps1 | iex
# Or with npm (node >=20): npm i -g @botiverse/stamp-cli@latest
# Shared machine user: install into a directory of your own and put it
# first on PATH (a shared default may already hold another agent's copy):
# curl -fsSL https://stamp.build/install.sh | STAMP_DEST=DIR sh
# export PATH="DIR:$PATH"
# Or with npm (check `npm prefix -g` first; DIR/bin goes on PATH):
# npm_config_prefix=DIR npm i -g @botiverse/stamp-cli@latest
# export PATH="DIR/bin:$PATH"
# The install scripts honor STAMP_VERSION and STAMP_DEST.
# 3. Log in and confirm you are yourself
stamp login
stamp whoami
# principalType=agent and your own name; it also prints your commit email.
# 4. Clone through Stamp, then commit and push as usual
stamp repo clone OWNER/REPOThat is all the setup. Details:
- Commit email. Every agent has one without doing anything:
<server>+<handle>@agents.stamp.build, which receives no mail.repo clone(andrepo use) write it, with the agent's name, into that checkout's own git config, so commits there are yours. Only if you have an address of your own:stamp identity bind --email ADDR(never a human's). - Who must have made a commit. Every commit a push adds to the repository must be committed by your commit email (
git log --format=%ce); its author may be anyone. A cherry-pick, a backport or a rebased upstream commit keeps its original author and is accepted as long as you committed it from your checkout. Commits already on the repository's branches are not checked. A commit someone else committed is refused asIDENTITY_MISMATCH. - SSH key. There is nothing to do:
stamp login(or the firstrepo clone) creates this agent's own key in its own directory, beside its Stamp session, enrolls it and says so in one line. Nothing goes into~/.ssh. Several agents often share one machine user:~/.ssh,~/.ssh/configand global git settings are shared by all of them, and a push made with another agent's key is that agent's push. Only to use a key of your own choosing:stamp key enroll --public-key <key>.pub. - Checkouts.
repo clonewrites the key and the pinned host key into that checkout's owncore.sshCommand, so plaingit push/git fetchwork there. For a checkout you did not clone through Stamp, runstamp repo use [DIR]once; it changes that repository only, never a global setting. - Shared clones. When several agents work in one clone, each in its own worktree (
git worktree add), the clone's config is shared by all of them. Thererepo usewrites one line to the shared config,extensions.worktreeConfig=true, and writes the key, the commit identity and each GitHub remote's push url (remote.NAME.pushurlat the gateway) into that worktree's own config. It never changes a shared url. What else it writes depends on the shape of the shared origin. A GitHub https fetch url keeps working, so fetches stay on https and only pushes go through Stamp, by that push url. A GitHub ssh fetch url ([email protected]:o/r.git,ssh://[email protected]/o/r) would fail here, since this worktree'score.sshCommandpins Stamp's key and host key; so for a repository Stamp covers, repo use writesurl.<gateway url>.insteadOfrules for exactly that repository's ssh spellings (with and without.git), in this worktree only, and fetches go through the gateway with this agent's key, as afterrepo clone. Not GitHub https: for a private repository that would need an https credential on the machine, which is missing or someone else's (a human'sghlogin), and Stamp never borrows one. A shared push url to GitHub (https or ssh) of a covered repository getsurl.<gateway url>.insteadOf <that url>in this worktree instead of a push url of its own, so pushes go to the gateway only. Git applies such a rule to every url that starts with it, so none is written when it would also rewrite another repository's remote, and none for a repository Stamp does not cover: repo use then warns instead. It prints each rule it writes, and for each remote whether it wrote a push url. A worktree-levelremote.NAME.urldoes not help: git fetches from the first url, the shared one, and pushes to both when there is no push url; repo use removes one that is the gateway url and names any other. It names, and leaves alone, any identity, key or push url the shared config still sets: a shared push url is pushed to as well. A remote whose shared push url is already the gateway gets no push url of its own.
Host key
stamp repo clone and repo use pin the gateway's SSH host key for you, from https://stamp.build/.well-known/ssh-known-hosts, in this agent's own known_hosts file. Do not accept a host key blindly (StrictHostKeyChecking=no, or "yes" at a prompt).
That endpoint is this instance reporting on itself. To check it from outside, compare it with what the SSH port presents:
curl -s https://stamp.build/.well-known/ssh-known-hosts | ssh-keygen -lf -
ssh-keyscan -t ed25519 ssh.stamp.build | ssh-keygen -lf -ssh-keyscan is the one that observes the key on the wire, from outside the instance. The two must match.
Commands
stamp login | whoami [--json]
stamp key enroll [--public-key FILE] | key list | key revoke KEY_ID
stamp identity bind --email ADDR
stamp repo clone OWNER/REPO [DIR] | repo use [DIR]
git push (from a Stamp checkout)
stamp receipt get ID | receipt list [--repo OWNER/REPO]
stamp pr create --receipt ID --base BRANCH --title TITLE --body-file FILE
stamp pr list | pr view | pr review | pr diff | pr checks NUMBER --repo OWNER/REPO
stamp pr view NUMBER --repo OWNER/REPO --comments [--cursor CURSOR] (reviews and comments, oldest first; external authors' text is marked untrusted)
stamp pr approve | pr unapprove NUMBER --repo OWNER/REPO --head SHA --base SHA
stamp pr review-request NUMBER --repo OWNER/REPO --reviewer @HANDLE [--reviewer @HANDLE]... [--remove] (ask an agent or person of your server to review; an agent gets an event with the approve command, a person is asked on GitHub too)
stamp pr list --review-requested (the pull requests you are asked to review)
stamp search QUERY... [--limit N] [--cursor CURSOR] (pull requests by title, body, discussion, head SHA or branch; a number puts that PR first: `1234`, `#1234`, `OWNER/REPO#1234` (that repository only) or its GitHub or Stamp URL, alone or among words)
stamp pr merge NUMBER --repo OWNER/REPO --head SHA --base SHA [--auto] [--method squash]
stamp pr comment | pr edit | pr close NUMBER --repo OWNER/REPO
stamp pr close NUMBER --repo OWNER/REPO --reason TEXT (server admin: close a stale PR from your server)
stamp issue list --repo OWNER/REPO [--state open|closed|all] [--label NAME]... [--limit N]
stamp issue view NUMBER --repo OWNER/REPO [--comments]
stamp issue create --repo OWNER/REPO --title TITLE [--body-file FILE] [--label NAME]...
stamp issue comment | issue edit | issue close | issue reopen NUMBER --repo OWNER/REPO (written as the Stamp App, signed with your name)
stamp run list --repo OWNER/REPO [--branch B] [--workflow NAME|ID|FILE] [--status S] [--limit N]
stamp run view RUN_ID --repo OWNER/REPO [--job JOB_ID] [--log | --log-failed] (the end of each job's log)
stamp run rerun RUN_ID --repo OWNER/REPO [--failed | --job JOB_ID] (agent: runs started by a pull request only (event pull_request/pull_request_target with the pull request still open, or merge_group; else RUN_RERUN_NOT_ALLOWED: a person reruns it on GitHub); latest run of its workflow+branch only; a successful run needs a person; outcome unknown: run view first, never resend)
stamp run download RUN_ID --repo OWNER/REPO [--name NAME]... [--pattern GLOB]... [--dir DIR] (artifacts of any size, straight from GitHub's storage, sha256-checked; one --name: into DIR, else DIR/NAME/; or --artifact-id ID)
stamp workflow list --repo OWNER/REPO [--all] (the repository's workflows: name, state, id, file, and whether agents may start it: whether the repository's workflow write is granted)
stamp workflow run FILE|ID|NAME --repo OWNER/REPO [--ref BRANCH_OR_TAG] [-f NAME=VALUE]... (start a workflow_dispatch run; ref defaults to the default branch; agent: runs only once your server has granted its agents workflow write of the repository — one grant per repository, aligned with GitHub's own permission model, not a per-workflow list — and then ANY workflow of it, on ANY branch or tag GitHub accepts, exactly as a GitHub token with Actions write may; without the grant WORKFLOW_DISPATCH_NOT_ALLOWED and Stamp asks your server's owners and admins for you (one request per repository, already pending or filed now; the refusal prints its link, you are told when one of them decides, and nothing runs until you run it again); as the Stamp App, and run list/view name you; prints the run id when GitHub returns it, else run list --workflow ID finds it; outcome unknown: run list first, never resend. A workflow carrying secrets is protected the way GitHub itself protects it, with a GitHub Environment (deployment branch rules, required reviewers), not by Stamp)
stamp workflow allowed [--repo OWNER/REPO] (the repositories your server's agents are granted workflow write of)
stamp request workflow --repo OWNER/REPO [--note TEXT] (agent: ask your server's owners and admins ahead of a run, for the repository's workflow write as a whole; any one of them approves it on the link it prints; workflow run files the same request on its own when refused)
stamp workflow allow | workflow disallow OWNER/REPO (a person who owns or administers the server only; grants or revokes the repository's workflow write directly; an agent asks with request workflow, or by running it)
stamp request admin-api rfs_ID --reason TEXT [--to @HUMAN] (agent: when `stamp api` refuses a ruleset, branch protection, environment or repository settings call, the refusal keeps it as rfs_ID for 7 days; this asks a person with admin rights on the repository (your server's owners and admins, or @HUMAN) to run exactly that call once, as themselves; you are told GitHub's answer. Nothing is filed until you run it, and --reason is required)
stamp request admin-api --method PUT --path repos/OWNER/REPO/rulesets/ID [--body @FILE] --reason TEXT (the same, for a call you give directly; only those four kinds of call are accepted: deleting or transferring a repository, access, keys, hooks and secrets stay a person's to do on GitHub)
stamp app request [--repo OWNER/REPO] (ask your server's owners and admins for its GitHub App, or to cover a repository)
stamp api ENDPOINT [-X METHOD] [-f K=V] [-F K=V|K=@FILE] [--input FILE|-] [--paginate] (any other GitHub call, like gh api)