Skip to main content

An authenticated, contract-enforcing message broker that lets two developers' AI coding agents collaborate across the internet.

Project description

sys-buddy

Let your AI coding agent talk to your teammates' agents.

One task, your agents on it — they negotiate the contract, build, and ship while you just watch.


Status: built and dogfooding. The broker, MCP tools, enforced state machine, pairing (CLI + browser onboarding), dashboard API, live-updating dashboard UI, and Slack are implemented and covered by 470+ tests plus a live end-to-end. See the Quickstart to run it. Design/spec live in SPEC.md, KICKOFF.md, and DECISIONS.md.


The problem

You're the backend engineer. Your teammate is the frontend engineer. You both use Claude Code.

Every API contract, every field rename, every "ok it's deployed now" gets manually relayed by you, copy-pasting between two agent sessions. You're a message bus made of meat, sitting between two systems that could coordinate at machine speed.

Existing tools all assume one developer, one machine, one trust domain. sys-buddy is for agents belonging to different humans, coordinating over the internet, with authenticated identity, an enforced workflow, and an audit trail both people can watch.

The principle

The broker enforces. Agents request.

Rules that live in prompts get ignored, injected, and forgotten. Rules that live in database constraints don't. So the broker owns the workflow: it validates contracts, rejects out-of-order actions, counts test failures, and stamps every message with a cryptographically-verified identity the agent cannot forge.

How it works

                    ┌──────────────────────────────────┐
                    │       sys-buddy (FastMCP)        │
   your agent ─MCP─▶ │  /mcp        MCP tools           │
 buddy's agent ─MCP─▶ │  /pair       pairing REST        │ ─▶ Slack
     browser ─HTTP─▶ │  /ui + /api  dashboard           │
                    │  SQLite (WAL)                    │
                    └──────────────────────────────────┘

One Python process. One port. One tunnel.

  1. You create a task and mint a single-use invite for your buddy's role
  2. They run sys-buddy join <url> <code> — their agent gets a scoped token, they get a read-only dashboard link
  3. Both agents propose and lock a structured API contract — Slack pings both humans
  4. Backend builds, deploys, reports live. Only then can the frontend agent run its tests — the broker refuses earlier
  5. Tests fail? Frontend reports it, backend fixes, retry. The broker counts. Three strikes → task marked stuck, humans pinged
  6. Tests pass → VERIFIED → both agents stop → Slack says so

Nobody relayed a message.

Quickstart

Install

From PyPI (recommended) — a pinned, released version, isolated from any checkout:

uv tool install sys-buddy        # installs the `sys-buddy` command globally
# or:  pipx install sys-buddy    #  or:  pip install sys-buddy

Upgrade when a new version ships — uv tool upgrade sys-buddy — or pin/roll back exactly with uv tool install sys-buddy==1.3.0.

With Docker — a prebuilt container from GitHub Container Registry:

docker pull ghcr.io/tooney92/sys-buddy:latest        # or a pinned tag, e.g. :1.3.0
docker run -p 127.0.0.1:8787:8787 -v sysbuddy:/data ghcr.io/tooney92/sys-buddy

The image defaults to serve (auth enforced) — never local, which is unauthenticated. Put an https tunnel in front for a real remote deployment.

From source — only if you're hacking on sys-buddy itself:

git clone https://github.com/tooney92/sys-buddy && cd sys-buddy
uv sync
uv run sys-buddy ...             # runs your local checkout instead of the release

Once installed, the CLI is just sys-buddy ... — the examples below use that. Full step-by-step, including the remote/tunnel setup, is in SETUP.md.

Local — 60 seconds, no auth (solo dev, many repos on one machine)

# 1. start the broker (loopback, zero auth)
sys-buddy local                                    # → http://127.0.0.1:8787

# 2. register it with Claude Code in each repo
#    (re-pairing later? run `claude mcp remove sys-buddy` first — a name can't be overwritten)
claude mcp add --transport http sys-buddy http://127.0.0.1:8787/mcp

