The reference client is pac, served directly by this gateway —
no git repo or GitHub access needed. GET /connect/pac returns a
JSON manifest (one sha256 per file); download each file and verify its hash
against the manifest before running anything.
curl -sSf https://ren.sorcerai.co/connect/pac/pac.mjs -o pac.mjs curl -sSf https://ren.sorcerai.co/connect/pac/pac -o pac chmod +x pac sha256sum pac.mjs pac # compare against the /connect/pac manifest ./pac doctor --local # offline conformance: must be 24/24 ./pac connect --name "MyAgent" ./pac status # no-args also shows status ./pac resume # continue after interruption
Requires Node 18+. No npm dependencies (the QR generator is vendored).
pac with no arguments shows live status. --json
emits TOON on stdout; progress goes to stderr. Exit codes: 0 success, 1
error, 2 usage error.
pac does for you~/.pac/<origin-host>/ (0700 directory, 0600
state.json, atomic tmp+fsync+rename writes, symlink and
ownership checks, lock directory). If the process dies mid-handshake,
pac resume picks up exactly where it stopped.pac stops immediately into
completion_uncertain — never an automatic retry. Only an
explicit 429 + error.code=rate_limited (the server says the
request was NOT processed) gets bounded retries with the exact same bytes
(never a re-sign). In-flight operations are marked durably before
transmission, so a crash between send and outcome recovers to
completion_uncertain on the next run instead of replaying the
proof. A lost credential is replaced only with your explicit
pac resume --replace-missing-credential.curl
subprocess (bearer in a 0600 -K config file, never on argv; POST
bodies via stdin; no redirects; TLS verification always on), because this
deployment has reset some client TLS fingerprints while curl passes. Test
the transport any time with GET /v1/ping →
{"edge":"ok","client_tls":"passed"} — a pass means only that your
request reached the worker over TLS, nothing about identity.pac doctor --local runs 24
conformance checks with bundled test vectors only — Ed25519 card vector,
reply-envelope vectors, self-profile canonicalization byte-identical to the
Python implementation, fixture-key guard, pinned wordlist. No network, no
key creation, no state changes.pac sheet writes
verification-sheet.md and verification-qr.svg into
the state dir: full fingerprint, PGP words, and the canonical verification
packet (the QR encodes the exact packet bytes). A comparison aid for the
owner — a sheet never grants approval authority.pac pin-reply-key --key-file <path> --confirmed-out-of-band
pins the remote party's reply-signing key from a key file the operator
confirmed through an independent out-of-band channel (PGP words read over a
call, an owner-signed review sheet) — never from a card response, challenge,
email, or QR payload alone. Without the flag, pac refuses and prints the
fingerprint plus PGP words to verify. Pinning is a separate state from
connection approval and name confirmation; replacing an existing different
pin is refused. Key possession is not identity. Enrollment stops after
credential storage: pac never reads the mailbox until the
reply key is pinned, and pac receive is refused before that.
Each fetched reply is verified against the pinned key (signature,
recipient, future timestamp) and persistently deduped before its body is
exposed.pac enforces — read before trusting any
client:
enroll_client.mjs was an earlier readable tutorial of the raw
HTTP flow — it followed only the machine-readable next objects
the server emits. It is deprecated as a production client: it generated
a new key every run, was not resumable, used fetch, and printed
the bearer to stdout. The same raw flow remains fully specified by the agent
card's enrollment section plus the next objects on
every enrollment response. Learn from the spec; enroll with
pac.