selatis the command-line runner for SELAT Agent Payments: an AI agent discovers, vets, and pays x402 / MPP APIs in USDC — per call, with no API keys, no gas token, and no seed phrase — from the user's own self-custodied agent wallet.
SELAT is a discovery and payment layer for AI agents. The agent states an intent ("search the web", "look up a Twitter profile"); SELAT finds matching paid endpoints across a federated x402 / MPP catalog, ranks them by price, rail, and reliability, and settles the call in USDC. SELAT never holds your keys or your funds.
The package is @selat-ai/selat-cli; it installs the selat command.
Prerequisites: Node.js ≥ 18 (ships with npm). No Python needed.
Install from npm:
npm install -g @selat-ai/selat-cliThat exposes the selat command on your PATH.
Then run:
selat initThat command:
- Checks your
node. - Checks whether the agent-payment skill is installed.
- Checks for its signing dependency (the Circle CLI).
- Signs you into your agent wallet (one email + one OTP code).
- Prompts to reuse your existing agent wallet or create a new one. If you hold several agent wallets, it lists them all with their Gateway balances and defaults to the configured or best-funded one — so a fresh host doesn't silently adopt an empty wallet. (
--forcere-creates non-interactively.) - Checks whether
selat-payis onPATH. - Writes
~/.config/selat-pay/.envwith your router URL and wallet address. - Checks for spendable USDC — on-chain balance across Base / Optimism / Arbitrum / Polygon and your Gateway balance (broken down per chain, so you can see which chain holds it) — and, if there's none, points you to
selat fund(a gasless top-up with sponsored gas — no native ETH required).
Then either describe an intent and let the CLI discover + pay:
selat run "summarize the latest news on gold prices"…or install and run a packaged agent skill:
selat skill install twitter-profile-lookup
selat skill run twitter-profile-lookup --handle openaiEither way you get a real paid API response. No API keys. No native ETH. No bridging, no chain-picking. No payment-scheme guesswork.
| Command | What it does |
|---|---|
selat init |
Full bootstrap. Idempotent — safe to re-run. |
selat run "<intent>" |
Discover + rank + pay in one pipe. Sugar for the discovery skill's rank.mjs --pick payment plan. --param key=value (repeatable) fills endpoint parameters: path placeholders are substituted, query params appended/replaced, and body params merged for POST hints — when a pick is refused because required params are missing, selat run prints which ones and the exact --param retry line (nothing is charged). For Apify picks, selat run uses the prepaid-token model (buy a token via the Router, then call the Actor with a Bearer token) — pass Actor input with --input '<json>' or --input-file <path>. --auto-rebuy (Apify picks only) buys a replacement token ($1.05 — $1 of Apify credit + SELAT's 5% fee; a new spend) and retries once if the token drains mid-run; without it, a depleted token surfaces an error and re-running buys the replacement. On any non-Apify (per-call x402) pick the flag is ignored with a warning. |
selat skill list [--available] |
List installed skills, or the catalog of skills available to install — each with a live reliability badge (● ok / ● degraded / ● down / ○ unknown) from the selat-skills auto-verify registry. |
selat skill install <name|path> [--force] |
Install an agent skill by name (from the public selat-skills registry) or from a local path. |
selat skill run <name> [--param value ...] |
Run an installed agent skill, passing its params as --flags. |
selat skill compare "<intent>" [--limit N] [--json] [--pay] |
Vet catalog candidates for an intent side-by-side, without accounts or keys: shortlists the top N (default 5) via the same federated discovery as selat search, free-probes each candidate's live 402 at its catalog serviceUrl (never settles), and prints one aligned table — live price, rail (direct x402 / routed MPP), probe latency, reachability, and the selat-skills registry reliability badge — sorted reachable-first, then price. --json for machine consumption. --pay adds one capped settled test call per candidate (asks for confirmation first; --yes to authorize non-interactively; --max-amount overrides the per-call cap, which otherwise defaults to live price + 25 % clamped to $1) and saves each response body as an output sample. Apify prepaid-token candidates are probed but skipped by --pay — test those with selat run. |
selat skill new/validate/verify/register/submit |
Author and contribute a skill: scaffold → static SOP check → live-402 verify (writes the receipt that gates submission) → index entry → PR to selat-skills. submit opens the PR from your fork by default unless you have write access to the skills repo; --fork / --no-fork force either flow. |
selat fund [--chain ... --amount ... --method direct|eco] |
Top up Gateway balance. Dry-runs first; requires explicit confirm. Both methods are gasless — the deposit runs through your agent wallet (a smart-contract account) with sponsored gas, so you never need to hold native ETH. The difference is destination: --method direct keeps the balance on the chain you deposited from; --method eco sources from Base, Optimism, or Arbitrum but settles the resulting Gateway balance on Polygon regardless of source chain. After an Eco deposit, pay and check balance with --chain polygon (not the source chain), or the call fails with insufficient_balance. |
selat spend [--json|--wallet 0x..] |
Unified spend report (read-only): settled spend from the selat-pay ledger (per-call payments + Apify token buys, with a charged-but-failed/disputable total) plus Apify token utilization (consumed vs remaining, flagging prepaid-balance waste). |
selat budget [--json] |
Show the wallet's spending caps and remaining per-window budget (read-only). The caps are enforced at the wallet layer — the hard ceiling a runaway agent cannot bypass; selat setup-policy sets them. |
selat setup-policy |
Set hard spending caps on your agent wallet, enforced at the money layer. Requires an email OTP — every policy write demands fresh human authorization. Recommended before any deposit > $20. |
selat doctor |
Diagnose setup problems in one pass. Run when something looks off. |
selat --help |
This page. |
An agent skill is a named, reusable recipe composed of one or more
catalogue API endpoints, paid via selat-pay and the SELAT Router. Each skill
is a declarative manifest — no executable code — so installing one only ever
writes data, never runs it.
selat skill list --available # browse the catalog (with reliability badges)
selat skill install twitter-profile-lookup # install a skill
selat skill run twitter-profile-lookup --handle openai # run it
selat skill run person-lookup --query "Patrick Collison Stripe"Composing a skill and choosing between competing endpoints? Benchmark them first — free:
selat skill compare "search the web for recent news" --limit 3 # price/rail/latency/reliability, no spend
selat skill compare "token prices" --pay --max-amount 0.05 # + one capped settled test call each (confirmed)- Where skills live: skill content is maintained in the separate, public repo
SELAT-AI/selat-skills. The CLI ships
no skills itself —
selat skill installfetches the manifest on demand and anonymously overraw.githubusercontent.com(no GitHub auth required) into~/.config/selat/skills/<name>/. - Rails: every skill step is paid through the SELAT Router. The step's rail describes the router's outbound leg to the upstream: Gateway-batched (same-rail passthrough, for upstreams that take Circle Gateway themselves) or erc-3009 / tempo-native MPP (cross-protocol translation). A run prints a per-rail summary, so a skill that mixes rails reports each separately.
- Params: pass a skill's inputs as
--flags(e.g.--handle openai).--chainand--max-amountare reserved per-run overrides applied to every step. The--chainyou pay on must match the chain your Gateway balance lives on: if you funded withselat fund --method eco(source Base/Optimism/Arbitrum), that balance settles on Polygon, so use--chain polygon. Runcircle gateway balance --address <wallet> --chain polygon --allto see which chain holds your USDC —--alllists every chain, so the--chainyou pass only resolves the wallet address. - Overrides:
SELAT_SKILLS_DIRpoints at a local checkout of the skills repo (dev);SELAT_SKILLS_REPO/SELAT_SKILLS_REF/SELAT_SKILLS_RAW_BASEretarget the registry. You can alsoselat skill install ./path/to/skillfrom disk.
Skills are authored to the Agent Skill SOP:
each is a folder with SKILL.md, manifest.json, references/endpoints.md, and evals/.
To contribute one, the CLI walks the whole loop inside a checkout of the skills repo:
selat skill new my-skill --dir skills # scaffold (SOP layout)
selat skill validate ./skills/my-skill # static SOP check
selat skill verify ./skills/my-skill # live 402 probe per step (free, no spend) — writes the receipt that gates submit
selat skill submit ./skills/my-skill # branch + commit + push + PR to SELAT-AI/selat-skillssubmit is fork-aware. With write access to the skills repo it pushes the
branch there (the maintainer flow); otherwise it forks on demand via gh,
pushes the branch to your fork as a separate fork remote — origin is never
rewired — and opens the PR cross-fork. No gh at all? The branch is still
pushed with plain git and you get the manual gh pr create command. --fork /
--no-fork force either flow, and --dry-run previews the branch, files, and
PR body without touching git.
selat is a thin orchestrator. It wires together four components and reimplements none of them:
- The
selat-payCLI (SELAT-AI/selat-pay) — probe + sign + retry against the SELAT Router, auto-detecting the upstream's protocol (Gateway-batched x402 / MPP) to pick the routed outbound leg. - The discovery skill (SELAT-AI/selat-discovery) — federated catalog, intent ranking, payment-plan emission (powers
selat run). - Agent skills (SELAT-AI/selat-skills) — installable catalogue-endpoint recipes (powers
selat skill). - The Circle CLI (
@circle-fin/cli) — the custody layerselatdelegates to: wallet creation, MPC-backed signing, Gateway deposits.selatnever signs anything itself.
One command — selat init — takes a new user to their first paid response with no hand-edited config files.
Your wallet is yours. SELAT never holds your keys, your funds, or your credentials. Here is the exact mechanism.
selat init provisions you a dedicated agent wallet with 2-of-2 MPC key
management, built on Circle's user-controlled wallet architecture.
The private key never exists in one piece: it exists only as two key shares,
and both are required to sign. The key shares are never exposed to the
agent — or to SELAT — and the user retains custody: Circle, the custody
provider, cannot unilaterally move your funds.
selat authorizes every signature through your email-OTP login (sessions
expire — circle wallet status shows the time remaining — so you re-enter
an OTP periodically). Policy writes —
spending caps, allowlists — require a fresh human OTP every time, so an
agent can never raise its own limits.
SELAT's own code never touches key material. selat and selat-pay request
signatures through the Circle CLI only:
- SELAT never sees or holds a private key or key share.
- SELAT never holds your funds or your Gateway balance.
- SELAT never holds your login credentials.
This is self-custody without a seed phrase: there is no mnemonic to lose, and no counterparty that can spend your money without you — not the custody provider alone, and not SELAT. Stop using SELAT tomorrow and your wallet and balance remain yours, accessible through Circle's own tooling with no SELAT software in the path.
Without it, the setup ordeal is:
- Install the agent-payment skill manually.
- Install Circle CLI manually.
- Run
circle wallet login <email> --type agent— wait for email — paste OTP. - Run
node scripts/setup.mjs create(from the skill repo). - Clone
selat-router,cd selat-pay,npm install,npm link. - Write
~/.config/selat-pay/.envby hand with router URL + wallet address. - Acquire mainnet USDC.
- Deposit it through Circle Gateway.
- Then try the paid request flow.
selat init checks the required local tools and skill, handles wallet login and creation, and writes the config that selat-pay consumes. It does not install global dependencies or clone the skill on your behalf.
selat init writes:
# ~/.config/selat-pay/.env (mode 0600)
SELAT_ROUTER_URL=https://router.selat.ai # default SELAT Router
SELAT_AGENT_WALLET_ADDRESS=0xYourAgentWalletAddress # written by `selat init` from your agent wallet
The default points at the SELAT Router at https://router.selat.ai.
selat init bootstraps your agent wallet and writes the selat-pay config; it skips wallet creation when an agent wallet already exists (use --force to re-run). selat run "<intent>" discovers, ranks, and pays an x402 / MPP service end to end.
The selat-discovery discovery skill and selat-pay ship as npm dependencies, so npm install -g @selat-ai/selat-cli pulls everything selat run needs — no separate skill install or repo clone. (SELAT_SKILL_PATH, or a local ~/.codex/skills / ~/.claude/skills checkout, still takes precedence if you're developing the discovery skill.)
Agent skills (selat skill) are not bundled — they're installed on demand from the public SELAT-AI/selat-skills repo, so the catalog can grow without a CLI release.
Does my wallet expire?
No. Never. The on-chain balance and the Circle Gateway balance of your
wallet have no expiry. Only Apify prepaid tokens expire — the Bearer
tokens selat run buys for Apify Actor picks ($1.05: $1 of Apify credit
- SELAT's 5% fee) lapse after 14 days.
What does recur is login: signing sessions expire (
circle wallet statusshows the time remaining), so you'll periodically re-enter an email OTP — that re-authenticates you; it does not touch the wallet or the funds.
I deposited on one chain — where did my money go?
Into one unified Gateway balance: one balance, spendable from any supported
chain. The per-chain breakdown you see in selat doctor is where the balance
is held — a routing detail, not a separate account per chain (today the
--chain you pass at pay time points at the chain that holds it — see the
selat fund row above). And your on-chain wallet balance dropping after a
deposit is by design: the funds moved into Gateway, they are not lost.
What stops a runaway agent from draining the wallet? A ladder of caps, each at a different scope:
- Per call —
--max-amountonselat run/selat skill run/selat skill compare --pay: a hard ceiling on any single payment. - Per session —
selat budget start --amount <usd>: a spending tripwire for the current work session (selat budget stopdisarms;selat budgetshows state). - Per day / week / month —
selat setup-policysets per-transaction, daily, weekly, and monthly caps on your agent wallet, enforced at the money layer across every service the agent pays — including ones discovered tomorrow. Policy writes require an email OTP, so an agent can't raise its own limits. - Freeze — a
selat freeze/unfreezekill switch (pause all signing instantly) is in flight (#73).
Keys slice spend by vendor. Wallets slice it by time. A capped API key and a capped wallet are the same safety model — a bounded pool with an enforced ceiling — sliced differently. The honest trade: wallet caps can't cap per-vendor, but the per-transaction ceiling is one no vendor billing dashboard offers.
Apache-2.0 — see LICENSE.