@recurrente/cli
v0.1.0
Published
The Recurrente API from your shell, and an MCP server that serves the same surface to any agent. Checkouts, subscriptions, customers, reports and money movement, with a sandbox where money cannot move.
Downloads
57
Readme
@recurrente/cli
The Recurrente API from your shell — and the same surface served over MCP to any agent.
npx @recurrente/cli login --profile sandbox
npx @recurrente/cli whoami --sandboxNothing to install and no runtime dependencies: one package.json, plain ESM, Node's built-in
fetch. If you run it more than once a day, npm i -g @recurrente/cli gives you recurrente on
your PATH and saves npx the round trip — the rest of this file writes it that way.
Requires Node 20 or newer.
Why a CLI and not only an MCP server
An MCP server sends every tool definition to the model on every turn. One tool per endpoint over
122 operations costs tens of thousands of tokens before the user has said anything. A CLI costs
nothing until it is invoked, --help is progressive disclosure for free, and it works in any
harness that can run a shell — no per-client plugin, no protocol negotiation.
So the CLI is the surface, and recurrente mcp is a second rendering of it for clients that
prefer tools. Both read the same catalog and enforce the same rules.
Using it
recurrente help # topics
recurrente help withdrawals # commands in one topic, with their risk tier
recurrente search reembolso # find a command, in Spanish or English
recurrente show checkouts create # parameters and body fields
recurrente checkouts list --items 5
recurrente checkouts create --data '{"items":[{"product_id":"prod_abc"}]}'
recurrente products update --id prod_abc --name "Camisa"Flags the CLI does not claim for itself become request fields: path parameters go in the path,
the rest become query parameters on a read and body fields on a write. Use --data for payloads
too nested to express as flags.
Output and exit codes
Every invocation prints one JSON object and exits with a typed code, so a script can branch on
$? without parsing prose.
| Code | Meaning |
| --- | --- |
| 0 | success |
| 1 | failed |
| 2 | usage — unknown command or bad arguments |
| 3 | unauthorized — no key, or the key was rejected |
| 4 | not found |
| 5 | forbidden — the key lacks a permission |
| 6 | invalid — the API rejected the payload |
| 7 | needs confirmation — the operation moves money and --yes was absent |
| 8 | unreachable — the network, not the API |
Money never moves on a guess
Operations that move funds, repoint a payout destination or charge a card are refused with exit 7
unless --yes is present:
$ recurrente withdrawals create --amount-in-cents 50000
{
"ok": false,
"error": { "message": "withdrawals create moves money and needs a human to confirm it." },
"hint": "Re-run with --yes once a person has approved it."
}Profiles
Keys live in ~/.recurrente/credentials.json, written at 0600. --sandbox and --live pick a
profile; --key sk_... uses one without storing it; RECURRENTE_SECRET_KEY overrides everything.
Develop against --sandbox. A Sandbox is a real tenant that simulates money: it has its own
objects, activity and webhooks, and every path that would reach a bank, a processor or a tax
certifier is refused server-side. It is the only place to let an agent try something for the
first time.
As an MCP server
claude mcp add recurrente -- recurrente mcp --sandboxInstall it globally first (npm i -g @recurrente/cli) and point the client at the binary. npx
re-resolves the package on every launch, which is fine for a one-off and wasteful for a server an
editor starts all day.
Four tools, not 122: recurrente_api_search, recurrente_api_details, recurrente_api_read and
recurrente_api_write. The agent searches for what it needs and calls it, instead of carrying the
whole API in context.
Money-moving operations are refused unless the server was started with --allow-money. The agent
cannot grant itself that flag.
Merchants who do not want to install anything can connect the hosted server at
https://app.recurrente.com/mcp from claude.ai instead, which asks for consent in a browser and
scopes access to read, write or money. That one needs no Node at all, which matters: our
integrators are not all on it.
Skills
npx skills add https://app.recurrente.comInstalls our integration guides — payments, subscriptions, webhooks, sandbox — into Claude Code, Codex, Cursor and anything else that reads the agent-skills standard.
Developing
The command surface is generated, not hand-written: it comes from data/agent_surface.json, which
bin/rails agent_surface:sync builds from config/agent_surface.yml and the OpenAPI spec in the
main repo. Adding an endpoint to the API adds a command here without a line of code. The generated
file is JSON rather than YAML because parsing it must not cost a dependency.
Renaming or removing a command breaks whoever scripted it, so the set of command names is pinned in a committed list and CI fails when it changes without that list changing too.
Tests live with the app's, in test/javascript/cli/, and run with the rest of the suite:
npx vitest run test/javascript/cli