@scrylog/cli 0.1.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/LICENSE +21 -0
- package/README.md +836 -0
- package/package.json +75 -0
- package/src/api/docs/sessions.keys.ts +6 -0
- package/src/api/docs/sessions.ts +81 -0
- package/src/api/docs/system.keys.ts +5 -0
- package/src/api/docs/system.ts +66 -0
- package/src/api/docs/usage.keys.ts +3 -0
- package/src/api/docs/usage.ts +24 -0
- package/src/api/docs/webhooks.keys.ts +5 -0
- package/src/api/docs/webhooks.ts +78 -0
- package/src/api/index.ts +18 -0
- package/src/api/lib/auth.ts +43 -0
- package/src/api/lib/errors.ts +28 -0
- package/src/api/lib/route.ts +18 -0
- package/src/api/models/claude.ts +4 -0
- package/src/api/models/codex.ts +4 -0
- package/src/api/models/opencode.ts +11 -0
- package/src/api/routes/sessions.ts +47 -0
- package/src/api/routes/system.ts +103 -0
- package/src/api/routes/usage.ts +15 -0
- package/src/api/routes/webhooks/claude.ts +161 -0
- package/src/api/routes/webhooks/codex.ts +175 -0
- package/src/api/routes/webhooks/opencode.ts +107 -0
- package/src/api/routes.ts +93 -0
- package/src/api/schemas/common.ts +21 -0
- package/src/api/schemas/sessions.ts +72 -0
- package/src/api/schemas/usage.ts +50 -0
- package/src/api/schemas/webhooks/claude.ts +32 -0
- package/src/api/schemas/webhooks/codex.ts +34 -0
- package/src/api/schemas/webhooks/opencode.ts +29 -0
- package/src/api/services/claude-session.ts +9 -0
- package/src/api/services/codex-session.ts +8 -0
- package/src/api/services/opencode-session.ts +73 -0
- package/src/classifier.ts +206 -0
- package/src/cli/commands.ts +498 -0
- package/src/cli/prompt.ts +44 -0
- package/src/daemon/cli.ts +27 -0
- package/src/daemon/collectors/claude/README.md +108 -0
- package/src/daemon/collectors/claude/collector.ts +413 -0
- package/src/daemon/collectors/claude/discovery.ts +148 -0
- package/src/daemon/collectors/claude/hooks.ts +181 -0
- package/src/daemon/collectors/claude/index.ts +8 -0
- package/src/daemon/collectors/claude/jsonl.ts +85 -0
- package/src/daemon/collectors/claude/transcript.ts +246 -0
- package/src/daemon/collectors/codex/README.md +147 -0
- package/src/daemon/collectors/codex/collector.ts +661 -0
- package/src/daemon/collectors/codex/discovery.ts +104 -0
- package/src/daemon/collectors/codex/hooks.ts +179 -0
- package/src/daemon/collectors/codex/index.ts +7 -0
- package/src/daemon/collectors/codex/jsonl.ts +108 -0
- package/src/daemon/collectors/codex/transcript.ts +299 -0
- package/src/daemon/collectors/git.ts +295 -0
- package/src/daemon/collectors/opencode/README.md +106 -0
- package/src/daemon/collectors/opencode/collector.ts +543 -0
- package/src/daemon/collectors/opencode/discovery.ts +257 -0
- package/src/daemon/collectors/opencode/index.ts +5 -0
- package/src/daemon/collectors/opencode/session-builder.ts +59 -0
- package/src/daemon/collectors/opencode-db.ts +282 -0
- package/src/daemon/collectors/process.ts +201 -0
- package/src/daemon/collectors/tmux/README.md +128 -0
- package/src/daemon/collectors/tmux/collector.ts +472 -0
- package/src/daemon/collectors/tmux/enrichment.ts +241 -0
- package/src/daemon/collectors/tmux/index.ts +4 -0
- package/src/daemon/collectors/tmux/parse.ts +128 -0
- package/src/daemon/collectors/usage.ts +193 -0
- package/src/daemon/index.ts +207 -0
- package/src/daemon/scheduler.ts +86 -0
- package/src/daemon/store.ts +535 -0
- package/src/detect.ts +143 -0
- package/src/hooks/claude.ts +596 -0
- package/src/hooks/codex.ts +517 -0
- package/src/legacy/classifier.ts +215 -0
- package/src/legacy/detect.ts +143 -0
- package/src/mcp/client-server.ts +21 -0
- package/src/mcp/http-handler.ts +126 -0
- package/src/mcp/index.ts +61 -0
- package/src/mcp/resources/config-current.ts +19 -0
- package/src/mcp/resources/index.ts +11 -0
- package/src/mcp/resources/sessions-active.ts +19 -0
- package/src/mcp/resources/sessions-all.ts +19 -0
- package/src/mcp/schemas/sessions.ts +3 -0
- package/src/mcp/server.ts +17 -0
- package/src/mcp/services/api-adapter.ts +48 -0
- package/src/mcp/services/data-source.ts +22 -0
- package/src/mcp/services/store-adapter.ts +40 -0
- package/src/mcp/tools/get-active-sessions.ts +16 -0
- package/src/mcp/tools/get-session-children.ts +24 -0
- package/src/mcp/tools/get-session-messages.ts +24 -0
- package/src/mcp/tools/get-session.ts +23 -0
- package/src/mcp/tools/index.ts +15 -0
- package/src/mcp/tools/list-sessions.ts +16 -0
- package/src/neo-blessed.d.ts +4 -0
- package/src/oc/index.ts +302 -0
- package/src/service/manager.ts +242 -0
- package/src/shared/config.ts +478 -0
- package/src/shared/ipc.ts +80 -0
- package/src/shared/logger.ts +248 -0
- package/src/shared/paths.ts +73 -0
- package/src/shared/platform.ts +110 -0
- package/src/shared/session-view.ts +241 -0
- package/src/shared/types.ts +299 -0
- package/src/shared/utils.ts +339 -0
- package/src/tui/app.ts +920 -0
- package/src/tui/client.ts +149 -0
- package/src/tui/index.ts +181 -0
- package/src/types.ts +113 -0
- package/src/usage/README.md +323 -0
- package/src/usage/api.ts +99 -0
- package/src/usage/client.ts +3 -0
- package/src/usage/clients/anthropic-oauth-usage.ts +178 -0
- package/src/usage/clients/anthropic-web-usage.ts +245 -0
- package/src/usage/clients/claude-cli-probe.ts +187 -0
- package/src/usage/clients/codex-oauth-usage.ts +113 -0
- package/src/usage/clients/opencode-go-usage.ts +441 -0
- package/src/usage/index.ts +19 -0
- package/src/usage/mappers.ts +273 -0
- package/src/usage/planner.ts +54 -0
- package/src/usage/providers/claude.ts +113 -0
- package/src/usage/providers/codex.ts +34 -0
- package/src/usage/providers/opencode-go.ts +37 -0
- package/src/usage/resolver.ts +4 -0
- package/src/usage/resolvers/browser-cookies.ts +198 -0
- package/src/usage/resolvers/claude-auth.ts +99 -0
- package/src/usage/resolvers/claude-cli.ts +24 -0
- package/src/usage/resolvers/claude-web.ts +16 -0
- package/src/usage/resolvers/codex-auth.ts +117 -0
- package/src/usage/resolvers/opencode-go-web.ts +14 -0
- package/src/usage/types.ts +190 -0
package/README.md
ADDED
|
@@ -0,0 +1,836 @@
|
|
|
1
|
+
# scrylog
|
|
2
|
+
|
|
3
|
+
`scrylog` is a Bun-based terminal dashboard and daemon for monitoring AI coding sessions in `tmux` and as standalone processes.
|
|
4
|
+
|
|
5
|
+
It ships four commands:
|
|
6
|
+
|
|
7
|
+
| Command | Purpose |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| `scrylog` | TUI dashboard and operator CLI |
|
|
10
|
+
| `scrylogd` | Foreground daemon process |
|
|
11
|
+
| `scrylog-mcp` | stdio MCP server that proxies daemon data |
|
|
12
|
+
| `oc` | OpenCode launcher and attach helper |
|
|
13
|
+
|
|
14
|
+
## Features
|
|
15
|
+
|
|
16
|
+
- `tmux` monitoring for OpenCode, Codex, Copilot, and shell panes
|
|
17
|
+
- OpenCode integration in `hooks` or `sse` mode
|
|
18
|
+
- Claude transcript collection
|
|
19
|
+
- Codex transcript collection and hook-based state tracking
|
|
20
|
+
- Local daemon with Unix socket IPC on macOS and Linux, TCP fallback on Windows
|
|
21
|
+
- Optional TCP REST API exposure (enabled by default on Windows)
|
|
22
|
+
- Optional MCP HTTP exposure with bearer token support
|
|
23
|
+
- User-service installation on macOS and Linux
|
|
24
|
+
- Interactive setup wizard and diagnostics
|
|
25
|
+
|
|
26
|
+
## Requirements
|
|
27
|
+
|
|
28
|
+
- [Bun](https://bun.sh) `>= 1.3.0`
|
|
29
|
+
- `tmux` if you want `tmux` monitoring
|
|
30
|
+
- OpenCode if you want OpenCode monitoring
|
|
31
|
+
- `ps` on Unix or `wmic` on Windows for process auto-discovery
|
|
32
|
+
|
|
33
|
+
## Platform Support
|
|
34
|
+
|
|
35
|
+
| Tier | Platform | Status | Notes |
|
|
36
|
+
| --- | --- | --- | --- |
|
|
37
|
+
| Tier 1 | macOS | Tested daily | Full feature set including Keychain OAuth and Safari cookies |
|
|
38
|
+
| Tier 2 | Linux / WSL 2 | Compatible | Claude OAuth via `~/.claude/.credentials.json`, Chrome/Chromium cookies, systemd service when available |
|
|
39
|
+
| 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. |
|
|
40
|
+
|
|
41
|
+
## WSL 2 Notes
|
|
42
|
+
|
|
43
|
+
- The daemon runs as a Linux process and uses the same paths as native Linux.
|
|
44
|
+
- Service installation requires systemd. If `systemctl --user` is not available, `scrylog daemon status` reports `platform: wsl` (WSL) or `platform: linux-no-systemd` (native Linux) with guidance.
|
|
45
|
+
- `tmux` monitoring works inside WSL but cannot see Windows-native processes.
|
|
46
|
+
- Browser cookie extraction works for Chrome/Chromium running inside WSL, not for the Windows host browser.
|
|
47
|
+
|
|
48
|
+
## Linux Notes
|
|
49
|
+
|
|
50
|
+
- Linux without systemd (containers, minimal distros) reports `platform: linux-no-systemd` — the daemon runs but service management commands throw descriptive errors.
|
|
51
|
+
- OpenCode port discovery falls back to `/proc/<pid>/net/tcp` when `lsof` is unavailable.
|
|
52
|
+
|
|
53
|
+
## Install
|
|
54
|
+
|
|
55
|
+
### Main package
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
bun install -g @scrylog/cli
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
This installs the user-facing commands `scrylog`, `scrylogd`, `scrylog-mcp`, `scrylog-claude-hook`, `scrylog-codex-hook`, and `oc`.
|
|
62
|
+
|
|
63
|
+
### OpenCode plugin for hooks mode
|
|
64
|
+
|
|
65
|
+
Install this only if you want `opencode.mode: "hooks"`:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
bun install -g @scrylog/opencode-plugin
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### From source
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
git clone https://github.com/scrylog/scrylog.git
|
|
75
|
+
cd scrylog
|
|
76
|
+
bun install
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Quick Start
|
|
80
|
+
|
|
81
|
+
### Simplest setup
|
|
82
|
+
|
|
83
|
+
Run the setup wizard:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
scrylog setup
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The wizard can:
|
|
90
|
+
|
|
91
|
+
- create the config file
|
|
92
|
+
- optionally configure OpenCode
|
|
93
|
+
- enable or disable the TCP API
|
|
94
|
+
- enable or disable CORS for browser access
|
|
95
|
+
- enable or disable MCP HTTP
|
|
96
|
+
- generate an MCP bearer token
|
|
97
|
+
- install the daemon as a user service
|
|
98
|
+
|
|
99
|
+
Validated wizard paths:
|
|
100
|
+
|
|
101
|
+
- skip OpenCode entirely and keep defaults
|
|
102
|
+
- configure OpenCode `hooks` mode
|
|
103
|
+
- configure OpenCode `sse` mode with explicit instance URLs
|
|
104
|
+
|
|
105
|
+
### Launch the dashboard
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
scrylog
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
If the daemon is not running, `scrylog` prints an error with the commands to start it.
|
|
112
|
+
|
|
113
|
+
### Recommended local setup
|
|
114
|
+
|
|
115
|
+
For most users on macOS or Linux:
|
|
116
|
+
|
|
117
|
+
1. Install `@scrylog/cli`.
|
|
118
|
+
2. Run `scrylog setup`.
|
|
119
|
+
3. Keep the TCP API disabled unless you explicitly want HTTP access from outside local IPC.
|
|
120
|
+
4. Keep MCP HTTP disabled unless you explicitly need remote MCP over HTTP.
|
|
121
|
+
5. Install the daemon as a user service from the wizard.
|
|
122
|
+
6. Launch the dashboard with `scrylog`.
|
|
123
|
+
|
|
124
|
+
## Operator CLI
|
|
125
|
+
|
|
126
|
+
`scrylog` is both the TUI entrypoint and the operator CLI.
|
|
127
|
+
|
|
128
|
+
### TUI
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
scrylog
|
|
132
|
+
scrylog --config ~/.config/scrylog/config.json
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Keyboard shortcuts:
|
|
136
|
+
|
|
137
|
+
| Key | Action |
|
|
138
|
+
| --- | --- |
|
|
139
|
+
| `↑` / `k` | Move selection up |
|
|
140
|
+
| `↓` / `j` | Move selection down |
|
|
141
|
+
| `Enter` | Open session detail |
|
|
142
|
+
| `t` | Attach to selected `tmux` session |
|
|
143
|
+
| `/` | Search |
|
|
144
|
+
| `f` | Cycle filters |
|
|
145
|
+
| `a` | Show actionable sessions only |
|
|
146
|
+
| `r` | Refresh now |
|
|
147
|
+
| `Esc` | Close detail |
|
|
148
|
+
| `q` / `Ctrl+C` | Quit |
|
|
149
|
+
|
|
150
|
+
### Setup
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
scrylog setup
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Daemon service management
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
scrylog daemon install
|
|
160
|
+
scrylog daemon uninstall
|
|
161
|
+
scrylog daemon start
|
|
162
|
+
scrylog daemon stop
|
|
163
|
+
scrylog daemon restart
|
|
164
|
+
scrylog daemon status
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Supported service managers:
|
|
168
|
+
|
|
169
|
+
- macOS: `launchd` user agent
|
|
170
|
+
- Linux: `systemd --user`
|
|
171
|
+
- WSL without systemd: reported as `platform: wsl` with guidance
|
|
172
|
+
- Windows: reported as `platform: unsupported` — run `scrylogd` manually or use Task Scheduler
|
|
173
|
+
|
|
174
|
+
Typical service workflow:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
scrylog daemon install
|
|
178
|
+
scrylog daemon start
|
|
179
|
+
scrylog daemon status
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
To stop automatic startup later:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
scrylog daemon stop
|
|
186
|
+
scrylog daemon uninstall
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Config commands
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
scrylog config path
|
|
193
|
+
scrylog config show
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Token commands
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
scrylog token generate
|
|
200
|
+
scrylog token rotate
|
|
201
|
+
scrylog token clear
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Diagnostics and logs
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
scrylog doctor
|
|
208
|
+
scrylog logs
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Foreground Daemon
|
|
212
|
+
|
|
213
|
+
Use `scrylogd` when you want to run the daemon manually in the foreground:
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
scrylogd
|
|
217
|
+
scrylogd --config ~/.config/scrylog/config.json
|
|
218
|
+
scrylogd --log-level debug
|
|
219
|
+
scrylogd --log-format json
|
|
220
|
+
scrylogd --no-log-file
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Use the foreground daemon mainly for:
|
|
224
|
+
|
|
225
|
+
- debugging startup issues
|
|
226
|
+
- verifying listener behavior manually
|
|
227
|
+
- local development
|
|
228
|
+
|
|
229
|
+
Logging options:
|
|
230
|
+
|
|
231
|
+
| Flag | Purpose |
|
|
232
|
+
| --- | --- |
|
|
233
|
+
| `--log-level debug|info|warn|error` | Override the configured minimum log level |
|
|
234
|
+
| `--log-format pretty|json` | Override stderr output format for this process |
|
|
235
|
+
| `--no-log-file` | Disable daemon JSONL file logging for this process |
|
|
236
|
+
|
|
237
|
+
For normal daily use on macOS and Linux, prefer `scrylog daemon install` so the daemon starts automatically with your user session.
|
|
238
|
+
|
|
239
|
+
## Configuration
|
|
240
|
+
|
|
241
|
+
Config is loaded from the first path that exists:
|
|
242
|
+
|
|
243
|
+
1. `--config <path>`
|
|
244
|
+
2. `SCRYLOG_CONFIG`
|
|
245
|
+
3. `~/.config/scrylog/config.json`
|
|
246
|
+
4. `~/.scrylog.json`
|
|
247
|
+
5. built-in defaults
|
|
248
|
+
|
|
249
|
+
Example config:
|
|
250
|
+
|
|
251
|
+
```jsonc
|
|
252
|
+
{
|
|
253
|
+
"daemon": {
|
|
254
|
+
"pollIntervalMs": 10000,
|
|
255
|
+
"socketPath": null,
|
|
256
|
+
"commandTimeoutMs": 5000,
|
|
257
|
+
"networkTimeoutMs": 10000,
|
|
258
|
+
"logLevel": "info",
|
|
259
|
+
"logFormat": "auto",
|
|
260
|
+
"logFileEnabled": true,
|
|
261
|
+
"logFilePath": "~/.scrylog/logs/scrylogd.log",
|
|
262
|
+
"logFileMaxBytes": 5242880,
|
|
263
|
+
"logFileMaxFiles": 3
|
|
264
|
+
},
|
|
265
|
+
"api": {
|
|
266
|
+
"tcpEnabled": false,
|
|
267
|
+
"host": "127.0.0.1",
|
|
268
|
+
"port": 7788
|
|
269
|
+
},
|
|
270
|
+
"cors": {
|
|
271
|
+
"enabled": false,
|
|
272
|
+
"origins": [],
|
|
273
|
+
"methods": ["GET", "POST", "OPTIONS"],
|
|
274
|
+
"allowedHeaders": ["Content-Type", "Authorization"],
|
|
275
|
+
"exposedHeaders": [],
|
|
276
|
+
"credentials": false,
|
|
277
|
+
"maxAge": 600
|
|
278
|
+
},
|
|
279
|
+
"opencode": {
|
|
280
|
+
"mode": "hooks",
|
|
281
|
+
"instances": [],
|
|
282
|
+
"autoDiscover": true
|
|
283
|
+
},
|
|
284
|
+
"claude": {
|
|
285
|
+
"claudeDir": "/Users/you/.claude",
|
|
286
|
+
"hooksEnabled": false,
|
|
287
|
+
"hooksDir": "/tmp/scrylog-claude-hooks"
|
|
288
|
+
},
|
|
289
|
+
"codex": {
|
|
290
|
+
"codexDir": "/Users/you/.codex",
|
|
291
|
+
"hooksEnabled": false,
|
|
292
|
+
"hooksDir": "/tmp/scrylog-codex-hooks"
|
|
293
|
+
},
|
|
294
|
+
"tmux": {
|
|
295
|
+
"previewLines": 50,
|
|
296
|
+
"detailLines": 200
|
|
297
|
+
},
|
|
298
|
+
"tui": {
|
|
299
|
+
"refreshMs": 5000,
|
|
300
|
+
"showStandalone": true,
|
|
301
|
+
"usePushUpdates": true,
|
|
302
|
+
"standaloneMaxAgeHours": 6
|
|
303
|
+
},
|
|
304
|
+
"mcp": {
|
|
305
|
+
"stdioEnabled": true,
|
|
306
|
+
"httpEnabled": false,
|
|
307
|
+
"host": "127.0.0.1",
|
|
308
|
+
"port": 7789,
|
|
309
|
+
"bearerToken": null
|
|
310
|
+
},
|
|
311
|
+
"usage": {
|
|
312
|
+
"enabled": true,
|
|
313
|
+
"pollIntervalMs": 300000,
|
|
314
|
+
"providers": ["claude", "opencode-go", "codex"]
|
|
315
|
+
},
|
|
316
|
+
"retention": {
|
|
317
|
+
"maxSessions": 500,
|
|
318
|
+
"standaloneMaxAgeHours": 168,
|
|
319
|
+
"localCommandTtlHours": 72,
|
|
320
|
+
"cacheMaxEntries": 1000,
|
|
321
|
+
"transcriptMaxBytes": 10485760
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
Notes:
|
|
327
|
+
|
|
328
|
+
- On macOS and Linux, local clients use the Unix socket even when `api.tcpEnabled` is `false`.
|
|
329
|
+
- `api.tcpEnabled` controls TCP exposure of the REST API, not local daemon IPC.
|
|
330
|
+
- `mcp.httpEnabled` controls the HTTP MCP listener.
|
|
331
|
+
- `scrylog-mcp` uses local daemon access and is separate from MCP HTTP.
|
|
332
|
+
- `cors.enabled` controls whether the API and MCP HTTP handlers include CORS headers. Enable it when consuming the API from a browser (e.g. a web dashboard).
|
|
333
|
+
- `cors.origins` accepts an array of allowed origins. Use `["*"]` to allow any origin.
|
|
334
|
+
- `daemon.logFormat: "auto"` uses pretty stderr output in a terminal and JSONL when stderr is not a TTY.
|
|
335
|
+
- `daemon.socketPath` overrides the local Unix socket on macOS/Linux. Leave it unset for the per-user default `/tmp/scrylog-<uid>.sock`.
|
|
336
|
+
- `daemon.commandTimeoutMs` bounds daemon-owned commands such as `ps`, `tmux`, `git`, `lsof`, and `pgrep`.
|
|
337
|
+
- `daemon.networkTimeoutMs` bounds daemon-owned usage/integration network requests.
|
|
338
|
+
- `usage.enabled: false` disables periodic Claude/OpenCode usage probes without disabling session monitoring.
|
|
339
|
+
- `retention` limits in-memory state. Active `working` and `waiting-input` sessions are preserved even when old.
|
|
340
|
+
- The daemon log file is always JSONL and rotates by size: `scrylogd.log`, `scrylogd.1.log`, `scrylogd.2.log` by default.
|
|
341
|
+
- The current CLI preserves an existing legacy config path when updating config, so older `~/.scrylog.json` users are not forced onto a new file immediately.
|
|
342
|
+
|
|
343
|
+
### Long-Running Operation
|
|
344
|
+
|
|
345
|
+
`scrylogd` is a monitor for active and recent sessions, not a permanent historical archive. Defaults are tuned for unattended daemon usage:
|
|
346
|
+
|
|
347
|
+
| Setting | Default | Effect |
|
|
348
|
+
| --- | ---: | --- |
|
|
349
|
+
| `retention.maxSessions` | `500` | Prunes oldest inactive sessions above this count |
|
|
350
|
+
| `retention.standaloneMaxAgeHours` | `168` | Prunes inactive standalone sessions older than 7 days |
|
|
351
|
+
| `retention.cacheMaxEntries` | `1000` | Bounds internal path/project caches |
|
|
352
|
+
| `retention.transcriptMaxBytes` | `10485760` | Parses only a bounded tail for very large Claude transcripts |
|
|
353
|
+
| `daemon.commandTimeoutMs` | `5000` | Prevents external commands from blocking indefinitely |
|
|
354
|
+
|
|
355
|
+
Expected daemon RSS depends on active sessions and transcript size:
|
|
356
|
+
|
|
357
|
+
| Scenario | Expected RSS |
|
|
358
|
+
| --- | ---: |
|
|
359
|
+
| No active sessions | 35-70 MB |
|
|
360
|
+
| Normal local usage | 50-120 MB |
|
|
361
|
+
| Heavy tmux/Claude/OpenCode usage | 100-250 MB |
|
|
362
|
+
|
|
363
|
+
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.
|
|
364
|
+
|
|
365
|
+
Run diagnostics after changing operational settings:
|
|
366
|
+
|
|
367
|
+
```bash
|
|
368
|
+
scrylog doctor
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
Doctor reports the effective socket path, log path, retention limits, timeout values, and whether usage collection is enabled.
|
|
372
|
+
|
|
373
|
+
### Daemon Logs
|
|
374
|
+
|
|
375
|
+
`scrylogd` writes structured logs to stderr and, by default, to:
|
|
376
|
+
|
|
377
|
+
```text
|
|
378
|
+
~/.scrylog/logs/scrylogd.log
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
The file format is JSONL for bug reports and tooling. Terminal stderr output defaults to pretty formatting when interactive.
|
|
382
|
+
|
|
383
|
+
Default file rotation keeps three files total:
|
|
384
|
+
|
|
385
|
+
| File | Purpose |
|
|
386
|
+
| --- | --- |
|
|
387
|
+
| `scrylogd.log` | Active log file |
|
|
388
|
+
| `scrylogd.1.log` | Previous active file |
|
|
389
|
+
| `scrylogd.2.log` | Oldest retained file |
|
|
390
|
+
|
|
391
|
+
Example JSONL entry:
|
|
392
|
+
|
|
393
|
+
```json
|
|
394
|
+
{"ts":"2026-05-05T18:42:31.123Z","level":"info","source":"daemon","event":"daemon.started","msg":"Started"}
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
Logs sanitize home-directory paths, bearer tokens, authorization values, and URL query strings before writing.
|
|
398
|
+
|
|
399
|
+
The daemon's own file logs are capped by `daemon.logFileMaxBytes * daemon.logFileMaxFiles` (15 MB by default). Stderr logs written by `systemd --user` or `launchd` are retained according to the operating system's service logging policy.
|
|
400
|
+
|
|
401
|
+
### Exposure Recommendations
|
|
402
|
+
|
|
403
|
+
Recommended defaults for a local machine:
|
|
404
|
+
|
|
405
|
+
```json
|
|
406
|
+
{
|
|
407
|
+
"api": {
|
|
408
|
+
"tcpEnabled": false
|
|
409
|
+
},
|
|
410
|
+
"cors": {
|
|
411
|
+
"enabled": false
|
|
412
|
+
},
|
|
413
|
+
"mcp": {
|
|
414
|
+
"httpEnabled": false
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
Enable `api.tcpEnabled` only when you want TCP access to the REST API.
|
|
420
|
+
|
|
421
|
+
Enable `cors.enabled` when a browser-based client needs to consume the API directly.
|
|
422
|
+
|
|
423
|
+
Enable `mcp.httpEnabled` only when you want MCP over HTTP. If you enable it, also set or generate `mcp.bearerToken`.
|
|
424
|
+
|
|
425
|
+
## OpenCode Integration
|
|
426
|
+
|
|
427
|
+
OpenCode setup is optional. If you skip it in `scrylog setup`, defaults remain unchanged until you configure it later.
|
|
428
|
+
|
|
429
|
+
`scrylog` supports two mutually exclusive OpenCode modes.
|
|
430
|
+
|
|
431
|
+
### `hooks` mode
|
|
432
|
+
|
|
433
|
+
Recommended mode when you run OpenCode inside `tmux`.
|
|
434
|
+
|
|
435
|
+
Use it when you want:
|
|
436
|
+
|
|
437
|
+
- immediate session updates from OpenCode events
|
|
438
|
+
- permission prompt visibility
|
|
439
|
+
- the best available pane correlation in `tmux`
|
|
440
|
+
|
|
441
|
+
Requirements:
|
|
442
|
+
|
|
443
|
+
- `scrylog`
|
|
444
|
+
- `@scrylog/opencode-plugin`
|
|
445
|
+
- OpenCode config with the plugin enabled
|
|
446
|
+
|
|
447
|
+
Setup:
|
|
448
|
+
|
|
449
|
+
1. Install the plugin.
|
|
450
|
+
|
|
451
|
+
```bash
|
|
452
|
+
bun install -g @scrylog/opencode-plugin
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
2. Set `opencode.mode` to `hooks`.
|
|
456
|
+
|
|
457
|
+
3. Add the plugin to `~/.config/opencode/opencode.json`:
|
|
458
|
+
|
|
459
|
+
```json
|
|
460
|
+
{
|
|
461
|
+
"plugin": ["@scrylog/opencode-plugin"]
|
|
462
|
+
}
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
4. Start `scrylogd` or install the service.
|
|
466
|
+
|
|
467
|
+
Recommended command flow:
|
|
468
|
+
|
|
469
|
+
```bash
|
|
470
|
+
scrylog setup
|
|
471
|
+
scrylog daemon install
|
|
472
|
+
scrylog daemon status
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
What it allows:
|
|
476
|
+
|
|
477
|
+
- webhook-driven OpenCode updates
|
|
478
|
+
- better `tmux` correlation when the plugin writes `@opencode-session`
|
|
479
|
+
- child session visibility when OpenCode emits parent IDs
|
|
480
|
+
|
|
481
|
+
What it does not allow:
|
|
482
|
+
|
|
483
|
+
- heuristic `opencode attach` correlation inside `tmux`
|
|
484
|
+
- complete exact-session tracking without an upstream OpenCode signal
|
|
485
|
+
|
|
486
|
+
### `sse` mode
|
|
487
|
+
|
|
488
|
+
Use this when OpenCode exposes an HTTP endpoint, such as:
|
|
489
|
+
|
|
490
|
+
- `opencode --port 4096`
|
|
491
|
+
- `opencode serve`
|
|
492
|
+
- `oc`
|
|
493
|
+
|
|
494
|
+
Setup:
|
|
495
|
+
|
|
496
|
+
1. Set `opencode.mode` to `sse`.
|
|
497
|
+
2. Optionally configure `opencode.instances`.
|
|
498
|
+
3. Leave `opencode.autoDiscover` enabled if you want local process discovery.
|
|
499
|
+
4. Start OpenCode with `opencode --port 4096`, `opencode serve`, or `oc`.
|
|
500
|
+
|
|
501
|
+
What it allows:
|
|
502
|
+
|
|
503
|
+
- standalone OpenCode monitoring through the SDK
|
|
504
|
+
- explicit instance URLs
|
|
505
|
+
- `oc` launch and attach workflows
|
|
506
|
+
|
|
507
|
+
What it does not allow:
|
|
508
|
+
|
|
509
|
+
- OpenCode `tmux` rows
|
|
510
|
+
- plugin-driven updates
|
|
511
|
+
|
|
512
|
+
Important behavior:
|
|
513
|
+
|
|
514
|
+
- in `sse` mode, OpenCode is shown as standalone only
|
|
515
|
+
- the daemon ignores webhook payloads from the plugin in `sse` mode
|
|
516
|
+
|
|
517
|
+
## `oc`
|
|
518
|
+
|
|
519
|
+
`oc` is the OpenCode helper included in `scrylog`. It is mainly intended for `sse` mode.
|
|
520
|
+
|
|
521
|
+
```bash
|
|
522
|
+
oc
|
|
523
|
+
oc --continue
|
|
524
|
+
OPENCODE_LOCAL_PORT=4097 oc
|
|
525
|
+
OPENCODE_HOST=mac-mini.my-tailnet.ts.net OPENCODE_LOCAL_PORT=4096 oc
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
How it works:
|
|
529
|
+
|
|
530
|
+
1. scans running processes for OpenCode instances exposing a port
|
|
531
|
+
2. probes each candidate with `GET /global/health`
|
|
532
|
+
3. does one of the following:
|
|
533
|
+
- no live instance: launches `opencode --port 4096`
|
|
534
|
+
- one live instance: runs `opencode attach <url>`
|
|
535
|
+
- multiple live instances: prompts you to choose one
|
|
536
|
+
|
|
537
|
+
Environment variables:
|
|
538
|
+
|
|
539
|
+
| Variable | Default | Purpose |
|
|
540
|
+
| --- | --- | --- |
|
|
541
|
+
| `OPENCODE_LOCAL_PORT` | `4096` | Force a specific port |
|
|
542
|
+
| `OPENCODE_HOST` | `127.0.0.1` | Force a specific host |
|
|
543
|
+
|
|
544
|
+
## HTTP API
|
|
545
|
+
|
|
546
|
+
The daemon always exposes local IPC on Unix socket on macOS and Linux. The TCP HTTP API is optional.
|
|
547
|
+
|
|
548
|
+
Enable it with:
|
|
549
|
+
|
|
550
|
+
```json
|
|
551
|
+
{
|
|
552
|
+
"api": {
|
|
553
|
+
"tcpEnabled": true,
|
|
554
|
+
"host": "127.0.0.1",
|
|
555
|
+
"port": 7788
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
Endpoints:
|
|
561
|
+
|
|
562
|
+
| Method | Path | Returns |
|
|
563
|
+
| --- | --- | --- |
|
|
564
|
+
| `GET` | `/api/health` | daemon health, timestamps, collector status |
|
|
565
|
+
| `GET` | `/api/status` | visible counts, collector status, generated timestamp |
|
|
566
|
+
| `GET` | `/api/sessions` | visible session tree plus counts |
|
|
567
|
+
| `GET` | `/api/sessions/:id` | full session detail |
|
|
568
|
+
| `GET` | `/api/sessions/:id/children` | visible child sessions |
|
|
569
|
+
| `GET` | `/api/sessions/:id/messages` | recent messages when available |
|
|
570
|
+
| `GET` | `/api/config` | active config with sensitive fields redacted |
|
|
571
|
+
| `GET` | `/api/events` | SSE stream of store events |
|
|
572
|
+
| `POST` | `/api/webhook/opencode` | OpenCode plugin webhook |
|
|
573
|
+
|
|
574
|
+
All error responses follow a consistent format:
|
|
575
|
+
|
|
576
|
+
```json
|
|
577
|
+
{ "error": "Session 'abc' not found", "code": "NOT_FOUND" }
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
Known codes: `NOT_FOUND`, `UNAUTHORIZED`, `VALIDATION_ERROR`, `INTERNAL_ERROR`.
|
|
581
|
+
|
|
582
|
+
Example:
|
|
583
|
+
|
|
584
|
+
```bash
|
|
585
|
+
curl http://127.0.0.1:7788/api/health
|
|
586
|
+
curl http://127.0.0.1:7788/api/sessions
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
## MCP
|
|
590
|
+
|
|
591
|
+
### stdio MCP
|
|
592
|
+
|
|
593
|
+
Use `scrylog-mcp` for local MCP clients:
|
|
594
|
+
|
|
595
|
+
```bash
|
|
596
|
+
scrylog-mcp
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
Example MCP client config:
|
|
600
|
+
|
|
601
|
+
```json
|
|
602
|
+
{
|
|
603
|
+
"mcpServers": {
|
|
604
|
+
"scrylog": {
|
|
605
|
+
"command": "scrylog-mcp"
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
Available tools:
|
|
612
|
+
|
|
613
|
+
- `list_sessions`
|
|
614
|
+
- `get_active_sessions`
|
|
615
|
+
- `get_session`
|
|
616
|
+
- `get_session_messages`
|
|
617
|
+
- `get_session_children`
|
|
618
|
+
|
|
619
|
+
Available resources:
|
|
620
|
+
|
|
621
|
+
- `sessions://all`
|
|
622
|
+
- `sessions://active`
|
|
623
|
+
- `config://current`
|
|
624
|
+
|
|
625
|
+
### MCP HTTP
|
|
626
|
+
|
|
627
|
+
MCP HTTP is disabled by default.
|
|
628
|
+
|
|
629
|
+
Enable it with:
|
|
630
|
+
|
|
631
|
+
```json
|
|
632
|
+
{
|
|
633
|
+
"mcp": {
|
|
634
|
+
"httpEnabled": true,
|
|
635
|
+
"host": "127.0.0.1",
|
|
636
|
+
"port": 7789,
|
|
637
|
+
"bearerToken": "your-secret-token"
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
If `bearerToken` is set, clients must send:
|
|
643
|
+
|
|
644
|
+
- `Authorization: Bearer <token>`
|
|
645
|
+
|
|
646
|
+
For streamable HTTP clients, include:
|
|
647
|
+
|
|
648
|
+
- `Accept: application/json, text/event-stream`
|
|
649
|
+
|
|
650
|
+
The server uses stateful MCP HTTP sessions:
|
|
651
|
+
|
|
652
|
+
1. send `initialize`
|
|
653
|
+
2. read the `mcp-session-id` response header
|
|
654
|
+
3. send `notifications/initialized` with the same `mcp-session-id`
|
|
655
|
+
4. send later MCP requests with the same `mcp-session-id`
|
|
656
|
+
|
|
657
|
+
### MCP HTTP Security
|
|
658
|
+
|
|
659
|
+
Generate a token from the operator CLI:
|
|
660
|
+
|
|
661
|
+
```bash
|
|
662
|
+
scrylog token generate
|
|
663
|
+
```
|
|
664
|
+
|
|
665
|
+
Rotate it later with:
|
|
666
|
+
|
|
667
|
+
```bash
|
|
668
|
+
scrylog token rotate
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
Clear it with:
|
|
672
|
+
|
|
673
|
+
```bash
|
|
674
|
+
scrylog token clear
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
## Service Installation
|
|
678
|
+
|
|
679
|
+
You can keep the daemon running automatically with the operator CLI:
|
|
680
|
+
|
|
681
|
+
```bash
|
|
682
|
+
scrylog daemon install
|
|
683
|
+
scrylog daemon start
|
|
684
|
+
scrylog daemon status
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
macOS uses a LaunchAgent under `~/Library/LaunchAgents/`.
|
|
688
|
+
|
|
689
|
+
Linux uses `systemd --user` under `~/.config/systemd/user/`.
|
|
690
|
+
|
|
691
|
+
The service lifecycle was validated with:
|
|
692
|
+
|
|
693
|
+
- install
|
|
694
|
+
- start
|
|
695
|
+
- restart
|
|
696
|
+
- stop
|
|
697
|
+
- uninstall
|
|
698
|
+
|
|
699
|
+
If you want to inspect the current service state or listener reachability, run:
|
|
700
|
+
|
|
701
|
+
```bash
|
|
702
|
+
scrylog daemon status
|
|
703
|
+
scrylog doctor
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
## Troubleshooting
|
|
707
|
+
|
|
708
|
+
### `scrylog` cannot connect to the daemon
|
|
709
|
+
|
|
710
|
+
Start it manually:
|
|
711
|
+
|
|
712
|
+
```bash
|
|
713
|
+
scrylogd --log-level debug
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
Or inspect the service:
|
|
717
|
+
|
|
718
|
+
```bash
|
|
719
|
+
scrylog daemon status
|
|
720
|
+
scrylog logs
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
If you normally use the user service, also try:
|
|
724
|
+
|
|
725
|
+
```bash
|
|
726
|
+
scrylog daemon restart
|
|
727
|
+
```
|
|
728
|
+
|
|
729
|
+
### OpenCode is missing in hooks mode
|
|
730
|
+
|
|
731
|
+
Check:
|
|
732
|
+
|
|
733
|
+
1. `opencode.mode` is `hooks`
|
|
734
|
+
2. `@scrylog/opencode-plugin` is installed
|
|
735
|
+
3. OpenCode config includes `"plugin": ["@scrylog/opencode-plugin"]`
|
|
736
|
+
4. the daemon is running
|
|
737
|
+
|
|
738
|
+
### OpenCode is missing in sse mode
|
|
739
|
+
|
|
740
|
+
Check:
|
|
741
|
+
|
|
742
|
+
1. `opencode.mode` is `sse`
|
|
743
|
+
2. OpenCode is exposing a reachable HTTP endpoint
|
|
744
|
+
3. `opencode.instances` is correct or `autoDiscover` is enabled
|
|
745
|
+
4. `GET /global/health` succeeds on the OpenCode endpoint
|
|
746
|
+
|
|
747
|
+
### MCP HTTP returns `401 Unauthorized`
|
|
748
|
+
|
|
749
|
+
Send the configured bearer token.
|
|
750
|
+
|
|
751
|
+
### MCP HTTP returns `No valid session ID provided`
|
|
752
|
+
|
|
753
|
+
Start with `initialize`, then reuse the returned `mcp-session-id`.
|
|
754
|
+
|
|
755
|
+
### I want a guided setup again
|
|
756
|
+
|
|
757
|
+
Run:
|
|
758
|
+
|
|
759
|
+
```bash
|
|
760
|
+
scrylog setup
|
|
761
|
+
```
|
|
762
|
+
|
|
763
|
+
## Validated User Flows
|
|
764
|
+
|
|
765
|
+
These user-facing flows were exercised after implementation:
|
|
766
|
+
|
|
767
|
+
- operator CLI help and subcommands
|
|
768
|
+
- daemon foreground startup
|
|
769
|
+
- daemon user-service install, start, restart, stop, uninstall on macOS
|
|
770
|
+
- `scrylog` TUI launch and quit
|
|
771
|
+
- setup wizard skip, `hooks`, and `sse` flows
|
|
772
|
+
- MCP token generate, rotate, and clear
|
|
773
|
+
- TCP API enable and disable behavior
|
|
774
|
+
- MCP HTTP enable, disable, and bearer-token enforcement
|
|
775
|
+
- `scrylog-mcp` stdio startup and tool discovery
|
|
776
|
+
|
|
777
|
+
## Development And Release
|
|
778
|
+
|
|
779
|
+
### Development Hooks
|
|
780
|
+
|
|
781
|
+
When developing from this checkout, use local hook paths instead of the published package. This is only for local development and manual testing; normal users should follow the published package setup above.
|
|
782
|
+
|
|
783
|
+
Claude Code hook commands should point to this checkout:
|
|
784
|
+
|
|
785
|
+
```text
|
|
786
|
+
bun run /Volumes/Files/Workspace/Projects/other/scrylog/src/hooks/claude.ts
|
|
787
|
+
```
|
|
788
|
+
|
|
789
|
+
Use that command for every Claude hook event that `scrylog` tracks.
|
|
790
|
+
|
|
791
|
+
Codex hook commands should point to this checkout:
|
|
792
|
+
|
|
793
|
+
```text
|
|
794
|
+
bun run /Volumes/Files/Workspace/Projects/other/scrylog/src/hooks/codex.ts
|
|
795
|
+
```
|
|
796
|
+
|
|
797
|
+
Use that command for every Codex hook event that `scrylog` tracks.
|
|
798
|
+
|
|
799
|
+
For OpenCode local plugin testing, create or update:
|
|
800
|
+
|
|
801
|
+
```text
|
|
802
|
+
~/.config/opencode/plugins/scrylog.ts
|
|
803
|
+
```
|
|
804
|
+
|
|
805
|
+
with:
|
|
806
|
+
|
|
807
|
+
```ts
|
|
808
|
+
export { server } from "file:///Volumes/Files/Workspace/Projects/other/scrylog/packages/opencode-plugin/src/index.ts"
|
|
809
|
+
```
|
|
810
|
+
|
|
811
|
+
For package usage, prefer the published plugin configuration:
|
|
812
|
+
|
|
813
|
+
```json
|
|
814
|
+
{
|
|
815
|
+
"plugin": ["@scrylog/opencode-plugin"]
|
|
816
|
+
}
|
|
817
|
+
```
|
|
818
|
+
|
|
819
|
+
Validation:
|
|
820
|
+
|
|
821
|
+
```bash
|
|
822
|
+
bun run check-types
|
|
823
|
+
bun run test
|
|
824
|
+
```
|
|
825
|
+
|
|
826
|
+
Publish-readiness checks:
|
|
827
|
+
|
|
828
|
+
```bash
|
|
829
|
+
bun run release:check
|
|
830
|
+
```
|
|
831
|
+
|
|
832
|
+
Public packages are versioned with Changesets and validated through Turborepo. The release workflow creates a version PR on `main`; merging that PR publishes `@scrylog/cli` and `@scrylog/opencode-plugin` to npm.
|
|
833
|
+
|
|
834
|
+
## OpenSpec
|
|
835
|
+
|
|
836
|
+
Design and behavior artifacts live in `openspec/`.
|