Relayer

command module
v0.8.19 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 9, 2026 License: MIT Imports: 7 Imported by: 0

README

Relayer

Run several AI coding agents at once, and answer their prompts from one place.

Go Version Build Release

Two agents run side by side, both stop at a confirmation prompt, and the supervisor answers each one in turn

Leave an agent unattended and it waits on a question you never see. Watch it and you do nothing else. Run four and you are switching terminals to find whichever one stopped.

Relayer runs one to eight interactive CLI agents side by side, watches their output for confirmation, permission and credential prompts, and holds each agent there until a human answers. Every decision is recorded in a local audit log that has no field for your terminal output.

No API key, no per-token billing, no proxy. Relayer drives the CLI tools you already have, with your existing subscriptions and local models. It does not provide, proxy, or alter access to any AI service: the tools you launch keep their own authentication, billing, usage limits, terms, and network behavior.

Try it in one command — no configuration, no credentials, two synthetic agents:

go run github.com/Hocsman/Relayer/cmd/relayer@latest

[!NOTE] Relayer v0.8.19 is General Availability (GA). It provides production-ready supervision, a headless web gateway (relayer serve) with operator/viewer roles, a fully interactive browser terminal shared between several operators, optional session recording with in-browser replay, MCP tool-call badges, real-time Web Push alerts, enterprise telemetry, system alerts, and visual configuration. Prompt detection is heuristic: it assists human operators rather than replacing security boundaries. Always review proposed actions and maintain independent backups. See the security model.

What works today

  • One to eight agents, with up to four visible per page.
  • Granular per-agent process lifecycle: stop, start, or restart individual agents in-place without restarting the supervisor session or affecting siblings.
  • Exact argument-vector commands, or explicitly requested shell commands (/bin/sh -c on Unix, cmd.exe /c on Windows).
  • PTY, tmux, automatic tmux-to-PTY selection, and mixed concrete backends.
  • Native Windows Pseudo Console (ConPTY) support for full native Windows execution.
  • Headless web gateway (relayer serve) with role-based access control: --token grants read-write operator authority, --viewer-token grants read-only observation. It supervises prompts through the same core as the Desktop GUI: the policy's automatic decisions are delivered, and a failed audit write stops every further answer. Named tokens (alice:secret) put that name on every answer, line, attach and terminal hand-over the token makes; the policy's own decisions name nobody, and a Stop, Start or Restart is journaled as a person's without the name. See the web gateway guide.
  • Several operators can watch one interactive session at once, with exactly one holding the terminal. Asking for a terminal a colleague holds is a request they answer, not a takeover. See multi-operator sessions.
  • Optional session recording to standard asciicast v2 .cast files, replayable in the browser for audit or training. Off by default; it captures terminal output verbatim, which the audit journal deliberately never stores. See session recording.
  • Fully bidirectional interactive browser terminal: attach to an agent and type directly into its PTY, including arrow keys, VT escape sequences and Ctrl+C, streamed over WebSocket binary frames. Attach and detach are audited; keystrokes are not. Only the connection holding the terminal can type into it, never while an answer or a line is being written, and while anybody holds it the policy answers nothing on that agent.
  • Visual configuration editor in the Desktop GUI and the web gateway for agents, policies, guardrails and webhooks. Notification changes apply at once; policy and agent changes apply when the run is restarted, and the editor says when one is due.
  • Interactive terminal text search (Ctrl+F) with circular navigation and highlighting via @xterm/addon-search.
  • Operator arbitration shortcuts: Alt+1..8 (agent focus/modal), Ctrl+Enter (Allow), Esc (Deny).
  • Fullscreen TUI metrics overlay (m / M) reporting uptime, decision ratios, and reaction latency stats.
  • Enterprise telemetry: built-in Prometheus exporter (:9090/metrics), OTLP batch exporter, and Grafana Docker Compose stack.
  • Multi-channel notifications: native OS desktop alerts (Windows Toast, macOS Notification Center, Linux notify-send) and remote webhooks (Slack, Discord, generic JSON).
  • A bounded terminal-output view and bounded streaming prompt detection.
  • Deliberate single-line operator input in the TUI and GUI, separate from semantic prompt decisions and guarded by an atomic no-pending-event check.
  • A shared, read-only doctor preflight for the CLI and GUI that reports the effective tools, adapters, backends, policies, platform, and audit readiness without starting an agent or creating a missing configuration. When tmux is the effective backend it also proves tmux can run a session, inside its own private socket.
  • A stable, product-neutral generic regex adapter.
  • Experimental Claude Code, Codex CLI, Aider, Open Interpreter and Goose adapters backed by fixtures in internal/adapters/testdata/ (for Claude Code, the 2.1.285 cases have unconfirmed provenance and the 2.1.286 layouts are test strings); the answers of the last three were each typed into the real CLI and their effect checked. All of them retain the stable generic detector as fallback.
  • Structured MCP tool-call badges beside an arbitration prompt, naming the server, the tool, its risk and the bounded arguments an agent printed, so an operator can see what a tool is about to be given before answering. Detection and display only: Relayer never intercepts the call, the badge is suppressed on a confidential prompt, and an absent badge is not evidence no tool ran. Heuristic, and not fixture-backed. See MCP tool calls.
  • First-match approval policies with conservative handling of credentials, sensitive events, high or unknown risk, and dry runs.
  • Optional local JSONL audit records with rotation, restrictive Unix permissions, bounded fields, and mandatory redaction.
  • Two deterministic Bash mock agents when agents: [] is configured.
  • Desktop GUI (Wails) for macOS, Linux, and Windows; the Bubble Tea TUI remains fully available.

