@scrylog/cli 0.4.2 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,23 +1,28 @@
1
1
  # scrylog
2
2
 
3
- `scrylog` is a Bun-based terminal dashboard and daemon for monitoring AI coding sessions in `tmux`, herdr, and as standalone processes.
3
+ **scrylog** monitors AI coding sessions from Claude Code, Codex, and OpenCode in one terminal dashboard: session states, required attention, provider usage limits, and optional Telegram notifications, with REST/SSE and MCP access for integrations.
4
+
5
+ Sessions are discovered as standalone processes or through `tmux` and herdr. `tmux` is optional — every collector degrades gracefully when its source is absent.
4
6
 
5
7
  It ships four commands:
6
8
 
7
- | Command | Purpose |
8
- | --- | --- |
9
- | `scrylog` | TUI dashboard and operator CLI |
10
- | `scrylogd` | Foreground daemon process |
9
+ | Command | Purpose |
10
+ | ------------- | ----------------------------------------- |
11
+ | `scrylog` | TUI dashboard and operator CLI |
12
+ | `scrylogd` | Foreground daemon process |
11
13
  | `scrylog-mcp` | stdio MCP server that proxies daemon data |
12
- | `oc` | OpenCode launcher and attach helper |
14
+ | `oc` | OpenCode launcher and attach helper |
13
15
 
14
16
  ## Features
15
17
 
18
+ - Claude Code session monitoring via transcript collection
19
+ - Codex session monitoring via transcript collection and hook-based state tracking
20
+ - OpenCode integration in `hooks` or `sse` mode, with SQLite-based session enrichment
21
+ - Session states (`working`, `idle`, `waiting-input`, `error`) and permission/question attention visibility
22
+ - Provider usage and subscription limits for Claude, Codex, and OpenCode Go, on the dashboard and `GET /api/usage`
23
+ - Telegram notifications for session events and usage alerts, including `user-idle` delivery gating
16
24
  - `tmux` monitoring for OpenCode, Codex, Copilot, and shell panes
17
25
  - herdr default-session monitoring through its structured agent and pane API
18
- - OpenCode integration in `hooks` or `sse` mode
19
- - Claude transcript collection
20
- - Codex transcript collection and hook-based state tracking
21
26
  - Local daemon with Unix socket IPC on macOS and Linux, TCP fallback on Windows
22
27
  - Optional TCP REST API exposure (enabled by default on Windows)
23
28
  - Optional MCP HTTP exposure with bearer token support
@@ -27,6 +32,8 @@ It ships four commands:
27
32
 
28
33
  ## Requirements
29
34
 
