Skip to content

rileyhilliard/rr

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

212 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

rr (Road Runner)

demo-extended

Run heavy workloads on remote machines without the hassle.

CI Go Release License


rr syncs your code to a remote machine and runs commands there. One command, no context switching.

rr run "make test"

Your project rsyncs to the remote, the command runs, and output streams back. Works from home, a coffee shop, or anywhere—rr figures out which connection works.

Contents

Why rr

I got tired of my laptop fan spinning up and battery draining every time I ran tests. I have a few beefy machines sitting in the corner doing nothing most of the time, so I wanted an easy way to sync code over and run heavy stuff on those instead.

Pi7_GIF_CMP

Especially useful for agentic coding: If you're doing TDD with Claude Code, Cursor, or similar tools, AI agents want to run tests constantly to verify their work. With multiple sub-agents running in parallel—or multiple features being developed simultaneously—your test suite gets hammered from all directions. rr queues test runs across your machine pool so agents aren't all fighting over localhost (and failing tests because they're stomping on each other).

The problem with existing tools:

Tool Issue
rsync && ssh Manual, repetitive, no connection failover
Ansible Requires inventory files, YAML playbooks, Python
DevPod/Tilt Container-focused, overkill for "sync + run"
VS Code Remote IDE-coupled, doesn't solve CLI workflows

rr fills the gap: a single binary that handles sync, execution, locking, load balancing, and connection failover—nothing more.

Features

  • Parallel task execution — Run multiple tasks across multiple hosts simultaneously with animated progress indicators
  • Smart connection failover — Configure multiple SSH paths (LAN, Tailscale, backup host) and rr picks the first one that works
  • File sync with rsync — Excludes .git, node_modules, etc. by default; preserves remote-only dirs like .venv
  • Distributed locking — Prevents concurrent runs on shared machines; auto-detects and waits if someone else is working
  • Load balancing — Single tasks are distributed across available hosts; parallel tasks use all hosts concurrently
  • Agentic coding friendly — Queues parallel test runs from AI agents (Claude Code, Cursor, etc.) across your machine pool
  • Claude Code skill — Install the rr skill and let Claude set up your environment and troubleshoot issues
  • Named tasks — Define test, build, deploy commands in config, run with rr test
  • Output formatters — Auto-formats pytest, Jest, Go test, and Cargo output for readable failure summaries
  • Real-time monitor — TUI dashboard showing CPU, RAM, GPU across all your hosts
  • Remote environment bootstrap — Declare required tools with require:, rr verifies they exist before running
  • Zero dependencies — Single Go binary, no runtime requirements
  • Works anywhere — macOS, Linux, Windows (WSL)

Quick start

# 1. Install
brew install rileyhilliard/tap/rr    # or see Install section below

# 2. Set up in your project
cd your-project
rr init                               # Creates .rr.yaml config

# 3. Run something
rr run "make test"                    # Syncs files + runs command

That's the whole flow. rr syncs your code to the remote, runs the command, and streams output back.

Install

Homebrew (macOS/Linux)

brew install rileyhilliard/tap/rr

Install script

curl -sSL https://raw.githubusercontent.com/rileyhilliard/rr/main/scripts/install.sh | bash

Go install

go install github.com/rileyhilliard/rr/cmd/rr@latest

Manual download

Grab the binary for your platform from releases.

Setup

Prerequisite: You need passwordless SSH access to your remote machine. If you can run ssh user@yourhost without entering a password, you're good. If not, see the SSH setup guide.

rr init          # Creates .rr.yaml - interactive prompts walk you through it
rr doctor        # Verifies everything works

If rr init doesn't detect your SSH config, you can add hosts manually. See configuration docs.

Usage

rr run "make test"    # Sync files, then run command
rr exec "git status"  # Run command without syncing (faster for quick checks)
rr sync               # Just sync files, no command

You can also define named tasks in your config:

tasks:
    test:
        run: pytest -n auto
    build:
        run: make build

Then run them by name:

rr test                    # Same as: rr run "pytest -n auto"
rr build
rr test tests/test_api.py  # Pass extra args: pytest -n auto tests/test_api.py
rr tasks                   # List all available tasks

demo-tasks

Parallel execution

parallel

Run multiple tasks across multiple hosts simultaneously. Define a parallel task that references other tasks, and rr distributes them across your machine pool with animated progress:

# .rr.yaml
tasks:
    test-backend:
        run: cd backend && pytest
    test-frontend:
        run: cd frontend && npm test
    test-opendata:
        run: cd opendata && python -m pytest

    # Parallel task - runs all three simultaneously across hosts
    test:
        parallel: [test-backend, test-frontend, test-opendata]
        fail_fast: false     # Continue even if one fails
        max_parallel: 3      # Limit concurrency (optional)
rr test
⣾ test-backend [m1-linux]
⣽ test-frontend [m1-mini]
⣻ test-opendata [m4-mini]

Tasks animate while running, then flip to success/failure in place:

◉ test-backend [m1-linux]
◉ test-frontend [m1-mini]
◉ test-opendata [m4-mini]

Parallel Execution Summary

  ◉ test-backend on m1-linux (52.9s)
  ◉ test-frontend on m1-mini (4.0s)
  ◉ test-opendata on m4-mini (40.0s)

  ◉ 3 passed  ✕ 0 failed  ● 3 total  (52.9s)
  Hosts: m1-linux, m1-mini, m4-mini

Why this is powerful: A 10-minute test suite split across 4 hosts finishes in ~2.5 minutes. For agentic coding workflows where AI agents constantly run tests to verify their work, this means faster feedback loops and less waiting. Multiple agents or features being developed simultaneously get distributed across your machine pool automatically.

Nested parallel tasks: Parallel tasks can reference other parallel tasks. rr flattens the hierarchy automatically:

tasks:
    test-opendata:
        parallel: [opendata-1, opendata-2, opendata-3]
    test-backend:
        parallel: [backend-1, backend-2, backend-3]
    # References both parallel tasks - expands to 7 tasks total
    test:
        parallel: [test-opendata, test-backend, frontend]

Run rr test-opendata for just the opendata splits, or rr test for everything. Add splits to test-opendata and test automatically includes them.

Output modes:

rr test              # Default: animated progress
rr test --stream     # Real-time output with [host:task] prefixes
rr test --verbose    # Full output shown when each task completes
rr test --quiet      # Summary only
rr test --dry-run    # Show plan without executing

Configuration

rr uses two config files to separate personal settings from shareable project settings:

File Location Purpose Commit to git?
Global ~/.rr/config.yaml Your hosts, SSH paths, directories No
Project .rr.yaml Sync rules, tasks, host selection Yes

Global config — your machine definitions:

# ~/.rr/config.yaml
version: 1

hosts:
    mini:
        ssh:
            - mac-mini.local # Try LAN first
            - mac-mini-tailscale # Fall back to VPN
        dir: ${HOME}/projects/${PROJECT}
        require: [go, node]  # Tools that must exist on this host

Project config — shareable settings:

# .rr.yaml
version: 1
hosts: [mini] # Optional: defaults to all hosts

require: [go, golangci-lint]  # Project-level requirements

sync:
    exclude: [.git/, node_modules/, .venv/]

tasks:
    build:
        run: cargo build
        require: [cargo]  # Task-specific requirement

${PROJECT} expands to your local directory name. See configuration docs for all options.

How It Works

Connection failover: rr tries each SSH path in order and uses the first one that connects. Configure your fastest option first:

hosts:
    gpu-box:
        ssh:
            - 192.168.1.50 # LAN - fastest
            - gpu-tailscale # VPN - works from anywhere
            - user@backup-gpu # Backup machine
Your location What happens
Home (LAN) Uses 192.168.1.50
Coffee shop LAN times out → uses Tailscale
gpu-box busy Skips to backup-gpu

File sync: Wraps rsync with smart defaults. Excludes build artifacts, preserves remote-only directories (like .venv installed on the remote).

Locking: Creates a lock before running commands. If a host is locked, rr tries the next host. If all hosts are locked, it round-robins until one frees up.

Output formatting: Auto-detects pytest, Jest, Go test, Cargo and formats failures for readability. Disable with --format=generic.

Commands

# Core workflow
rr run "make test"      # Sync + run command
rr exec "git status"    # Run without syncing
rr sync                 # Sync only

# Tasks
rr test                 # Run named task
rr tasks                # List available tasks

# Monitoring & status
rr monitor              # TUI dashboard: CPU/RAM/GPU across hosts
rr status               # Show connection and sync status
rr doctor               # Diagnose issues

# Host management
rr host list            # List configured hosts
rr host add             # Add a new host interactively
rr host remove mini     # Remove a host

# Maintenance
rr unlock               # Release a stuck lock
rr update               # Update to latest version
rr completion bash      # Shell completions (also: zsh, fish, powershell)

Troubleshooting

Start with rr doctor — it checks your config, SSH setup, and dependencies:

rr doctor

demo-doctor

Common issues:

Problem Solution
Connection fails Run rr doctor to check SSH. Ensure you can ssh user@host without a password.
Command not found on remote Remote PATH differs from interactive shell. Add shell: "zsh -l -c" to host config.
Sync is slow Check exclude patterns — syncing node_modules or .git tanks performance.
Lock stuck Run rr unlock to release. Locks auto-expire after 10 minutes.

For more, see the troubleshooting guide.

Documentation

Guide Description
SSH Setup Get passwordless SSH working
Configuration All config options explained
Troubleshooting Common issues and fixes
Architecture How rr works under the hood
Migration Upgrading from older versions
Examples Sample configs for different setups

Claude Code Integration

If you use Claude Code, install the rr skill to let Claude help set up and manage your rr environment:

/plugin marketplace add https://github.com/rileyhilliard/rr
/plugin install rr@rr

Once installed, Claude can help with setup and troubleshooting. To set up rr for your project. From your project root, run:

/rr:setup

This walks through creating configs, verifying SSH connectivity, testing remote execution, and ensuring dependencies are available on your remote hosts.

See docs/claude-code.md for details.

Contributing

Contributions welcome! See CONTRIBUTING.md for development setup and guidelines.

License

MIT

About

Easily sync code to a remote machine and run commands there. That's it.

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors