Sandbox
@slaveOftime/open-relay

CLI supervisor for persistent agent sessions

oly runs interactive CLIs and AI agents as durable sessions owned by a daemon instead of one terminal window. You can detach, close the terminal, inspect logs, send input, reattach, and manage sessions from the CLI or web UI.

93 stars11 forksRustUpdated 7d ago
Who it's for

Builders who run terminal agents or other interactive CLI workflows and want them to survive terminal closes.

What it delivers

You can keep long-running agent work alive, check progress later, and step in only when input is needed.

What it does

Detached session management

Start a command once, detach, and keep the process running under the daemon.

Log inspection with prompt waiting

Read buffered output and wait for likely input-needed checkpoints with `oly logs --wait-for-prompt`.

Remote input and takeover

Send text or special keys without attaching, then reattach and take full control.

Local web control plane

Serve an HTTP API and web UI on localhost for browser-based supervision.

Multi-node supervision

Connect daemons so one primary can manage sessions on other nodes.

Notification hooks

Trigger desktop or custom notification scripts when a session needs attention.

How to get it

  1. 1Run
    npm i -g @slaveoftime/oly
  2. 2Run
    cargo install oly
  3. 3Run
    brew tap slaveOftime/open-relay https://github.com/slaveOftime/open-relay
    brew install slaveOftime/open-relay/oly

README

oly — Open Relay

oly logo

npm version License: MIT

https://github.com/user-attachments/assets/bd52a474-d9c4-48a7-824b-8df328a9d5a7

Run interactive CLIs and AI agents like managed services.

oly gives long-running terminal jobs a durable home.

Start a command once, detach, close your terminal, come back later, inspect logs, send input only when needed, or reattach and take over. It is built for AI agent workflows, interactive CLIs, and any session you do not want tied to one fragile terminal window.

If oly saves you time, please star the repo. That helps more people discover it.

For deep implementation details, see ARCHITECTURE.md, ARCHITECTURE_PTY.md.


Why people use oly

  • Detach without losing the process. The daemon owns the session, not your terminal.
  • Stop babysitting prompts. Watch logs or wait for likely input-needed checkpoints.
  • Intervene surgically. Send text or keys without attaching.
  • Resume with context. Reattach and replay buffered output first.
  • Keep an audit trail. Session output and lifecycle events persist on disk.
  • Control it from more than one place. Use the CLI, the web UI, or route work to connected nodes.

oly is not trying to replace your favorite terminal. It is a supervision layer for long-lived, interactive workloads. A simple CLI proxy.


Install

npm

npm i -g @slaveoftime/oly

The published npm package bundles the supported platform binaries directly, so users do not need to download a GitHub release asset during npm install.

Cargo

cargo install oly

Homebrew

brew tap slaveOftime/open-relay https://github.com/slaveOftime/open-relay
brew install slaveOftime/open-relay/oly

Prebuilt binaries

Download the latest release from the Releases page.

Current release artifacts are published for:

  • macOS: Apple Silicon (arm64)
  • Linux: x86_64 / AMD64
  • Windows: x86_64 / AMD64

Quick start

If you only try one workflow, make it this one:

# Start the daemon.
# By default, the local web UI/API is enabled and protected by a password
# you set at startup.
oly daemon start --detach

# Launch a detached session
oly start copilot

# See what's running
oly ls

# Check recent output and optionally wait for an input-needed checkpoint
oly logs <id> --wait-for-prompt --timeout 1m

# Send input without attaching
oly send <id> "yes" key:enter

# Reattach when you want full control
oly attach <id>

# Stop the session
oly stop <id>

Useful behavior to know:

  • oly attach, oly logs, oly send, oly stop, and oly notify accept an optional session ID. If you omit it, oly targets the most recently created session.
  • To detach from an attached session, press Ctrl-], then d.
  • oly ls --json prints machine-readable output for scripts and agents.

What oly does well

1. Supervise agent sessions

