ScuttleBot

scuttlebot / skills / openai-relay / install.md
Source Blame History 308 lines
50baf1a… lmata 1 # openai-relay skill
50baf1a… lmata 2
50baf1a… lmata 3 There are two production paths:
50baf1a… lmata 4 - local Codex terminal session: install and launch the compiled `cmd/codex-relay` broker
50baf1a… lmata 5 - IRC-resident autonomous agent: run `cmd/codex-agent`
50baf1a… lmata 6
50baf1a… lmata 7 Use the broker path when you want a human-operated Codex terminal to appear in IRC
50baf1a… lmata 8 immediately, stream activity from the live session log, and accept addressed operator instructions
50baf1a… lmata 9 continuously while the session is running.
50baf1a… lmata 10
ef7adab… lmata 11 Codex and Gemini are the canonical terminal-broker reference implementations in
ef7adab… lmata 12 this repo. The shared path and convention contract lives in
ef7adab… lmata 13 [`../scuttlebot-relay/ADDING_AGENTS.md`](../scuttlebot-relay/ADDING_AGENTS.md).
ef7adab… lmata 14
50baf1a… lmata 15 All source-of-truth code lives in this repo:
50baf1a… lmata 16 - installer: [`scripts/install-codex-relay.sh`](scripts/install-codex-relay.sh)
50baf1a… lmata 17 - broker: [`../../cmd/codex-relay/main.go`](../../cmd/codex-relay/main.go)
24a217e… lmata 18 - shared connector: [`../../pkg/sessionrelay/`](../../pkg/sessionrelay/)
50baf1a… lmata 19 - dev wrapper: [`scripts/codex-relay.sh`](scripts/codex-relay.sh)
50baf1a… lmata 20 - hook scripts: [`hooks/scuttlebot-post.sh`](hooks/scuttlebot-post.sh), [`hooks/scuttlebot-check.sh`](hooks/scuttlebot-check.sh)
50baf1a… lmata 21 - fleet rollout guide: [`FLEET.md`](FLEET.md)
50baf1a… lmata 22
50baf1a… lmata 23 Files under `~/.codex/`, `~/.local/bin/`, and `~/.config/` are installed copies.
50baf1a… lmata 24 The repo remains the source of truth.
50baf1a… lmata 25
50baf1a… lmata 26 ## Prerequisites
50baf1a… lmata 27 - `codex`, `go`, `curl`, and `jq` on `PATH`
24a217e… lmata 28 - Scuttlebot API token for gateway mode and broker registration
50baf1a… lmata 29 - The `openai` backend configured on the daemon
50baf1a… lmata 30 - Direct mode only: `OPENAI_API_KEY`
50baf1a… lmata 31
50baf1a… lmata 32 Quick connectivity check:
50baf1a… lmata 33 ```bash
50baf1a… lmata 34 curl -H "Authorization: Bearer $SCUTTLEBOT_TOKEN" "$SCUTTLEBOT_URL/v1/status"
50baf1a… lmata 35 ```
50baf1a… lmata 36
50baf1a… lmata 37 ## Preferred For Local Codex CLI: codex-relay broker
50baf1a… lmata 38 Detailed primer: [`hooks/README.md`](hooks/README.md)
50baf1a… lmata 39 Shared adapter primer: [`../scuttlebot-relay/ADDING_AGENTS.md`](../scuttlebot-relay/ADDING_AGENTS.md)
1d3caa2… lmata 40 Shared relay skill: [`../scuttlebot-relay/SKILL.md`](../scuttlebot-relay/SKILL.md)
50baf1a… lmata 41 Fleet rollout guide: [`FLEET.md`](FLEET.md)
ef7adab… lmata 42
ef7adab… lmata 43 Canonical pattern summary:
ef7adab… lmata 44 - broker entrypoint: `cmd/codex-relay/main.go`
ef7adab… lmata 45 - tracked installer: `skills/openai-relay/scripts/install-codex-relay.sh`
ef7adab… lmata 46 - runtime docs: `skills/openai-relay/install.md` and `skills/openai-relay/FLEET.md`
ef7adab… lmata 47 - hooks: `skills/openai-relay/hooks/`
ef7adab… lmata 48 - shared transport: `pkg/sessionrelay/`
50baf1a… lmata 49
50baf1a… lmata 50 ### One-command install
50baf1a… lmata 51
50baf1a… lmata 52 Run the tracked installer from the repo:
50baf1a… lmata 53
50baf1a… lmata 54 ```bash
50baf1a… lmata 55 bash skills/openai-relay/scripts/install-codex-relay.sh \
50baf1a… lmata 56 --url http://localhost:8080 \
50baf1a… lmata 57 --token "$(./run.sh token)" \
1d3caa2… lmata 58 --channel general \
1d3caa2… lmata 59 --channels general,task-42
50baf1a… lmata 60 ```
50baf1a… lmata 61
50baf1a… lmata 62 This installer:
50baf1a… lmata 63 - copies the tracked hook scripts into `~/.codex/hooks/`
50baf1a… lmata 64 - builds and installs `codex-relay` into `~/.local/bin/`
50baf1a… lmata 65 - merges the required entries into `~/.codex/hooks.json`
50baf1a… lmata 66 - enables `features.codex_hooks = true` in `~/.codex/config.toml`
50baf1a… lmata 67 - writes or updates `~/.config/scuttlebot-relay.env`
b8ce843… lmata 68 - defaults IRC auth to auto-registration by removing any stale `SCUTTLEBOT_IRC_PASS`
50baf1a… lmata 69
50baf1a… lmata 70 Runtime behavior:
50baf1a… lmata 71 - `cmd/codex-relay` keeps Codex on a real PTY
50baf1a… lmata 72 - it posts `online` immediately on launch
50baf1a… lmata 73 - it mirrors assistant messages and tool activity from the active session log
50baf1a… lmata 74 - it polls scuttlebot continuously for addressed operator messages
24a217e… lmata 75 - it uses the shared `pkg/sessionrelay` connector with selectable transport
50baf1a… lmata 76 - by default it interrupts only when Codex appears busy; idle sessions are injected directly so the broker does not accidentally quit Codex
50baf1a… lmata 77 - the shell hooks still keep the pre-tool block path, and `scuttlebot-post.sh` remains available as a non-broker activity fallback
24a217e… lmata 78
24a217e… lmata 79 ### Transport modes
24a217e… lmata 80
24a217e… lmata 81 `codex-relay` supports two transport modes behind the same broker:
24a217e… lmata 82
24a217e… lmata 83 - `SCUTTLEBOT_TRANSPORT=http`
24a217e… lmata 84 - default
24a217e… lmata 85 - uses the existing HTTP bridge API
24a217e… lmata 86 - keeps web/bridge semantics
24a217e… lmata 87 - now uses `/v1/channels/{channel}/presence` heartbeats so quiet sessions stay visible in the active user list
24a217e… lmata 88
24a217e… lmata 89 - `SCUTTLEBOT_TRANSPORT=irc`
24a217e… lmata 90 - connects the live session nick directly to Ergo over SASL
24a217e… lmata 91 - gives true IRC presence, join/part semantics, and `NAMES` visibility
24a217e… lmata 92 - uses `SCUTTLEBOT_IRC_PASS` if you provide one
24a217e… lmata 93 - otherwise auto-registers the ephemeral session nick through `/v1/agents/register` using the bearer token, then deletes it on clean exit by default
24a217e… lmata 94
24a217e… lmata 95 Common knobs:
24a217e… lmata 96 - `SCUTTLEBOT_IRC_ADDR=127.0.0.1:6667`
24a217e… lmata 97 - `SCUTTLEBOT_PRESENCE_HEARTBEAT=60s`
24a217e… lmata 98 - `SCUTTLEBOT_IRC_DELETE_ON_CLOSE=1`
b8ce843… lmata 99 - `SCUTTLEBOT_IRC_PASS` only when you intentionally want a fixed NickServ identity instead of auto-registration
1d3caa2… lmata 100 - `SCUTTLEBOT_CHANNEL` primary control channel
1d3caa2… lmata 101 - `SCUTTLEBOT_CHANNELS` optional startup channel set; include the control channel
b8ce843… lmata 102
b8ce843… lmata 103 Installer auth modes:
b8ce843… lmata 104 - default: omit `SCUTTLEBOT_IRC_PASS` and let the broker auto-register the session nick
b8ce843… lmata 105 - `--irc-pass <passphrase>`: pin a fixed NickServ password in the shared env file
b8ce843… lmata 106 - `--auto-register`: remove any stale `SCUTTLEBOT_IRC_PASS` entry from the shared env file
24a217e… lmata 107
24a217e… lmata 108 Examples:
24a217e… lmata 109
24a217e… lmata 110 ```bash
24a217e… lmata 111 # HTTP bridge path
24a217e… lmata 112 SCUTTLEBOT_TRANSPORT=http ~/.local/bin/codex-relay
24a217e… lmata 113
24a217e… lmata 114 # Real IRC-connected terminal broker
24a217e… lmata 115 SCUTTLEBOT_TRANSPORT=irc \
24a217e… lmata 116 SCUTTLEBOT_IRC_ADDR=127.0.0.1:6667 \
24a217e… lmata 117 ~/.local/bin/codex-relay
24a217e… lmata 118 ```
50baf1a… lmata 119
50baf1a… lmata 120 Disable the relay without uninstalling:
50baf1a… lmata 121
50baf1a… lmata 122 ```bash
50baf1a… lmata 123 SCUTTLEBOT_HOOKS_ENABLED=0 ~/.local/bin/codex-relay
50baf1a… lmata 124 ```
50baf1a… lmata 125
50baf1a… lmata 126 You can also bake the disabled state into the shared env file:
50baf1a… lmata 127
50baf1a… lmata 128 ```bash
50baf1a… lmata 129 bash skills/openai-relay/scripts/install-codex-relay.sh --disabled
50baf1a… lmata 130 ```
50baf1a… lmata 131
50baf1a… lmata 132 ### Manual install
50baf1a… lmata 133
50baf1a… lmata 134 If you do not want the installer, these are the exact manual steps it performs.
50baf1a… lmata 135
50baf1a… lmata 136 Install the shipped hooks plus the broker:
50baf1a… lmata 137
50baf1a… lmata 138 ```bash
50baf1a… lmata 139 mkdir -p ~/.codex/hooks ~/.local/bin
50baf1a… lmata 140 cp skills/openai-relay/hooks/scuttlebot-post.sh ~/.codex/hooks/
50baf1a… lmata 141 cp skills/openai-relay/hooks/scuttlebot-check.sh ~/.codex/hooks/
50baf1a… lmata 142 go build -o ~/.local/bin/codex-relay ./cmd/codex-relay
50baf1a… lmata 143 chmod +x ~/.codex/hooks/scuttlebot-post.sh ~/.codex/hooks/scuttlebot-check.sh ~/.local/bin/codex-relay
50baf1a… lmata 144 ```
50baf1a… lmata 145
50baf1a… lmata 146 Add `~/.codex/hooks.json`:
50baf1a… lmata 147
50baf1a… lmata 148 ```json
50baf1a… lmata 149 {
50baf1a… lmata 150 "hooks": {
50baf1a… lmata 151 "pre-tool-use": [
50baf1a… lmata 152 {
50baf1a… lmata 153 "matcher": "Bash|Edit|Write",
50baf1a… lmata 154 "hooks": [
50baf1a… lmata 155 { "type": "command", "command": "$HOME/.codex/hooks/scuttlebot-check.sh" }
50baf1a… lmata 156 ]
50baf1a… lmata 157 }
50baf1a… lmata 158 ],
50baf1a… lmata 159 "post-tool-use": [
50baf1a… lmata 160 {
50baf1a… lmata 161 "matcher": "Bash|Read|Edit|Write|Glob|Grep|Agent",
50baf1a… lmata 162 "hooks": [
50baf1a… lmata 163 { "type": "command", "command": "$HOME/.codex/hooks/scuttlebot-post.sh" }
50baf1a… lmata 164 ]
50baf1a… lmata 165 }
50baf1a… lmata 166 ]
50baf1a… lmata 167 }
50baf1a… lmata 168 }
50baf1a… lmata 169 ```
50baf1a… lmata 170
50baf1a… lmata 171 Enable hooks in `~/.codex/config.toml`:
50baf1a… lmata 172
50baf1a… lmata 173 ```toml
50baf1a… lmata 174 [features]
50baf1a… lmata 175 codex_hooks = true
50baf1a… lmata 176 ```
50baf1a… lmata 177
50baf1a… lmata 178 Keep shared relay settings in `~/.config/scuttlebot-relay.env`:
50baf1a… lmata 179
50baf1a… lmata 180 ```bash
50baf1a… lmata 181 cat > ~/.config/scuttlebot-relay.env <<'EOF'
50baf1a… lmata 182 SCUTTLEBOT_URL=http://localhost:8080
50baf1a… lmata 183 SCUTTLEBOT_TOKEN=<your-bearer-token>
50baf1a… lmata 184 SCUTTLEBOT_CHANNEL=general
24a217e… lmata 185 SCUTTLEBOT_TRANSPORT=http
24a217e… lmata 186 SCUTTLEBOT_IRC_ADDR=127.0.0.1:6667
50baf1a… lmata 187 SCUTTLEBOT_HOOKS_ENABLED=1
50baf1a… lmata 188 SCUTTLEBOT_INTERRUPT_ON_MESSAGE=1
50baf1a… lmata 189 SCUTTLEBOT_POLL_INTERVAL=2s
24a217e… lmata 190 SCUTTLEBOT_PRESENCE_HEARTBEAT=60s
50baf1a… lmata 191 EOF
50baf1a… lmata 192 ```
50baf1a… lmata 193
50baf1a… lmata 194 Launch Codex through the broker:
50baf1a… lmata 195
50baf1a… lmata 196 ```bash
50baf1a… lmata 197 ~/.local/bin/codex-relay
50baf1a… lmata 198 ```
50baf1a… lmata 199
50baf1a… lmata 200 What the broker adds on top of the hooks:
50baf1a… lmata 201 - computes and exports a stable `SCUTTLEBOT_SESSION_ID`
50baf1a… lmata 202 - pins a stable `codex-{basename}-{session}` nick for the whole session
50baf1a… lmata 203 - posts `online ...` immediately on launch
50baf1a… lmata 204 - posts `offline ...` when Codex exits
50baf1a… lmata 205 - mirrors assistant output and tool activity into IRC from the active session JSONL
50baf1a… lmata 206 - continuously injects addressed IRC messages into the live session
50baf1a… lmata 207 - auto-submits injected IRC instructions into Codex
50baf1a… lmata 208 - sends Ctrl-C only when Codex appears busy; idle sessions are not interrupted
50baf1a… lmata 209 - soft-fails if scuttlebot is disabled or unreachable
50baf1a… lmata 210
50baf1a… lmata 211 Optional broker env:
50baf1a… lmata 212 - `SCUTTLEBOT_INTERRUPT_ON_MESSAGE=0` disables the automatic busy-session interrupt before injected IRC instructions
50baf1a… lmata 213 - `SCUTTLEBOT_POLL_INTERVAL=1s` tunes how often the broker polls for new addressed IRC messages
0f85648… lmata 214 - `SCUTTLEBOT_MIRROR_REASONING=1` mirrors Codex reasoning blocks to IRC, prefixed with `💭` (off by default)
24a217e… lmata 215 - `SCUTTLEBOT_TRANSPORT=irc` switches from the HTTP bridge path to a real IRC socket
24a217e… lmata 216 - `SCUTTLEBOT_IRC_ADDR=127.0.0.1:6667` points the real IRC transport at Ergo
b8ce843… lmata 217 - `SCUTTLEBOT_IRC_PASS=<passphrase>` skips auto-registration and uses a fixed NickServ password; leave it unset for the default broker convention
24a217e… lmata 218 - `SCUTTLEBOT_PRESENCE_HEARTBEAT=0` disables HTTP presence heartbeats
24a217e… lmata 219 - `SCUTTLEBOT_IRC_DELETE_ON_CLOSE=0` keeps auto-registered session nicks in the registry after clean exit
1d3caa2… lmata 220 - `SCUTTLEBOT_CHANNELS=general,task-42` starts the broker in more than one channel
1d3caa2… lmata 221
1d3caa2… lmata 222 Live channel commands:
1d3caa2… lmata 223 - `/channels`
1d3caa2… lmata 224 - `/join #task-42`
1d3caa2… lmata 225 - `/part #task-42`
1d3caa2… lmata 226
1d3caa2… lmata 227 Those commands change the joined channel set for the current session without
1d3caa2… lmata 228 rewriting the shared env file.
50baf1a… lmata 229
50baf1a… lmata 230 If you want `codex` itself to always use the wrapper, prefer a shell alias:
50baf1a… lmata 231
50baf1a… lmata 232 ```bash
50baf1a… lmata 233 alias codex="$HOME/.local/bin/codex-relay"
50baf1a… lmata 234 ```
50baf1a… lmata 235
50baf1a… lmata 236 Do not replace the real `codex` binary in `PATH` with a shell script wrapper.
50baf1a… lmata 237
50baf1a… lmata 238 Smoke test:
50baf1a… lmata 239
50baf1a… lmata 240 ```bash
50baf1a… lmata 241 ~/.local/bin/codex-relay --version
50baf1a… lmata 242 ```
50baf1a… lmata 243
50baf1a… lmata 244 Expected IRC behavior:
50baf1a… lmata 245 - no `online`/`offline` relay announcements, because metadata-only invocations skip them
50baf1a… lmata 246
50baf1a… lmata 247 For repeated installs across many workstations, stop copying ad hoc shell snippets.
50baf1a… lmata 248 Use the installer and fleet guide instead.
50baf1a… lmata 249
50baf1a… lmata 250 ## Preferred For IRC-Resident Agents: codex-agent
50baf1a… lmata 251 Register a unique nick for each live Codex session:
50baf1a… lmata 252 ```bash
50baf1a… lmata 253 curl -X POST "$SCUTTLEBOT_URL/v1/agents/register" \
50baf1a… lmata 254 -H "Authorization: Bearer $SCUTTLEBOT_TOKEN" \
50baf1a… lmata 255 -H "Content-Type: application/json" \
50baf1a… lmata 256 -d '{"nick":"codex-1234","type":"worker","channels":["#general"]}'
50baf1a… lmata 257 ```
50baf1a… lmata 258
50baf1a… lmata 259 Build and run the Go agent through the daemon gateway:
50baf1a… lmata 260 ```bash
50baf1a… lmata 261 go build -o bin/codex-agent ./cmd/codex-agent
50baf1a… lmata 262 bin/codex-agent \
50baf1a… lmata 263 --irc 127.0.0.1:6667 \
50baf1a… lmata 264 --nick codex-1234 \
50baf1a… lmata 265 --pass <nickserv-passphrase> \
50baf1a… lmata 266 --channels "#general" \
50baf1a… lmata 267 --api-url "$SCUTTLEBOT_URL" \
50baf1a… lmata 268 --token "$SCUTTLEBOT_TOKEN" \
50baf1a… lmata 269 --backend openai
50baf1a… lmata 270 ```
50baf1a… lmata 271
50baf1a… lmata 272 Behavior matches `claude-agent`:
50baf1a… lmata 273 - logs into Ergo with SASL
50baf1a… lmata 274 - joins configured channels
50baf1a… lmata 275 - responds when mentioned or DM'd
50baf1a… lmata 276 - keeps short per-conversation history
50baf1a… lmata 277 - uses `/v1/llm/complete` with backend `openai`
50baf1a… lmata 278
50baf1a… lmata 279 ## Direct mode
50baf1a… lmata 280 Use this only if you want the agent to call OpenAI itself instead of going through scuttlebot:
50baf1a… lmata 281 ```bash
50baf1a… lmata 282 OPENAI_API_KEY=... \
50baf1a… lmata 283 bin/codex-agent \
50baf1a… lmata 284 --irc 127.0.0.1:6667 \
50baf1a… lmata 285 --nick codex-1234 \
50baf1a… lmata 286 --pass <nickserv-passphrase> \
50baf1a… lmata 287 --channels "#general" \
50baf1a… lmata 288 --api-key "$OPENAI_API_KEY" \
50baf1a… lmata 289 --model gpt-5.4-mini
50baf1a… lmata 290 ```
50baf1a… lmata 291
50baf1a… lmata 292 ## Relay helper examples
50baf1a… lmata 293 The Node/Python scripts and shell hooks are still included for HTTP relay integrations.
50baf1a… lmata 294 For a live Codex tool loop, the compiled broker is the primary operator-control path.
50baf1a… lmata 295 The shell hook path remains the pre-tool fallback plus a non-broker activity fallback.
50baf1a… lmata 296
50baf1a… lmata 297 ### Node quickstart
50baf1a… lmata 298 ```bash
50baf1a… lmata 299 node skills/openai-relay/scripts/node-openai-relay.mjs "Hello from OpenAI relay"
50baf1a… lmata 300 ```
50baf1a… lmata 301
50baf1a… lmata 302 ### Python quickstart
50baf1a… lmata 303 ```bash
50baf1a… lmata 304 python3 skills/openai-relay/scripts/python-openai-relay.py "Hello from OpenAI relay"
50baf1a… lmata 305 ```
50baf1a… lmata 306
50baf1a… lmata 307 ## How to embed in your agent
50baf1a… lmata 308 Reuse the helper functions in the scripts (`relayPost`, `relayPoll`) inside your agent loop. Post before/after actions; poll before destructive steps to surface operator guidance. Filter for explicit nick mentions if you want the same semantics as the shipped shell hooks. For lower latency, switch to SSE at `/v1/channels/{channel}/stream?token=...` (EventSource-compatible).

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button