| name | rr |
| description | Sync code and run commands on remote machines. Use when running tests, builds, or commands remotely, syncing files to hosts, setting up remote development, or troubleshooting rr configuration. |
| user-invocable | true |
| allowed-tools | ["Bash","Read","Edit","Grep","Glob"] |
rr (Road Runner) CLI
rr syncs code to remote machines and runs commands there. Handles host failover, file sync with rsync, distributed locking, and test output formatting.
Quick Reference
rr run "make test"
rr exec "git status"
rr sync
rr <taskname>
rr provision
rr doctor
rr monitor
Two-Config System
rr uses two config files:
| Config | Location | Purpose |
|---|
| Global | ~/.rr/config.yaml | Personal host definitions (SSH, directories) |
| Project | .rr.yaml | Shareable project settings (tasks, sync rules) |
See config.md for complete config reference.
Minimal Global Config
version: 1
hosts:
mini:
ssh: [mac-mini.local, mac-mini-tailscale]
dir: ${HOME}/projects/${PROJECT}
Minimal Project Config
version: 1
hosts: [mini]
sync:
exclude: [.git/, node_modules/, .venv/]
tasks:
test:
run: pytest -v
Commands Overview
| Command | Purpose |
|---|
rr run "cmd" | Sync files, then run command |
rr exec "cmd" | Run command without syncing |
rr sync | Just sync files |
rr <taskname> | Run named task |
rr tasks | List available tasks |
rr provision | Install missing tools on hosts |
rr doctor | Diagnose issues |
rr host list/add/remove | Manage hosts |
See commands.md for full command reference.
Common Flags
--pretty / -p - Opt into human-readable output (spinners, colors). Default is structured JSON.
--host <name> - Target specific host
--tag <tag> - Select host by tag
--local - Force local execution
--skip-requirements - Skip requirement checks
Run rr --help or rr <command> --help for complete flag reference.
Tasks
Define reusable commands in .rr.yaml:
tasks:
test:
description: Run tests
run: pytest -v
deploy:
steps:
- name: Build
run: make build
- name: Deploy
run: ./deploy.sh
Run with: rr test, rr deploy
Extra arguments append to single-command tasks: rr test -k "test_login"
See tasks.md for parallel tasks, multi-step tasks, and advanced configuration.
Task Types and Arguments
Tasks come in three types. The type determines whether extra args work:
| Type | Config field | Accepts args? | Example |
|---|
| Single-command | run: | YES | rr test -k "test_foo" |
| Multi-step | steps: | NO (errors) | rr deploy |
| Parallel | parallel: | NO unless forward_args: true | rr test-all |
When you need custom args on a parallel task, bypass it:
rr run --cwd backend "uv run pytest tests/bond/ -v"
rr run "cd backend && uv run pytest tests/bond/ -v"
To check which type a task is: rr <task> --help
To forward args to all subtasks in a parallel task, set forward_args: true in the task config:
tasks:
test-backend:
parallel: [test-backend-api, test-backend-services]
forward_args: true
Choosing the Right Command
Need to run something remotely?
├── Named task exists? → rr <task>
│ ├── Single-command task → rr <task> <args> (args forwarded)
│ ├── Parallel task (forward_args: true) → rr <task> <args>
│ └── Parallel task (default) → rr run "cd <dir> && <cmd> <args>"
├── No task, files may have changed → rr run "<command>" (syncs first)
└── Files already synced → rr exec "<command>" (faster, skips sync)
Never nest rr inside rr exec — rr may not be installed on the remote:
Reading rr Output
rr sends phase events (connect, sync, exec) to stderr and command output to stdout.
rr test-opendata 2>/dev/null
rr test-opendata --no-phases
rr test-opendata 2>&1
The final result is always a JSON line on stderr with "type":"result" containing exit code, host, and duration.
Remote Environment Bootstrap
Declare required tools with require: - rr verifies they exist before running commands:
require:
- go
- node
tasks:
build:
run: make build
require: [cargo]
hosts:
gpu-box:
ssh: [gpu.local]
require: [nvidia-smi, python3]
Run with: rr test-all, rr quick-check
Setup Phase (Once Per Host)
Avoid redundant setup work (dependency sync, migrations) when multiple subtasks run on the same host:
tasks:
test-all:
setup: pip install -r requirements.txt
parallel:
- test-unit
- test-integration
- test-e2e
Setup runs exactly once per host before any subtasks execute. If a host runs 3 subtasks, setup runs once (not 3 times).
Parallel Task Flags
| Flag | Purpose |
|---|
--stream | Show real-time interleaved output with [host:task] prefixes |
--verbose | Show full output per task on completion |
--quiet | Summary only |
--fail-fast | Stop on first failure (overrides config) |
--max-parallel N | Limit concurrent tasks |
--dry-run | Show plan without executing |
--local | Force local execution (no remote hosts) |
Task Dependencies
Define task execution order with depends. Tasks run their dependencies first, then execute their own command:
tasks:
lint:
run: golangci-lint run
test:
run: go test ./...
build:
run: go build ./...
ci:
description: Full CI pipeline
depends:
- lint
- test
- build
Run with: rr ci
Parallel Groups in Dependencies
Run multiple dependencies simultaneously:
tasks:
lint:
run: golangci-lint run
typecheck:
run: mypy .
test:
run: pytest
ci:
depends:
- parallel: [lint, typecheck]
- test
Executes: [lint, typecheck] (parallel) -> test
Orchestrator Tasks
Tasks with only depends orchestrate without running their own command:
tasks:
lint:
run: golangci-lint run
test:
run: go test ./...
verify:
description: Run all checks
depends: [lint, test]
Dependency Flags
| Flag | Purpose |
|---|
--skip-deps | Skip dependencies, run only the target task |
--from <task> | Start from a specific task in the chain |
rr ci
rr ci --skip-deps
rr ci --from test
Dependency Features
- Deduplication: Tasks run once even if referenced multiple times (diamond deps)
- Validation: Circular dependencies detected at config load
- Fail-fast: Stops on first failure when
fail_fast: true
- Timeout: Honor
timeout field for entire dependency chain
Output Modes
- progress (default): Live status indicators with spinners
- stream: Real-time output with
[host:task] prefixes
- verbose: Full output shown when each task completes
- quiet: Summary only at the end
Example:
rr test-all --stream
rr test-all --dry-run
rr test-all --local
Missing tools trigger actionable error messages. Tools with built-in installers (40+) can be auto-installed.
See requirements.md for complete requirements reference.
How It Works
- Host Selection: Tries SSH aliases in order until one connects
- Requirements: Verifies required tools exist (if configured)
- File Sync: Uses rsync with exclude/preserve patterns
- Locking: Creates lock on remote; if locked, tries next host
- Execution: Runs command with configured environment
Troubleshooting
| Problem | Fix |
|---|
| SSH fails | Check ssh <alias> manually, verify ~/.ssh/config |
| "handshake failed" but ssh works | Key not in agent: ssh-add ~/.ssh/id_rsa, add AddKeysToAgent yes to SSH config |
| "command not found" | Add setup_commands or check require config |
| Sync slow | Add large dirs to sync.exclude |
| Lock stuck | rr unlock |
| Lock timeout after crash or cancel | rr unlock --all — stale locks from sessions that didn't exit cleanly |
Self-Documentation
When you're unsure about a task's type, subtasks, or flags, run rr <task> --help before executing it. The help output shows whether the task is parallel (and lists subtasks), what flags it accepts, and whether it takes extra arguments. This is faster than reading .rr.yaml and avoids the silent-arg-drop problem.
See troubleshooting.md for detailed diagnostics.
Structured Output (Default)
rr defaults to structured output (agent-first). No flags needed. Phase events are emitted as JSON lines to stderr, command stdout/stderr passes through undecorated.
rr run "make test"
rr test
rr run --pretty "make test"
The --machine / -m flag still works but is a no-op (structured is already the default).
See machine-interface.md for JSON event format and error codes.
Quick Setup
rr host add
cd your-project && rr init
rr doctor
rr run "make test"
When to Use Each Command
| Situation | Command |
|---|
| Run tests with latest code | rr run "make test" |
| Quick check on remote | rr exec "git log -1" |
| Prep remote before multiple runs | rr sync |
| Install missing tools on hosts | rr provision |
| Debug connection issues | rr doctor |
| Watch resource usage | rr monitor |
| First time setup | rr init |
| Add new machine | rr host add |
Reference Files