Skip to main content
runtm-api is a small Go CLI that wraps the Runtime Cloud API. It is intentionally separate from the pip runtm CLI (which handles local sandboxes, scaffolding, and deploys): Most humans use both: the pip CLI for day-to-day work, the Go CLI when an agent needs to act on the hosted platform programmatically.

Install

This downloads a pre-built binary for your platform (macOS / Linux × amd64 / arm64), verifies its SHA-256 checksum, and installs runtm-api to /usr/local/bin. If Claude Code or Cursor is detected, the bundled agent skill is auto-installed too.

Install a specific version

Install into a directory you own (no sudo prompt)

Installer environment variables

Install via go install (Go developers)

If you already have Go 1.23+ and prefer to compile from source:

Auth and config

The same API key works for both this CLI and the pip CLI.

Commands

Run runtm-api --help or runtm-api <command> --help for full flag reference.

Running commands in a sandbox

session exec prints the raw PTY stream by default, which merges stderr into stdout and carries the sandbox shell’s startup banners. Pass --json whenever the output will be parsed:
The two streams are captured separately and PTY carriage returns are stripped. The process still exits with the remote exit code, so under set -e capture the output with || true and read exit_code instead. Bash history expansion is disabled for the command in both modes, so a literal ! in a heredoc, commit message, or regex reaches the sandbox intact. A paused sandbox is resumed automatically by exec, connect, and the file commands.

Output contract and exit codes

  • Stdout is always JSON. Parse it directly; never scrape the PTY stream (see --json above).
  • Stderr carries structured error JSON: {"error": "...", "status": 401, "hint": "..."}.
  • Streaming commands (session prompt, session events, session deploy run, template build-logs) emit JSON lines, one per server event: {"event": "<type>", "data": <payload>}. The stream ends with an event of done.
  • Exit codes:

Org context

Org-scoped operations (templates, agents, scheduled agents, skills, MCP servers, tools, guardrails, team secrets, org instructions, team telemetry) need an org-scoped API key. The org is bound to the key when it is created and cannot be changed at call time. --org and RUNTM_ORG_ID can only restate the key’s own binding. If a command reports the key is personal, create an org-scoped key under Settings > API Keys; setting the env var does nothing.
Writes to agents, triggers, scheduled agents, team secrets, org instructions and guardrails also need an admin or owner role behind the key.

Resolving required inputs

  1. Check context first: prior command output, the conversation, environment variables.
  2. If a value is missing, run the matching list or get: session list for a session id, template list for a template id, agents list for an agent id, agents list --type slack for a Slack integration id.
  3. If it is still ambiguous, ask the user.
  4. Never run a command with an unresolved placeholder such as <id> or <org>.

Endpoint strategy

Everything goes to the Cloud API at https://app.runtm.com/api/cloud. Three deliberate /api/v0/ fallbacks remain because they were built for fire-and-forget agent use: deployments list|get|logs|destroy also proxies /api/v0/deployments*, so a deployment a session shipped can be tracked and torn down without the pip CLI.

Error recovery

Which command carries which capability

Everything an agent can do hangs off one template. The roster row carries identity; the template carries capability. Plan the list before creating anything, and check what the org already has.

Assembly order and the failures that are silent

Create the template first, attach everything, verify, build once, then the roster agent, then the trigger. The Build pages explain why; this is the CLI shape.
template create --skip-agent implies --build: the clone-only fast path builds immediately, so anything attached afterwards needs a rebuild. Batch attachments and build once; rebuilding after every attach churns the snapshot. These fail with no error, only an agent that cannot do its job: Prove a capability landed before wiring the trigger:

Roster versus triggers

