Local-first multi-agent coordination for messages, leases, shared plans, status, and resources.
A local-first coordination bus for a fleet of AI agents working in parallel — within a single repository or spread across a whole ecosystem of them. One WebSocket hub is the shared source of truth for presence, work claims, chat, task status, and resource offers: agents address each other across projects and share one plan, while file-scope claims keep the agents in any one repository from receiving overlapping live authority. Documented provider hooks and the staged Git gate enforce that authority only on their covered mutation surfaces.
New here? Read Why SYNAPSE CHANNEL — a five-minute read on what it is, what you build on it, how it differs from the tools next to it, and why coordination becomes the bottleneck once you run more than one agent.
Project lineage: SYNAPSE CHANNEL dates back to September 2025.
The bus is transport-light (one dependency, websockets), hub-centric by design
(one place owns presence, leases, and history), and runs entirely on the local
machine. Model workers reply on-channel through any OpenAI-compatible endpoint,
including a local Ollama server, with a deterministic rule-based fallback for
offline use.
Your existing agents plug in without new code. Any Model Context Protocol
host — Claude Code, Claude Desktop, Cursor — reaches the bus through the bundled
synapse mcp server, which exposes send, durable inbox, status, claim, release,
handoff, and task verbs as MCP tools plus the board, agents, and resources as
read-only MCP resources. Agents that speak A2A connect through the Agent Card face instead.
The hub itself stays protocol-agnostic and the core install keeps its single
dependency — the MCP and A2A adapters are optional extras (pip install 'synapse-channel[mcp]'). See the MCP guide.
python -m pip install synapse-channel && synapse demo
Synapse's daily promise is three explicit loops:
synapse git-init, synapse git-claim,
synapse git-claim-check --staged, synapse task, and syn ack turn work
scope, dependencies, and evidence into shared state instead of side-channel
notes.synapse who, synapse state,
synapse dashboard, synapse event-query, and observed peer rows show who is
present, what is claimed, what changed, and which peer-hub facts are advisory.Seven shipped coordination surfaces, each named by the command or doc that delivers it today:
Claim before edit. synapse git-init installs claim-aware Git hooks; synapse git-claim records an exact worktree, branch, and path scope so an overlapping claim can be refused before files diverge.
Block unclaimed native file edits. Provider file-edit claim hooks adapt Claude Code Edit|Write, Codex apply_patch, Gemini CLI replace|write_file, and Kimi Edit|Write to one live-claim decision engine.
Share the plan. synapse task and synapse board keep task state, dependencies, and ready work on the hub instead of in separate agent notes.
Hand work over without an ownership gap. Atomic handoff moves the held task, scope, status, and checkpoint to an online recipient without a release-and-reclaim window.
Expose a dark seat. After 30 continuous seconds without the owner's exact waiter, the hub emits one dark_seat_alert for affected claims or assigned work, including the permanent-arm remedy; it does not release or reassign work automatically.
Read the fleet from one cockpit. synapse dashboard serves the local command centre, exact-status task columns, claims, conflicts, security posture, and an optional durable event feed; the read-only Studio projection adds no new hub authority.
Connect existing agent protocols at the edge. synapse mcp exposes coordination tools and read-only resources over stdio; the A2A bridge exposes a local Agent Card and HTTP+JSON surface while keeping its partial validation boundary explicit.
graph LR
A1["Agent"] --> H
A2["Agent"] --> H
A3["Worker"] --> H
SUP["Supervisor"] --> H
H["SynapseHub<br/>single source of truth"] --> CL["Claims & leases<br/>scope · epoch · checkpoint"]
H --> BB["Blackboard<br/>plan + progress"]
H --> CAP["Capabilities<br/>cards + routing"]
H --> LOG["Event log (SQLite WAL)<br/>durable · optional SQLCipher at rest"]
A claim leases a declared unit of work with a file scope, so the hub refuses overlapping live claims. Provider hooks and the staged Git gate enforce that authority on their documented surfaces; they do not sandbox every filesystem or external side effect. Plans, handoffs, checkpoints, and a stall supervisor keep the work moving, and the durable event log means a hub restart resumes live leases rather than losing them.
SYNAPSE CHANNEL ships as one installable package, but the public surface is tiered so the lean bus stays clear:
| Layer | Taxonomy tier | What belongs there |
|---|---|---|
| Local coordination core | stable | The hub, send/wait/listen/arm, claims, tasks, locks, status, board, init, and fleet bootstrap commands used for daily coordination. |
| Edge adapters | adapter | MCP, A2A, git hooks, tmux/provider bridges, shell hooks, ingestion, and worker seats that connect existing tools to the bus. |
| Operator analysis | analysis | Doctor, state, dashboard, causality, multihub, reliability, trust graph, directory, accounting, fleet scorecard export, manifests, and event queries. These do not mutate coordination state; explicit export modes can write to an operator-selected sink. |
| Governance and integrity | governance | Policy checks, approvals, ACL/role surfaces, federation, Merkle roots, release receipts, reproduction, compaction, encrypt-key / SQLCipher key operations. |
| Lab surfaces | experimental | Benchmarking, participant fabric, route-task, sandbox, workflow, TTL advice, memory recall, auto-action, and resource bidding. |
The authoritative map is synapse_channel.surface_taxonomy
and the generated operator view is Public surface and stability.
Adapters and lab surfaces can be installed and used from the same package, but
they do not change the single-dependency local core.
Six measurable discovery profiles keep those layers explicit without hiding or
removing commands: first-use, core, adapters, governance, labs, and
all. Inspect any profile without starting a hub or optional process:
synapse commands --profile first-use
synapse commands --profile first-use --json
The JSON contract records three first-use concepts and three shell commands, against a hard limit of eight concepts, with zero optional extras and zero implicitly started persistent services. Profile inspection is read-only; optional capabilities activate only through their documented package extra and command or flag, and deactivate by stopping that exact process or omitting the opt-in. See installation profiles.
participant ask, participant exchange, and participant convene can wrap
their seats with bounded, read-only recall from REMANENTIA's lightweight HTTP
API. Recall is disabled unless --memory-url is present; no memory process is
started implicitly. Tokens are accepted only through --memory-token-file, and
recalled snippets enter TurnRequest.context inside a data-only fence while the
operator prompt remains unchanged.
synapse participant ask claude "review this design" \
--memory-url http://127.0.0.1:8001 \
--memory-token-file /run/secrets/remanentia
Current HTTP results omit REMANENTIA's honesty axes, so every recalled hit is shown as boundary data; similarity is relevance evidence, not truth evidence. No-hit and unavailable states remain visible without failing the provider turn. See Participant memory recall for setup, limits, CLI flags, library use, and audit boundaries.
Coming: Studio — the dashboard is growing into an operator Studio: a control plane that answers, at a glance, what is happening, what is at risk, and what is safe to do next. The instrument-panel design system,
/studioreference, live/studio/commandshell, security-posture panel, and event-log LiveFeed have shipped. Local-first and read-only by default — an organisation-level workbench is planned as a separate layer.
python -m pip install synapse-channel # the release from PyPI
python -m pip install -e ".[dev]" # or an editable dev checkout
# optional: live hub event-store page encryption (SQLCipher)
python -m pip install 'synapse-channel[sqlcipher]'
# optional: whole-file AES-GCM envelope helpers (encrypt-key profile/migrate/rekey)
python -m pip install 'synapse-channel[encryption]'
For an editable checkout, keep the local .venv aligned with the repository's
declared dev, docs, and benchmark extras:
.venv/bin/python tools/check_dev_dependency_drift.py --check
.venv/bin/python tools/audit_dependency_tooling.py --check
The second check is offline. It verifies that local preflight still covers the expected tool gates, GitHub Actions are pinned to full commit SHAs, Dependabot covers actions/Python/Docker, and the PyPI publish/download metadata surfaces remain wired.
This installs the synapse command. To run the hub as an always-on local service
or a container, see the deployment guide (a systemd user
unit and docker compose are both included). On Linux, install only a permanent
exact-identity waiter with
synapse arm install --identity myproject/agent --start; it uses mailbox replay
and Restart=always, without installing a hub. Its
myproject/agent-rx receiver can coexist with agent-tmux's distinct
myproject/agent-pane-rx bridge, preserving durable gap recovery and active
pane delivery without name takeover. The pane bridge fails closed on busy,
modal, unknown, or ambiguous provider screens: it persists the pending wake and
submits its fixed prompt only after two provider-specific idle-composer probes.
It acknowledges delivery only after the pane shows prompt consumption; an Enter
ignored during asynchronous provider startup leaves the single staged prompt
pending for a safe Enter-only retry.
It accepts only exact identity, role, or group targets; global priority and CEO
broadcasts remain durable inbox traffic but never inject into provider panes.
For unattended active delivery, supervise that pane bridge independently of agent turns:
synapse waker install \
--identity myproject/agent \
--session myproject-agent \
--cwd "$PWD" \
--agent-command codex \
--start
synapse waker status --identity myproject/agent
The generated synapse-waker@.service has Restart=always and a main-loop
watchdog, so a dead bridge is recreated without relying on the agent to remember
to re-arm it. waker stop --reason ... first persists an inhibited state and
then stops only the exact bridge; systemd cannot immediately resurrect it, and
the tmux provider terminal is not killed or restarted. Only an explicit
waker resume clears the inhibit.
Native Windows service setup is not
claimed; use WSL with systemd as documented in the deployment guide.
For agent-assisted environment preparation, synapse setup spec, inspect,
plan, authorize, apply, verification-plan, authorize-verification,
and verify expose the packaged synapse-setup.v1
contract. The first three describe requirements, observe the host, and bind a
credential-free target to a non-executable SHA-256 plan. authorize emits a
short-lived envelope for one reviewed plan. Restart authority must match the
exact hub PID observed in that plan; first-start authority carries no PID. On
Linux with systemd-user,
apply re-inspects the target and plan-bound executable generation, atomically
reserves the authorization in a private replay ledger, and may install or start
only the package-owned local hub and exact waiter units. It preserves declared
PIDs, emits a digest-bound receipt, and restores prior unit and service state on
failure. After a successful application, the separate verification transaction
sends one directed canary, requires the exact waiter's durable ACK, restarts
only the authorized hub PID, proves replay through a new hub PID, re-inspects
the bound generation, and preserves declared terminal/provider PIDs. It emits a
single-use, digest-bound verification receipt; an application receipt alone is
not strict end-to-end readiness evidence. Package, Python, identity, secret,
remote, macOS, native Windows, and container changes remain blocked. See
Machine-readable setup for the schema,
expiry, nonce-consumption, and exact-PID authority rules.
Two optional shell conveniences ship with the CLI: synapse completions bash|zsh|fish prints tab completion for every subcommand (generated from the
live parser, so it never drifts), and synapse install-shell-hook adds the
guarded block that auto-arms a wake listener in each new terminal:
synapse completions bash > ~/.local/share/bash-completion/completions/synapse
synapse install-shell-hook # auto-arm Bash, Zsh, and Fish terminals
See use cases for when it fits, when it is overkill, and who reaches for it.
The one path to follow. Run the three-command self-contained proof below, then follow the multi-seat golden path for persistent agents. Optional adapters and generated workspaces come later.
On a clean Python environment, verify the installed CLI before wiring agents into a real repository:
python -m pip install synapse-channel
synapse doctor
synapse demo --output ./synapse-golden-demo
synapse doctor reports local setup issues such as identity, hub exposure,
root-filesystem pressure, and missing waiters. A brand-new machine may warn that
no hub or waiter is running; that is expected before service setup. synapse demo starts its own local hub, drives a planner/worker coordination flow, and
succeeds when it prints:
The CLAUDE and CODEX names in that flow are scripted in-process
SynapseAgent identities. The demo launches no provider CLI and spends no model
turn.
success: coordination demo completed
After the self-contained proof, synapse quickstart-coding remains available as
an optional generated-workspace demo. It creates a temporary coding-fleet
workspace, runs the live overlapping-claim refusal demo, removes the workspace
after success, and prints:
success: coding fleet demo completed
Or run the whole first-run sequence as one command:
synapse fleet-init
It runs the doctor (--fix to repair the default local hub and waiter),
scaffolds a persistent ./synapse-fleet workspace, probes which provider CLIs
this machine can seat (claude, codex, kimi, ollama, …), runs the demo smoke,
and prints the next-steps plan — waiter arming, per-provider seat commands,
git-init, dashboard — with the workspace's project name filled in.
Use one self-contained path before changing a real checkout:
python -m pip install synapse-channel
synapse doctor
synapse demo --output ./synapse-golden-demo
The demo starts and stops its own local hub, uses a disposable committed Git
repository, proves separate claims and overlapping-claim refusal, denies a
mutation before handoff, permits it after handoff, and writes an observed
verification receipt plus a static dashboard. It needs no persistent hub,
provider CLI, Git hook, MCP host, or A2A bridge. The same exact three-command
block is regression-bound across this README, the quick start, and the CLI
reference, and its synapse demo command is exercised as a real subprocess.
After that proof passes, use synapse fleet-init --fix to prepare a persistent
local workspace, hub, and waiter, then run synapse git-init --name trial-agent inside the real repository before an agent edits it. Optional A2A
interoperability is a follow-on in the A2A bridge guide; it is
not a prerequisite for first coordination value.
This package is developed in the open and dogfooded daily: a fleet of coding
agents runs its own coordination on it, so problems surface in real use and are
fixed quickly. Releases are therefore frequent and mostly small — fixes and
hardening rather than churn. Current 0.x releases do not promise backward
compatibility across minor releases. The wire vocabulary and public Python API
are guarded against accidental drift, but a reviewed 0.x minor release may
deliberately change either surface. Every such change updates the frozen
contract tests, bumps WIRE_PROTOCOL_VERSION for a wire-incompatible change,
and ships changelog plus migration notes. Starting with 1.0.0, a breaking
stable public Python API change requires a package major release; a breaking
wire change requires a wire-protocol version bump. See
API and wire stability.
1.0.0 is planned as the first stable commercial release of SYNAPSE CHANNEL,
with the operational contracts, packaging, support surface, and commercial
licensing terms documented as part of that release.
SYNAPSE CHANNEL is seeking startup funding, strategic partners, and aligned
ecosystem co-owners who want to help mature the coordination layer for
production multi-agent development. See commercial licensing
or write to protoscience@anulum.li.
If you need a fixed target, pin a version (synapse-channel==X.Y.Z); to get the
latest fixes, track the newest release. Both are supported.
Launch a hub plus one or two local model workers in one command:
synapse team
If Ollama isn't running, synapse team falls back to a single offline
rule-based worker (deterministic canned replies) so the flow still works; start
Ollama and re-run for real model replies.
Then, from another terminal, watch the channel or send a message:
synapse listen --name USER # terminal A: watch the channel as USER
synapse send --target FAST "what is the status of TASK-1?" # terminal B: one-shot, unique ephemeral sender
synapse send --require-recipient --target FAST "ping" # also print the positive receipt
A send without --name uses a unique ephemeral sender, so a one-shot send
never trips the hub's one-owner-per-name rule against a listener you already
have connected under the same name. One-shot sends also avoid the waiter-name
collision: synapse send --name api-dev-rx ... sends as api-dev, leaving the
persistent api-dev-rx wake
socket connected. Directed sends request a private receipt by default and exit
non-zero when no consume-live recipient matches — including when a stale socket
is still connected but has neither a recent reaction nor a live waiter. The
message remains journalled and best-effort routed, while the hub records a dead
letter instead of reporting socket presence as delivery. Each one-shot send
uses a unique message identity and accepts only its matching receipt, so an old
pending receipt replayed when the sender reconnects cannot be reported as the
new send's result. Add
--require-recipient when the positive receipt should also be printed and a hub
too old to return receipts must fail closed.
For selected sensitive payloads, encrypt the body before it reaches the hub and decrypt it only on the recipient side:
synapse send --target FAST \
--encrypt-key-file ./payload.key \
--encrypt-key-id project-main-v1 \
--encrypt-recipient FAST \
"private handoff note"
synapse listen --name FAST --for FAST --decrypt-key-file ./payload.key
The hub still sees sender, target, channel id, key id, recipient names, nonce, ciphertext, and delivery metadata. This does not manage key discovery or rotation.
synapse hub --port 8876
synapse hub --port 8876 --db ./synapse.db # crash-safe: resumes leases + history on restart
synapse hub --port 8876 --relay-log ./feed.ndjson # mirror the channel to a compact file for observers
synapse hub --shutdown-close-timeout 5 # bound active socket close handshakes on stop
synapse hub --max-progress-per-author 500 # cap retained board progress per author
synapse hub --max-findings-per-agent 200 # cap durable findings admitted per agent
synapse hub --tls-certfile ./hub.crt --tls-keyfile ./hub.key # native wss://
synapse worker --name FAST --provider ollama --model gemma3:4b
synapse worker --name OFFLINE --provider rule # no network, canned replies
synapse worker --name TIER --provider tiered --model small --heavy-model big # route trivial→rule, hard→heavy
synapse relay ./feed.ndjson # decode and print that file as readable lines
synapse ingest ./synapse.db --memory --cursor ./mem.cursor # stream durable memory events since a seq cursor (NDJSON)
synapse memory-recall ./synapse.db "transport handoff" # local recall over durable memory records
synapse compact ./synapse.db --all --max-checkpoints-per-task 3 --archive-report ./compact-report.html
synapse board # print the shared task/progress blackboard
synapse task declare BUILD --title "compile" --idem-key build-v1 # retry-safe durable write
synapse task update BUILD --status done # mark a plan task done so dependents unblock
syn ack BUILD --evidence "pytest -q" # post evidence and mark a board task done
synapse supervisor --idle-seconds 300 --history-multiplier 3 # re-offer stalled plan tasks
synapse manifest # print capability cards, including contract counts
synapse capability-card keygen --key-id PROJECT:worker:v1 --private-out ./card.pem --agent PROJECT/worker --project PROJECT --trust ./card-trust.json
synapse directory # print discovery-only agents/resources
synapse route-task BUILD --limit 3 --event-store ./synapse.db # add observed evidence
synapse resource-bids BUILD --resource-kind gpu # rank live resource offers without reserving capacity
synapse a2a-card --endpoint-url https://agent.example.com/a2a/v1 # emit A2A Agent Card JSON
synapse a2a-serve --endpoint-url http://127.0.0.1:8877 # run the HTTP+JSON A2A bridge
synapse doctor # check for common misconfigs (identity, exposure, hub, waiter)
synapse demo # installed self-check: local hub + planner/worker flow
synapse quickstart-coding # create a temporary coding fleet workspace and run it
synapse new coding-fleet ./demo-fleet # scaffold a runnable two-agent coding demo workspace
synapse hub --host 0.0.0.0 --token s3cret # require a shared secret when binding off-loopback
synapse hub --host 0.0.0.0 --token s3cret --tls-certfile ./hub.crt --tls-keyfile ./hub.key
synapse hub --max-connections-per-host 4 # cap simultaneous sockets from one remote host
synapse send --token s3cret --name USER "hello" # agents present the token to a secured hub
For an observed cross-hub task revision, task declare and task update also
accept --causal-parent HUB_ID:SEQ:SHA256. The SHA-256 is the complete event
fingerprint exposed in multi-hub board provenance. A verified same-task parent
lets the observed fold discard only that proven ancestor; a missing or
mismatched reference remains unresolved and never becomes a concurrency claim.
This metadata changes the advisory observed board, not local claim authority.
Synapse coordinates the agents you already run; it does not replace them. Its MCP and A2A adapters are interop surfaces: they let Claude Code, Claude Desktop, Cursor, Codex, Copilot-style hosts, Aider, orchestration frameworks, and other agent tools participate in one local coordination bus while those tools still own prompting, model choice, tool use, and editor/runtime behavior. The integration demo matrix lists three narrow, repeatable paths and the unsupported behavior that remains outside each demo.
Claude Code / Codex / Claude Desktop / Cursor (MCP): register the stdio server and its coordination tools load automatically — no shell hook or Synapse-specific client code.
python -m pip install 'synapse-channel[mcp]'
claude mcp add synapse -- synapse mcp # resolves <git-project>/mcp
codex mcp add synapse -- synapse mcp --name my-repo/codex
Cursor and Claude Desktop can reuse the secret-free
examples/mcp/.mcp.json template. MCP does not wake
an idle provider in this adapter; call synapse_inbox at turn start and keep
synapse arm install --identity NAME --start active for prompt delivery.
Claude Code / Codex / Gemini / Grok / Kimi native file edits: print a
provider-native pre-tool recipe (PreToolUse for the Claude family,
Grok, and Kimi; BeforeTool for Gemini CLI) that checks the authoritative live
claim before a supported file tool runs.
synapse adapters claude-claim-hook --identity my-repo/claude --print-config
synapse adapters codex-claim-hook --identity my-repo/codex --print-config
synapse adapters gemini-claim-hook --identity my-repo/gemini --print-config
synapse adapters grok-claim-hook --identity my-repo/grok --print-config
synapse adapters kimi-claim-hook --identity my-repo/kimi --print-config
synapse adapters kimi-claim-hook --identity my-repo/kimi --install-config
--print-config is read-only. Save the Grok fragment under
~/.grok/hooks/*.json; synapse adapters install grok separately installs
the kebab-case ~/.grok/skills/synapse/SKILL.md coordination skill. Kimi's
opt-in installer writes only one marked block in
$KIMI_CODE_HOME/config.toml (default ~/.kimi-code/config.toml), and
--uninstall-config removes only that block. The equivalent combined Kimi
path is synapse adapters install kimi --identity my-repo/kimi --with-hook.
The provider claim-hook guide documents exact tool coverage, token-file setup, and the native-host limits. These are bounded file guards, not complete Bash or filesystem isolation.
Aider, or any non-MCP tool: claim a file scope before editing and let a git hook release it on commit. The claim prevents conflicting grants; enforcement of the tool's working-tree writes remains the operator's responsibility, with the staged Git gate providing a separate commit-time check.
synapse quickstart-coding # optional: run a temporary overlapping-claim refusal demo
synapse new coding-fleet ./demo-fleet # optional: keep the generated workspace
synapse git-init --name aider-1 # one step: install the hooks + write the conventions guide
synapse git-claim --task-id AUTH --paths src/auth --name aider-1
aider src/auth/*.py # ... edit; the post-commit hook releases the claim
Check the wiring: synapse doctor reports the common setup mistakes — no live
waiter, a hub exposed without a token, an accidental identity, or a pressured
root filesystem — each with its fix. With a durable hub it also reports
N undelivered messages pending for <identity> from the receiver watermark;
this is mailbox transport acknowledgement, not proof a model processed the
messages. Use --disk-path <path> to check the filesystem that holds a
specific workspace or cache.
Inspect the live board: synapse dashboard --port 8765 opens a
loopback-only read-only HTML view of roster, exact blackboard/claim status
columns, progress,
fleet visibility, task-dependency graph edges, branch-conflict candidates,
release receipts, and advertised capabilities, with the same snapshot
available at /snapshot.json for local tooling. Pass --a2a-state-file <path>
to add persisted A2A task and push-config counts to the fleet section. The
dashboard derives task dependencies from the blackboard snapshot and uses live
claim metadata for branch conflicts; run synapse conflicts --check-diff when
you need client-side git-diff refinement. The state snapshot also carries
dead_letters — directed chats that reached no live connection, per target
with counts — so a message nobody is listening for shows up on the page
instead of being discovered by a human relaying it. The dashboard is growing
into an operator Studio — open /studio for the
design-system reference — and ships a React cockpit under clients/cockpit/
(build instructions in its README; serve the
built bundle with synapse dashboard --cockpit-dist clients/cockpit/dist).
If you deliberately expose the
dashboard with --allow-non-loopback, pass --dashboard-token <token> and
require clients to send Authorization: Bearer <token>; the React cockpit
loads its token-free static shell, asks for that bearer, and retains it only
in the tab's session storage. It never accepts the bearer in a URL. When the
token is omitted on an exposed bind, Synapse generates and prints a startup
token. Teams can instead pass an owner-only
--dashboard-access-file mapping separate viewer/operator/admin token files
to browser principals and distinct relay identities. The server-authored
capability descriptor removes unauthorized write controls from the DOM and
command search, but every POST is still re-authorized server-side and at the
hub; admin currently gains no mutation beyond the three shipped operator
writes. With --operator, the authorized command palette exposes governed
message, task-declaration, and task-update forms; each reports the hub's
strict outcome and grants no authority beyond the hub's validation, ACL, rate
limit, and audit decision. With --feeds-db, the cockpit's Audit tab incrementally renders the
universal receipt ledger and governed operator-relay history as two distinct,
bounded store-attested feeds. The receipt ledger includes minimized claim and
guard denials, dead-letter escalations, and identity-pin reclaim outcomes;
every declared durable EventKind is explicitly classified as receipt-bearing or
intentionally omitted. Absence and stale last-good data remain visible.
Add
--observed-peer HUB=URI to include advisory peer-hub rows in the browser and
/snapshot.json; those rows are labelled observed@HUB and never grant local
claims.
Verify a release redeploy: synapse doctor --redeploy-checklist prints
package, service, roster, durable-state, and git-hook checks for a post-release
local fleet restart. It does not restart services by itself, and restart
commands are withheld by default. After inspecting the exact live hub PID and
roster, an operator with fresh disruption authority can add
--redeploy-authorize-restart-pid PID; the rendered command rechecks that PID
while holding a fail-fast host-local custody lock. Dogfooding requires every
new release tag to be adopted by the local hub immediately after publication,
using that bounded authorised path and post-restart health verification.
Install the always-on local services: synapse init prints or installs the
hub, project presence, and non-LLM wake listener units. doctor --fix prints
the exact commands when a waiter is missing.
synapse init --project myrepo --identity myrepo/worker --install-user-services
synapse init --project myrepo --identity myrepo/worker --start-user-services
synapse doctor --fix
Launch a provider command with Synapse identity: worker-session exports
the identity variables before the provider starts. Interactive terminal
providers such as Codex, Claude, Kimi, and Grok run in a persistent tmux
session by default when launched from an interactive terminal, with a directed
waiter kept alive in the background. Non-terminal commands keep the temporary
syn arm sidecar path.
synapse worker-session --identity myrepo/worker -- codex --sandbox danger-full-access
Inspect or control the tmux wake path manually: codex-tmux is the
diagnostic/admin surface behind the automatic provider launch path. It keeps a
provider TUI in a named tmux session and injects a fixed wake prompt when
Synapse receives a directed message. It does not paste the Synapse payload into
the terminal; the provider reads the inbox itself after waking. Existing
sessions are accepted only when their live tmux environment matches the
configured SYN_PROJECT and exact SYN_IDENTITY; a session already owned by
another seat is refused by start, status, and wake before any keys are sent.
A successful tmux send-keys call is not treated as provider delivery: the
bridge observes prompt consumption and retains an unacknowledged staged prompt
for a later Enter-only retry, so provider startup cannot strand or duplicate it.
While waiting, the bridge disconnects at a bounded interval and re-proves the
session, binding, and live agent pane before registering again, so a vanished
pane cannot remain advertised indefinitely.
synapse codex-tmux start --identity myrepo/codex-main --session myrepo-codex --cwd "$PWD"
synapse codex-tmux wait --identity myrepo/codex-main --session myrepo-codex --cwd "$PWD"
For unattended operation, replace the manually maintained wait process with
synapse waker install --identity myrepo/codex-main --session myrepo-codex --cwd "$PWD" --agent-command codex --start. The waker supervises only the
delivery bridge and attaches to the existing bound session; it never owns the
provider terminal lifecycle.
syn commandsFor the short loop an agent runs every session — arm a waiter, send a message,
read the inbox, glance at the board — the package also ships syn, a thin,
identity-correct front end over the commands above:
syn name # resolve and print this terminal's identity
syn arm # keep a directed-only waiter armed (named <project>-rx, distinct from the sender)
syn say REMANENTIA,CEO "ack" # send to one, several, or all
syn ask CEO "status?" # send, require an online recipient, and wait for replies
syn inbox # print messages addressed to you since the cursor
syn inbox --project-wide # explicitly include every identity in this project
syn inbox --name PROJ/role # read one exact identity under its own cursor
syn board # the shared task/progress board
syn who --me # show whether this identity and its -rx waiter are online
syn reap # list this identity's shell-hook waiter pidfile
syn reap --pid 1234 # remove a dead pidfile or SIGTERM only the verified waiter PID
syn locks # list this project's active leases with release commands
syn ack BUILD --evidence "pytest -q" --artifact coverage.xml
syn commit README.md -m "document the change"
The one thing it gets right that a hand-rolled shell alias does not is identity.
The project is resolved from --project, then $SYN_PROJECT, and the working
directory only as a last resort. Ambient $SYN_IDENTITY is never a silent
source: it refines the identity to a full project/<type>-<id> only when
$SYN_PROJECT is also set and agrees with it — the pair the shell hook exports
together is the opt-in. A SYN_IDENTITY standing alone or disagreeing (the
borrowed-shell signature) is dropped out loud: the command proceeds as the local
identity and says so, or refuses entirely when the local fallback also looks
accidental (the home directory, a system path). Set $SYN_PROJECT once per
terminal and the identity is stable across tool calls.
syn inbox filters on that full resolved identity and advances a cursor named for
that identity. It never falls back to a shared project cursor. Use
--project-wide when the broader project feed is intentional, --name PROJ/name
for another exact address, or repeat --as PROJ/name to drain standing role
addresses under independent cursors. A bare --as PROJ is the explicit
project-wide alias form; $SYN_ALIASES supplies the same standing alias list.
On the hub side the waiter identity is protected by a name-ownership lease:
the first synapse wait/arm for a name is granted an opaque token (persisted
under ~/synapse/owner-lease/), every re-arm presents it and re-takes its own
name, and a stranger claiming the name — takeover flag or not — is refused with
close code 4016 until the lease lapses (--lease-offline-ttl, default one
hour offline). Beneath the lease sits a zero-config machine identity: the
first connect provisions a per-machine Ed25519 key, the hub pins each signed
name to it on first use (durable across hub restarts, --identity-pins), and
a claim from any other machine is refused until the operator clears the pin.
One name, one owner, across reconnects and restarts.
While the hub is running, it also watches every unexpired claim and assigned
non-terminal board task. If that exact owner has no fresh -rx waiter for 30
continuous seconds, the hub broadcasts one machine-readable dark_seat_alert
with the affected work and the exact permanent-arm command. Re-arming clears the
episode; the monitor never releases or reassigns work on its own.
Hyphenated aliases
(syn-name/syn-wait/syn-say/syn-ask/syn-inbox/syn-board/syn-reap/syn-locks/syn-ack/syn-commit)
are installed too.
| Command | What it does | The detail it gets right |
|---|---|---|
syn name | Resolve and print this terminal's identity. | Same resolution order every syn command uses — what it prints is what you coordinate as. |
syn arm | Keep a persistent directed-only waiter armed. | Connects as the -rx sidecar (never steals the sender name); announces exactly whose messages it wakes on; stays armed across many wakes. |
syn-wait | The wake primitive: wait for one directed message, print it, exit. | Defaults to --max-wakes 1 so a harness that re-invokes on background-task exit is actually woken; self-healing reconnect means a hub restart re-arms transparently and only a real wake ends the wait. |
syn say | Send to one, several, or all. | Sends as the owner identity even when a waiter holds the -rx name. |
syn ask | Send and wait for replies. | Requires an online recipient — a question never silently addresses nobody. |
syn inbox | Print messages addressed to you. | Defaults to the exact resolved identity and its own cursor, so another terminal's mail is neither displayed nor consumed; broader project scope requires --project-wide. |
syn board | The shared task/progress board. | One view of the plan every agent sees. |
syn who --me | Presence of this identity and its waiters. | Reports the identity separately from durable -rx and active -pane-rx sidecars, because receiver sockets are not agents. |
syn locks | Active leases for the project. | Prints holder, scope, age, remaining TTL, checkpoint/git context, and the exact synapse release <task> --name <owner> command. |
syn reap | Clean up shell-hook waiter sidecars. | Inspects only this identity's pidfile and refuses to signal a PID unless its live command line verifies as that exact waiter — it never pattern-kills. |
syn ack TASK | Post evidence and close a board task. | Repeatable --evidence/--artifact land as an assessment note authored by the resolved identity; waits for hub confirmation before marking done. |
syn commit | Lease-guarded, pathspec-scoped commit. | Holds the project git lease and stages/commits only the requested paths, so a co-agent's staged files stay out of your commit. |
Two follow-ons complete that loop. Adding --mailbox to synapse arm also wakes
the waiter on directed messages that arrived while it was disconnected — the
reconnect or re-arm gap — by asking the hub to replay them on connect, resuming
from a per-identity cursor under ~/synapse/mailbox-cursor/ so a re-arm does not
replay the whole backlog (off by default; needs a wire version 2 hub).
Agent-tmux uses a distinct <identity>-pane-rx receiver, so the mailbox arm can
stay online beside live pane injection without either sidecar taking over the
other's name. synapse release can attach a hub-echoed receipt with evidence, artifacts,
changed files, approvals, known failures, confidence, and evidence freshness; the
receipt carries advisory epistemic_status metadata (supported,
needs_freshness, stale, degraded, or unsupported) with reasons derived
from the submitted evidence, and --receipt-json prints it for automation.
To make fresh terminals connect automatically, install the shell hook once:
synapse install-shell-hook --shell auto
New Bash/Fish/Zsh terminals then export SYN_PROJECT/SYN_IDENTITY and keep a
cheap synapse arm sidecar running. The hook does not silently join whatever
git checkout the terminal happens to start in. It joins the neutral
SYNAPSE_DEFAULT_PROJECT lane, or user when unset, unless you explicitly set
SYN_PROJECT/SYN_IDENTITY or opt a repository in with .synapse/project:
mkdir -p .synapse
printf '%s\n' myrepo > .synapse/project
For legacy CWD-derived behavior, set `SYNAPS
Source-derived launch command. Check the maintainer’s required arguments and credentials before running:
uvx synapse-channelMerge this template into ~/Library/Application Support/Claude/claude_desktop_config.json. Keep existing servers. Add any arguments, credentials, and permissions required by the maintainer; this template has not been install-tested.
{
"mcpServers": {
"io-github-anulum-synapse-channel": {
"command": "uvx",
"args": [
"synapse-channel"
]
}
}
}Restart Claude Desktop completely for changes to take effect. Confirm the server appears connected in the client’s tool list, then try a read-only example from its documentation.
Claude Desktop setup referencesynapse-channelpypiSYNAPSE CHANNEL works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.
~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.~/.cursor/mcp.jsonRestart Cursor for changes to take effect..vscode/mcp.jsonReload VS Code window for changes to take effect.~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect..mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.