Run coding agents, REPLs, installers, or approval-heavy workflows in the background without keeping one terminal open forever.

2. Detect likely human checkpoints

oly logs --wait-for-prompt lets you block until a session likely needs attention, then inspect the output before deciding what to do next.

3. Let humans stay in the loop

When a process needs confirmation, credentials, or a decision, you or agent can send input directly:

oly send <id> "continue" key:enter
oly send <id> key:ctrl+c
oly send <id> key:up key:enter

4. Keep a browser-accessible control plane

By default, oly daemon start -d also serves a local web UI and HTTP API on http://127.0.0.1:15443.

  • Use --bind to change the bind address (for example --bind 0.0.0.0).
  • Use --port to change the port.
  • Use --no-http for CLI-only operation.
  • Use --no-auth only if you understand the risk and are protecting access elsewhere.

5. Route work to other machines

oly can connect multiple daemons together so one primary can supervise sessions on secondary nodes.


Core workflow patterns

Detached agent run

oly start --title "fix failing tests" --detach copilot
oly logs --wait-for-prompt
oly send <id> "approve" key:enter

Watch logs without attaching

oly logs <id> --tail 80
oly logs <id> --tail 80 --keep-color
oly logs <id> --tail 120 --no-truncate

Start on a connected node

oly start --node worker-1 --title "nightly task" --detach claude
oly logs --node worker-1 --wait-for-prompt <id>

Command reference

Session and daemon commands

CommandPurpose
oly daemon start [--detach] [--bind <addr>] [--port <port>] [--no-auth] [--no-http]Start the daemon, optional local web API/UI
oly daemon stop [--grace <seconds>]Stop the daemon and let sessions exit cleanly first
oly start [--title <title>] [--detach] [--disable-notifications] [--cwd <dir>] [--node <name>] <cmd> [args...]Start a session
oly ls [--search <text>] [--json] [--status <status>]... [--since <rfc3339>] [--until <rfc3339>] [--limit <n>] [--node <name>]... [--node-local]List sessions
oly attach [id] [--node <name>]Reattach to a session
oly logs [id] [--tail <n>] [--keep-color] [--no-truncate] [--wait-for-prompt] [--timeout <duration>] [--node <name>]Read logs without attaching
oly send [id] [chunk]... [--node <name>]Send text or special keys to a session
oly stop [id] [--grace <seconds>] [--node <name>]Stop a session
oly notify enable [id] [--node <name>]Enable notifications for a session
oly notify disable [id] [--node <name>]Disable notifications for a session
oly skillPrint the bundled oly skill markdown

The interactive view can monitor several nodes at once, for example oly ls --follow --node worker-a --node worker-b. Add --node-local to include sessions from the current daemon (or the primary itself); the table shows a node column when multiple sources are selected. Ctrl+D opens a clone editor prefilled from the selected session, while Ctrl+U opens an update editor for the selected session's title, tags, and notification setting. Tab/Ctrl+Tab move between dialog fields, Space toggles notifications, and Enter submits the current dialog. Use Ctrl+K to stop the selected running session, Enter to open it inline, Ctrl+Enter to open it in another terminal window, and Ctrl+C to exit the list view.

Supported oly send key forms include named keys like key:enter, key:tab, key:esc, arrows, home/end, pgup/pgdn, del/ins, modifier forms like key:ctrl+c, key:alt+x, key:meta+enter, key:shift+tab, and raw bytes via key:hex:....

Federation commands

CommandPurpose
oly api-key add <name>Create an API key on the primary and print it once
oly api-key lsList API key labels on the primary
oly api-key remove <name>Revoke an API key on the primary
oly join start --name <name> --key <key> <url>Connect this daemon to a primary
oly join stop --name <name>Disconnect and remove a saved join config
oly join lsList saved outbound join configs on this daemon
oly join ls --primaryAsk the daemon for currently active primary-side joins
oly node lsList secondary nodes currently connected to the primary

Browser access and remote supervision

