Agents

Agent mesh

Relay lets independent coding-agent sessions — Claude Code, Codex, and others — talk to each other through Sinclair: a supervisor coordinating a team. Agents share one bus, message each other directly or over channels, and park for free between tasks, so an idle agent costs nothing while it waits for work.

What the relay is

Relay ships as a small sidecar binary (relay) bundled inside Sinclair and managed from Settings → AI. It is its own process, not part of the terminal: a crash or hang in the mesh can never take down your terminal, and the same binary works standalone — over SSH, in CI, with any terminal.

A typical session: launch a supervisor, launch a couple of workers (frontend, backend), and drive the supervisor — it delegates over the bus while you watch the feed.

Enable it

Open Settings → AI with ⌘,:

SettingWhat it does
Enable AI featuresMaster switch. Off means no MCP server, no mesh, no network activity. On is enough to launch agents — Relay starts on demand.
Optimize tokensCompact the prompts sent to agents (collapse whitespace, use a terse relay harness) to spend fewer tokens without dropping content.
MCP serverExpose this terminal to agents (see the MCP server page).
Relay agent meshRun the mesh. When on, Sinclair starts the bundled relay daemon and an AI menu appears.
Start Relay on launchBring the mesh up automatically when Sinclair opens.
Relay addressBind address for the server. Default 127.0.0.1:7777.
Default agentThe agent CLI used by Launch Agent…. Default claude.

When Relay is enabled the section also shows a live status dot — green when the server is listening, red when stopped, re-probed every ~1.5 seconds — and the log path.

Everything maps to plain config keys, so it round-trips through the file too:

// ~/.config/sinclair/settings.json
{
  "ai-enabled": true,
  "ai-optimize-tokens": true,
  "mcp-server-enabled": true,
  "relay-enabled": true,
  "relay-start-on-launch": true,
  "relay-address": "127.0.0.1:7777"
relay-default-agent = claude

Toggling Relay agent mesh starts or stops the daemon immediately; Start Relay on launch only affects what happens at startup.

Note

The AI and agent config keys are documented alongside every other option on the Configuration page, and the terminal-facing MCP server has its own MCP server page.

Use it from Sinclair

With AI enabled, an AI menu appears; with Relay on it offers:

The same actions are bound to keys you can use directly or rebind:

ActionDefault keyAction name
Launch agent⌘⇧Arelay_launch
Open Feed⌘⇧Irelay_feed
View Logs⌘⇧Lrelay_log

The Relay and Agents sidebar panels mirror the menu: live server status with Start / Stop / Restart, and the roster of saved and running agents.

The relay CLI

The same binary backs the menu and works on its own. Sinclair points every call at one shared state directory via --home (under ~/.config/sinclair/relay); used standalone it defaults to ./.relay in the current directory.

relay start            # start the server (background daemon)
relay stop             # stop it (and its workers)
relay restart
relay status

relay launch <name>    # launch an agent under relay (foreground, this terminal)
relay launch <name> --background   # ...as a server-monitored worker instead
relay ps               # registered agents + background workers
relay kill <name>      # stop a background worker
relay feed [--follow]  # print the message bus
relay role <list|info|create|edit|delete>   # manage role templates
relay team <list|info|create|edit|delete>   # manage teams (layout + roster)

launch flags: --agent claude|codex|gemini, --role, --task, --channel (repeatable), --model, --cwd, --cmd <template>, --background, --lead (launch interactively as the human-driven lead).

Roles

A role is a reusable identity an agent launches with — a brief (what it owns, how it coordinates) plus optional defaults. It is distinct from --task: the role is durable ("the frontend owner"), the task is the one-off assignment ("build the login page"). At launch the brief is injected into the harness; explicit flags override the role's defaults, and --channel flags merge with the role's.

Roles resolve highest-priority-first:

  1. project./.relay/roles/<name>.toml (travels with the repo)
  2. user~/.config/relay/roles/<name>.toml (or $XDG_CONFIG_HOME)
  3. built-in — embedded: supervisor, worker, frontend, backend, reviewer, devops, qa

Manage them like git config — CRUD with an $EDITOR drop-in:

relay role list                 # all roles + their source
relay role info <name>          # show the resolved role
relay role create <name>        # new role in $EDITOR (--user for the user dir)
relay role edit <name>          # edit in $EDITOR; copies a built-in/lower layer first
relay role delete <name>        # remove a project (or --user) role file

create/edit open $VISUAL/$EDITOR (default vi) on a seeded file and only save once it parses. Editing a built-in copies it into your project (or --user) dir first, so built-ins stay pristine. Files are TOML:

name = "frontend"
channels = ["frontend"]   # auto-joined at launch
agent = "claude"          # default agent CLI (optional)
# model = "claude-..."    # default model (optional)
# driver = true           # human-driven lead: stay interactive, don't park on wait
description = """
You own the frontend. Follow the existing component conventions and report
blockers to the supervisor.
"""

Then relay launch alice --role frontend joins #frontend, uses claude, and opens with that brief.

Teams & tiles

A team is a layout plus a roster: open one and Sinclair arranges a set of panes and launches the right agent in each. Teams are Relay files (relay team …, layered project → user → built-in, like roles); tiles (the layouts) are a Sinclair feature, so they are useful on their own too.

From Sinclair, with AI on, the AI menu lists teams under Teams ▸ — click one to open it in a fresh tab. The agent panes live under that one tab, which is titled after the team (e.g. web).

Build Team… (also under Teams ▸) opens a builder window to assemble a team without hand-writing TOML. Pick Manual to choose a layout and add member rows (name + role + agent), or Guided to describe the team in plain English and have Claude draft it — the draft drops into the Manual form for review before you save. Saved teams land in your user (or project) teams dir and appear under Teams ▸ immediately. Standalone, manage teams with the CLI:

relay team list                 # all teams + source
relay team info <name>          # roster + layout (add --json for tooling)
relay team create <name>        # new team in $EDITOR (--user for the user dir)
relay team edit <name>          # edit; copies a built-in/lower layer first
relay team delete <name>
relay team save [--user]        # write a team from JSON on stdin (used by Build Team…)

A team is TOML — a layout shape and ordered members (first = the main pane):

name = "web"
layout = "main-bottom"   # columns | rows | grid | main-bottom | main-right

[[member]]
name = "lead"
role = "supervisor"

[[member]]
name = "frontend"
role = "frontend"

Built-ins: web (lead + frontend + backend + reviewer, main-bottom) and pair (driver + reviewer, columns).

Tiles live in Sinclair under the Workspace menu: built-in presets (Two/Three Columns, Two Rows, Grid, Main + Bottom Row, Main + Right Stack) open that arrangement of shells in a new tab. Save Current Layout… captures the focused tab's split structure, asks for a name, and adds it to the menu (stored as JSON under ~/.config/sinclair/layouts/). Layout shapes scale to any pane count, which is how a team of N members maps onto one shape.

How agents connect

Every launched agent receives an opening harness in one of two shapes:

Coordination happens through MCP tools the agent calls:

ToolPurpose
registerJoin under a unique name (first, once).
send / post / broadcastMessage an agent / a channel / everyone.
join / leaveSubscribe / unsubscribe from a channel.
waitBlock (free) until messages arrive, then return them.
inboxPending messages now, without blocking.
agents / channels / whoamiIntrospection.
spawn / workers / stop_workerA supervisor agent grows / manages its own team.
report_statusReport your semantic state — working, idle, blocked, done, or a short custom label — so teammates and the UI can see it.
wait_statusBlock (free) until a named agent reaches one of the given states, then return it — how a supervisor waits for a worker to be done or blocked.
Tip

wait is the key to zero idle cost: it is a single blocking tool call (held open as an SSE response with keepalives), not a poll loop, so a parked agent burns no tokens until a message actually arrives.

Agent status

Every agent has a semantic stateworking, blocked (waiting on you), done, or idle — that shows up as a colored dot on its tab, is rolled up in the Activity panel, and appears in a status column in the Relay panel. It's the fastest way to read a whole team at a glance: who's heads-down, who's blocked, who's finished.

Agents report it two ways, and both land in the same place:

Supported agents

Tools join the mesh at one of three integration tiers:

Pick the agent per launch with --agent claude|codex|ollama|gemini (or --cmd), or per team member. CLI background agents run with --dangerously-skip-permissions since they can't answer prompts.

In Settings → AI → Agent tools, each tool has an enable toggle, a Test button that checks it is reachable (CLI --version, or the Ollama API port), an explicit path field (for a binary that isn't on PATH), and a flags field.

Agent CLI flags

Each built-in provider can carry extra command-line flags, appended to its own invocation on every launch — quick-launch, Define Agent, saved agents, and team members alike. Edit them under Settings → AI → Agent tools, or in the config file:

// ~/.config/sinclair/settings.json
{
  "agent-claude-args": "--dangerously-skip-permissions",
  "agent-codex-args": "--model o3",
  "agent-gemini-args": "--yolo",

  // and an explicit binary path when it isn't on PATH
  "agent-claude-path": "/opt/homebrew/bin/claude"
}

The most common use is running Claude Code with --dangerously-skip-permissions so it doesn't stop to ask. Values with spaces can be quoted; Ollama has no flags field (it is driven by relay's own bridge, not a CLI).

Notes & limits

Internals

State lives under ~/.config/sinclair/relay/ (or $XDG_CONFIG_HOME): the SQLite bus (relay.db), the server record (server.json), logs, and per-agent MCP configs. The CLI talks to the server over a small plain-HTTP control plane (/control/state, /control/feed, /control/spawn, /control/stop), separate from the MCP bus on /mcp. The crate is crates/relay; it is bundled into the .app beside the sinclair executable by scripts/bundle.sh.