Drive Ranla from your coding agent

Claude Code, Codex, Cursor or any agent that can run a terminal command can work Ranla for you through ranla-cli: the same commands Ranla uses in chat (campaign list, segment create, page propose, …), plus the approval cards for anything that needs your sign-off.

Nobody pastes an API key. The agent runs login, you approve a link in your browser, and the CLI saves its own key for the workspace you pick.


Start

Tell your agent:

Or run it yourself:

npx -y ranla-cli@latest login

It prints a link and a code like BCDF-GHJK:

  1. Open the link. Sign up or sign in to Ranla as usual.
  2. Check the code on the page matches the one in your terminal.
  3. Pick the workspace, and approve.

At a terminal the command waits and finishes on its own. An agent's command exits right away with the link (an agent can't pass you a link from a command that is still running), so after you approve, it runs login again and the sign-in completes.

The key is saved in ~/.config/ranla/config.json, readable only by you. Check who you're signed in as:

npx -y ranla-cli@latest whoami

Approving needs permission to create API keys in that workspace (the owner, or API keys at Full access). The key shows up in Settings → API keys, where you can revoke it any time. ranla logout revokes it too.


Run Ranla's commands

npx -y ranla-cli@latest run help              # every noun and its verbs
npx -y ranla-cli@latest run help campaign     # a noun's verbs with every field
npx -y ranla-cli@latest run campaign list
npx -y ranla-cli@latest run list create --input '{"name":"Beta testers"}'

Pass a command's fields as a JSON object with --input '<json>', --file input.json, or --input - to read it from stdin. A wrong noun, verb or field fails with the valid options, so the agent can correct itself.

Output is JSON when the agent reads it (a pipe) and readable text at your terminal; --json forces JSON. Errors go to stderr with a non-zero exit: 1 when the request failed, 2 when the command line was wrong.

The same rules apply as in the app: the workspace's roles, your plan, credits, and approvals.


Approvals

Anything that sends, publishes or spends doesn't run straight away. It is parked as an approval card, exactly as when Ranla does it in chat, and nothing changes until it is approved:

Waiting for approval: Send "Week 1" to 540 people
  Approve: ranla approvals approve 6f1c…
  Reject:  ranla approvals reject 6f1c…
  In the app: https://app.ranla.ai/overview?approval=6f1c…
npx -y ranla-cli@latest approvals list
npx -y ranla-cli@latest approvals get <id>
npx -y ranla-cli@latest approvals approve <id>
npx -y ranla-cli@latest approvals reject <id>

You can also decide in the app: the card waits on Home. Affiliate payout runs move money and are only approved in the app, signed in.


Several workspaces

An API key belongs to one workspace. To work in another, sign in again and pick it in the browser:

npx -y ranla-cli@latest login --workspace "Acme"
npx -y ranla-cli@latest workspaces list
npx -y ranla-cli@latest workspaces use "Acme"

--workspace <name> on any command uses that workspace for one call. When you're signed in to several and none is picked, commands stop and ask instead of guessing.


Rules for the agent

Paste this into your agent's instructions (CLAUDE.md, AGENTS.md, Cursor rules):

## Ranla
- Use `npx -y ranla-cli@latest`. Sign in with `login`: give me the link it prints, wait until I say I approved, then run `login` again.
- Never ask me for a password or an API key, and never print one.
- Start with `run help`, then `run help <noun>` for a noun's fields.
- Ask me before anything that sends email, publishes, posts or spends money, and before `approvals approve`. Show me the card's summary first.
- Prefer reads and drafts. If a command waits for approval, tell me and stop.

Environment

Variable Use
RANLA_API_KEY Use this key instead of the saved sign-in (CI, servers).
RANLA_API_URL Another API host.
RANLA_CONFIG_DIR Where the sign-in is saved.

The CLI tells you once a day, on stderr, when a newer version is out. Running it with npx -y ranla-cli@latest always gets the newest.