35
+ Only [Bun](https://bun.sh) is required. The rest are optional per data source, and their absence is handled automatically:
36
+
30
37
  - [Bun](https://bun.sh) `>= 1.3.0`
31
38
  - `tmux` if you want `tmux` monitoring
32
39
  - [herdr](https://herdr.dev) if you want herdr monitoring; absence is handled automatically
@@ -35,41 +42,106 @@ It ships four commands:
35
42
 
36
43
  ## Platform Support
37
44
 
38
- | Tier | Platform | Status | Notes |
39
- | --- | --- | --- | --- |
40
- | Tier 1 | macOS | Tested daily | Full feature set including Keychain OAuth and Safari cookies |
41
- | Tier 2 | Linux / WSL 2 | Compatible | Claude OAuth via `~/.claude/.credentials.json`, Chrome/Chromium cookies, systemd service when available |
45
+ | Tier | Platform | Status | Notes |
46
+ | ------ | ---------------- | ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
47
+ | Tier 1 | macOS | Tested daily | Full feature set including Keychain OAuth and Safari cookies |
48
+ | Tier 2 | Linux / WSL 2 | Compatible | Claude OAuth via `~/.claude/.credentials.json`, Chrome/Chromium cookies, systemd service when available |
42
49
  | Tier 3 | Windows (native) | Experimental / not recommended | TCP IPC, `wmic` process scan, degraded service status. Chrome cookie decryption not available (DPAPI not implemented). Primary use is ad-hoc debugging, not daily monitoring. |
43
50
 
44
51
  ## Terminal Icon Rendering
45
52
 
46
53
  The Usage view renders provider icons with one of these values for `tui.providerIcons`:
47
54
 
48
- | Mode | Behavior |
49
- | --- | --- |
50
- | `blocks` (default) | Bundled pixel-art PNGs rendered with Unicode half-blocks on the Usage cards. Works in any terminal, including multiplexers. |
51
- | `graphics` | Full artwork. Probes the terminal (`XTVERSION`, kitty graphics query, Sixel support) and falls back to `blocks` when nothing is confirmed. |
52
- | `kitty` / `sixel` | Force a specific image protocol even when detection does not confirm it (useful for terminals whose detection response is ambiguous). |
53
- | `text` | Two-letter provider monogram on Usage cards. Never uses images. |
55
+ | Mode | Behavior |
56
+ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
57
+ | `blocks` (default) | Bundled pixel-art PNGs rendered with Unicode half-blocks on the Usage cards. Works in any terminal, including multiplexers. |
58
+ | `graphics` | Full artwork. Probes the terminal (`XTVERSION`, kitty graphics query, Sixel support) and falls back to `blocks` when nothing is confirmed. |
59
+ | `kitty` / `sixel` | Force a specific image protocol even when detection does not confirm it (useful for terminals whose detection response is ambiguous). |
60
+ | `text` | Two-letter provider monogram on Usage cards. Never uses images. |
54
61
 
55
62
  In the sessions list the Tool column also depends on the mode: image modes render 2x1-cell mini icons, `blocks` shows the colored brand monogram (`CL`, `CX`, `OC`, ...) plus child-session badges, and `text` keeps the full tool name. Press `?` in the dashboard to see a legend mapping each icon or monogram to its tool name (legend shown only when an image mode is active).
56
63
 
57
64
  Compatibility of `graphics` by environment:
58
65
 
59
- | Environment | Works | Detail |
60
- | --- | --- | --- |
61
- | Ghostty | Yes | Kitty graphics protocol (`TERM=xterm-ghostty`) |
62
- | Kitty | Yes | Kitty graphics protocol (reference implementation) |
63
- | WezTerm | Yes | Kitty graphics and Sixel |
64
- | iTerm2 | Yes | Inline images and Sixel |
65
- | Konsole, Foot | Yes | Sixel, requires pixel-resolution detection to confirm |
66
- | Direct SSH (no multiplexer) | Yes | Inherits the local terminal's protocol support |
67
- | tmux / herdr | Forced `blocks` | The multiplexer sits between the client and the terminal; passthrough is not reliable, so rendering degrades to `blocks` |
68
- | Alacritty, Terminal.app, GNOME Terminal | No | No image protocol; falls back to `blocks` |
69
- | Windows native (Tier 3) | No | Sixel support is partial/experimental; falls back to `blocks` |
66
+ | Environment | Works | Detail |
67
+ | --------------------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------ |
68
+ | Ghostty | Yes | Kitty graphics protocol (`TERM=xterm-ghostty`) |
69
+ | Kitty | Yes | Kitty graphics protocol (reference implementation) |
70
+ | WezTerm | Yes | Kitty graphics and Sixel |
71
+ | iTerm2 | Yes | Inline images and Sixel |
72
+ | Konsole, Foot | Yes | Sixel, requires pixel-resolution detection to confirm |
73
+ | Direct SSH (no multiplexer) | Yes | Inherits the local terminal's protocol support |
74
+ | tmux / herdr | Forced `blocks` | The multiplexer sits between the client and the terminal; passthrough is not reliable, so rendering degrades to `blocks` |
75
+ | Alacritty, Terminal.app, GNOME Terminal | No | No image protocol; falls back to `blocks` |
76
+ | Windows native (Tier 3) | No | Sixel support is partial/experimental; falls back to `blocks` |
70
77
 
71
78
  Run `scrylog doctor` for a "Terminal graphics" section with detected capabilities and the recommended value for the current terminal.
72
79
 
80
+ ## Notification Activity Sources
81
+
82
+ `user-idle` delivery modes gate notifications on user inactivity. scrylog supports two sources that answer "how long has the user been away?":
83
+
84
+ | Source (`notifications.activity.source`) | Signal | When to use |
85
+ | ---------------------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------- |
86
+ | `system` (default) | OS idle time (keyboard **and mouse movement**) | Normal desktops |
87
+ | `keyboard-clicks` | Key presses and mouse button press/release only | Machines where a utility or device jitters the mouse cursor to keep Slack/Teams presence "active" |
88
+
89
+ **Why the second source exists:** some users run a driver-level tool that moves the cursor a few pixels on a cycle so messaging apps never show "away". That synthetic movement is indistinguishable from real input and resets OS-wide idle time, so with the default `system` source the idle threshold is never reached and `user-idle` notifications never fire. The `keyboard-clicks` source ignores cursor movement and wheel events entirely; only key presses and mouse button clicks signal activity.
90
+
91
+ Enable it in the config:
92
+
93
+ ```json
94
+ {
95
+ "notifications": {
96
+ "enabled": true,
97
+ "activity": { "source": "keyboard-clicks" }
98
+ }
99
+ }
100
+ ```
101
+
102
+ Backends per platform:
103
+
104
+ | Platform | Backend | Notes |
105
+ | ----------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
106
+ | macOS | `CGEventSource` query (poll-on-demand, via `bun:ffi`) | No helper process. Idle includes history before the daemon started. |
107
+ | Windows native | Resident PowerShell helper with low-level input hooks | One extra PowerShell process exists while the source is on; it exits when the daemon stops. |
108
+ | WSL 2 | Same PowerShell helper, running on the Windows host via interop | `powershell.exe` must be reachable from WSL (PATH or `/mnt/c/...`). |
109
+ | Linux (X11 and Wayland) | Read-only `evdev` drains of `/dev/input/event*` | Works under both X11 and Wayland compositors; requires the daemon user to be able to read input devices (usually the `input` group). |
110
+
111
+ Known limitations (they are the deliberate trade-off of ignoring cursor movement):
112
+
113
+ - Reading documentation, watching a presentation, or working with no keyboard presses or mouse clicks counts as idle under this source: expect a notification while you are still at the machine if you are not touching input.
114
+ - Media keys and special hardware buttons may not be reported by the OS as key presses; the idle clock stays valid but such events do not reset it.
115
+ - On Windows and Linux the activity clock starts when the daemon starts (observation begins with the notification service, before the first notification); input before that moment is unrecoverable, so an idle-before-start machine behaves as "unknown" and follows the channel's `onUnknown` policy. Backends keep running across the whole daemon lifetime once started, and a bounded heartbeat on Linux keeps the input queues healthy.
116
+ - `scrylog doctor` shows the configured source, the resolved backend, and any availability reason when `keyboard-clicks` is selected. On WSL, `powershell-hook (windows host, ready)` means a PowerShell candidate is reachable through interop; it does not verify that the running daemon's input hooks are installed or receiving events.
117
+
118
+ ### Observed WSL behavior with an automatic mouse mover
119
+
120
+ In a user-reported manual test on WSL, the daemon was restarted after changing the activity source. The following notification behavior was observed:
121
+
122
+ | Activity source | Input during the test | Observed result |
123
+ | ----------------- | ------------------------------------------------------- | -------------------------- |
124
+ | `system` | Only movement from the automatic mouse-mover device | Notification was not sent. |
125
+ | `keyboard-clicks` | Only movement from the automatic mouse-mover device | Notification was sent. |
126
+ | `keyboard-clicks` | Manual mouse movement, without clicks or keyboard input | Notification was not sent. |
127
+
128
+ This was useful in the tested environment: automatic movement allowed notifications during the user's absence, while manual mouse use blocked them.
129
+
130
+ The distinction between manual and automatic movement is an observation, not an explicit capability of the implemented filter. The filter ignores mouse-movement and wheel events and observes key presses and mouse button events. The cause of the observed difference has not been determined, and this result has not been validated with other devices or platforms. Windows version, WSL version, device model, and input-event traces were not captured for this report.
131
+
132
+ ### Verifying activity detection
133
+
134
+ To confirm the source is actually working, set `daemon.logLevel: "debug"` (with `daemon.logFileEnabled: true`) and watch the daemon log (`scrylog logs`) for these events — none of them ever log key content, coordinates, or event history:
135
+
136
+ | Event | Meaning |
137
+ | ----------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
138
+ | `notify.activity_observing` | Observation started; names the resolved backend |
139
+ | `notify.activity_first_input` | First key press or button click observed by the watcher (once per backend lifetime) |
140
+ | `notify.activity_gate` | A delivery gate decision: `idleMs`, `idleThresholdMs`, `activitySource`, event `kind`, and `outcome` (`send`, `defer`, `suppress`) |
141
+ | `notify.activity_backend_restarting` / `notify.activity_backend_failed` | The resident helper died and is restarting / exhausted its restart budget |
142
+
143
+ Expected trace for the artificial-cursor-movement case: a starting `notify.activity_observing`, then `notify.activity_first_input` when you next touch the keyboard or a button, `notify.activity_gate ... outcome: suppress` while only cursor moves happen, and `outcome: send` once real inactivity (movement ignored) reaches the threshold. If you only ever see `notify.activity_unknown`, the backend cannot observe input on your machine — the log reason and `scrylog doctor` will name what is missing.
144
+
73
145
  ## WSL 2 Notes
74
146
 
75
147
  - The daemon runs as a Linux process and uses the same paths as native Linux.
@@ -169,28 +241,28 @@ By default, sessions whose tool could not be identified (`tool: "unknown"`) are
169
241
 
170
242
  The dashboard header layout is configurable through `tui.headerLayout`, and the setup wizard prompts for the same preference:
171
243
 
172
- | Value | Behavior |
173
- | --- | --- |
174
- | `auto` | Uses a right or left sidebar below 33 rows when the terminal is at least 64 columns wide; otherwise uses the horizontal header. |
175
- | `horizontal` | Always keeps the header above Sessions and Usage. |
176
- | `vertical` | Always uses the 15-column sidebar, even below 64 columns. |
244
+ | Value | Behavior |
245
+ | ------------ | ------------------------------------------------------------------------------------------------------------------------------- |
246
+ | `auto` | Uses a right or left sidebar below 33 rows when the terminal is at least 64 columns wide; otherwise uses the horizontal header. |
247
+ | `horizontal` | Always keeps the header above Sessions and Usage. |
248
+ | `vertical` | Always uses the 15-column sidebar, even below 64 columns. |
177
249
 
178
250
  Set `tui.headerSide` to `left` or `right` to place the vertical header. The value is retained but ignored while the resolved layout is horizontal. While the sidebar is active, the tab row displays a compact colored `scrylog` label opposite Sessions and Usage. A forced vertical layout can significantly reduce or clip session content on narrow terminals.
179
251
 
180
252
  Keyboard shortcuts:
181
253
 
182
- | Key | Action |
183
- | --- | --- |
184
- | `↑` / `k` | Move selection up |
185
- | `↓` / `j` | Move selection down |
186
- | `Enter` | Open session detail |
187
- | `t` | Attach to selected `tmux` or herdr session |
188
- | `/` | Search |
189
- | `f` | Cycle filters |
190
- | `a` | Show actionable sessions only |
191
- | `r` | Refresh now |
192
- | `Esc` | Close detail |
193
- | `q` / `Ctrl+C` | Quit |
254
+ | Key | Action |
255
+ | -------------- | ------------------------------------------ |
256
+ | `↑` / `k` | Move selection up |
257
+ | `↓` / `j` | Move selection down |
258
+ | `Enter` | Open session detail |
259
+ | `t` | Attach to selected `tmux` or herdr session |
260
+ | `/` | Search |
261
+ | `f` | Cycle filters |
262
+ | `a` | Show actionable sessions only |
263
+ | `r` | Refresh now |
264
+ | `Esc` | Close detail |
265
+ | `q` / `Ctrl+C` | Quit |
194
266
 
195
267
  ### Setup
196
268
 
@@ -273,11 +345,11 @@ Use the foreground daemon mainly for:
273
345
 
274
346
  Logging options:
275
347
 
276
- | Flag | Purpose |
277
- | --- | --- |
278
- | `--log-level debug|info|warn|error` | Override the configured minimum log level |
279
- | `--log-format pretty|json` | Override stderr output format for this process |
280
- | `--no-log-file` | Disable daemon JSONL file logging for this process |
348
+ | Flag | Purpose |
349
+ | -------------------- | -------------------------------------------------- | ---------------------------------------------- | ------ | ----------------------------------------- |
350
+ | `--log-level debug | info | warn | error` | Override the configured minimum log level |
351
+ | `--log-format pretty | json` | Override stderr output format for this process |
352
+ | `--no-log-file` | Disable daemon JSONL file logging for this process |
281
353
 
282
354
  For normal daily use on macOS and Linux, prefer `scrylog daemon install` so the daemon starts automatically with your user session.
283
355
 
@@ -305,12 +377,12 @@ Example config:
305
377
  "logFileEnabled": true,
306
378
  "logFilePath": "~/.scrylog/logs/scrylogd.log",
307
379
  "logFileMaxBytes": 5242880,
308
- "logFileMaxFiles": 3
380
+ "logFileMaxFiles": 3,
309
381
  },
310
382
  "api": {
311
383
  "tcpEnabled": false,
312
384
  "host": "127.0.0.1",
313
- "port": 7788
385
+ "port": 7788,
314
386
  },
315
387
  "cors": {
316
388
  "enabled": false,
@@ -319,26 +391,26 @@ Example config:
319
391
  "allowedHeaders": ["Content-Type", "Authorization"],
320
392
  "exposedHeaders": [],
321
393
  "credentials": false,
322
- "maxAge": 600
394
+ "maxAge": 600,
323
395
  },
324
396
  "opencode": {
325
397
  "mode": "hooks",
326
398
  "instances": [],
327
- "autoDiscover": true
399
+ "autoDiscover": true,
328
400
  },
329
401
  "claude": {
330
402
  "claudeDir": "/Users/you/.claude",
331
403
  "hooksEnabled": false,
332
- "hooksDir": "/tmp/scrylog-claude-hooks"
404
+ "hooksDir": "/tmp/scrylog-claude-hooks",
333
405
  },
334
406
  "codex": {
335
407
  "codexDir": "/Users/you/.codex",
336
408
  "hooksEnabled": false,
337
- "hooksDir": "/tmp/scrylog-codex-hooks"
409
+ "hooksDir": "/tmp/scrylog-codex-hooks",
338
410
  },
339
411
  "tmux": {
340
412
  "previewLines": 50,
341
- "detailLines": 200
413
+ "detailLines": 200,
342
414
  },
343
415
  "tui": {
344
416
  "refreshMs": 5000,
@@ -348,27 +420,27 @@ Example config:
348
420
  "pushDebounceMs": 120,
349
421
  "headerLayout": "auto",
350
422
  "headerSide": "left",
351
- "providerIcons": "blocks"
423
+ "providerIcons": "blocks",
352
424
  },
353
425
  "mcp": {
354
426
  "stdioEnabled": true,
355
427
  "httpEnabled": false,
356
428
  "host": "127.0.0.1",
357
429
  "port": 7789,
358
- "bearerToken": null
430
+ "bearerToken": null,
359
431
  },
360
432
  "usage": {
361
433
  "enabled": true,
362
434
  "pollIntervalMs": 300000,
363
- "providers": ["claude", "opencode-go", "codex"]
435
+ "providers": ["claude", "opencode-go", "codex"],
364
436
  },
365
437
  "retention": {
366
438
  "maxSessions": 500,
367
439
  "standaloneMaxAgeHours": 168,
368
440
  "localCommandTtlHours": 72,
369
441
  "cacheMaxEntries": 1000,
370
- "transcriptMaxBytes": 10485760
371
- }
442
+ "transcriptMaxBytes": 10485760,
443
+ },
372
444
  }
