Skip to content

CLI reference ​

The desktop and CLI share workflow contracts. Use the CLI when you want reviewable commands, machine-readable diagnostics, or an external automation entry point.

Find commands ​

bash
Raticode --help
Raticode rattish --help
Raticode rattish docs --format json

The CLI command index lists every command with its options, generated from the CLI itself.

The last command prints where the installed language documentation, grammar, node contracts and schemas are. These files describe the installed compiler without requiring a source checkout. Raticode schema prints the same paths.

Scripting conventions ​

  • Commands that print records, such as lists and status, accept --format json. Commands that had a --json flag keep it as a shorter spelling, and the rem lists also accept --format table.
  • There are two JSON shapes. Commands that work on files in the data folder, such as rattish list or runner list, print the bare data with --format json. Commands that talk to a running backend print a JSON envelope by default, with the data under data (see Output and exit codes).
  • Data goes to stdout. Errors and warnings go to stderr, so Raticode … --format json | jq never receives an error message as JSON input.
  • Exit code 0 means success and 1 means the command failed. Exit code 2 means the command was used wrongly: an unknown option or format, an invalid input, or a Rattish workflow given to a command that only reads legacy TOML workflows (see below).
  • The data folder is GOFER_DATA_DIR when it is set (the desktop app sets it when you choose a custom folder), otherwise the standard one, such as ~/.local/share/gofer on Linux. Most commands also take --data-dir.

Rattish commands ​

CommandPurposeExecutes nodes?
Raticode rattish create "Name" --project PATH --format jsonRegister a workflow and return its allocated ID and source pathNo
Raticode rattish list --format jsonList registered Rattish workflowsNo
Raticode rattish format PATHFormat an existing source fileNo
Raticode rattish check PATH --format jsonParse and perform static checksNo
Raticode rattish compile PATH --format jsonCompile validated source to JSON IRNo
Raticode rattish inspect-ir PATH --prettyPrint the compiled representationNo
Raticode rattish preflight PATH --format jsonCheck required runtime resourcesNo
Raticode rattish run PATH --format jsonExecute the workflowYes
Raticode rattish triggers add cron|file|webhook PATH ...Start the workflow on a schedule, file change, or local webhook. See TriggersLater, when it fires

Run help on an individual command for its current options; most also take --data-dir to use a different data folder. PATH is the source file; use the exact source path returned by create for a registered workflow.

format edits its target. Other authoring and inspection commands do not execute workflow nodes. Run can write files, call providers, and contact services, according to the authored source.

Inputs and limits ​

bash
Raticode rattish run WORKFLOW_PATH --input 'message="Hello"' --format json

Input values after = are JSON. Repeat the option for multiple public inputs. Check the input schema and workflow limits before running it. The inputs guide contains a complete example.

For shell automation, preserve the exit status and machine-readable result. Do not treat a printed message as proof that every node succeeded. A failed request with an uncertain external outcome may need inspection before retrying.

Provider profiles and health ​

bash
Raticode provider --help
Raticode provider profile list --format json
Raticode provider profile create NAME --subscription codex --model MODEL
Raticode provider profile edit NAME --model MODEL
Raticode provider profile rm NAME
Raticode doctor --json

Provider profiles are reusable deployment settings. Discover supported subscription and permission options in Raticode provider profile create --help; edit replaces only the values you pass, and rm asks first unless you add --yes. Authenticate native CLIs separately. A profile does not override a Rattish node's explicit provider, model, or effort.

Doctor checks installation health, and reports whether the Organizations Feature Preview is turned on in the current environment. Its workflow-specific legacy option is not a replacement for Raticode rattish preflight.

Other command families ​

