@scrylog/cli 0.4.1 → 0.5.0

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
@@ -4,12 +4,12 @@
4
4
 
5
5
  It ships four commands:
6
6
 
7
- | Command | Purpose |
8
- | --- | --- |
9
- | `scrylog` | TUI dashboard and operator CLI |
10
- | `scrylogd` | Foreground daemon process |
7
+ | Command | Purpose |
8
+ | ------------- | ----------------------------------------- |
9
+ | `scrylog` | TUI dashboard and operator CLI |
10
+ | `scrylogd` | Foreground daemon process |
11
11
  | `scrylog-mcp` | stdio MCP server that proxies daemon data |
12
- | `oc` | OpenCode launcher and attach helper |
12
+ | `oc` | OpenCode launcher and attach helper |
13
13
 
14
14
  ## Features
15
15
 
@@ -35,41 +35,90 @@ It ships four commands:
35
35
 
36
36
  ## Platform Support
37
37
 
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 |
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 |
42
42
  | 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
43
 
44
44
  ## Terminal Icon Rendering
45
45
 
46
46
  The Usage view renders provider icons with one of these values for `tui.providerIcons`:
47
47
 
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. |
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. |
54
54
 
55
55
  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
56
 
57
57
  Compatibility of `graphics` by environment:
58
58
 
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` |
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` |
70
70
 
71
71
  Run `scrylog doctor` for a "Terminal graphics" section with detected capabilities and the recommended value for the current terminal.
72
72
 