Relayer is not a sandbox, a policy enforcement boundary, a terminal emulator, or a substitute for reviewing an agent's work. See the security model before using it on valuable data.

Platform status

Platform Status Notes
Linux Supported (GA) PTY backend; tmux backend when tmux is installed. Desktop GUI and CLI packages published.
macOS Supported (GA) PTY backend; tmux backend when tmux is installed. Universal Desktop GUI and CLI packages published.
Windows, native Supported (GA) Native ConPTY backend for PTY execution. Desktop GUI and CLI packages published.
WSL Community PTY and tmux backends functional under WSL Linux distributions.

Prerequisites

  • Go 1.26.9, or 1.27.2 or newer, to build from source: 1.27.0 and 1.27.1 still carry the standard library advisories that 1.26.9 fixes. The patch-level minimum keeps release binaries on a standard library version covered by the vulnerability gate.
  • A UTF-8 interactive terminal.
  • Bash for the bundled mock agents and the reproducible demo.
  • tmux only when selecting tmux or when you want auto to choose it.
  • The agent CLIs you configure, installed and authenticated independently.

Install

Build from source
git clone https://github.com/Hocsman/Relayer.git
cd Relayer
go build -o relayer ./cmd/relayer
./relayer --version

The root entry point remains available for compatibility:

go build -o relayer main.go

Development builds report relayer dev (commit unknown) unless build metadata is injected.

Read-only doctor

Inspect an existing configuration before starting Relayer:

./relayer doctor --config config.yaml

The command does not create a missing configuration, open the audit journal, construct a PTY/tmux backend, execute a provider CLI, or start an agent. Its report uses agent ordinals and fixed tool catalogue labels; commands, environment values, configured names and IDs, full paths, and raw dependency errors are omitted.

Checks are passive with one deliberate exception. When tmux is the effective backend, doctor runs tmux itself: it creates one short-lived session on a private socket inside a 0700 temporary directory, reads its identity, and removes that session by name. Finding the tmux binary is not evidence that it can serve Relayer's machine-readable protocol, and a report that cannot observe that difference would announce a healthy backend immediately before startup fails. The probe never reads, attaches to, or modifies your tmux server, and never calls kill-server. An unusable tmux blocks an explicitly requested tmux backend and makes auto fall back to PTY with a distinct warning.

Exit status is 0 when there is no blocker, including when the report contains warnings, and 1 when startup should remain blocked. The desktop GUI exposes the same report through Health and Check the installation. See the doctor guide for the checks and their limits.

Desktop GUI

Two agents side by side, one stopped and marked as needing action, with the supervision queue and the audit and policy state on the right

The same supervision, in a high-performance desktop window. Each agent keeps its own pane; the queue on the right is what is waiting for a human, and both agents here are marked SIMULATED because the demo runs scripted mocks rather than real CLIs.

A supervision prompt with the end of the agent output, an Allow and a Deny button of equal weight, and a field to answer manually

A prompt carries the end of the agent's own output, so the decision is not made on a one-line summary. Allow and Deny appear only when the adapter has verified bytes for them — here the Codex adapter — and they carry the same weight, because a supervision tool must not make the permissive answer the one the eye picks. Everything else is answered by typing what the CLI expects.

Pre-compiled, signed standalone desktop bundles are published for Windows (x64), macOS (Universal x64 + arm64), and Linux (amd64) on the Releases page. On Windows, relayer-desktop_<version>_windows_amd64_setup.exe installs Relayer for the current user, without administrator rights, with a desktop and Start menu shortcut; see the desktop GUI guide.

You can also build the desktop GUI from source using Wails v2.14.0:

go install github.com/wailsapp/wails/v2/cmd/wails@v2.14.0
cd cmd/relayer-gui
wails doctor
wails dev       # development window
wails build     # local production artifact below build/bin/

By default the GUI loads os.UserConfigDir()/relayer/config.yaml; set RELAYER_CONFIG to use another path. Applications opened from Finder or desktop launchers may not inherit the shell PATH, so use absolute executable paths or launch the app with an explicit PATH when required.

The Desktop GUI features:

  • Visual Settings Editor: Interactive tabs for 🤖 Agents, 🛡️ Security & Guardrails, and 🔔 Notifications & Webhooks. Notification and webhook changes apply at once. Policy and guardrail changes are saved immediately and take effect when the run is restarted — the running policy engine is built once per run — and the editor says so rather than claiming they are already applied.
  • Per-Agent Process Controls: Granular Stop, Restart, and Start controls on each agent terminal card in the workspace to manage individual agents in place without interrupting sibling processes.
  • Terminal Search (Ctrl+F): Integrated xterm search toolbar with match count, highlighting, circular Enter / Shift+Enter navigation, and Esc dismissal.
  • Arbitration Shortcuts: Alt+1..8 to focus agents / open pending arbitration modals, Ctrl+Enter to approve (Allow), and Esc to deny (Deny).
  • Live Observability Dashboard: Circular SVG gauges for decision ratios, operator reaction latency histograms, guardrail block counts, and live exporter status.

See the desktop GUI guide for prerequisites, configuration, shortcuts, and settings reference.

Releases

Release archives, checksums, signatures and SBOMs are published on the Releases page for authorized tags only. Do not treat an unreviewed third-party binary as an official Relayer release; verify the signature as shown below.

Select a published OS (linux or darwin) and ARCH (amd64 or arm64), then download and verify the matching archive:

VERSION=0.8.19
OS=linux
ARCH=amd64
ARCHIVE="relayer_${VERSION}_${OS}_${ARCH}.tar.gz"
BASE_URL="https://github.com/Hocsman/Relayer/releases/download/v${VERSION}"

curl -fLO "${BASE_URL}/${ARCHIVE}"
curl -fLO "${BASE_URL}/relayer_${VERSION}_checksums.txt"
grep "  ${ARCHIVE}$" "relayer_${VERSION}_checksums.txt" | sha256sum -c -
tar -xzf "${ARCHIVE}"
"./relayer_${VERSION}_${OS}_${ARCH}/relayer" --version

On macOS, replace the verification command with:

grep "  ${ARCHIVE}$" "relayer_${VERSION}_checksums.txt" | shasum -a 256 -c -

Compare the reported version with the authorized tag before placing the binary on your PATH.

A checksum file published beside the binaries only proves the download was not corrupted in transit; anyone able to write to the release could replace both. Verify the signature over that checksum file instead:

curl -fLO "${BASE_URL}/relayer_${VERSION}_checksums.txt.sig"
curl -fLO "${BASE_URL}/relayer_${VERSION}_checksums.txt.pem"

cosign verify-blob \
  --certificate "relayer_${VERSION}_checksums.txt.pem" \
  --signature "relayer_${VERSION}_checksums.txt.sig" \
  --certificate-identity-regexp '^https://github\.com/Hocsman/Relayer/\.github/workflows/release\.yml@refs/tags/' \
  --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
  "relayer_${VERSION}_checksums.txt"

Signing is keyless: the release workflow's own identity is bound into a short-lived certificate and recorded in the public transparency log, so there is no private key to trust or leak. The identity flags are what make the check meaningful — without them any valid Sigstore signature would pass.

Build provenance is attested separately and can be checked with the GitHub CLI:

gh attestation verify "${ARCHIVE}" --repo Hocsman/Relayer

Each archive also ships an SBOM (<archive>.sbom.json) listing what went into that build.

Code signing

The Windows desktop installer (relayer-desktop_<version>_windows_amd64_setup.exe) and the executable it installs are not code-signed yet, so Windows SmartScreen may ask to confirm them: More info, then Run anyway. Every release is still verifiable. The installer is listed in relayer-desktop_<version>_checksums.txt, whose keyless cosign signature and build provenance are checked as described under Releases. On Windows, compare the installer's hash with its line in that file:

(Get-FileHash .\relayer-desktop_<version>_windows_amd64_setup.exe -Algorithm SHA256).Hash.ToLower()

Only this repository's release workflow, from an authorized tag, builds and publishes release artifacts.

Privacy

Relayer does not collect or share any data. It has no analytics and contacts no server run by the project. Configuration, transcripts and the audit log stay on the machine that runs it.

The desktop application checks for a new version once per launch: it asks GitHub's public API for the repository's latest release, with a request that carries nothing but the running version in its User-Agent; GitHub sees the request's network address, as it does any visitor's. It can be turned off in Settings → Notifications, or for every user of a machine with RELAYER_NO_UPDATE_CHECK=1. relayer serve and the command line never check.

Starting a run also executes each vendor agent's own binary once, as <argv[0]> --version, to warn about a version its adapter was not captured against — locally, with no configured argument and no network, and never for a wrapped or launched agent. RELAYER_NO_VERSION_CHECK=1 turns that off for every user of a machine.

Otherwise it sends data over the network only where the user configures it to:

  • Webhooks in the notifications block post each notification to the URLs the user lists.
  • OTLP export of telemetry, off by default, sends metrics to the endpoint the user sets.
  • relayer serve and the Prometheus endpoint listen for connections; they answer whoever the user lets reach them and send nothing unprompted.

The agents Relayer supervises are separate programs, with their own network access and privacy policies.

Quick start with safe mocks

On first launch, Relayer creates config.yaml without overwriting an existing file. The generated agents: [] activates two synthetic Bash agents:

./relayer

Each mock prints 20 progress lines, asks Overwrite file? [Y/n], waits for a human answer, and displays that answer. It does not call Claude, Codex, Ollama, or another remote service.

Use another configuration path with:

./relayer --config ./examples/local.yaml

The old --pane1 and --pane2 flags still override the first two configured agents, but they are deprecated. Their values are tokenized into an argument vector; shell operators, variable expansion, globbing, pipes, substitutions, and redirections are not interpreted.

Observability with Prometheus & Grafana

Relayer exports enterprise-grade telemetry out of the box. Spin up the bundled Prometheus and Grafana stack in one command:

docker compose -f docker-compose.telemetry.yml up -d
  • Prometheus runs at http://localhost:9090 and scrapes Relayer's :9090/metrics endpoint.
  • Grafana is pre-configured at http://localhost:3000 (anonymous viewer access, or admin/admin) with the official dashboard visualising active sessions, pending prompts, decision ratios (allow/deny/auto), guardrail violations, and 95th percentile human reaction latencies.
  • See the observability guide for metric schemas and OTLP exporter setup.

TUI controls

Key or input Action
Ctrl+Left, Ctrl+Right Move focus between agents and the supervisor.
Ctrl+PageUp, Ctrl+PageDown Move between pages of agents.
Up, Down, PageUp, PageDown Scroll the focused viewport.
Mouse wheel Scroll the viewport under the pointer.
Left click Select an agent or the supervisor.
m, M Toggle fullscreen session metrics & latency overlay.
i on a focused idle agent Compose one ordinary line for that agent.
Esc while composing Cancel and erase the ordinary line (or close metrics overlay).
Enter while composing Send the ordinary line with one carriage return.
Enter on a pending prompt Send the supervisor input to that agent. An empty field is refused: the answer must be typed.
F2, F3 on a pending prompt Answer semantically: allow, or deny. The adapter encodes it, and the audit records the decision as made by a human. Adapters that cannot represent the answer leave the prompt pending.
Enter on an idle tmux agent Attach the native tmux client.
Ctrl+B, then d Default tmux detach sequence; custom tmux bindings may differ.
Ctrl+C Stop supervision and begin backend shutdown.

When a prompt is pending, Relayer highlights the pane and focuses the supervisor. The supervisor title shows how many agents are waiting once more than one is, so a queue building up behind the agent you are answering — on another page, possibly — is visible rather than implicit. By default, Relayer emits an operator alert when a human decision is needed: an ASCII terminal bell (\a) and a native OS desktop notification (configurable under notifications in config.yaml). Credential and sensitive inputs are masked in the TUI. Masking does not prevent the target program from echoing the value into its own terminal or tmux scrollback.

Ordinary input is application text, not raw terminal passthrough: it must be valid UTF-8, contain no Unicode control character, and fit within 4096 bytes. It is refused if that session already has a detected prompt, a decision or attach is in flight, the session exited, or delivery state is uncertain. A prompt already emitted by the target but not yet read by Relayer remains a fundamental observation race; the input action is not a policy approval.

The in-TUI viewport is a bounded text view, not a full VT emulator. Use native tmux attach for full-screen interactive applications.

Configuration

Version 1 configuration is strict YAML: unknown fields, aliases, merge keys, multiple documents, and incorrect scalar types are rejected before any backend starts. The following example shows every top-level section:

version: 1
backend: auto # pty, tmux, or auto

telemetry:
  enabled: true
  service_name: "relayer-local"
  prometheus:
    enabled: true
    address: ":9090"
    path: "/metrics"
  otlp:
    enabled: false
    endpoint: ""
    export_interval: 15s

notifications:
  enabled: true
  desktop: true
  bell: true
  webhooks:
    - name: slack-ops
      format: slack # slack, discord, generic
      url: https://hooks.slack.com/services/...
      min_severity: warning

sessions:
  persist_on_exit: false
  cleanup_on_success: true

policies:
  profile: developer-friendly # developer-friendly, strict, permissive, custom
  default_action: ask
  dry_run: false
  guardrails:
    block_destructive: true        # Blocks rm -rf, mkfs, format
    block_exfiltration: true       # Blocks curl | bash, reading .ssh / .env
    block_sensitive_paths: true    # Protects .env, .git, keys and credentials
    block_outside_workspace: true  # Intercepts file access outside workspace_root
    workspace_root: .              # Resolved against this file's directory
  rules:
    - name: ask-reviewer-confirmations
      match:
        event_types: [confirmation]
        agent_ids: [reviewer]
        risk_levels: [unknown]
        sensitive: false
        text_regex: '(?i)continue'
      action: ask

audit:
  enabled: true
  mode: metadata # off, metadata, or detailed
  path: ""       # empty selects the private per-user default
  max_file_size_mb: 10
  max_files: 5

recording:
  enabled: false # transcripts of agent output; see docs/recording.md

agents:
  - id: builder
    name: Builder
    command: ["claude"]
    cwd: .
    env:
      RELAYER_ROLE: builder
    adapter: generic
    backend: pty

  - id: reviewer
    name: Local reviewer
    command: ["ollama", "run", "llama3.2"]
    adapter: generic
    backend: tmux

  - id: scripted
    name: Explicit shell example
    shell: 'printf "ready\\n"; exec ./local-agent'
    adapter: generic
    backend: auto

intercept_patterns:
  - pattern: '(?i)overwrite.*\[y/n\]'
    description: overwrite confirmation
  - pattern: '(?im)password:[[:space:]]*$'
    description: credential prompt
  - pattern: '(?i)enter the code we sent you'
    description: second factor challenge
    sensitive: true

Important configuration behavior:

  • command is an exact argument vector and does not invoke a shell. Prefer it.
  • shell is mutually exclusive with command and explicitly invokes /bin/sh -c on supported Unix systems. Treat shell text as code.
  • Relative cwd and audit paths are resolved from the configuration file's directory. An agent working directory must already exist.
  • Agent environment entries override the inherited process environment. Avoid putting credentials in YAML: generated configuration files use mode 0644.
  • A blank per-agent backend inherits the global backend. auto chooses tmux when its executable is found and otherwise falls back to PTY with a visible warning. An explicit unavailable tmux backend is an error before startup.
  • persist_on_exit concerns detached tmux sessions during ordinary application shutdown. PTY sessions remain owned by the Relayer process. An explicit GUI Stop the run or restart strictly stops both PTY and owned tmux sessions, regardless of this setting. Relayer never kills the tmux server.
  • cleanup_on_success removes a successful Relayer-owned tmux session even when persistence is enabled.
  • agents: [] means the two mocks; otherwise one to eight agents are accepted.

See configuration for validation, inheritance, backends, deprecated flags, policies, and legacy pattern-only files.

Prompt detection and decisions

The generic adapter strips ANSI sequences, handles fragmented output and carriage-return rewrites, and tests the active prompt line against ordered regular expressions. It suppresses common quotation, code-fence, table, history, and old-log shapes to reduce false positives. Regex interception is still heuristic: it can miss a prompt or be tricked by output that resembles one.

Policies use first-match order. Match fields are combined with AND, while values inside one list use OR. Conservative invariants always win:

  • credentials and sensitive events require a human;
  • automatic allow requires explicit low risk; unknown or high risk cannot be auto-allowed;
  • a matched deny may be automatic for an otherwise valid, non-sensitive confirmation, including at unknown or high risk;
  • invalid, incomplete, or non-actionable events ask;
  • dry-run mode records the proposal but asks instead of delivering it;
  • if an adapter cannot encode an automatic decision, Relayer asks instead.

The Desktop GUI and the web gateway, which evaluate a prompt when it is detected, add three guards: the policy is asked again just before its decision, so a limit reached while a prompt waited is honoured; a question asked again within two seconds of an answer to it is asked, never answered automatically; and a deny the policy is kept from delivering, by a limit, a repeat, a held web terminal or the adapter, is offered to the operator as Deny alone.

The current generic adapter encodes manual supervisor input only. Consequently, an allow or deny policy evaluated against a generic prompt falls back to a human ask; on the Desktop GUI and the web gateway, a deny asked this way can only be answered by typing into the web terminal, on the gateway, or by stopping the agent. deny means an adapter-defined refusal, not process termination.

Six adapters are implemented: stable generic, plus experimental aider, claude, codex, goose and interpreter. Claude Code coverage is limited to the workspace-trust and detected-environment-key prompts observed with 2.1.59, the Bash and create-file prompts of 2.1.285 and 2.1.286 and the edit-file prompt of 2.1.285, all of them answered by a person, with no allow or deny byte claimed for any; Codex coverage is limited to directory trust and command approval observed with codex-cli 0.148.0-alpha.21; Aider coverage to six questions of Aider 0.86.2, Open Interpreter coverage to the run and scan questions of 0.4.3, and Goose coverage to the two tool-call approval menus of Goose 1.52.0. A version that words its questions differently is not detected by them. Every other prompt still uses the configured intercept_patterns fallback. See adapters for the exact decision bytes and non-claims.

Audit log

Newly generated configuration enables local metadata auditing. Configurations created before the audit block existed and legacy pattern-only configurations remain disabled for compatibility.

The audit is JSONL and records Relayer lifecycle, event, policy, delivery, ordinary-input outcome, attach, terminal hand-over, recording, and cleanup metadata, from every front end. It never has fields for raw terminal output, commands, environment values, manual or ordinary input values, encoded decision bytes, or raw errors. Detailed summaries are bounded and redacted. Sensitive events use a constant summary and omit derivative event IDs.

On Unix, the dedicated audit directory and files are checked for restrictive ownership, type, and permissions. Writes are synchronized line by line, and files rotate within configured bounds. Audit failure is fail-closed for startup and for every further answer, line and attach, and on the web gateway for keystrokes too, but the audit is not signed and redaction is not a data-loss-prevention guarantee.

See audit logging for the schema, default path, retention, failure behavior, and confidentiality limits.

Architecture and security

Relayer separates configuration and validation, adapter event processing, policy evaluation, audit recording, terminal backends, and the TUI. Sessions communicate through typed events; terminal output, prompt windows, supervisor logs, and queues are bounded. Startup validates all plans and initializes the audit before launching an agent, and partial startup is rolled back.

The tmux backend creates one marked session per agent and checks immutable ownership metadata before cleanup. Runtime launch files and FIFOs are private, but a process still runs with the current user's authority. Native tmux attach temporarily leaves the TUI and is outside policy interception until Relayer resynchronizes after detach.

Read architecture, the security model, and SECURITY.md before using Relayer with untrusted commands or sensitive repositories.

Limits worth knowing

  • An agent may act before emitting a detectable prompt.
  • An ordinary line can precede a prompt that the target emitted but Relayer has not read yet; the no-pending CAS protects only events already detected.
  • Prompt-like output can spoof the supervisor; a real prompt can evade regexes.
  • Generic and Claude cannot automate allow/deny delivery; Codex automation is limited to the exact fixture-backed interactions documented above. Aider, Goose and Open Interpreter encode allow and deny with bytes observed to do what they say, on the questions captured from the versions named above.
  • An MCP tool-call reading is a guess about agent output, not an interception point: a call can run with nothing printed for it to read, and text shaped like a tool name is read as a call whether or not one is being made.
  • Terminal rendering is intentionally bounded and not a complete emulator.
  • tmux persistence can intentionally leave processes running after Relayer exits; inspect them with tmux list-sessions.
  • A write to an agent that reads nothing waits for room in its terminal's input buffer, and its request context cannot interrupt it, except for the web terminal's keystrokes, which give up after five seconds on Linux, macOS, the BSDs and Windows. Stopping the agent ends such a write there; on illumos and AIX it waits until the agent reads again or every process holding the terminal has exited.
  • Terminal output reaches every web client verbatim, viewers included, unless the gateway runs with --viewer-terminals hidden; only prompt cards and notifications are redacted.
  • Separate Relayer processes do not coordinate rotation of one shared audit path.
  • Configuration files and command-line arguments are not secret stores.
  • Native Windows agent execution uses ConPTY; the tmux backend remains Unix-only.

See troubleshooting for startup, tmux, prompt, rendering, persistence, and audit diagnostics.

Development and contribution

go test -race ./...
go vet ./...
go build ./cmd/relayer

Contributions are welcome, especially product-neutral prompt fixtures, backend lifecycle tests, accessibility improvements, and documentation that narrows ambiguous security claims. Read CONTRIBUTING.md first. Report security issues using the private process in SECURITY.md, not a public issue containing secrets.

The reproducible docs/demo.tape exercises only bundled mocks and tmux; it does not reference a pre-rendered image or vendor transcript.

License

Relayer is distributed under the MIT License.

Documentation

Overview

Command relayer is kept at the repository root for compatibility with the original `go build -o relayer main.go` installation command. New builds should use the canonical ./cmd/relayer entrypoint.

Directories

Path Synopsis
cmd
relayer command
Command relayer starts the human-in-the-loop PTY orchestrator.
Command relayer starts the human-in-the-loop PTY orchestrator.
relayer-capture command
Command relayer-capture records bounded, anonymized output-only PTY or tmux fixture artifacts.
Command relayer-capture records bounded, anonymized output-only PTY or tmux fixture artifacts.
internal
adapters
Package adapters defines backend-neutral agent events and the adapters that derive them from normalized terminal text.
Package adapters defines backend-neutral agent events and the adapters that derive them from normalized terminal text.
agent
Package agent defines and validates the process specifications used by Relayer.
Package agent defines and validates the process specifications used by Relayer.
agentprofile
Package agentprofile is the agent editor both front ends share: what an editor is shown of each agent in the configuration, and how the profiles it sends back become the agents that are written.
Package agentprofile is the agent editor both front ends share: what an editor is shown of each agent in the configuration, and how the profiles it sends back become the agents that are written.
app
Package app composes Relayer's configuration, PTY sessions, and terminal UI.
Package app composes Relayer's configuration, PTY sessions, and terminal UI.
audit
Package audit writes a bounded, local JSONL audit trail without retaining terminal input, raw prompt matches, environment values, or backend errors.
Package audit writes a bounded, local JSONL audit trail without retaining terminal input, raw prompt matches, environment values, or backend errors.
buffer
Package buffer provides a concurrency-safe, byte-bounded circular buffer.
Package buffer provides a concurrency-safe, byte-bounded circular buffer.
config
Package config loads and creates Relayer interception configuration files.
Package config loads and creates Relayer interception configuration files.
fixturecapture
Package fixturecapture records bounded, anonymized terminal output for adapter fixtures.
Package fixturecapture records bounded, anonymized terminal output for adapter fixtures.
intercept
Package intercept preserves the historical regex-interceptor API as a thin compatibility facade over the backend-neutral adapters package.
Package intercept preserves the historical regex-interceptor API as a thin compatibility facade over the backend-neutral adapters package.
platform
Package platform contains the small amount of process behaviour that is inherently operating-system specific.
Package platform contains the small amount of process behaviour that is inherently operating-system specific.
policy
Package policy evaluates immutable, side-effect-free automation rules for semantic agent events.
Package policy evaluates immutable, side-effect-free automation rules for semantic agent events.
preflight
Package preflight performs read-only readiness checks for Relayer.
Package preflight performs read-only readiness checks for Relayer.
ptybackend
Package ptybackend adapts Relayer's established PTY session manager to the context-aware terminal.Backend contract.
Package ptybackend adapts Relayer's established PTY session manager to the context-aware terminal.Backend contract.
record
Package record writes and reads asciicast v2 transcripts so an interactive terminal session can be replayed later for audit or training.
Package record writes and reads asciicast v2 transcripts so an interactive terminal session can be replayed later for audit or training.
screen
Package screen renders a terminal byte stream into the grid of cells a person would actually see.
Package screen renders a terminal byte stream into the grid of cells a person would actually see.
session
Package session owns PTY-backed process lifecycles and exposes neutral, typed events.
Package session owns PTY-backed process lifecycles and exposes neutral, typed events.
supervise
Package supervise is the supervision core shared by Relayer's front ends.
Package supervise is the supervision core shared by Relayer's front ends.
telemetry
Package telemetry provides Prometheus and OpenTelemetry (OTel) metrics export for Relayer's supervised agent sessions, policy decisions, and guardrails.
Package telemetry provides Prometheus and OpenTelemetry (OTel) metrics export for Relayer's supervised agent sessions, policy decisions, and guardrails.
terminal
Package terminal defines the process-neutral contract implemented by every Relayer terminal backend.
Package terminal defines the process-neutral contract implemented by every Relayer terminal backend.
tmuxbackend
Package tmuxbackend owns Relayer-created tmux sessions.
Package tmuxbackend owns Relayer-created tmux sessions.
toolcatalog
Package toolcatalog describes local CLI launch profiles without coupling them to terminal backends, provider APIs, credentials, or model selection.
Package toolcatalog describes local CLI launch profiles without coupling them to terminal backends, provider APIs, credentials, or model selection.
tui
Package tui implements Relayer's Bubble Tea user interface.
Package tui implements Relayer's Bubble Tea user interface.
version
Package version exposes build metadata injected into release binaries.
Package version exposes build metadata injected into release binaries.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL