<!doctype html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>gage — hand context between agents</title>
<meta name="description" content="Hand context between agents — files, prompts and decisions — with a trust boundary that survives the hop.">
<style>
:root{
--bg:#fbfaf8; --sheet:#ffffff; --sunk:#f3f1ec; --line:#e7e3dc;
--fg:#191815; --dim:#5b5751; --faint:#8b867d;
--accent:#2c5a4d; --accent-soft:#e6eee9;
--sans:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
--mono:ui-monospace,"SF Mono",SFMono-Regular,Menlo,Consolas,monospace;
--shadow:0 1px 2px rgba(25,24,21,.04), 0 10px 28px -20px rgba(25,24,21,.30);
}
@media (prefers-color-scheme:dark){
:root:not([data-theme="light"]){
--bg:#121316; --sheet:#1b1d21; --sunk:#232529; --line:#2b2e34;
--fg:#edebe7; --dim:#a8a49d; --faint:#7a766f;
--accent:#86c7b1; --accent-soft:#1f2f2a;
--shadow:0 1px 2px rgba(0,0,0,.45), 0 12px 32px -22px rgba(0,0,0,.9);
}
}
*{box-sizing:border-box}
body{
margin:0; background:var(--bg); color:var(--fg);
font-family:var(--sans); line-height:1.6;
-webkit-text-size-adjust:100%;
}
.wrap{max-width:46rem; margin:0 auto; padding:4rem 16px 5rem}
h1{font-size:2.6rem; line-height:1.1; margin:0 0 .4rem; letter-spacing:-.02em}
.tag{font-size:1.15rem; color:var(--dim); margin:0 0 2.5rem}
h2{font-size:1.1rem; margin:2.75rem 0 .6rem; letter-spacing:.02em; text-transform:uppercase; color:var(--faint)}
h3{font-size:1rem; margin:1.6rem 0 .4rem; color:var(--fg)}
p{margin:0 0 1rem}
a{color:var(--accent); text-decoration-thickness:1px; text-underline-offset:2px}
code,pre{font-family:var(--mono)}
pre{
background:var(--sunk); border:1px solid var(--line); border-radius:8px;
padding:.9rem 1rem; overflow-x:auto; font-size:.9rem; margin:0 0 1rem;
}
code:not(pre code){
background:var(--sunk); border:1px solid var(--line); border-radius:4px;
padding:.1em .35em; font-size:.88em;
}
.words{
background:var(--accent-soft); border-left:3px solid var(--accent);
border-radius:0 6px 6px 0; padding:.85rem 1rem; margin:0 0 1rem;
font-family:var(--mono); font-size:.9rem;
}
figure{margin:1.25rem 0 0}
img{
width:100%; height:auto; display:block;
border:1px solid var(--line); border-radius:10px; box-shadow:var(--shadow);
}
figcaption{font-size:.85rem; color:var(--faint); margin-top:.55rem}
ul{margin:0 0 1rem; padding-left:1.2rem}
li{margin:.3rem 0}
.links{display:flex; flex-wrap:wrap; gap:.6rem; margin:.25rem 0 1rem; padding:0; list-style:none}
.links a{
display:inline-block; padding:.45rem .9rem; border:1px solid var(--line);
border-radius:999px; background:var(--sheet); text-decoration:none;
font-size:.92rem; box-shadow:var(--shadow);
}
footer{
margin-top:3.5rem; padding-top:1.25rem; border-top:1px solid var(--line);
font-size:.86rem; color:var(--faint);
}
.note{font-size:.9rem; color:var(--dim)}
</style>
<div class="wrap">
<h1>gage</h1>
<p class="tag">Hand context between agents — files, prompts and decisions — with a trust boundary that survives the hop.</p>
<p>Your Claude hands a task to Codex. A colleague's agent sends you their project state.
Normally nothing on the receiving side says who wrote it, or whether it can be trusted.
gage wraps that handoff so the agent reading it is told who signed it, whether you have
ever confirmed that person, and that nothing inside carries any authority.</p>
<p>It works across vendors because it is not a protocol. A bundle is a signed directory,
so it moves over a shared folder, git, email, your own network, or a relay — anything you
already have.</p>
<h2>Get going</h2>
<pre>curl -fsSL https://gage.sh/install.sh | sh</pre>
<p class="note">Piping a script into a shell is a thing worth being asked to
trust. <a href="https://gage.sh/install.sh">Read it first</a> if you would
rather — it is about a hundred lines of POSIX <code>sh</code>: it works out
your OS and architecture, downloads the matching binary and its
<code>SHA256SUMS</code> from the latest release, <strong>checks the
checksum before installing anything</strong>, and puts one file in
<code>~/.local/bin</code>. No sudo, ever. <code>cargo install gage</code>
works too, anywhere Rust does.</p>
<p>Then three beats. The middle one is the only part that needs a human.</p>
<h3>1 · Who you are</h3>
<pre>gage init alice # or just `gage quickstart` and answer four questions</pre>
<p class="note">Makes a keypair on this machine. <code>gage whoami</code>
prints the one public line you send a colleague, and the four word-pairs
that line's key derives.</p>
<h3>2 · Who you trust</h3>
<pre>gage add bob <their-key></pre>
<p class="note">Then <strong>read the four word-pairs to each other out
loud</strong> — on a call, in person, not in the channel you sent the key
through. If one word differs, it is not their key. This is the step nothing
can do for you, and skipping it is what makes <code>SENDER VERIFIED</code>
mean only "this is the key I was handed".</p>
<h3>3 · One handoff</h3>
<pre>gage send --to bob --subject "spec review" \
--prompt ask.md --file spec.md --out ./pkg</pre>
<p class="note">A bundle is a signed directory, so get it to them however
you already can — a shared folder, git, email, <code>gage push</code>
through a relay, or <code>gage send --lan</code> on the same network. On
their side, <code>gage open ./pkg</code>, and what they see is the screen
below.</p>
<p>The full tour is in the
<a href="https://github.com/warewithall2/gage#readme">README</a>. Driving it
with no human at the keyboard — the command table, the exit codes, how to
read a verdict, and a complete worked script — is in
<a href="https://github.com/warewithall2/gage/blob/master/docs/agents.md">docs/agents.md</a>.</p>
<h2>Keys, said out loud</h2>
<p>A gage is a pledge, and historically the glove thrown down to open a challenge.
Two people compare four word-pairs over a channel neither machine controls — a phone
call, in person — and everything downstream rests on that one human moment. The words
are derived from the signing key, so nobody picks their own, and two machines showing
the same words are holding the same key.</p>
<div class="words">this key says : humble pillar · ruddy lobster · marine armour · eastern dovecote</div>
<p class="note">Four pairs is 64 bits, and is what a person confirms. The single pair
shown as a label is 16 bits — enough to tell two machines apart in a list, never enough
to confirm anything against.</p>
<h2>Other ways to install</h2>
<pre>cargo install gage</pre>
<p class="note">Works anywhere Rust does, and is the route for any platform
without a prebuilt binary. The binaries and their checksums are attached to
the <a href="https://github.com/warewithall2/gage/releases/latest">latest
release</a> if you would rather fetch one by hand and check it yourself —
<strong>linux-x86_64</strong> and <strong>darwin-arm64</strong>, with one
<code>SHA256SUMS</code> over both.</p>
<h2>What it looks like</h2>
<figure>
<img src="screenshots/inbox.png" alt="The gage viewer: conversations on the left, a received bundle on the right with its trust verdict stated above the contents.">
<figcaption><code>gage ui</code> serves a local viewer on 127.0.0.1 — loopback only,
nothing leaves the machine. The verdict is the headline, not a caption.</figcaption>
</figure>
<h2>Where it is</h2>
<p>v0.2.0. 118 unit tests and 776 adversarial checks pass, along with the
identity restore drill and the viewer end-to-end suite. It is early
software, and the honest way to try it is the twenty-minute packet in the
repository.</p>
<p><strong>0.2.0 fixes a security defect in <code>gage open</code></strong>,
the one part of gage that is a security control: a sender could get a line
of their own into the trust frame — including a forged authorisation line
carrying the frame's real marker. <strong>0.1.0 is affected and upgrading is
recommended.</strong> What it was, who could do it and how it is fixed are
in the
<a href="https://github.com/warewithall2/gage/blob/master/CHANGELOG.md">changelog</a>.
It was found by self-review rather than by an outside reporter, which is
worth knowing in both directions.</p>
<p>If you lose the key, that is no longer the end of the identity —
<code>gage export-identity</code> writes a passphrase-encrypted copy you
keep yourself. It is opt-in, and it is a trade rather than a free
improvement: it converts "lose the key, lose everything" into "your security
is your passphrase's strength", so the file belongs somewhere other than the
machine it came from.</p>
<p>Two documents say what this actually is rather than what it hopes to be. The
<a href="https://github.com/warewithall2/gage/blob/master/docs/spec.md">spec</a> is the
wire reality, derived from the code. The
<a href="https://github.com/warewithall2/gage/blob/master/docs/threat-model.md">threat
model</a> lists the adversaries, the mitigation for each, and the non-goals — including
that nothing here can make a language model obey the frame, and that the security review
so far has been self-review.</p>
<ul class="links">
<li><a href="https://github.com/warewithall2/gage/blob/master/docs/spec.md">Spec</a></li>
<li><a href="https://github.com/warewithall2/gage/blob/master/docs/threat-model.md">Threat model</a></li>
<li><a href="https://github.com/warewithall2/gage">GitHub</a></li>
<li><a href="https://crates.io/crates/gage">crates.io</a></li>
<li><a href="https://docs.rs/gage">docs.rs</a></li>
</ul>
<footer>
gage 0.2.0 · dual-licensed MIT or Apache-2.0 · no trackers and no scripts on this page
</footer>
</div>