373
445
  ```
374
446
 
@@ -398,21 +470,21 @@ Notes:
398
470
 
399
471
  `scrylogd` is a monitor for active and recent sessions, not a permanent historical archive. Defaults are tuned for unattended daemon usage:
400
472
 
401
- | Setting | Default | Effect |
402
- | --- | ---: | --- |
403
- | `retention.maxSessions` | `500` | Prunes oldest inactive identified standalone sessions above this count (tmux/herdr/unknown rows never count) |
404
- | `retention.standaloneMaxAgeHours` | `168` | Prunes inactive standalone sessions older than 7 days |
405
- | `retention.cacheMaxEntries` | `1000` | Bounds internal path/project caches |
406
- | `retention.transcriptMaxBytes` | `10485760` | Parses only a bounded tail for very large Claude transcripts |
407
- | `daemon.commandTimeoutMs` | `5000` | Prevents external commands from blocking indefinitely |
473
+ | Setting | Default | Effect |
474
+ | --------------------------------- | ---------: | ------------------------------------------------------------------------------------------------------------ |
475
+ | `retention.maxSessions` | `500` | Prunes oldest inactive identified standalone sessions above this count (tmux/herdr/unknown rows never count) |
476
+ | `retention.standaloneMaxAgeHours` | `168` | Prunes inactive standalone sessions older than 7 days |
477
+ | `retention.cacheMaxEntries` | `1000` | Bounds internal path/project caches |
478
+ | `retention.transcriptMaxBytes` | `10485760` | Parses only a bounded tail for very large Claude transcripts |
479
+ | `daemon.commandTimeoutMs` | `5000` | Prevents external commands from blocking indefinitely |
408
480
 
409
481
  Expected daemon RSS depends on active sessions and transcript size:
410
482
 
411
- | Scenario | Expected RSS |
412
- | --- | ---: |
413
- | No active sessions | 35-70 MB |
414
- | Normal local usage | 50-120 MB |
415
- | Heavy tmux/Claude/OpenCode usage | 100-250 MB |
483
+ | Scenario | Expected RSS |
484
+ | -------------------------------- | -----------: |
485
+ | No active sessions | 35-70 MB |
486
+ | Normal local usage | 50-120 MB |
487
+ | Heavy tmux/Claude/OpenCode usage | 100-250 MB |
416
488
 
417
489
  If you want longer history, increase `retention.maxSessions` or `retention.standaloneMaxAgeHours`. Setting age to `0` disables age-based pruning, but count-based pruning can still apply.
418
490
 
@@ -436,16 +508,22 @@ The file format is JSONL for bug reports and tooling. Terminal stderr output def
436
508
 
437
509
  Default file rotation keeps three files total:
438
510
 
439
- | File | Purpose |
440
- | --- | --- |
441
- | `scrylogd.log` | Active log file |
511
+ | File | Purpose |
512
+ | ---------------- | -------------------- |
513
+ | `scrylogd.log` | Active log file |
442
514
  | `scrylogd.1.log` | Previous active file |
443
515
  | `scrylogd.2.log` | Oldest retained file |
444
516
 
445
517
  Example JSONL entry:
446
518
 
447
519
  ```json
