Riby
Setup guides

Headless and CI

Run unattended agents that page you and genuinely wait, with claude -p and an MCP config.

Headless is where Riby earns its keep: an agent running with nobody at the terminal, pausing for a human decision that arrives from a phone.

Prerequisites: the machine (or runner) has riby-mcp installed and valid credentials — see Credentials on a runner below.

The pattern

Write an MCP config file:

riby-mcp.json
{
  "mcpServers": {
    "riby": {
      "command": "riby-mcp"
    }
  }
}

Then run Claude Code in print mode with the config and an explicit tool allowlist:

claude -p "Upgrade the dependencies. Page me before publishing anything." \
  --mcp-config riby-mcp.json \
  --allowedTools "mcp__riby__request_permission,mcp__riby__request_plan_check,mcp__riby__request_steering,mcp__riby__check_pending"

MCP tools are named mcp__<server>__<tool>, so the four Riby tools are mcp__riby__request_permission and friends. Without --allowedTools, a headless session has no way to grant tool permission interactively and the page never fires.

Why the wait holds

Harnesses background or time out long-running tool calls — Claude Code's auto-background threshold is around two minutes, and most hosted approval APIs die there. Riby's server emits an MCP progress notification every 20 seconds while a request is pending. That keepalive holds the call in the foreground: we have verified real headless sessions blocking well past the two-minute threshold and returning the human's answer cleanly.

So the run does what you want: it stops at the page, sits there, and continues with your answer — or with a definitive deny if the TTL (6 hours by default) runs out. Expiry is deny, never a hang. Size the TTL to your response habits in the dashboard settings; a CI job that pages at 2 a.m. will wait for you or fail safe.

Credentials on a runner

riby-mcp reads its server URL and token from ~/.riby/config.json, written by riby login. Login is a one-time interactive device flow, so on a machine you own, just run it once.

On an ephemeral CI runner, provision the file instead: run riby login somewhere trusted, store the resulting ~/.riby/config.json as a CI secret, and write it to ~/.riby/config.json in the job before starting the agent. Treat the file as a secret — it holds the token that lets an agent page you as you.

Naming the run

Pages from CI should say where they came from. Set RIBY_SESSION_NAME (100 characters max) in the job environment:

RIBY_SESSION_NAME="nightly-deps · run 4821" claude -p "..." --mcp-config riby-mcp.json --allowedTools "..."

Otherwise the label defaults to folder · branch, which on a runner is often less than helpful.

Crashes and restarts

If the runner dies mid-wait, the request survives on the server and in the local ledger. A restarted agent should call check_pending first — it returns this instance's outstanding requests with their current status, including answers that arrived while it was down. The page-your-human skill bakes this into session start.

On this page