downbeat
Stop copy-pasting between AI terminals. downbeat is a local, human-in-the-loop message bus for coordinating parallel AI coding-agent sessions on one machine — register a few peers, hand off tasks, and read replies back, all through a filesystem-backed broker + TUI + CLI + skill. Nothing happens without you: every watcher notifies, nothing auto-executes on the parent side, and a child only acts because you told it to at registration time.
Want to see it before installing? examples/parent-child-handoff/
is a five-command walkthrough of the whole loop (this GIF is demo.sh from that
directory, recorded verbatim with VHS).
Install
uv tool install downbeat # or: pipx install downbeat
downbeat init # one command installs the WHOLE runtime
downbeat init is the single source of truth for the entire relay runtime. It:
- bootstraps
~/.claude/relay/data dirs and migrates legacy messages, - installs the skill →
~/.claude/skills/downbeat/, - writes the
relay.pyshim →~/.claude/relay/relay.py, - installs the bundled hooks (
relay-inbox.py,relay-poll-offer.py,relay-resume-check.py) →~/.claude/hooks/(chmod +x), - installs the bundled slash commands (
relay-register/send/reply/peers/monitor.md) →~/.claude/commands/, - registers the relay hooks in
~/.claude/settings.json(idempotent, backed up, atomic).
It is safe to re-run: content-equal files are left as-is, already-registered hooks are
skipped, and a hook that differs from the bundled copy is kept (your local edit
wins) unless you pass --force. settings.json edits never clobber non-relay hooks
sharing the same event/matcher.
downbeat also ships as a native Claude Code plugin — an optional,
Claude-Code-only fast path alongside init's hand-merge, not a replacement
for it:
claude plugin marketplace add FreddieMcHeart/downbeat
claude plugin install downbeat@downbeat
See docs/plugin.md for how the two install paths coexist
(and what to do if you ran init before installing the plugin).
Use
downbeat register parent --role parent
downbeat register child --role child
downbeat send child "task" "do the thing"
downbeat inbox --peer child
downbeat reply <msg_id> "done"
downbeat tui # full management UI
kind is an open string: task (default for all normal messages) and backflow-ready
(structured RLM findings from a child — see the downbeat skill). Future kinds
(workflow-request, workflow-result) are planned for Phase 3.
Automatic idle-recipient notify
No manual step needed. If the TUI (downbeat tui) is open, its resident
event-driven watcher (watchdog FSEvents/inotify) fires a native OS
notification the moment mail arrives for a peer that's been idle for more
than 10 minutes. If the TUI isn't open, a Claude Code session
sending/replying to an idle peer gets the same native notification from
its own hook, independent of the TUI. Either way: notify-only, never
drains/acks/acts.
Background inbox polling
The first time you invoke a relay action in a Claude Code session, the skill
offers to start a 3-minute inbox poll via /loop. Accept to get notified of
incoming messages without having to manually check.
Continuous self-monitoring (/relay-monitor)
In a registered Claude Code session, run the /relay-monitor slash command to make that
session continuously pull its own inbox and act on new messages:
/relay-monitor # start monitoring, default 3-minute interval
/relay-monitor 5m # custom interval
/relay-monitor stop # stop
Behaviour is role-asymmetric:
- child session: auto-executes arriving tasks per its role briefing and replies with results (consent-at-startup autonomy).
- parent session: surfaces new messages concisely and asks the human how to handle each; never auto-executes.
Before starting the monitor, check your identity with:
downbeat whoami # prints: <name> <role>
downbeat whoami --json # prints: {"name": "...", "role": "..."}
Automatic notify vs /relay-monitor — key distinction:
| Automatic idle-notify | /relay-monitor |
|
|---|---|---|
| Runs as | TUI's resident watcher, or a Claude Code hook — no separate process to start | in-session /loop |
| Does | fires a native OS notification (human reads it, decides what to do) | session pulls mail into its own context + acts per role |
| Acts? | never | child: yes (autonomous); parent: no (surfaces) |
| Idle cost | ~0 (event-driven when TUI open; hook-adjacent cadence otherwise) | a model turn every interval |
| Use when | you want a nudge, not automation | a session should self-drive on its inbox |
Both are complementary and can run at the same time.
TUI keybindings
| Key | Action |
|---|---|
| Tab/Shift+Tab | Cycle focus: Messages → Composer |
| s | Switch acting-as parent |
| a | Toggle archived history (chat view, 📥 inbox tab) |
| c | Clear inbox — archive this peer's backlog → processed/ (chat view, 📥 inbox tab) |
| Left/Right | Prev / next group member |
| Up/Down | Within focused region (messages, composer) |
| Enter | Send (in composer) / Open message detail (in message list) |
| Escape / q | Back (in message detail) |
| e | Edit (in message detail, only NEW) |
| r | Reply (in message detail) |
| d | Delete with confirm (in message detail) |
| Shift+B | Broadcast status (in message detail, when applicable) |
| y | Yank (copy) message body to clipboard (chat view and message detail) |
| c | Copy message id to clipboard (in message detail) |
| Up/k, Down/j | Scroll up / down in message detail |
| Ctrl+B / PgUp | Page up in message detail (Fn+↑ alias) |
| Ctrl+F / PgDn | Page down in message detail (Fn+↓ alias) |
| g / Home | Top of message detail (Fn+← alias) |
| G / End | Bottom of message detail (Fn+→ alias) |
| Ctrl+P | Peers screen (add / remove / gc) |
| f | Find message by id |
| ? / F1 | Help |
| Ctrl+R | Refresh |
| Ctrl+L / F6 | Toggle log viewer |
| q | Quit |
Uninstall
downbeat uninstall # removes skill + shim + hooks + commands + relay
# settings.json regs; leaves data + backups in ~/.claude/relay
Layout
- Source:
src/downbeat/{core,cli,tui,skill} - Bundled runtime assets:
src/downbeat/assets/{hooks/,commands/,hooks_manifest.json} - Tests:
tests/ - Examples:
examples/ - Roadmap:
ROADMAP.md— where downbeat is headed - Docs site: freddiemcheart.github.io/downbeat (source)
- State:
~/.claude/relay/{sessions.json, inbox/, processed/, logs/, groups.json}
Metadata
Release files for downbeat 0.18.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| downbeat-0.18.0.tar.gz | 576.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| downbeat-0.18.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 691.8 kB
Release files / downbeat-0.18.0.tar.gz
| Download URL | downbeat-0.18.0.tar.gz |
|---|---|
| Size | 576.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
62f13030b1d94c3631406e7c9261ac87d469433c8b8add3d4134e766e14b66d1
|
|
BLAKE2b-256 checksum How to use checksums |
e438b7bc3a289f1a9fd696e018520013ea20f5696ff495278f0fe5ce268494e6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.6 {"installer":{"name":"uv","version":"0.12.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / downbeat-0.18.0-py3-none-any.whl
| Download URL | downbeat-0.18.0-py3-none-any.whl |
|---|---|
| Size | 115.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b3a1999b3d77d19c5eeb74c42d46bc42449205353376b1eaeca75dce46120ebd
|
|
BLAKE2b-256 checksum How to use checksums |
1cec9eb0892b29fd7ad7a62204e46828ed8d98d34af4123691198d2d9d4d75ce
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.6 {"installer":{"name":"uv","version":"0.12.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for downbeat 0.18.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.