448
- {"ts":"2026-05-05T18:42:31.123Z","level":"info","source":"daemon","event":"daemon.started","msg":"Started"}
520
+ {
521
+ "ts": "2026-05-05T18:42:31.123Z",
522
+ "level": "info",
523
+ "source": "daemon",
524
+ "event": "daemon.started",
525
+ "msg": "Started"
526
+ }
449
527
  ```
450
528
 
451
529
  Logs sanitize home-directory paths, bearer tokens, authorization values, and URL query strings before writing.
@@ -513,7 +591,7 @@ scrylog setup
513
591
  scrylog opencode hooks install
514
592
  ```
515
593
 
516
- Alternatively, add the plugin to `~/.config/opencode/opencode.json` manually:
594
+ Alternatively, add the plugin to `~/.config/opencode/opencode.json` manually:
517
595
 
518
596
  ```json
519
597
  {
@@ -595,10 +673,10 @@ How it works:
595
673
 
596
674
  Environment variables:
597
675
 
598
- | Variable | Default | Purpose |
599
- | --- | --- | --- |
600
- | `OPENCODE_LOCAL_PORT` | `4096` | Force a specific port |
601
- | `OPENCODE_HOST` | `127.0.0.1` | Force a specific host |
676
+ | Variable | Default | Purpose |
677
+ | --------------------- | ----------- | --------------------- |
678
+ | `OPENCODE_LOCAL_PORT` | `4096` | Force a specific port |
679
+ | `OPENCODE_HOST` | `127.0.0.1` | Force a specific host |
602
680
 
603
681
  ## HTTP API
604
682
 
@@ -618,17 +696,17 @@ Enable it with:
618
696
 
619
697
  Endpoints:
620
698
 
621
- | Method | Path | Returns |
622
- | --- | --- | --- |
623
- | `GET` | `/api/health` | daemon health, timestamps, collector status |
624
- | `GET` | `/api/status` | visible counts, collector status, generated timestamp (`?includeUnknown=true` opts in) |
625
- | `GET` | `/api/sessions` | visible session tree plus counts (`?includeUnknown=true` opts in; unknown-tool rows hidden by default) |
626
- | `GET` | `/api/sessions/:id` | full session detail |
627
- | `GET` | `/api/sessions/:id/children` | visible child sessions |
628
- | `GET` | `/api/sessions/:id/messages` | recent messages when available |
629
- | `GET` | `/api/config` | active config with sensitive fields redacted |
630
- | `GET` | `/api/events` | SSE stream of store events |
631
- | `POST` | `/api/webhook/opencode` | OpenCode plugin webhook |
699
+ | Method | Path | Returns |
700
+ | ------ | ---------------------------- | ------------------------------------------------------------------------------------------------------ |
701
+ | `GET` | `/api/health` | daemon health, timestamps, collector status |
702
+ | `GET` | `/api/status` | visible counts, collector status, generated timestamp (`?includeUnknown=true` opts in) |
703
+ | `GET` | `/api/sessions` | visible session tree plus counts (`?includeUnknown=true` opts in; unknown-tool rows hidden by default) |
704
+ | `GET` | `/api/sessions/:id` | full session detail |
705
+ | `GET` | `/api/sessions/:id/children` | visible child sessions |
706
+ | `GET` | `/api/sessions/:id/messages` | recent messages when available |
707
+ | `GET` | `/api/config` | active config with sensitive fields redacted |
708
+ | `GET` | `/api/events` | SSE stream of store events |
709
+ | `POST` | `/api/webhook/opencode` | OpenCode plugin webhook |
632
710
 
633
711
  All error responses follow a consistent format:
634
712
 
@@ -864,7 +942,7 @@ For OpenCode local plugin testing, create or update:
864
942
  with:
865
943
 
866
944
  ```ts