# 3. watch it happen (optional)
sys-buddy host-viewer                              # prints a dashboard link → /ui?v=...

That's it. Your agents call send_message / check_messages / propose_contract / report_status with a task and agent name — the broker auto-creates the task on first use. Drop the CLAUDE.md snippet from SPEC.md §13 into each repo to make coordination automatic.

Remote — two humans, two machines (the real thing)

# ── HOST ─────────────────────────────────────────────
ngrok http 8787                                    # or Tailscale / real infra

# tell every command the tunnel origin — serve AND invite/host-viewer read this,
# so the links they print point at the tunnel, not loopback:
export SYS_BUDDY_PUBLIC_URL=https://abc123.ngrok.app

sys-buddy serve                                    # binds 0.0.0.0, auth enforced
sys-buddy task create signin --roles backend,frontend
sys-buddy invite --task signin --role frontend     # → prints the buddy's https://…/join link + code
# send your buddy that /join link over Slack/Signal (or the sb1_ blob for CLI/desktop)

# ── BUDDY ────────────────────────────────────────────
sys-buddy join https://abc123.ngrok.app signin-J7fK2mQx --name dave-frontend
# → prints the agent token + the exact `claude mcp add ... --header "Authorization: Bearer sbk_..."`
#   command to run, plus a read-only dashboard link

--name is your agent's alias — the label that stamps every message and Slack ping (e.g. dave-frontend). Pick something recognizable; it's how the other humans tell whose agent said what.

No CLI required for the buddy. The invite doubles as a browser link — the host can send it straight over Slack/Signal. Opening it lands on /join, which walks the buddy through the Claude setup command, the briefing prompt, and their dashboard link. Cloning the repo is optional (only needed if they want to run their own broker).

Slack pings (optional): set SLACK_WEBHOOK_URL before sys-buddy serve and both humans get a message on contract-lock, verified, and stuck.

Revoke anytime: sys-buddy revoke-agent dave-frontend, sys-buddy revoke-viewer dave, or sys-buddy close signin (kills everything for that task).

Two modes

sys-buddy local sys-buddy serve
loopback, no auth, zero friction invite-pairing, scoped tokens, enforced state machine
your repos, your machine two humans, two machines, two orgs

Same tools, same schema, same dashboard. One flag.

Security, honestly

The full model is in SPEC.md §9. The short version:

  • An ngrok URL is not a secret. They get scanned within minutes, leak via link previews, and appear in certificate transparency logs. All security lives in authentication, never in obscurity.
  • You cannot filter prompt injection to zero. So the model doesn't try. Assume injection sometimes succeeds and make success worthless: agents can't request file reads or shell commands, staging URLs come only from signed contracts (never from chat), tokens are role-scoped to one task, irreversible steps need a human tap in Slack, and an injected loop still dies at three strikes.
  • Agent access and dashboard access are separate credentials. A leaked viewer link reads one task's transcript until you revoke it. It can't send anything.

Repo layout

SPEC.md          ← the complete specification. Start here.
KICKOFF.md       ← build instructions for a coding agent
DECISIONS.md     ← design decisions and spec deviations, with reasoning
SETUP.md         ← install + run: PyPI, Docker (ghcr), source, pairing, remote
CHANGELOG.md     ← released changes (Keep a Changelog + SemVer)
CONTRIBUTING.md  ← how to contribute: fork, branch, test, PR
v2.md            ← the backlog, with a build-difficulty score per entry
design/          ← Claude Design handoff: the dashboard prototype (visual source of truth)
reference/       ← agent_bus.py: working local-only predecessor + its ops guide
releases/        ← the fuller note per tagged release

Development

uv sync                        # install deps into .venv
uv run pytest -q               # the full spec suite (470+ tests)
uv run sys-buddy --help        # the CLI surface

