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