867
- export { server } from "file:///Volumes/Files/Workspace/Projects/other/scrylog/packages/opencode-plugin/src/index.ts"
945
+ export { server } from 'file:///Volumes/Files/Workspace/Projects/other/scrylog/packages/opencode-plugin/src/index.ts';
868
946
  ```
869
947
 
870
948
  For package usage, prefer the published plugin configuration:
@@ -2,19 +2,19 @@
2
2
 
3
3
  Retrieved from official provider properties. The images are bundled so the dashboard never fetches artwork at runtime.
4
4
 
5
- | File | Official source |
6
- | --- | --- |
7
- | `claude.png` | `https://assets-proxy.anthropic.com/claude-ai/v2/assets/v1/c129d018a-0ZbJsTbu.png` |
8
- | `opencode.png` | `https://opencode.ai/apple-touch-icon-v3.png` |
9
- | `openai.png` | OpenAI official app icon (`https://cdn.oaistatic.com/assets/apple-touch-icon-mz9nytnj.webp`, white tile with black Blossom from the official brand guidelines); the standalone mono Blossom SVG (`File:OpenAI_logo_2025_(symbol).svg`, Wikimedia Commons, PD-textlogo) served as design reference. Formerly `codex.png` (OpenAI Codex app art). |
5
+ | File | Official source |
6
+ | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
7
+ | `claude.png` | `https://assets-proxy.anthropic.com/claude-ai/v2/assets/v1/c129d018a-0ZbJsTbu.png` |
8
+ | `opencode.png` | `https://opencode.ai/apple-touch-icon-v3.png` |
9
+ | `openai.png` | OpenAI official app icon (`https://cdn.oaistatic.com/assets/apple-touch-icon-mz9nytnj.webp`, white tile with black Blossom from the official brand guidelines); the standalone mono Blossom SVG (`File:OpenAI_logo_2025_(symbol).svg`, Wikimedia Commons, PD-textlogo) served as design reference. Formerly `codex.png` (OpenAI Codex app art). |
10
10
 
