ScuttleBot
fix: gemini/codex mirroring — update installed hooks, clean up dead code Root cause: the installed hooks at ~/.gemini/hooks/ were outdated and only posted to SCUTTLEBOT_CHANNEL (single channel, usually "general"). The repo versions post to all channels via relay_channels() which reads SCUTTLEBOT_CHANNELS from the process env or channel state file. The channel routing pipeline: 1. .scuttlebot.yaml in project root defines project channel 2. Relay reads it at startup, adds to channel list 3. Relay sets SCUTTLEBOT_CHANNELS=general,kohakku in subprocess env 4. Relay writes channel state file to TMPDIR 5. Hooks load state file (overrides env file defaults) 6. Hooks post to ALL channels, not just the control channel Key learnings: - Hooks must be kept in sync with repo versions (installer should copy) - The env file (~/.config/scuttlebot-relay.env) has global defaults - The relay subprocess env has per-session overrides (includes project) - The channel state file is the final authority for hook channel routing - Gemini CLI mirrors via AfterAgent/AfterTool hooks, not session files - Claude relay mirrors via JSONL session file tailing Also removed dead PTY-scraping mirror code from gemini-relay — hooks are the right approach for Gemini CLI output mirroring.
4e1ede94a29bee6d0842e11065d68c202a0e3209c48516f8f3f8ba9f0bb65b0a
| --- cmd/gemini-relay/main.go | ||
| +++ cmd/gemini-relay/main.go | ||
| @@ -473,10 +473,11 @@ | ||
| 473 | 473 | if err != nil { |
| 474 | 474 | return |
| 475 | 475 | } |
| 476 | 476 | } |
| 477 | 477 | } |
| 478 | + | |
| 478 | 479 | |
| 479 | 480 | func (s *relayState) observeOutput(data []byte, now time.Time) { |
| 480 | 481 | if s == nil { |
| 481 | 482 | return |
| 482 | 483 | } |
| 483 | 484 |
| --- cmd/gemini-relay/main.go | |
| +++ cmd/gemini-relay/main.go | |
| @@ -473,10 +473,11 @@ | |
| 473 | if err != nil { |
| 474 | return |
| 475 | } |
| 476 | } |
| 477 | } |
| 478 | |
| 479 | func (s *relayState) observeOutput(data []byte, now time.Time) { |
| 480 | if s == nil { |
| 481 | return |
| 482 | } |
| 483 |
| --- cmd/gemini-relay/main.go | |
| +++ cmd/gemini-relay/main.go | |
| @@ -473,10 +473,11 @@ | |
| 473 | if err != nil { |
| 474 | return |
| 475 | } |
| 476 | } |
| 477 | } |
| 478 | |
| 479 | |
| 480 | func (s *relayState) observeOutput(data []byte, now time.Time) { |
| 481 | if s == nil { |
| 482 | return |
| 483 | } |
| 484 |