ctrlrelay

Local-first orchestrator that drives headless Claude Code (claude -p) across your GitHub repos. Watches for assigned issues, runs the dev pipeline in an isolated git worktree, opens a PR, and asks you on Telegram when it gets stuck.

Get started Configure Set up the bridge


Use it

  • Getting started — install, write your first config, run the dev pipeline against an issue.
  • Configuration — every key in orchestrator.yaml, with defaults and what they actually do.
  • Telegram bridge — BotFather walkthrough, starting the bridge, troubleshooting Telegram delivery.
  • Feedback loop — how BLOCKED_NEEDS_INPUT checkpoints reach you and how your reply resumes the paused Claude session.
  • CLI reference — every subcommand and flag.
  • Operations — running the bridge and poller under launchd (macOS) or systemd (Linux), tailing logs, reading the state DB.

Build on it

  • Architecture — layered overview, dispatcher ↔ Claude contract, state DB shape, worktree lifecycle.
  • Development — local dev setup, tests, ruff, contributing.

What is this?

ctrlrelay sits between GitHub and your laptop’s claude install. The poller checks each configured repo for issues newly assigned to you. When it sees one, it acquires a per-repo lock, creates a worktree on a fresh branch, spawns claude -p with the issue title and body in the prompt, and lets the agent work TDD-style toward a PR. When the agent gets stuck, it writes a checkpoint, the orchestrator routes the question to your Telegram chat, and your reply resumes the same Claude session.

Everything runs locally. State lives in a SQLite file. Bridge state lives in a Unix socket. The Telegram bot is the only outbound dependency, and it’s optional — ctrlrelay will run without it for local testing.