11
11
  The `*-terminal.svg` files are editable 8x8, square integer-grid adaptations of those marks. Their generated `*-terminal.png` counterparts map directly to a compact 8x4-cell block target with square half-block pixels (2 pixel rows per cell), avoiding destructive downsampling and aspect distortion. Hand-drawn tool glyphs (no official small-mark equivalent; used for the 2x1-cell mini column icon in image-capable modes, replaced by a brand monogram in blocks mode):
12
12
 
13
- | File | Source |
14
- | --- | --- |
13
+ | File | Source |
14
+ | ----------------------------- | ------------------------------------------------------------------- |
15
15
  | `copilot.svg` / `copilot.png` | Original 8x8 grid drawing modelled on GitHub Copilot's goggles mark |
16
- | `shell.svg` / `shell.png` | Original 8x8 grid drawing of a `>_` prompt glyph |
17
- | `unknown.svg` / `unknown.png` | Original 8x8 grid drawing of a `?` marker |
16
+ | `shell.svg` / `shell.png` | Original 8x8 grid drawing of a `>_` prompt glyph |
17
+ | `unknown.svg` / `unknown.png` | Original 8x8 grid drawing of a `?` marker |
18
18
 
19
19
  They deliberately avoid gradients and antialiasing so Claude's inverted cream spark on an orange tile, OpenCode's light "O" plate, and OpenAI's black Blossom on a white tile remain identifiable after character-cell rendering. Square official artwork uses a separate 6x3-cell fitted target.
20
20