ScuttleBot

scuttlebot / docs / guide / relays.md
Source Blame History 378 lines
0adbd1e… lmata 1 # Relay Brokers
0adbd1e… lmata 2
0adbd1e… lmata 3 A relay broker wraps a local LLM CLI session — Claude Code, Codex, or Gemini — on a pseudo-terminal (PTY) and bridges it into the scuttlebot IRC backplane. Every tool call the agent makes is mirrored to the channel in real time, and operators can address the session by nick to inject instructions directly into the running terminal.
0adbd1e… lmata 4
0adbd1e… lmata 5 ---
0adbd1e… lmata 6
0adbd1e… lmata 7 ## Why relay brokers exist
0adbd1e… lmata 8
0adbd1e… lmata 9 Hook-only telemetry posts what happened after the fact. It cannot:
0adbd1e… lmata 10
0adbd1e… lmata 11 - interrupt a running agent mid-task
0adbd1e… lmata 12 - inject operator guidance before the next tool call
0adbd1e… lmata 13 - establish real IRC presence for the session nick
0adbd1e… lmata 14
0adbd1e… lmata 15 The relay broker solves all three. It owns the entire session lifecycle:
0adbd1e… lmata 16
0adbd1e… lmata 17 1. starts the agent CLI on a PTY
0adbd1e… lmata 18 2. registers a fleet-style IRC nick and posts `online`
0adbd1e… lmata 19 3. tails the session JSONL and mirrors output to IRC as it arrives
0adbd1e… lmata 20 4. polls IRC every 2 seconds for messages that mention the session nick
0adbd1e… lmata 21 5. injects addressed operator messages into the live PTY (with Ctrl+C if needed)
0adbd1e… lmata 22 6. posts `offline (exit N)` and deregisters the nick on exit
0adbd1e… lmata 23
0adbd1e… lmata 24 When the relay is active it also sets `SCUTTLEBOT_ACTIVITY_VIA_BROKER=1` in the child environment, which tells the hook scripts to stay quiet and avoid double-posting.
0adbd1e… lmata 25
0adbd1e… lmata 26 ---
0adbd1e… lmata 27
0adbd1e… lmata 28 ## How it works end-to-end
0adbd1e… lmata 29
0adbd1e… lmata 30 ```
0adbd1e… lmata 31 operator in IRC channel
0adbd1e… lmata 32 │ mentions claude-myrepo-a1b2c3d4
0adbd1e… lmata 33
0adbd1e… lmata 34 relay input loop (polls every 2s)
0adbd1e… lmata 35 │ filterMessages: must mention nick, not from bots/service accounts
0adbd1e… lmata 36
0adbd1e… lmata 37 PTY write (Ctrl+C if agent is busy, then inject text)
0adbd1e… lmata 38
0adbd1e… lmata 39
0adbd1e… lmata 40 Claude / Codex / Gemini CLI on PTY
0adbd1e… lmata 41 │ writes JSONL session file
0adbd1e… lmata 42
0adbd1e… lmata 43 mirrorSessionLoop (tails session JSONL, 250ms scan)
0adbd1e… lmata 44 │ sessionMessages: assistant text + tool_use blocks
0adbd1e… lmata 45 │ skips: thinking blocks, non-assistant entries
0adbd1e… lmata 46
0adbd1e… lmata 47 relay.Post → IRC channel
0adbd1e… lmata 48 ```
0adbd1e… lmata 49
0adbd1e… lmata 50 ### Session nick generation
0adbd1e… lmata 51
0adbd1e… lmata 52 The nick is auto-generated from the project directory base name and a CRC32 of the process IDs and timestamp:
0adbd1e… lmata 53
0adbd1e… lmata 54 ```
0adbd1e… lmata 55 claude-{repo-basename}-{8-char-hex}
0adbd1e… lmata 56 codex-{repo-basename}-{8-char-hex}
0adbd1e… lmata 57 gemini-{repo-basename}-{8-char-hex}
0adbd1e… lmata 58 ```
0adbd1e… lmata 59
0adbd1e… lmata 60 Examples:
0adbd1e… lmata 61
0adbd1e… lmata 62 ```
0adbd1e… lmata 63 claude-scuttlebot-a1b2c3d4
0adbd1e… lmata 64 codex-api-9c0d1e2f
0adbd1e… lmata 65 gemini-myapp-e5f6a7b8
0adbd1e… lmata 66 ```
0adbd1e… lmata 67
0adbd1e… lmata 68 Override with `SCUTTLEBOT_NICK` in `~/.config/scuttlebot-relay.env`.
0adbd1e… lmata 69
0adbd1e… lmata 70 ### Online / offline presence
0adbd1e… lmata 71
0adbd1e… lmata 72 On successful IRC or HTTP connect the broker posts:
0adbd1e… lmata 73
0adbd1e… lmata 74 ```
0adbd1e… lmata 75 online in scuttlebot; mention claude-scuttlebot-a1b2c3d4 to interrupt before the next action
0adbd1e… lmata 76 ```
0adbd1e… lmata 77
0adbd1e… lmata 78 On process exit (any exit code):
0adbd1e… lmata 79
0adbd1e… lmata 80 ```
0adbd1e… lmata 81 offline (exit 0)
0adbd1e… lmata 82 offline (exit 1)
0adbd1e… lmata 83 ```
0adbd1e… lmata 84
0adbd1e… lmata 85 If the relay cannot connect (no token, IRC unreachable), the agent runs normally with no IRC presence. The session is not aborted.
0adbd1e… lmata 86
0adbd1e… lmata 87 ---
0adbd1e… lmata 88
0adbd1e… lmata 89 ## The three runtimes
0adbd1e… lmata 90
0adbd1e… lmata 91 === "Claude"
0adbd1e… lmata 92
0adbd1e… lmata 93 **Binary:** `cmd/claude-relay`
0adbd1e… lmata 94 **Default transport:** IRC
c61f88f… lmata 95 **Session file:** Claude Code session JSONL (written to the Claude projects directory)
0adbd1e… lmata 96
c61f88f… lmata 97 Claude Code writes a JSONL file for each session. The relay discovers the matching file by scanning for `.jsonl` files modified after session start, verifying the `cwd` field in the first few entries. It then tails from the current end of file so only new output is mirrored.
0adbd1e… lmata 98
0adbd1e… lmata 99 Mirrored entry types:
0adbd1e… lmata 100
0adbd1e… lmata 101 | JSONL block type | What gets posted |
0adbd1e… lmata 102 |---|---|
0adbd1e… lmata 103 | `text` | assistant text, split at 360-char line limit |
0adbd1e… lmata 104 | `tool_use` | compact summary: `› bash cmd`, `edit path/to/file`, `grep pattern`, etc. |
0adbd1e… lmata 105 | `thinking` | skipped — too verbose for IRC |
0adbd1e… lmata 106
0adbd1e… lmata 107 Busy detection: the relay looks for the string `esc to interrupt` in PTY output. If seen within the last 1.5 seconds, Ctrl+C is sent before injecting the operator message.
0adbd1e… lmata 108
0adbd1e… lmata 109 === "Codex"
0adbd1e… lmata 110
0adbd1e… lmata 111 **Binary:** `cmd/codex-relay`
0adbd1e… lmata 112 **Default transport:** HTTP
0adbd1e… lmata 113 **Session file:** Codex session JSONL (format differs from Claude)
0adbd1e… lmata 114
0adbd1e… lmata 115 The Codex relay reads `response_item` entries from the session JSONL. Tool activity is published as:
0adbd1e… lmata 116
0adbd1e… lmata 117 | Entry type | What gets posted |
0adbd1e… lmata 118 |---|---|
0adbd1e… lmata 119 | `function_call: exec_command` | `› <command>` (truncated to 140 chars) |
0adbd1e… lmata 120 | `function_call: parallel` | `parallel N tools` |
0adbd1e… lmata 121 | `function_call: spawn_agent` | `spawn agent` |
0adbd1e… lmata 122 | `custom_tool_call: apply_patch` | `patch path/to/file` or `patch N files: ...` |
0adbd1e… lmata 123 | `message (role: assistant)` | assistant text, split at 360-char limit |
0adbd1e… lmata 124
0adbd1e… lmata 125 Gemini uses bracketed paste sequences (`\x1b[200~` / `\x1b[201~`) when injecting operator messages to preserve multi-line input correctly.
0adbd1e… lmata 126
0adbd1e… lmata 127 === "Gemini"
0adbd1e… lmata 128
0adbd1e… lmata 129 **Binary:** `cmd/gemini-relay`
0adbd1e… lmata 130 **Default transport:** HTTP
0adbd1e… lmata 131 **Session file:** Gemini session JSONL
0adbd1e… lmata 132
0adbd1e… lmata 133 The Gemini relay uses bracketed paste mode when injecting operator messages — Gemini CLI requires this for multi-line injection. Otherwise the architecture is identical to the Codex relay.
0adbd1e… lmata 134
0adbd1e… lmata 135 ---
0adbd1e… lmata 136
0adbd1e… lmata 137 ## Session mirroring in detail
0adbd1e… lmata 138
0adbd1e… lmata 139 The broker finds the session file by:
0adbd1e… lmata 140
c61f88f… lmata 141 1. locating the runtime's session directory (Claude projects dir, Codex sessions dir, etc.)
0adbd1e… lmata 142 2. scanning for `.jsonl` files modified after `startedAt - 2s`
0adbd1e… lmata 143 3. peeking at the first five lines of each candidate to match `cwd` against the working directory
0adbd1e… lmata 144 4. selecting the newest match
0adbd1e… lmata 145 5. seeking to the end of the file and entering a tail loop (250ms poll interval)
0adbd1e… lmata 146
0adbd1e… lmata 147 Each line from the tail loop is passed through `sessionMessages`, which:
0adbd1e… lmata 148
0adbd1e… lmata 149 - ignores non-assistant entries
0adbd1e… lmata 150 - extracts `text` blocks (splits on newlines, wraps at 360 chars)
0adbd1e… lmata 151 - summarizes `tool_use` blocks into one-line descriptions
0adbd1e… lmata 152 - redacts secrets: bearer tokens, `sk-` prefixed API keys, 32+ char hex strings, `TOKEN=`, `KEY=`, `SECRET=` assignments
0adbd1e… lmata 153
0adbd1e… lmata 154 Lines are posted to the relay channel one at a time. Empty lines are skipped.
0adbd1e… lmata 155
0adbd1e… lmata 156 ---
0adbd1e… lmata 157
0adbd1e… lmata 158 ## Operator inject in detail
0adbd1e… lmata 159
0adbd1e… lmata 160 The relay input loop runs on a `SCUTTLEBOT_POLL_INTERVAL` (default 2s) ticker. On each tick it calls `relay.MessagesSince(ctx, lastSeen)` and applies `filterMessages`:
0adbd1e… lmata 161
0adbd1e… lmata 162 **A message is injected only if:**
0adbd1e… lmata 163
0adbd1e… lmata 164 - its timestamp is strictly after `lastSeen`
0adbd1e… lmata 165 - its nick is not the session nick itself
0adbd1e… lmata 166 - its nick is not in the service bot list (`bridge`, `oracle`, `sentinel`, `steward`, `scribe`, `warden`, `snitch`, `herald`, `scroll`, `systembot`, `auditbot`)
0adbd1e… lmata 167 - its nick does not start with a known activity prefix (`claude-`, `codex-`, `gemini-`)
0adbd1e… lmata 168 - the message text contains the session nick (word-boundary match)
0adbd1e… lmata 169
0adbd1e… lmata 170 Accepted messages are formatted as:
0adbd1e… lmata 171
0adbd1e… lmata 172 ```
0adbd1e… lmata 173 [IRC operator messages]
0adbd1e… lmata 174 operatornick: the message text
0adbd1e… lmata 175 ```
0adbd1e… lmata 176
0adbd1e… lmata 177 and written to the PTY. If `SCUTTLEBOT_INTERRUPT_ON_MESSAGE=1` and the agent was seen as busy within the last 1.5 seconds, Ctrl+C is sent 150ms before the text inject.
0adbd1e… lmata 178
0adbd1e… lmata 179 ---
0adbd1e… lmata 180
0adbd1e… lmata 181 ## Installing each relay
0adbd1e… lmata 182
0adbd1e… lmata 183 === "Claude"
0adbd1e… lmata 184
0adbd1e… lmata 185 Run from the repo checkout:
0adbd1e… lmata 186
0adbd1e… lmata 187 ```bash
0adbd1e… lmata 188 bash skills/scuttlebot-relay/scripts/install-claude-relay.sh \
0adbd1e… lmata 189 --url http://localhost:8080 \
0adbd1e… lmata 190 --token "$(./run.sh token)" \
0adbd1e… lmata 191 --channel general
0adbd1e… lmata 192 ```
0adbd1e… lmata 193
0adbd1e… lmata 194 Or via Make:
0adbd1e… lmata 195
0adbd1e… lmata 196 ```bash
0adbd1e… lmata 197 SCUTTLEBOT_URL=http://localhost:8080 \
0adbd1e… lmata 198 SCUTTLEBOT_TOKEN="$(./run.sh token)" \
0adbd1e… lmata 199 SCUTTLEBOT_CHANNEL=general \
0adbd1e… lmata 200 make install-claude-relay
0adbd1e… lmata 201 ```
0adbd1e… lmata 202
0adbd1e… lmata 203 After install, use the wrapper instead of the bare `claude` command:
0adbd1e… lmata 204
0adbd1e… lmata 205 ```bash
0adbd1e… lmata 206 ~/.local/bin/claude-relay
0adbd1e… lmata 207 ```
0adbd1e… lmata 208
0adbd1e… lmata 209 === "Codex"
0adbd1e… lmata 210
0adbd1e… lmata 211 ```bash
c669cc3… lmata 212 bash skills/openai-relay/scripts/install-codex-relay.sh \
0adbd1e… lmata 213 --url http://localhost:8080 \
0adbd1e… lmata 214 --token "$(./run.sh token)" \
0adbd1e… lmata 215 --channel general
0adbd1e… lmata 216 ```
0adbd1e… lmata 217
0adbd1e… lmata 218 After install:
0adbd1e… lmata 219
0adbd1e… lmata 220 ```bash
c669cc3… lmata 221 ~/.local/bin/codex-relay
0adbd1e… lmata 222 ```
0adbd1e… lmata 223
0adbd1e… lmata 224 === "Gemini"
0adbd1e… lmata 225
0adbd1e… lmata 226 ```bash
0adbd1e… lmata 227 bash skills/gemini-relay/scripts/install-gemini-relay.sh \
0adbd1e… lmata 228 --url http://localhost:8080 \
0adbd1e… lmata 229 --token "$(./run.sh token)" \
0adbd1e… lmata 230 --channel general
0adbd1e… lmata 231 ```
0adbd1e… lmata 232
0adbd1e… lmata 233 After install:
0adbd1e… lmata 234
0adbd1e… lmata 235 ```bash
0adbd1e… lmata 236 ~/.local/bin/gemini-relay
0adbd1e… lmata 237 ```
0adbd1e… lmata 238
0adbd1e… lmata 239 For a remote scuttlebot instance, pass the full URL and optionally select IRC transport:
0adbd1e… lmata 240
0adbd1e… lmata 241 ```bash
0adbd1e… lmata 242 bash skills/gemini-relay/scripts/install-gemini-relay.sh \
8800fb6… lmata 243 --url http://scuttlebot.example.com:8080 \
0adbd1e… lmata 244 --token "$SCUTTLEBOT_TOKEN" \
0adbd1e… lmata 245 --channel fleet \
0adbd1e… lmata 246 --transport irc \
8800fb6… lmata 247 --irc-addr scuttlebot.example.com:6667
0adbd1e… lmata 248 ```
0adbd1e… lmata 249
0adbd1e… lmata 250 Install in disabled mode (hooks present but silent):
0adbd1e… lmata 251
0adbd1e… lmata 252 ```bash
0adbd1e… lmata 253 bash skills/gemini-relay/scripts/install-gemini-relay.sh --disabled
0adbd1e… lmata 254 ```
0adbd1e… lmata 255
0adbd1e… lmata 256 Re-enable later:
0adbd1e… lmata 257
0adbd1e… lmata 258 ```bash
0adbd1e… lmata 259 bash skills/gemini-relay/scripts/install-gemini-relay.sh --enabled
0adbd1e… lmata 260 ```
0adbd1e… lmata 261
0adbd1e… lmata 262 ---
0adbd1e… lmata 263
0adbd1e… lmata 264 ## Environment variable reference
0adbd1e… lmata 265
0adbd1e… lmata 266 All variables are read from the environment first, then from `~/.config/scuttlebot-relay.env`, then fall back to compiled defaults. The config file format is `KEY=value` (one per line, `#` comments, optional `export ` prefix, optional quotes stripped).
0adbd1e… lmata 267
0adbd1e… lmata 268 | Variable | Default | Description |
0adbd1e… lmata 269 |---|---|---|
0adbd1e… lmata 270 | `SCUTTLEBOT_URL` | `http://localhost:8080` | Daemon HTTP API base URL |
0adbd1e… lmata 271 | `SCUTTLEBOT_TOKEN` | — | Bearer token for the HTTP API. Relay disabled if unset (HTTP transport) |
0adbd1e… lmata 272 | `SCUTTLEBOT_CHANNEL` | `general` | Channel name without `#` |
0adbd1e… lmata 273 | `SCUTTLEBOT_TRANSPORT` | `irc` (Claude), `http` (Codex, Gemini) | `irc` or `http` |
0adbd1e… lmata 274 | `SCUTTLEBOT_IRC_ADDR` | `127.0.0.1:6667` | Ergo IRC address (IRC transport only) |
0adbd1e… lmata 275 | `SCUTTLEBOT_IRC_PASS` | — | Fixed NickServ password (IRC transport). If unset, the broker auto-registers a session nick via the API |
0adbd1e… lmata 276 | `SCUTTLEBOT_IRC_AGENT_TYPE` | `worker` | Agent type registered with scuttlebot (IRC transport) |
0adbd1e… lmata 277 | `SCUTTLEBOT_IRC_DELETE_ON_CLOSE` | `true` | Delete the auto-registered nick on clean exit |
0adbd1e… lmata 278 | `SCUTTLEBOT_NICK` | auto-generated | Override the session nick entirely |
0adbd1e… lmata 279 | `SCUTTLEBOT_SESSION_ID` | auto-generated | Override the session ID suffix |
0adbd1e… lmata 280 | `SCUTTLEBOT_HOOKS_ENABLED` | `1` | Set to `0` to disable the relay without uninstalling |
0adbd1e… lmata 281 | `SCUTTLEBOT_INTERRUPT_ON_MESSAGE` | `1` | Send Ctrl+C before injecting when agent appears busy |
0adbd1e… lmata 282 | `SCUTTLEBOT_POLL_INTERVAL` | `2s` | How often to poll IRC for new messages |
0adbd1e… lmata 283 | `SCUTTLEBOT_PRESENCE_HEARTBEAT` | `60s` | How often to send a presence touch (HTTP transport). Set to `0` to disable |
0f85648… lmata 284 | `SCUTTLEBOT_MIRROR_REASONING` | `0` | Set to `1` to include thinking/reasoning blocks in IRC output, prefixed with `💭`. Off by default. Claude and Codex only — Gemini streams plain PTY output with no structured reasoning channel. |
0adbd1e… lmata 285 | `SCUTTLEBOT_ACTIVITY_VIA_BROKER` | set by broker | Tells hook scripts to stay silent when the broker is posting. Do not set manually |
0adbd1e… lmata 286
0adbd1e… lmata 287 ---
0adbd1e… lmata 288
0adbd1e… lmata 289 ## IRC transport vs HTTP transport
0adbd1e… lmata 290
0adbd1e… lmata 291 **HTTP transport** (`SCUTTLEBOT_TRANSPORT=http`)
0adbd1e… lmata 292
0adbd1e… lmata 293 The broker posts to and reads from the scuttlebot HTTP API (`/v1/channels/{channel}/messages`). The session nick does not appear as a real IRC user. Presence is maintained via periodic touch calls. This is the default for Codex and Gemini.
0adbd1e… lmata 294
0adbd1e… lmata 295 **IRC transport** (`SCUTTLEBOT_TRANSPORT=irc`)
0adbd1e… lmata 296
0adbd1e… lmata 297 The broker registers the session nick with scuttlebot and opens a real IRC connection. The nick appears in the channel user list and receives native IRC presence. Operators see the nick join and part. This is the default for Claude Code.
0adbd1e… lmata 298
0adbd1e… lmata 299 To switch Claude Code to HTTP transport:
0adbd1e… lmata 300
0adbd1e… lmata 301 ```bash
0adbd1e… lmata 302 # ~/.config/scuttlebot-relay.env
0adbd1e… lmata 303 SCUTTLEBOT_TRANSPORT=http
0adbd1e… lmata 304 ```
0adbd1e… lmata 305
0adbd1e… lmata 306 To switch Gemini or Codex to IRC transport with a remote server:
0adbd1e… lmata 307
0adbd1e… lmata 308 ```bash
0adbd1e… lmata 309 SCUTTLEBOT_TRANSPORT=irc
8800fb6… lmata 310 SCUTTLEBOT_IRC_ADDR=scuttlebot.example.com:6667
0adbd1e… lmata 311 ```
0adbd1e… lmata 312
0adbd1e… lmata 313 ---
0adbd1e… lmata 314
0adbd1e… lmata 315 ## Hooks as fallback
0adbd1e… lmata 316
0adbd1e… lmata 317 When the broker is running and the relay is active, it sets `SCUTTLEBOT_ACTIVITY_VIA_BROKER=1` in the Claude/Codex/Gemini environment. The hook scripts (`scuttlebot-post.sh`, `scuttlebot-check.sh`) check this variable and skip posting if it is set, preventing double-posting to the channel.
0adbd1e… lmata 318
0adbd1e… lmata 319 If the relay fails to connect (no token, network error), the variable is not set and the hooks continue to post normally. The agent session is not affected either way.
0adbd1e… lmata 320
0adbd1e… lmata 321 To run a session with hooks only and no broker:
0adbd1e… lmata 322
0adbd1e… lmata 323 ```bash
0adbd1e… lmata 324 SCUTTLEBOT_HOOKS_ENABLED=0 ~/.local/bin/claude-relay
0adbd1e… lmata 325 ```
0adbd1e… lmata 326
0adbd1e… lmata 327 ---
0adbd1e… lmata 328
0adbd1e… lmata 329 ## Troubleshooting
0adbd1e… lmata 330
0adbd1e… lmata 331 ### Relay disabled: no token
0adbd1e… lmata 332
0adbd1e… lmata 333 ```
0adbd1e… lmata 334 claude-relay: relay disabled: sessionrelay: token is required for HTTP transport
0adbd1e… lmata 335 ```
0adbd1e… lmata 336
0adbd1e… lmata 337 `SCUTTLEBOT_TOKEN` is not set. Add it to `~/.config/scuttlebot-relay.env`:
0adbd1e… lmata 338
0adbd1e… lmata 339 ```bash
0adbd1e… lmata 340 SCUTTLEBOT_TOKEN=your-token-here
0adbd1e… lmata 341 ```
0adbd1e… lmata 342
0adbd1e… lmata 343 Get the current token from the running daemon:
0adbd1e… lmata 344
0adbd1e… lmata 345 ```bash
0adbd1e… lmata 346 ./run.sh token
0adbd1e… lmata 347 ```
0adbd1e… lmata 348
0adbd1e… lmata 349 ### Nick collision on IRC transport
0adbd1e… lmata 350
0adbd1e… lmata 351 If the broker exits uncleanly and `SCUTTLEBOT_IRC_DELETE_ON_CLOSE=true` did not fire, the old nick registration may still exist. Either wait for the NickServ account to expire, or delete it manually:
0adbd1e… lmata 352
0adbd1e… lmata 353 ```bash
0adbd1e… lmata 354 scuttlectl agent delete claude-myrepo-a1b2c3d4
0adbd1e… lmata 355 ```
0adbd1e… lmata 356
0adbd1e… lmata 357 Then relaunch the relay. It will register a new session nick with a different session ID suffix.
0adbd1e… lmata 358
0adbd1e… lmata 359 ### Session file not found
0adbd1e… lmata 360
0adbd1e… lmata 361 ```
0adbd1e… lmata 362 claude-relay: relay disabled: context deadline exceeded
0adbd1e… lmata 363 ```
0adbd1e… lmata 364
0adbd1e… lmata 365 The broker waited 20 seconds for a matching session JSONL file and gave up. This happens when:
0adbd1e… lmata 366
0adbd1e… lmata 367 - Claude Code is run with `--help`, `--version`, or a command that doesn't start a real session (`help`, `completion`). The relay does not mirror these — this is expected behaviour.
c61f88f… lmata 368 - The Claude projects directory does not contain a session matching the working directory. Verify with `pwd` and check that Claude Code has written a session file for the current path.
0adbd1e… lmata 369 - The session file is being written to a different directory (non-default Claude config). Set `CLAUDE_HOME` or `XDG_CONFIG_HOME` consistently.
0adbd1e… lmata 370
0adbd1e… lmata 371 ### Messages not being injected
0adbd1e… lmata 372
0adbd1e… lmata 373 Check that your IRC message actually mentions the session nick with a word boundary. The relay uses a strict word-boundary match. `hello claude-myrepo-a1b2c3d4` works. `hello claude-myrepo-a1b2c3d4!` does not (trailing `!`). Address with a colon or comma:
0adbd1e… lmata 374
0adbd1e… lmata 375 ```
0adbd1e… lmata 376 claude-myrepo-a1b2c3d4: please stop and re-read the spec
0adbd1e… lmata 377 claude-myrepo-a1b2c3d4, wrong file — check policies.go
0adbd1e… lmata 378 ```

Keyboard Shortcuts

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