agents with no --type is the roster (identity, instructions, rubric, budget). --type slack|github|linear|email is a trigger integration. Same verbs, different resource.
  • update is a partial patch: only the flags you pass change. --config '<json>' merges into the trigger’s config server-side, so a one-key patch never clobbers triggers or channel_template_map. --model is shorthand for config.default_model.
  • --clear-template sends an explicit null and clears the roster’s default template, fanning out to every linked trigger. Omitting --template leaves it unchanged.
  • The rubric’s version bumps on every edit, and every grade records the criteria_version that produced it.
  • Email has no get-by-id route; agents get <id> --type email is resolved from the list.
  • Deleting a roster row while a trigger still references it is not durable: the trigger’s lazy sync recreates the row. Delete or reassign triggers first.

Trigger preflight

Check these before agents create --type ... so you fail with an explanation instead of a bare 400:
  • Slack needs the org’s Slack app configuration token, set once in the dashboard. There is no CLI command for it. Create returns an authorize_url to open; the trigger is created on approval.
  • GitHub cannot be a clickable link. The App-manifest flow requires a form POST, so the CLI writes an auto-submitting HTML page (open in the response) for you to open in a browser. --github-org picks the owner, --return-url where GitHub sends you back.
  • Linear is headless only with --linear-api-key plus --service-user (the Runtime user id the bot’s sessions run as). Managed OAuth returns an install URL to open.
  • Email is fully headless and provisions an inbox. --agent-id binds it to a roster agent so runs inherit defaults and rubric. If it returns 400, check GET /api/v1/email/status.
Slack, GitHub and managed Linear finish in a browser. When running unattended, prefer Email or a scheduled agent and hand the browser step back to a person; do not loop on the manifest endpoint.

Scheduled agents from the CLI

Aliases: scheduled-agents also answers to schedules and cron; run-now also answers to run and trigger.
  • The order that works is create --disabled, run-now, read the session, then update --enabled. run-now works on disabled agents and stamps last_run_at and last_session_id like any tick.
  • Cron is five fields in UTC with no per-agent time zone. Daily 11:00 Pacific is 0 19 * * * in winter and 0 18 * * * in summer; re-derive it when daylight saving shifts.
  • next_run_at is null while the agent is disabled, because a disabled agent has no scheduler job.
  • --slack-integration and --slack-channel travel as a pair; one without the other is rejected. Find integration ids with agents list --type slack. Runtime posts the result after the run; the sandbox does not need Slack egress.
  • The prompt decides the output shape. A prompt that ends “post the Block Kit JSON” pastes raw JSON into the channel; ask for a short plain-text summary when a person reads it.
  • Pause with --disabled rather than delete: the scheduler job goes away, the prompt, template and post target stay.
  • “It was supposed to run and nothing happened”, in order: get <id> and check enabled and next_run_at; compare last_run_at with the expected time (unchanged means the tick never fired, updated means the failure is inside the run); run-now to reproduce, a 502 carries the reason; session history <last_session_id>.

Subcommand discovery

The agent skill

The CLI embeds one SKILL.md (packages/agent/skills/) and installs it into ~/.claude/skills/runtm/ and ~/.cursor/skills/runtm/ when those directories exist. The installer does this automatically; re-run it any time with:
The skill is deliberately short. It teaches the golden paths, the rules that fail silently, and the output contract on this page, and it points at https://docs.runtm.com/llms.txt for everything else: an agent reads the index, picks a page by its description, fetches https://docs.runtm.com/<page>.md, and lifts the cli: lines that every Build and Guides step carries in an agent-only block (hidden on the website, present at the .md URL). A cli-handoff: comment marks a step only a person can do, usually entering a credential: the agent sends the person that URL (with the placeholders filled in), then runs the step’s cli-verify: to confirm it was done. Inside a sandbox the same content is reachable through the sandbox’s fetch tool or curl.

Source

The CLI lives at packages/agent/ in the open-source runtm-ai/runtm repository. Releases are cut by pushing a packages/agent/vX.Y.Z tag, which triggers a GitHub Actions workflow that publishes pre-built binaries to GitHub Releases. Apache-2.0 licensed (same as the pip CLI).