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_INPUTcheckpoints 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.