oly serves its HTTP API and web UI on loopback by default:

http://127.0.0.1:15443

That default is deliberate. The safe pattern is:

browser or phone -> your auth gateway -> your tunnel -> local oly HTTP service

Examples:

  • Cloudflare Access
  • Tailscale / Headscale
  • SSH tunnel
  • your own reverse proxy with strong auth

This keeps oly small and local-first while still supporting remote intervention when you need it.


Notification hooks

If desktop notifications are not enough, you can configure a custom notification hook in config.json under OLY_STATE_DIR (or the default state directory for your OS).

{
  "notification_hook": "python C:\\scripts\\oly_notify.py {kind} {session_ids}"
}

Placeholders available in the command:

  • {kind}
  • {title} / {summary}
  • {description}
  • {body}
  • {navigation_url}
  • {node}
  • {session_ids}
  • {trigger_rule}
  • {trigger_detail}

The same values are also exported as OLY_EVENT_* environment variables.

Hooks are best-effort: failures are logged, but they do not block the session or notification pipeline.


State, config, and files

Default state directory:

  • Windows: %LOCALAPPDATA%\oly
  • Linux: $XDG_STATE_HOME/oly or ~/.local/state/oly
  • macOS: ~/Library/Application Support/oly

You can override it with OLY_STATE_DIR.

Inside that directory, oly stores:

  • the SQLite database
  • daemon logs
  • session logs and metadata
  • generated default config.json
  • saved join configs on secondary nodes
  • optional wwwroot static content

Good fits for oly

  • GitHub Copilot CLI, Claude Code, Gemini CLI, OpenCode, and similar agent workflows
  • Long-running installs or migrations that may need approval later
  • Interactive REPLs or TUIs you want to resume safely
  • Background automation that still needs occasional human intervention
  • Single-operator or small-team setups that want a lightweight supervision layer

Learn more

If you are building agent workflows and want durable, inspectable terminal sessions, oly is for you.

Files in the repo

Repository payload28 top-level entries
  • .cargo
  • .github
  • .vscode
  • assets
  • docs
  • Formula
  • hooks
  • migrations
  • milestones
  • npm
  • src
  • tests
  • web
  • winget
  • .gitignore
  • ARCHITECTURE_NOTES.md
  • ARCHITECTURE_PTY.md
  • ARCHITECTURE.md
  • build.rs
  • Cargo.lock
  • Cargo.toml
  • CODE_OF_CONDUCT.md
  • CONTRIBUTING.md
  • LICENSE
  • README.md
  • SECURITY.md
  • SPEC.md
  • SUPPORT.md

Discussion (0)

Ask about usage, or say what you built with it

Sign in to join the discussion.

No comments yet. Be the first to say what this is good for.

More tools

JuliusBrussee/
caveman

🪨 why use many token when few token do trick — Claude Code skill that cuts 65% of tokens by talking like caveman

105k
1 add
MemPalace/
mempalace

The best-benchmarked open-source AI memory system. And it's free.

59k
stablyai/
orca

Orca is the ADE for working with a fleet of parallel agents. Run any coding agent with your own subscription. Available on desktop, mobile and remote runtime.

66k

A cross-platform desktop All-in-One assistant for Claude Code, Codex, OpenCode, OpenClaw, Grok Build & Hermes Agent. Only official website: ccswitch.io

132k

Never stop coding. Free MIT AI gateway: one endpoint, 352 providers (150+ free), 1200+ models Kimi, Claude, GPT, Gemini, GLM, DeepSeek, MiniMax. Works with Claude Code, Codex, Cursor, OpenCode, Cline & Copilot. Quota-aware auto-fallback, RTK+Caveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550+ contributors

64k
headroomlabs-ai/
headroom

Compress tool outputs, logs, files, and RAG chunks before they reach the LLM. 20% fewer tokens for coding agents, 60-95% fewer tokens for JSON, same answers. Library, proxy, MCP server.

71k