FamilyGuide
Raticode rattish triggersTriggers
Raticode scheduleSchedules
Raticode watchFile watchers
Raticode runnerRunner queue
Raticode workflow run PATHRuns a .rattish file, a workflow folder or a registered ID; --dry-run runs preflight only, and Raticode workflow resume --run-id ID resumes a run
Raticode remRem from the CLI for chat, tasks, memories, alerts and settings; Tools, skills and MCP for the skill and MCP library
Raticode tickets, Raticode selfworkTickets and self-work from the CLI
Raticode rattish start, stop, resume, runs, logs, approve and the other "(Backend)" commands; Raticode org, Raticode swarm, Raticode brain, Raticode usage, Raticode projects, Raticode devices, Raticode threads; Raticode provider list, models, status and setWorkflows, Organizations and more from the CLI: runs, approvals and trigger files through the backend, Organizations, swarms, Second Brain, providers, usage and live threads, with settings as files
Raticode schemaPrints where the Rattish docs, contracts and schemas are installed; --legacy-toml prints the old TOML authoring contract
Raticode serve --headlessRuns the backend with no desktop window. See Headless backend
Raticode tokensCreates, lists and revokes limited agent tokens. See Agent tokens
Raticode licenses --output DIRExports the third-party notices bundled with this build
Raticode ui serveRuns the backend the desktop app starts (port 8765 by default); the same as Raticode serve. It writes no token file and Rem waits for a window, so for scripts and servers use Raticode serve --headless

Legacy TOML commands ​

Raticode workflows used to be TOML files. Some commands still read only that format, and their help starts with [Legacy TOML]. New workflow source belongs in workflow.rattish.

These Raticode workflow commands accept a Rattish workflow ID, folder or .rattish file:

CommandWith a Rattish workflow
run, resumeRuns or resumes it, like Raticode rattish run
listLists Rattish and TOML workflows
validateRuns Raticode rattish check
planRuns Raticode rattish preflight
logs list, logs show, logs latest, logs prune, usageReads its run history
exportWrites a .raticode archive; import FILE.raticode --project PATH installs one
rm, rename, duplicateWorks as in the app

approvals, approve and reject work with approval gates of legacy TOML workflows. For a Rattish workflow's gates, use Raticode rattish approvals, approve and reject through the backend. Only you can decide a gate: inside a Rem or worker turn, workflow approve and reject refuse with exit 5 and change nothing, so a workflow can't approve its own gate. --by is not your name. It picks which of the gate's listed approvers you decide as, and it is refused when the gate lists none or the name isn't on its list. Without it the decision is recorded as made from the CLI.

rm, rename and duplicate work with TOML workflows too. When a headless backend is running for the same data folder, they ask it to make the change, so only the backend writes the workflow files and it updates schedules and continuous runs straight away. Inside a Rem or worker turn that request needs an agent token, and without one it fails with exit 5 instead of changing the files. With no headless backend running, they change the files themselves, as before. The desktop app's own backend doesn't publish its address, so with only the app open they also change the files themselves.

The other workflow commands (show, edit, build, create, recipe, set-info, add-node, add-edge, add-agent, rm-node, rm-edge, set-schedule, clear-schedule, set-watch, clear-watch, trigger, secrets, stop, history, diff, restore, preview-import) work only with TOML workflows. Given a Rattish workflow, they change nothing, exit with code 2 and print the Rattish command to use instead, such as Raticode rattish inspect-ir for show or Raticode rattish triggers add cron for set-schedule.

The Raticode agent, Raticode schedule, Raticode watch and Raticode runner groups are also legacy. Use triggers for schedules and file watching, and check the guides above before using the others. They refuse a Rattish workflow the same way, with exit code 2 and the command to use: agent list --workflow points to Raticode rattish inspect-ir, runner queue to Raticode rattish run or Raticode rattish start, and schedule add to Raticode rattish triggers add cron. watch only reads TOML workflows in the data folder and ignores Rattish ones. agent list, watch list, runner list and workflow approvals accept --format json.

Raticode workflow trigger reads a webhook token from --token-file PATH (a file only you can read) or from RATICODE_WEBHOOK_TOKEN. Its old --token option still works but is deprecated and prints a warning, because other accounts can read command lines. In the same way, workflow add-node --notification-smtp-password expects a secret reference such as secret:SMTP_PASSWORD and warns when it is given a password.

Talk to a running backend ​

New in 0.5.3

Raticode api, Raticode wait and Raticode completion arrived in Raticode 0.5.3. So did the resource commands built on them: Rem, tickets and self-work and workflows, Organizations and more.

The commands above work on files. Everything stateful in the app (Rem, tickets and the global board, self-work, Organizations, swarms, run control) lives in the backend, so scripts reach it through the backend's local API, the same one the desktop window and the phone use. The CLI never opens those stores itself. The CLI finds a headless backend on its own. It can't find the desktop app's backend yet, because the app doesn't publish its address or token, so these commands can't reach it while only the desktop app is running.

Raticode api METHOD PATH calls any endpoint, like gh api. Paths are relative to /api:

bash
Raticode api GET /health
Raticode api GET /rem/kanban | jq '.data.self_work'
Raticode api POST /rem/kanban/ticket -f action=create -f title="Fix flaky test" --request-id t-123
Raticode api PUT /rem/kanban/settings -F max_threads=3 --expected-revision 0
Raticode api POST /organizations --data @configure.json --expected-revision 7
OptionWhat it does
-d, --data JSONRequest body. @file reads a file and @- reads stdin.
-f, --raw-field key=valueA string field. For GET and DELETE it becomes a query parameter; otherwise it goes in the JSON body. Dots nest: params.taskId=t1.
-F, --field key=valueLike -f, but true, 3, null or [...] are sent as JSON values, and @file reads the value from a file.
--request-id IDAn idempotency key, sent as request_id. Only some endpoints deduplicate on it (listed below); for those, retrying with the same ID returns the first result instead of doing the work again. Other endpoints ignore it. auto makes one and prints it in the result.
--expected-revision REVRefuse the change (exit 4) if the record changed since you read it. Sent as expected_revision on /rem/... paths and expectedRevision elsewhere (inside params for Organizations).
--followStream an NDJSON endpoint such as /chat/events, or keep polling a GET that returns an events list such as /rem/events.
--timeout 30sGive up after this long. With --follow it limits the whole follow.
--rawPrint the response body as it came, without the envelope.

Finding the backend and its token ​

The CLI only talks to a backend on this computer: 127.0.0.1, ::1 or localhost. It refuses any other address. Raticode's backend listens only on TCP, not on a Unix socket. To reach a backend on another machine, forward its port with ssh -L and point the CLI at the local end.

api and wait have no --token option, because other accounts on a computer can read command lines. They look for the backend and token in this order:

Looked up in order
Address--endpoint http://127.0.0.1:PORT, then RATICODE_URL, then <data folder>/headless/endpoint.json, then http://127.0.0.1:8765
Token--token-file PATH, then RATICODE_TOKEN, then RATICODE_TOKEN_FILE, then the token file named in endpoint.json, then <data folder>/headless/owner-token
Data folder--data-dir, then RATICODE_DATA_DIR, then GOFER_DATA_DIR, then the standard folder

A token file has to belong to you and be readable only by you (chmod 600), and endpoint.json must not be writable by anyone else, since it decides where the token is sent. The CLI refuses them otherwise. On Windows the CLI doesn't check these permissions; see Headless backend. Inside a Rem worker or another provider turn that Raticode started (where RATICODE_AGENT_SESSION is set), the CLI never picks up the owner token from the data folder, and it accepts only a limited agent token from any source. An owner token in RATICODE_TOKEN, RATICODE_TOKEN_FILE or --token-file is refused there with exit 5 (error code owner_token_in_agent_session).

Raticode serve --headless publishes headless/endpoint.json and headless/owner-token in the data folder, so the CLI finds it with no setup. For scripts that shouldn't act as you, give the CLI a limited agent token with --token-file. Raticode ui serve on its own takes its token from GOFER_UI_API_TOKEN, or makes a new random one each time it starts and writes it nowhere. In that case, start it with a token you keep in a private file and give the CLI the same file:

bash
umask 077
python3 -c 'import secrets; print(secrets.token_urlsafe(32))' > ~/.config/raticode-token
GOFER_UI_API_TOKEN="$(cat ~/.config/raticode-token)" Raticode ui serve &
Raticode api GET /rem/tasks --token-file ~/.config/raticode-token

You can also export RATICODE_TOKEN_FILE in your own shell instead of passing --token-file. Raticode removes RATICODE_TOKEN and RATICODE_TOKEN_FILE from everything it starts (Rem's workers, providers and workflow commands), so they don't inherit your token even if you start the app from that shell.

Output and exit codes ​

Each command prints one JSON object on stdout, and messages for people go to stderr:

json
{"ok": false, "command": "api", "data": null,
 "error": {"code": "conflict", "message": "This ticket changed. Check it and try again.", "http": 409},
 "warnings": [], "request_id": "t-123"}

request_id is there only when the command sent one. With --follow, the output is one JSON object per line: {"kind": "event", "data": ...} for each event, then the result object above with "kind": "result" as the last line. --output ndjson gives the same line format for any command, and --output text prints readable output. --format is accepted as another name for --output.

ExitMeaning
0Done
1The operation ran and failed, or the backend had an internal error
2Invalid arguments or input (HTTP 400, 422)
3Not found (HTTP 404)
4Conflict or stale --expected-revision (HTTP 409)
5Missing, rejected or unsafe token, or forbidden (HTTP 401, 403)
6No backend answered
7Waiting on you: an approval, consent or answer is pending
8Timed out, or the request may or may not have taken effect

These endpoints deduplicate on request_id:

  • Rem: POST /rem/messages, POST /rem/tasks, PATCH and DELETE /rem/tasks/ID, POST /rem/tasks/ID/run and /pause, POST /rem/runs/ID/cancel, /acknowledge and /retry_review, and POST /rem/threads/ID/messages
  • The board: POST /rem/kanban/ticket with action create or comment

A request that never reached the backend is always retried. Once a request has been sent, the CLI resends it automatically after a timeout, a dropped connection or a busy backend only if it is a read, or carries a request ID to one of the endpoints above. Everything else, such as starting a workflow run, is sent once: if the answer is lost, the command exits 8 and you should check whether it happened before trying again. On exit 8 from one of the endpoints above, retry with the same --request-id instead of a new one. Existing rattish commands keep their own codes, where 2 also means a source file couldn't be read.

Waiting for a state ​

Raticode wait PATH polls a GET endpoint until a field reaches a final state:

bash
Raticode wait /rem/runs/RUN_ID --field run.state \
  --success succeeded --failure failed,cancelled,outcome_unknown --needs-user blocked \
  --timeout 30m

It exits 0 for a --success state, 1 for --failure, 7 for --needs-user and 8 when the timeout passes first. The last response is in data. If the backend restarts while you wait, wait keeps trying until the timeout.

Scripts and shell completion ​

The CLI never prompts when it is given --non-interactive (Raticode --non-interactive ...), when RATICODE_NON_INTERACTIVE=1 or CI=true is set, or when stdin isn't a terminal. A command that would ask for confirmation then fails with exit 2 unless you pass --yes.

Print a completion script for your shell with Raticode completion bash, zsh, fish or powershell. It completes commands and options, and for Raticode api the method and the API paths that have CLI coverage:

bash
Raticode completion bash > ~/.local/share/bash-completion/completions/Raticode
Raticode completion zsh > "${fpath[1]}/_Raticode"
Raticode completion fish > ~/.config/fish/completions/Raticode.fish

Raticode --install-completion installs it for the current shell instead.