73
+ ## Notification Activity Sources
74
+
75
+ `user-idle` delivery modes gate notifications on user inactivity. scrylog supports two sources that answer "how long has the user been away?":
76
+
77
+ | Source (`notifications.activity.source`) | Signal | When to use |
78
+ | ---------------------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------- |
79
+ | `system` (default) | OS idle time (keyboard **and mouse movement**) | Normal desktops |
80
+ | `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" |
81
+
82
+ **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.
83
+
84
+ Enable it in the config:
85
+
86
+ ```json
87
+ {
88
+ "notifications": {
89
+ "enabled": true,
90
+ "activity": { "source": "keyboard-clicks" }
91
+ }
92
+ }
93
+ ```
94
+
95
+ Backends per platform:
96
+
97
+ | Platform | Backend | Notes |
98
+ | ----------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
99
+ | macOS | `CGEventSource` query (poll-on-demand, via `bun:ffi`) | No helper process. Idle includes history before the daemon started. |
100
+ | 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. |
101
+ | WSL 2 | Same PowerShell helper, running on the Windows host via interop | `powershell.exe` must be reachable from WSL (PATH or `/mnt/c/...`). |
102
+ | 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). |
103
+
104
+ Known limitations (they are the deliberate trade-off of ignoring cursor movement):
105
+
106
+ - 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.
107
+ - 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.
108
+ - 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.
109
+ - `scrylog doctor` shows the effective source, the resolved backend, and any availability reason when `keyboard-clicks` is selected.
110
+
111
+ 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:
112
+
113
+ | Event | Meaning |
114
+ | ----------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
115
+ | `notify.activity_observing` | Observation started; names the resolved backend |
116
+ | `notify.activity_first_input` | First key press or button click observed by the watcher (once per backend lifetime) |
117
+ | `notify.activity_gate` | A delivery gate decision: `idleMs`, `idleThresholdMs`, `activitySource`, event `kind`, and `outcome` (`send`, `defer`, `suppress`) |
118
+ | `notify.activity_backend_restarting` / `notify.activity_backend_failed` | The resident helper died and is restarting / exhausted its restart budget |
119
+
120
+ 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.
121
+
73
122
  ## WSL 2 Notes
74
123
 
75
124
  - The daemon runs as a Linux process and uses the same paths as native Linux.
@@ -169,28 +218,28 @@ By default, sessions whose tool could not be identified (`tool: "unknown"`) are
169
218
 
170
219
  The dashboard header layout is configurable through `tui.headerLayout`, and the setup wizard prompts for the same preference:
171
220
 
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. |
221
+ | Value | Behavior |
222
+ | ------------ | ------------------------------------------------------------------------------------------------------------------------------- |
223
+ | `auto` | Uses a right or left sidebar below 33 rows when the terminal is at least 64 columns wide; otherwise uses the horizontal header. |
224
+ | `horizontal` | Always keeps the header above Sessions and Usage. |
225
+ | `vertical` | Always uses the 15-column sidebar, even below 64 columns. |
177
226
 
178
227
  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
228
 
180
229
  Keyboard shortcuts:
181
230
 
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 |
231
+ | Key | Action |
232
+ | -------------- | ------------------------------------------ |
233
+ | `↑` / `k` | Move selection up |
234
+ | `↓` / `j` | Move selection down |
235
+ | `Enter` | Open session detail |
236
+ | `t` | Attach to selected `tmux` or herdr session |
237
+ | `/` | Search |
238
+ | `f` | Cycle filters |
239
+ | `a` | Show actionable sessions only |
240
+ | `r` | Refresh now |
241
+ | `Esc` | Close detail |
242
+ | `q` / `Ctrl+C` | Quit |
194
243
 
195
244
  ### Setup
196
245
 
@@ -273,11 +322,11 @@ Use the foreground daemon mainly for:
273
322
 
274
323
  Logging options:
275
324
 
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 |
325
+ | Flag | Purpose |
326
+ | -------------------- | -------------------------------------------------- | ---------------------------------------------- | ------ | ----------------------------------------- |
327
+ | `--log-level debug | info | warn | error` | Override the configured minimum log level |
328
+ | `--log-format pretty | json` | Override stderr output format for this process |
329
+ | `--no-log-file` | Disable daemon JSONL file logging for this process |
281
330
 
282
331
  For normal daily use on macOS and Linux, prefer `scrylog daemon install` so the daemon starts automatically with your user session.
283
332
 
@@ -305,12 +354,12 @@ Example config:
305
354
  "logFileEnabled": true,
306
355
  "logFilePath": "~/.scrylog/logs/scrylogd.log",
307
356
  "logFileMaxBytes": 5242880,
308
- "logFileMaxFiles": 3
357
+ "logFileMaxFiles": 3,
309
358
  },
310
359
  "api": {
311
360
  "tcpEnabled": false,
312
361
  "host": "127.0.0.1",
313
- "port": 7788
362
+ "port": 7788,
314
363
  },
315
364
  "cors": {
316
365
  "enabled": false,
@@ -319,26 +368,26 @@ Example config:
319
368
  "allowedHeaders": ["Content-Type", "Authorization"],
320
369
  "exposedHeaders": [],
321
370
  "credentials": false,
322
- "maxAge": 600
371
+ "maxAge": 600,
323
372
  },
324
373
  "opencode": {
325
374
  "mode": "hooks",
326
375
  "instances": [],
327
- "autoDiscover": true
376
+ "autoDiscover": true,
328
377
  },
329
378
  "claude": {
330
379
  "claudeDir": "/Users/you/.claude",
331
380
  "hooksEnabled": false,
332
- "hooksDir": "/tmp/scrylog-claude-hooks"
381
+ "hooksDir": "/tmp/scrylog-claude-hooks",
333
382
  },
334
383
  "codex": {
335
384
  "codexDir": "/Users/you/.codex",
336
385
  "hooksEnabled": false,
337
- "hooksDir": "/tmp/scrylog-codex-hooks"
386
+ "hooksDir": "/tmp/scrylog-codex-hooks",
338
387
  },
339
388
  "tmux": {
340
389
  "previewLines": 50,
341
- "detailLines": 200
390
+ "detailLines": 200,
342
391
  },
343
392
  "tui": {
344
393
  "refreshMs": 5000,
@@ -348,27 +397,27 @@ Example config:
348
397
  "pushDebounceMs": 120,
349
398
  "headerLayout": "auto",
350
399
  "headerSide": "left",
351
- "providerIcons": "blocks"
400
+ "providerIcons": "blocks",
352
401
  },
353
402
  "mcp": {
354
403
  "stdioEnabled": true,
355
404
  "httpEnabled": false,
356
405
  "host": "127.0.0.1",
357
406
  "port": 7789,
358
- "bearerToken": null
407
+ "bearerToken": null,
359
408
  },
360
409
  "usage": {
361
410
  "enabled": true,
362
411
  "pollIntervalMs": 300000,
363
- "providers": ["claude", "opencode-go", "codex"]
412
+ "providers": ["claude", "opencode-go", "codex"],
364
413
  },
365
414
  "retention": {
366
415
  "maxSessions": 500,
367
416
  "standaloneMaxAgeHours": 168,
368
417
  "localCommandTtlHours": 72,
369
418
  "cacheMaxEntries": 1000,
370
- "transcriptMaxBytes": 10485760
371
- }
419
+ "transcriptMaxBytes": 10485760,
420
+ },
372
421
  }
373
422
  ```
374
423
 
@@ -398,21 +447,21 @@ Notes:
398
447
 
399
448
  `scrylogd` is a monitor for active and recent sessions, not a permanent historical archive. Defaults are tuned for unattended daemon usage:
400
449
 
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 |
450
+ | Setting | Default | Effect |
451
+ | --------------------------------- | ---------: | ------------------------------------------------------------------------------------------------------------ |
452
+ | `retention.maxSessions` | `500` | Prunes oldest inactive identified standalone sessions above this count (tmux/herdr/unknown rows never count) |
453
+ | `retention.standaloneMaxAgeHours` | `168` | Prunes inactive standalone sessions older than 7 days |
454
+ | `retention.cacheMaxEntries` | `1000` | Bounds internal path/project caches |
455
+ | `retention.transcriptMaxBytes` | `10485760` | Parses only a bounded tail for very large Claude transcripts |
456
+ | `daemon.commandTimeoutMs` | `5000` | Prevents external commands from blocking indefinitely |
408
457
 
409
458
  Expected daemon RSS depends on active sessions and transcript size:
410
459
 
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 |
460
+ | Scenario | Expected RSS |
461
+ | -------------------------------- | -----------: |
462
+ | No active sessions | 35-70 MB |
463
+ | Normal local usage | 50-120 MB |
464
+ | Heavy tmux/Claude/OpenCode usage | 100-250 MB |
416
465
 
417
466
  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
467
 
@@ -436,16 +485,22 @@ The file format is JSONL for bug reports and tooling. Terminal stderr output def
436
485
 
437
486
  Default file rotation keeps three files total:
438
487
 
439
- | File | Purpose |
440
- | --- | --- |
441
- | `scrylogd.log` | Active log file |
488
+ | File | Purpose |
489
+ | ---------------- | -------------------- |
490
+ | `scrylogd.log` | Active log file |
442
491
  | `scrylogd.1.log` | Previous active file |
443
492
  | `scrylogd.2.log` | Oldest retained file |
444
493
 
445
494
  Example JSONL entry:
446
495
 
447
496
  ```json
448
- {"ts":"2026-05-05T18:42:31.123Z","level":"info","source":"daemon","event":"daemon.started","msg":"Started"}
497
+ {
498
+ "ts": "2026-05-05T18:42:31.123Z",
499
+ "level": "info",
500
+ "source": "daemon",
501
+ "event": "daemon.started",
502
+ "msg": "Started"
503
+ }
449
504
  ```
450
505
 
451
506
  Logs sanitize home-directory paths, bearer tokens, authorization values, and URL query strings before writing.
@@ -513,7 +568,7 @@ scrylog setup
513
568
  scrylog opencode hooks install
514
569
  ```
515
570
 
516
- Alternatively, add the plugin to `~/.config/opencode/opencode.json` manually:
571
+ Alternatively, add the plugin to `~/.config/opencode/opencode.json` manually:
517
572
 
518
573
  ```json
519
574
  {
@@ -595,10 +650,10 @@ How it works:
595
650
 
596
651
  Environment variables:
597
652
 
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 |
653
+ | Variable | Default | Purpose |
654
+ | --------------------- | ----------- | --------------------- |
655
+ | `OPENCODE_LOCAL_PORT` | `4096` | Force a specific port |
656
+ | `OPENCODE_HOST` | `127.0.0.1` | Force a specific host |
602
657
 
603
658
  ## HTTP API
604
659
 
@@ -618,17 +673,17 @@ Enable it with:
618
673
 
619
674
  Endpoints:
620
675
 
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 |
676
+ | Method | Path | Returns |
677
+ | ------ | ---------------------------- | ------------------------------------------------------------------------------------------------------ |
678
+ | `GET` | `/api/health` | daemon health, timestamps, collector status |
679
+ | `GET` | `/api/status` | visible counts, collector status, generated timestamp (`?includeUnknown=true` opts in) |
680
+ | `GET` | `/api/sessions` | visible session tree plus counts (`?includeUnknown=true` opts in; unknown-tool rows hidden by default) |
681
+ | `GET` | `/api/sessions/:id` | full session detail |
682
+ | `GET` | `/api/sessions/:id/children` | visible child sessions |
683
+ | `GET` | `/api/sessions/:id/messages` | recent messages when available |
684
+ | `GET` | `/api/config` | active config with sensitive fields redacted |
685
+ | `GET` | `/api/events` | SSE stream of store events |
686
+ | `POST` | `/api/webhook/opencode` | OpenCode plugin webhook |
632
687
 
633
688
  All error responses follow a consistent format:
634
689
 
@@ -864,7 +919,7 @@ For OpenCode local plugin testing, create or update:
864
919
  with:
865
920
 
866
921
  ```ts
867
- export { server } from "file:///Volumes/Files/Workspace/Projects/other/scrylog/packages/opencode-plugin/src/index.ts"
922
+ export { server } from 'file:///Volumes/Files/Workspace/Projects/other/scrylog/packages/opencode-plugin/src/index.ts';
868
923
  ```
869
924
 
870
925
  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