Source lives in src/sys_buddy/: db (schema/WAL) · identity + middleware (auth) · service (messaging) · state + contracts (the enforced workflow) · pairing + admin (invites/tokens) · api (dashboard JSON) · server (assembly) · ui.html (single-file dashboard). Implementation decisions and spec deviations are logged in DECISIONS.md.

Versioning and releases

sys-buddy follows Semantic Versioning, and every notable change is recorded in CHANGELOG.md in Keep a Changelog format. Because this is a broker that agents talk to, the version boundaries are defined in terms of what an agent can see:

  • MAJOR — incompatible changes to the tool/wire contract or agent-visible behaviour.
  • MINOR — new, backwards-compatible capability.
  • PATCH — backwards-compatible fixes.

Releases are automated: contributors don't touch the version or the changelog. Merged PR titles follow Conventional Commits (feat: → minor, fix: → patch, feat!: → major), a release bot computes the next version and drafts the notes, and merging its release PR tags vX.Y.Z and publishes. See CONTRIBUTING.md for the commit conventions. Each release is git-tagged with a fuller note in releases/vX.Y.Z.md.

Contributing

Contributions are welcome — see CONTRIBUTING.md for the full walkthrough: forking, environment setup with uv, branch and commit conventions, what to run before review, and how to open the PR.

The short version:

# fork on GitHub, then:
git clone https://github.com/YOUR_USERNAME/sys-buddy.git && cd sys-buddy
git remote add upstream https://github.com/tooney92/sys-buddy.git
uv sync && git checkout -b feat/my-change
# ...change...
uv run pytest -q                      # must be green
git push -u origin feat/my-change && gh pr create --base main --fill

Three things worth knowing before you start:

  • main is branch-protected. Every change lands through a reviewed PR — the maintainer's included — so there is no faster path to take.
  • UI/dashboard changes need more than a green suite: prove them against a running local broker and attach screenshots. See CLAUDE.md.
  • Add a line to CHANGELOG.md under [Unreleased], and flag it in the PR if your change is agent-visible — that forces a MAJOR bump.

License

MIT.

Credits

Grew out of agent-bus, a ~130-line FastMCP message bus for coordinating Claude Code agents across repos on one machine (see reference/). sys-buddy is that idea taken across the internet, between people.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sys_buddy-1.4.0.tar.gz (1.2 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sys_buddy-1.4.0-py3-none-any.whl (188.8 kB view details)

Uploaded Python 3

File details

Details for the file sys_buddy-1.4.0.tar.gz.

File metadata

  • Download URL: sys_buddy-1.4.0.tar.gz
  • Upload date:
  • Size: 1.2 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for sys_buddy-1.4.0.tar.gz
Algorithm Hash digest
SHA256 2f77bf1d5edeaf9bc26639bcdffdf03b9927d51de7f30494be022af4e09acc58
MD5 64462f078c831bf51b789ca0328c152d
BLAKE2b-256 21dc32a84b2d2f8c4e04fb51302f19a638ff9855f4594fbcd3368e674a273208

See more details on using hashes here.

Provenance

The following attestation bundles were made for sys_buddy-1.4.0.tar.gz:

Publisher: release-please.yml on tooney92/sys-buddy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sys_buddy-1.4.0-py3-none-any.whl.

File metadata

  • Download URL: sys_buddy-1.4.0-py3-none-any.whl
  • Upload date:
  • Size: 188.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for sys_buddy-1.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 db88a88d3e1e697e2d5ada8b0a16f696a08facbbef67c030e7c7052a91451e0b
MD5 8ea5978a2b5abc6bfddc149b9a78ec14
BLAKE2b-256 5a0f07caf8f17b444be29b5f395f5864b19eaf15a973eaf74be889ab0c4636cb

See more details on using hashes here.

Provenance

The following attestation bundles were made for sys_buddy-1.4.0-py3-none-any.whl:

Publisher: release-please.yml on tooney92/sys-buddy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page