From xmtp-signet
Administer an xmtp-signet as an orchestrating agent or owner — bootstrap the daemon, initialize and rotate keys, create managed wallets, create and remove operators, define policies, issue and revoke credentials, create and link managed inboxes, verify seals and walk seal history, and drive the privileged `xs` command surface that sets agents up to operate against the signet. Use this skill whenever someone asks how to set up a signet for agents, how to issue or revoke a credential, how to provision an operator with a scoped policy, how to rotate or export operator keys, how to link an inbox to an operator, how to verify a seal chain, or how to run privileged admin flows. For day-to-day agent use (messaging, reading, inspecting credentials and seals, harness connection), use the `xmtp` skill.
How this skill is triggered — by the user, by Claude, or both
Slash command
/xmtp-signet:xmtp-adminThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> [!IMPORTANT]
[!IMPORTANT] You are the orchestrator. You set things up so other agents can operate through the signet safely. You do not hold raw message content, and you cannot read operator messages without an explicit, owner-approved elevation. Every flow below leans on that boundary — the signet enforces it structurally, not by policy alone.
[!NOTE] The current runtime model is v1: owner, admin, operator, credential, seal. The public CLI is credential-native.
Companion skill: for the conceptual model (owner/admin/operator/
credential/seal, projection pipeline, event types, harness lifecycle) and
for day-to-day agent use (messaging, inspecting, harness connection), use
the xmtp skill. This skill focuses on the privileged half of the CLI.
xs is not installed yetBefore you can provision operators, credentials, or adapters, the machine needs
an xmtp-signet checkout and a runnable CLI.
git clone https://github.com/galligan/xmtp-signet.git
cd xmtp-signet
bun run bootstrap
bun packages/cli/src/bin.ts --help
From a plain clone, the repo entrypoint is the reliable path. If you want
xs as a shell command, create an alias for the current session:
alias xs='bun packages/cli/src/bin.ts'
curl -fsSL https://xmtp.fyi/install.sh | bash
Repo-backed fallback:
curl -fsSL \
https://raw.githubusercontent.com/galligan/xmtp-signet/main/scripts/install.sh \
| bash
That installer clones the repo, runs bun run bootstrap, and writes xs
wrappers into an XDG-aware bin directory.
If xs is still not found in a new shell, add the installer's printed wrapper
path to your shell profile. Common defaults are:
# Linux / XDG
export PATH="$HOME/.local/bin:$PATH"
# macOS fallback (only if the installer chose ~/bin)
export PATH="$HOME/bin:$PATH"
Owner -> anchors trust, approves owner-gated operations (biometric)
Admin -> manages operators, credentials, policies, inboxes, keys
Operator -> conversational agent profile (per-chat or shared)
Credential -> time-bound, chat-scoped, policy-driven authorization
Seal -> public declaration of operator scope in a chat
You will spend most of your time at the Admin layer, occasionally asking the Owner to approve something that requires elevation.
xs init --env dev --label owner
Creates the local key hierarchy, writes a config when needed, sets
defaults.profileName from --label if it's still unset.
Presets:
xs init — recommended defaultsxs init trusted-local — shared identity mode, lower ceremony for local
smoke testsxs init hardened — stricter gates, shorter-lived defaultsRun xs init --help for the current preset deltas.
xs daemon start
xs daemon status
xs daemon stop
xs status --json # scheme, identity mode, network, connected inboxes
xs reset # wipe local state — destructive
xs agent setup # interactive bootstrap for a new operator+cred
xs agent status
xs agent doctor # diagnose keys, daemon, credential, seal health
Use agent setup for happy-path provisioning and agent doctor as the
first thing you run when something feels off.
For OpenClaw specifically, the happy-path adapter bootstrap is:
xs agent setup openclaw
Follow with xs agent status openclaw only when you want a verification pass,
and xs agent doctor openclaw when setup or wiring looks wrong.
Keys are per-operator. xs key init is not redundant with xs init —
xs init sets up the owner/admin hierarchy and daemon; xs key init
provisions key material for a specific operator profile.
xs key init --operator op_... # create key material for an operator
xs key rotate # operational rotation, chain preserved
xs key list
xs key info <key-id-or-identity-id>
xs key export-public [identity-id] # safe: public material only; defaults to first
Key material lives in the local encrypted vault. The Swift signet-signer
CLI in signet-signer/ handles Secure Enclave operations on macOS when
available.
Never export, paste, or log raw private material. The CLI doesn't surface it; if you find yourself reaching for it, stop and reconsider.
Managed wallets back operator identities.
xs wallet create --label ops-wallet
xs wallet list
xs wallet info wallet_...
xs wallet provider list # deferred: provider management stub
xs wallet provider set <name> --path <path> # deferred
xs wallet provider ... is the one surface that isn't fully live.
Everything else in wallet and key is.
xs operator create --label "support-bot" --scope per-chat
xs operator list
xs operator info op_...
xs operator rename op_... --label "support-bot-v2"
xs operator rm op_...
Scope choices:
per-chat — isolated state per conversation (default, strongest
isolation)shared — one context across multiple chatsRole levels (set at create time via --role, defaults to operator):
operator — can only act within its own credentialsadmin — can manage operators and resources it createdsuperadmin — can manage anything, but still cannot read messages
without owner-approved elevationPolicies are reusable allow/deny bundles over the 30 permission scopes
(categories: messaging, group-management, metadata, access,
observation, egress).
xs policy create --label "helper" --allow send,reply,react
xs policy list
xs policy info policy_...
xs policy update policy_... --deny forward-to-provider
xs policy rm policy_... --force
Design rule of thumb:
send, reply, react; deny
group-managementread-messages, stream-messages;
deny all egress scopes (forward-to-provider, store-excerpts,
use-for-memory)forward-to-provider explicitly; keep read-history deliberateDeny always wins. When in doubt, deny and add back.
xs cred is the canonical credential lifecycle surface. A credential binds
operator + chat scope + effective permission set (policy + inline
overrides) + content-type allowlist + TTL + status.
# Issue — --ttl is seconds (integer). 86400 == 24h.
xs cred issue \
--op op_a7f3 \
--chat conv_9e2d1a4b8c3f7e60 \
--policy policy_helper \
--allow send,reply \
--ttl 86400
# Inspect
xs cred list
xs cred list --op op_a7f3
xs cred info cred_b2c1
# Adjust scopes or policy in place
xs cred update cred_b2c1 --deny forward-to-provider
xs cred update cred_b2c1 --policy policy_restricted
# Revoke (dry-run by default; pass --force to execute)
xs cred revoke cred_b2c1 --force
Not every credential change requires reconnection.
On reauth the signet emits credential.reauthorization_required and
terminates the connection. The harness should re-auth with a fresh token.
xs cred revoke terminates the WebSocket connection and publishes a
xmtp.org/agentRevocation:1.0 seal to affected chats. The revocation is
public by design — participants can see that the operator no longer has
scope.
Inboxes are the daemon-backed mailbox surface for operators.
xs inbox create --label qa-inbox
xs inbox list
xs inbox info inbox_...
xs inbox link inbox_... --op op_...
xs inbox unlink inbox_...
xs inbox rm inbox_...
inbox complements the direct bootstrap path exposed through xs init.
Link is how you attach an inbox to an operator for ongoing use.
xs seal list and xs seal info are covered in the xmtp skill. The
admin-side verification flows:
xs seal verify seal_... # Ed25519 signature + chain integrity
xs seal history cred_... --chat conv_... # full chain for a credential in a chat
Verification checks:
Trust tiers surfaced on seals: source-verified (hardware-backed root
key) or unverified (software vault).
Some flows require the human owner to unlock through a biometric gate. Common triggers:
Ordinary admin auth is not ambient message access. The dangerous- looking flag on search/message-inspection flows isn't theatre — it's asking the daemon to request or reuse a short-lived, chat-scoped admin read elevation:
xs search "incident" --type messages --dangerously-allow-message-read
xs msg list --from conv_... --dangerously-allow-message-read
Don't paper over the noise — it's the mechanism telling you that this call is crossing a boundary.
# 1. Admin layer should already exist (xs init done once)
xs daemon status
# 2. Provision an operator profile
xs operator create --label "helper" --scope per-chat
xs key init --operator op_helper
xs key export-public op_helper # share with chat participants if needed
# 3. Define (or reuse) a policy
xs policy create --label "helper" --allow send,reply,react
# 4. Attach an inbox (or create one linked in a single step via `--op`)
xs inbox create --label helper-inbox
xs inbox link inbox_helper --op op_helper
# 5. Issue a credential for the chat (ttl in seconds — 86400 == 24h)
xs cred issue --op op_helper --chat conv_... --policy policy_helper --ttl 86400
# 6. Hand the credential token to the harness; it connects via WebSocket
xs key rotate # operational rotation, seal chain preserved
xs seal history cred_... --chat conv_... # confirm the new seal was stamped
xs cred revoke cred_... --force
xs seal history cred_... --chat conv_... # revocation seal is now on-chain
Expanding scopes is reauthorization-gated — issue a new credential and revoke the old one rather than mutating in place:
xs cred issue --op op_... --chat conv_... --policy policy_expanded --ttl 86400
xs cred revoke cred_old --force
# Harness receives credential.reauthorization_required on the old cred
# and reconnects with the new token.
--reason thoughtfully.--dangerously-allow-message- read in scripts; each use is a deliberate crossing.Handler failures use the shared categories from
@xmtp/signet-schemas:
| Category | When |
|---|---|
validation | Input fails schema validation or a business rule |
not_found | Resource does not exist |
permission | Caller lacks the required scope |
auth | Invalid or expired admin token or credential |
internal | Unexpected runtime failure |
timeout | Operation exceeded its deadline |
cancelled | Operation cancelled via abort signal |
auth in v1 generally means an invalid/expired admin token or credential;
permission means authenticated but out of scope.
xs --help, xs <group> --help, and xs <group> <command> --help are
the authoritative surface. If flags or options here look stale, trust
the help output and flag it.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub galligan/xmtp-signet --plugin xmtp-signet