@reppo/cli
v0.8.3
Published
Command-line interface for Reppo — mint pods, vote, lock REPPO, manage datanets. Built for AI agents.
Readme
@reppo/cli
Command-line interface for Reppo — mint pods, vote, lock REPPO, manage datanets. Built for AI agents as the primary user, but humans can use it too.
Status: v0.4.0 — fully wired against PodManager V2 on mainnet. Shipped:
approve,auth,query balance,query datanet,query epoch,query emissions-due,query pod,query voting-power,list datanets,list pods(incl.--all),claim-emissions,extend-lock,grant-access,lock,mint-pod,register-agent,unlock,vote. Remaining 2 commands (create-datanet,swap) are scaffolded but not yet wired.
Install
npm i -g @reppo/cliRequires Node ≥20.
Authentication
The CLI is non-interactive — all credentials come from environment variables:
| Variable | Required for | Description |
|---|---|---|
| REPPO_PRIVATE_KEY | All write commands | EOA private key (32-byte hex) |
| REPPO_VOTER_PRIVATE_KEY | vote (optional) | Separate EOA for voting (publishers cannot vote on their own pods) |
| REPPO_NETWORK | All commands (optional) | mainnet (default) or testnet |
| REPPO_RPC_URL | All commands (optional) | Override RPC endpoint |
| REPPO_API_URL | Platform-API commands (optional) | Override Reppo API base |
| REPPO_API_KEY | register-agent, create-datanet | Reppo platform API key |
| REPPO_AGENT_ID | mint-pod Phase-2 publishing | Agent id from register-agent; identifies the /agents/{id}/pods POST |
| REPPO_AGENT_API_KEY | mint-pod Phase-2 publishing (optional) | Agent Bearer key from register-agent; falls back to REPPO_API_KEY |
| PINATA_JWT | mint-pod --dataset (optional) | Pinata JWT for pinning a dataset to IPFS before publishing |
Network can also be set per-call via --network mainnet|testnet.
Output
All commands run in human-readable mode by default. Pass --json to emit a single JSON object per command on stdout — agents should always pass this.
Errors always emit JSON on stderr regardless of mode, with a stable code field:
{ "error": { "code": "INSUFFICIENT_VOTING_POWER", "message": "...", "hint": "Run `reppo lock <amount> --duration 7200` first." } }Commands
Read
reppo query balance [address]— ETH + REPPO + veREPPO + USDCreppo query voting-power [address]— veREPPO voting power + lockup countreppo query pod <podId>— pod existence + owner addressreppo query datanet <datanetId> [--for <addr>]— on-chain validity + REPPO access fee (optionally check access for an address) + the current on-chain epoch, plus off-chain catalog metadata: name, description, native token (symbol/address/decimals), per-epoch emissions, vote volumes, publisher/voter onboarding guidance, and the platformsubnetUuid(the--subnet-uuidformint-podpublishing). Catalog enrichment is best-effort — a platform outage degradesmetadatato{ unavailable }without affecting the on-chain answer.reppo query epoch— current on-chain epoch, read directly fromveReppo.currentEpoch()(the protocol's epoch time-base). JSON:{ network, epoch, epochStart, epochDurationSeconds, secondsRemaining }. Epochs are fixed ~48h windows; the timing fields are derived fromepochEnd/epochLengthand degrade tonullif those getters are unavailable. Pure read — no signer, no gas. Honor--rpc-urlagainst a private RPC (the public Base RPC rate-limits).reppo query emissions-due— list unclaimed REPPO emissions across all pods owned by the configured wallet (uses platform API)
List
reppo list datanets [--status ACTIVE|ALL] [--token-symbol <sym>] [--limit <n>]— list all datanets on the platform (public endpoint, no auth required)reppo list pods [--datanet <id>] [--include-emissions] [--limit <n>]— list pods owned by the configured wallet, optionally scoped to a single datanet (uses platform API)reppo list pods --all [--datanet <id>] [--limit <n>]— list pods published by any wallet, so a voter can discover pods to vote on (public endpoint, no auth required); each row'spodIdfeeds straight intoreppo vote --pod <podId>
Write
reppo approve --spender <pod-manager|subnet-manager|ve-reppo|0x…> [--amount <units|max>] [--token reppo|usdc]— set an ERC20 allowance so subsequent writes (lock, grant-access, mint-pod) don't fail with INSUFFICIENT_ALLOWANCE. Defaults to unlimited (max); reads the current allowance first and emits{status:'no-op'}if it already covers the request.reppo vote --pod <id> --votes <n> --like|--dislike— cast a vote on a pod, spending<n>voting powerreppo mint-pod --datanet <id> [--token reppo|primary] [--to <addr>]— mint a pod into a datanet. Add--pod-name <s>to also publish metadata (Phase 2): after the on-chain mint, register the pod with the platform (POST /agents/{id}/pods). Requires--subnet-uuid <cuid>(the platform UUID, not the numeric--datanetid),--agree-to-terms, andREPPO_AGENT_ID+ agent key. Optionally--pod-description,--category,--platform,--url, and a dataset:--dataset <file>(pinned to IPFS viaPINATA_JWT) or--dataset-uri <url>(used as-is). A Phase-2 failure does not fail the mint — it exits 0 withmetadata.published:false; re-run with the same--idempotency-keyto retry.reppo lock <amount> --duration <seconds>— lock REPPO into veREPPO for voting powerreppo unlock <lockupId> [--to <addr>]— withdraw an expired veREPPO lockup, returning the locked REPPOreppo extend-lock <lockupId> --duration <seconds>— extend an existing veREPPO lockupreppo grant-access --datanet <id> [--to <addr>]— pay the REPPO access fee and grant--toaccess to a datanetreppo claim-emissions --pod <id> --epoch <n>— claim a pod's emissions for an epochreppo register-agent --name <s> --description <s>— register a new agent identity on the Reppo platform; returns{ id, apiKey }. The apiKey is the Bearer token for subsequent agent-scoped calls (/agents/[id]/subnets,/agents/[id]/pods). On-chain mints use yourREPPO_PRIVATE_KEYwallet; the platform no longer provisions one server-side.reppo auth [--force]— sign in to the platform API (api.reppo.xyz); caches a 24h Bearer token used byquery emissions-dueand other platform-API commandsreppo create-datanet ...(planned — currently dashboard-only; the REST endpoint requires a Privy session cookie which is browser auth)reppo swap <from> <to> --amount <n>(planned, mainnet only)
Idempotency
Every write command accepts --idempotency-key <stable-string>. The CLI caches the result (in ~/.reppo/cli-state.json); repeat calls with the same key skip signing and return the prior tx hash. Critical for agent retry loops.
Dry run
Every write command accepts --dry-run. Simulates via eth_call, decodes custom errors, returns gas estimate. Exits 0 if would succeed, non-zero with a structured error if would revert.
Claude Code skill
Also available as a Claude Code skill that teaches agents how to invoke this CLI:
claude plugin install reppoThe skill ships with the same v0.3.0 feature subset.
License
MIT — see LICENSE.
