{"id":47072048,"url":"https://github.com/slaveoftime/open-relay","last_synced_at":"2026-04-01T22:35:38.470Z","repository":{"id":343053241,"uuid":"1176073062","full_name":"slaveOftime/open-relay","owner":"slaveOftime","description":"`oly` turns long-running and interactive CLI workflows into persistent, supervised sessions for humans and AI agents. Close the terminal, keep the process alive, get notified when input is needed, and jump back in from anywhere.","archived":false,"fork":false,"pushed_at":"2026-03-12T04:20:31.000Z","size":4013,"stargazers_count":15,"open_issues_count":1,"forks_count":2,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-12T10:27:18.272Z","etag":null,"topics":["agentops","ai-agents","claude-code","cli","codex-cli","copilot","gemini-cli","opencode","pty","rust","session-management"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/slaveOftime.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-08T15:27:15.000Z","updated_at":"2026-03-12T10:23:42.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/slaveOftime/open-relay","commit_stats":null,"previous_names":["slaveoftime/open-relay"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/slaveOftime/open-relay","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slaveOftime%2Fopen-relay","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slaveOftime%2Fopen-relay/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slaveOftime%2Fopen-relay/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slaveOftime%2Fopen-relay/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/slaveOftime","download_url":"https://codeload.github.com/slaveOftime/open-relay/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slaveOftime%2Fopen-relay/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30460818,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-13T06:34:02.089Z","status":"ssl_error","status_checked_at":"2026-03-13T06:33:49.182Z","response_time":60,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agentops","ai-agents","claude-code","cli","codex-cli","copilot","gemini-cli","opencode","pty","rust","session-management"],"created_at":"2026-03-12T06:03:24.348Z","updated_at":"2026-04-01T22:35:38.446Z","avatar_url":"https://github.com/slaveOftime.png","language":"Rust","readme":"# oly — Open Relay\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./assets/icon-demo.svg\" width=\"160\" alt=\"oly logo\" /\u003e\n\u003c/p\u003e\n\n[![npm version](https://img.shields.io/npm/v/@slaveoftime/oly.svg)](https://www.npmjs.com/package/@slaveoftime/oly)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)\n\nhttps://github.com/user-attachments/assets/bd52a474-d9c4-48a7-824b-8df328a9d5a7\n\n\u003e Run interactive CLIs and AI agents like managed services.\n\n`oly` gives long-running terminal jobs a durable home.\n\nStart 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.\n\nIf `oly` saves you time, please star the repo. That helps more people discover it.\n\nFor deep implementation details, see [ARCHITECTURE.md](./ARCHITECTURE.md), [ARCHITECTURE_PTY.md](./ARCHITECTURE_PTY.md).\n\n---\n\n## Why people use `oly`\n\n- **Detach without losing the process.** The daemon owns the session, not your terminal.\n- **Stop babysitting prompts.** Watch logs or wait for likely input-needed checkpoints.\n- **Intervene surgically.** Send text or keys without attaching.\n- **Resume with context.** Reattach and replay buffered output first.\n- **Keep an audit trail.** Session output and lifecycle events persist on disk.\n- **Control it from more than one place.** Use the CLI, the web UI, or route work to connected nodes.\n\n`oly` is not trying to replace your favorite terminal. It is a supervision layer for long-lived, interactive workloads. A simple CLI proxy.\n\n---\n\n## Install\n\n### npm\n\n```sh\nnpm i -g @slaveoftime/oly\n```\n\nThe published npm package bundles the supported platform binaries directly, so users do not need to download a GitHub release asset during `npm install`.\n\n### Cargo\n\n```sh\ncargo install oly\n```\n\n### Homebrew\n\n```sh\nbrew tap slaveOftime/open-relay https://github.com/slaveOftime/open-relay\nbrew install slaveOftime/open-relay/oly\n```\n\n### Prebuilt binaries\n\nDownload the latest release from the [Releases page](https://github.com/slaveOftime/open-relay/releases).\n\nCurrent release artifacts are published for:\n\n- **macOS**: Apple Silicon (`arm64`)\n- **Linux**: `x86_64` / AMD64\n- **Windows**: `x86_64` / AMD64\n\n---\n\n## Quick start\n\nIf you only try one workflow, make it this one:\n\n```sh\n# Start the daemon.\n# By default, the local web UI/API is enabled and protected by a password\n# you set at startup.\noly daemon start --detach\n\n# Launch a detached session\noly start copilot\n\n# See what's running\noly ls\n\n# Check recent output and optionally wait for an input-needed checkpoint\noly logs \u003cid\u003e --wait-for-prompt --timeout 1m\n\n# Send input without attaching\noly send \u003cid\u003e \"yes\" key:enter\n\n# Reattach when you want full control\noly attach \u003cid\u003e\n\n# Stop the session\noly stop \u003cid\u003e\n```\n\nUseful behavior to know:\n\n- `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.\n- To detach from an attached session, press `Ctrl-]`, then `d`.\n- `oly ls --json` prints machine-readable output for scripts and agents.\n\n---\n\n## What `oly` does well\n\n### 1. Supervise agent sessions\n\nRun coding agents, REPLs, installers, or approval-heavy workflows in the background without keeping one terminal open forever.\n\n### 2. Detect likely human checkpoints\n\n`oly logs --wait-for-prompt` lets you block until a session likely needs attention, then inspect the output before deciding what to do next.\n\n### 3. Let humans stay in the loop\n\nWhen a process needs confirmation, credentials, or a decision, you or agent can send input directly:\n\n```sh\noly send \u003cid\u003e \"continue\" key:enter\noly send \u003cid\u003e key:ctrl+c\noly send \u003cid\u003e key:up key:enter\n```\n\n### 4. Keep a browser-accessible control plane\n\nBy default, `oly daemon start -d` also serves a local web UI and HTTP API on `http://127.0.0.1:15443`.\n\n- Use `--port` to change the port.\n- Use `--no-http` for CLI-only operation.\n- Use `--no-auth` only if you understand the risk and are protecting access elsewhere.\n\n### 5. Route work to other machines\n\n`oly` can connect multiple daemons together so one primary can supervise sessions on secondary nodes.\n\n---\n\n## Core workflow patterns\n\n### Detached agent run\n\n```sh\noly start --title \"fix failing tests\" --detach copilot\noly logs --wait-for-prompt\noly send \u003cid\u003e \"approve\" key:enter\n```\n\n### Watch logs without attaching\n\n```sh\noly logs \u003cid\u003e --tail 80\noly logs \u003cid\u003e --tail 80 --keep-color\noly logs \u003cid\u003e --tail 120 --no-truncate\n```\n\n### Start on a connected node\n\n```sh\noly start --node worker-1 --title \"nightly task\" --detach claude\noly logs --node worker-1 --wait-for-prompt \u003cid\u003e\n```\n\n---\n\n## Command reference\n\n### Session and daemon commands\n\n| Command | Purpose |\n| --- | --- |\n| `oly daemon start [--detach] [--port \u003cport\u003e] [--no-auth] [--no-http]` | Start the daemon, optional local web API/UI |\n| `oly daemon stop [--grace \u003cseconds\u003e]` | Stop the daemon and let sessions exit cleanly first |\n| `oly start [--title \u003ctitle\u003e] [--detach] [--disable-notifications] [--cwd \u003cdir\u003e] [--node \u003cname\u003e] \u003ccmd\u003e [args...]` | Start a session |\n| `oly ls [--search \u003ctext\u003e] [--json] [--status \u003cstatus\u003e]... [--since \u003crfc3339\u003e] [--until \u003crfc3339\u003e] [--limit \u003cn\u003e] [--node \u003cname\u003e]` | List sessions |\n| `oly attach [id] [--node \u003cname\u003e]` | Reattach to a session |\n| `oly logs [id] [--tail \u003cn\u003e] [--keep-color] [--no-truncate] [--wait-for-prompt] [--timeout \u003cduration\u003e] [--node \u003cname\u003e]` | Read logs without attaching |\n| `oly send [id] [chunk]... [--node \u003cname\u003e]` | Send text or special keys to a session |\n| `oly stop [id] [--grace \u003cseconds\u003e] [--node \u003cname\u003e]` | Stop a session |\n| `oly notify enable [id] [--node \u003cname\u003e]` | Enable notifications for a session |\n| `oly notify disable [id] [--node \u003cname\u003e]` | Disable notifications for a session |\n| `oly skill` | Print the bundled `oly` skill markdown |\n\nSupported `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:...`.\n\n### Federation commands\n\n| Command | Purpose |\n| --- | --- |\n| `oly api-key add \u003cname\u003e` | Create an API key on the primary and print it once |\n| `oly api-key ls` | List API key labels on the primary |\n| `oly api-key remove \u003cname\u003e` | Revoke an API key on the primary |\n| `oly join start --name \u003cname\u003e --key \u003ckey\u003e \u003curl\u003e` | Connect this daemon to a primary |\n| `oly join stop --name \u003cname\u003e` | Disconnect and remove a saved join config |\n| `oly join ls` | List saved outbound join configs on this daemon |\n| `oly join ls --primary` | Ask the daemon for currently active primary-side joins |\n| `oly node ls` | List secondary nodes currently connected to the primary |\n\n---\n\n## Browser access and remote supervision\n\n`oly` serves its HTTP API and web UI on loopback by default:\n\n```text\nhttp://127.0.0.1:15443\n```\n\nThat default is deliberate. The safe pattern is:\n\n```text\nbrowser or phone -\u003e your auth gateway -\u003e your tunnel -\u003e local oly HTTP service\n```\n\nExamples:\n\n- Cloudflare Access\n- Tailscale / Headscale\n- SSH tunnel\n- your own reverse proxy with strong auth\n\nThis keeps `oly` small and local-first while still supporting remote intervention when you need it.\n\n---\n\n## Notification hooks\n\nIf 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).\n\n```json\n{\n  \"notification_hook\": \"python C:\\\\scripts\\\\oly_notify.py {kind} {session_ids}\"\n}\n```\n\nPlaceholders available in the command:\n\n- `{kind}`\n- `{title}` / `{summary}`\n- `{description}`\n- `{body}`\n- `{navigation_url}`\n- `{node}`\n- `{session_ids}`\n- `{trigger_rule}`\n- `{trigger_detail}`\n\nThe same values are also exported as `OLY_EVENT_*` environment variables.\n\nHooks are best-effort: failures are logged, but they do not block the session or notification pipeline.\n\n---\n\n## State, config, and files\n\nDefault state directory:\n\n- **Windows**: `%LOCALAPPDATA%\\oly`\n- **Linux**: `$XDG_STATE_HOME/oly` or `~/.local/state/oly`\n- **macOS**: `~/Library/Application Support/oly`\n\nYou can override it with `OLY_STATE_DIR`.\n\nInside that directory, `oly` stores:\n\n- the SQLite database\n- daemon logs\n- session logs and metadata\n- generated default `config.json`\n- saved join configs on secondary nodes\n- optional `wwwroot` static content\n\n---\n\n## Good fits for `oly`\n\n- GitHub Copilot CLI, Claude Code, Gemini CLI, OpenCode, and similar agent workflows\n- Long-running installs or migrations that may need approval later\n- Interactive REPLs or TUIs you want to resume safely\n- Background automation that still needs occasional human intervention\n- Single-operator or small-team setups that want a lightweight supervision layer\n\n---\n\n## Learn more\n\n- [SPEC.md](./SPEC.md) for the implementation-aligned product spec\n- [ARCHITECTURE.md](./ARCHITECTURE.md) for the system overview\n- [ARCHITECTURE_PTY.md](./ARCHITECTURE_PTY.md) for PTY behavior\n- [ARCHITECTURE_NOTES.md](./ARCHITECTURE_NOTES.md) for edge cases and operational notes\n\nIf you are building agent workflows and want durable, inspectable terminal sessions, `oly` is for you.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslaveoftime%2Fopen-relay","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fslaveoftime%2Fopen-relay","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslaveoftime%2Fopen-relay/lists"}