@scrylog/cli 0.3.0 → 0.3.2

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.
Files changed (195) hide show
  1. package/dist/assets/highlights-eq9cgrbb.scm +604 -0
  2. package/dist/assets/highlights-ghv9g403.scm +205 -0
  3. package/dist/assets/highlights-hk7bwhj4.scm +284 -0
  4. package/dist/assets/highlights-r812a2qc.scm +150 -0
  5. package/dist/assets/highlights-x6tmsnaa.scm +115 -0
  6. package/dist/assets/injections-73j83es3.scm +27 -0
  7. package/dist/assets/parser.worker-xyhf83rf.js +4563 -0
  8. package/dist/assets/tree-sitter-3jzf13jk.wasm +0 -0
  9. package/dist/assets/tree-sitter-javascript-nd0q4pe9.wasm +0 -0
  10. package/dist/assets/tree-sitter-markdown-411r6y9b.wasm +0 -0
  11. package/dist/assets/tree-sitter-markdown_inline-j5349f42.wasm +0 -0
  12. package/dist/assets/tree-sitter-typescript-zxjzwt75.wasm +0 -0
  13. package/dist/assets/tree-sitter-zig-e78zbjpm.wasm +0 -0
  14. package/dist/cli/index.js +499 -0
  15. package/dist/cli/index.js.map +61 -0
  16. package/dist/daemon/index.js +670 -0
  17. package/dist/daemon/index.js.map +1475 -0
  18. package/dist/hooks/claude.js +6 -0
  19. package/dist/hooks/claude.js.map +11 -0
  20. package/dist/hooks/codex.js +10 -0
  21. package/dist/hooks/codex.js.map +11 -0
  22. package/dist/mcp/index.js +100 -0
  23. package/dist/mcp/index.js.map +231 -0
  24. package/dist/oc/index.js +21 -0
  25. package/dist/oc/index.js.map +10 -0
  26. package/package.json +16 -13
  27. package/src/api/docs/sessions.keys.ts +0 -6
  28. package/src/api/docs/sessions.ts +0 -82
  29. package/src/api/docs/system.keys.ts +0 -5
  30. package/src/api/docs/system.ts +0 -69
  31. package/src/api/docs/usage.keys.ts +0 -3
  32. package/src/api/docs/usage.ts +0 -24
  33. package/src/api/docs/webhooks.keys.ts +0 -5
  34. package/src/api/docs/webhooks.ts +0 -78
  35. package/src/api/index.ts +0 -18
  36. package/src/api/lib/auth.ts +0 -43
  37. package/src/api/lib/errors.ts +0 -28
  38. package/src/api/lib/route.ts +0 -18
  39. package/src/api/models/claude.ts +0 -4
  40. package/src/api/models/codex.ts +0 -4
  41. package/src/api/models/opencode.ts +0 -11
  42. package/src/api/routes/sessions.ts +0 -51
  43. package/src/api/routes/system.ts +0 -106
  44. package/src/api/routes/usage.ts +0 -15
  45. package/src/api/routes/webhooks/claude.ts +0 -149
  46. package/src/api/routes/webhooks/codex.ts +0 -175
  47. package/src/api/routes/webhooks/opencode.ts +0 -112
  48. package/src/api/routes.ts +0 -93
  49. package/src/api/schemas/common.ts +0 -29
  50. package/src/api/schemas/sessions.ts +0 -86
  51. package/src/api/schemas/usage.ts +0 -51
  52. package/src/api/schemas/webhooks/claude.ts +0 -32
  53. package/src/api/schemas/webhooks/codex.ts +0 -34
  54. package/src/api/schemas/webhooks/opencode.ts +0 -29
  55. package/src/api/services/claude-session.ts +0 -9
  56. package/src/api/services/codex-session.ts +0 -8
  57. package/src/api/services/opencode-session.ts +0 -73
  58. package/src/classifier.ts +0 -206
  59. package/src/cli/commands.ts +0 -714
  60. package/src/cli/index.ts +0 -18
  61. package/src/cli/program.ts +0 -175
  62. package/src/cli/prompt.ts +0 -44
  63. package/src/daemon/cli.ts +0 -27
  64. package/src/daemon/collectors/claude/README.md +0 -108
  65. package/src/daemon/collectors/claude/collector.ts +0 -423
  66. package/src/daemon/collectors/claude/discovery.ts +0 -127
  67. package/src/daemon/collectors/claude/hooks.ts +0 -181
  68. package/src/daemon/collectors/claude/index.ts +0 -8
  69. package/src/daemon/collectors/claude/jsonl.ts +0 -85
  70. package/src/daemon/collectors/claude/transcript.ts +0 -246
  71. package/src/daemon/collectors/codex/README.md +0 -147
  72. package/src/daemon/collectors/codex/collector.ts +0 -661
  73. package/src/daemon/collectors/codex/discovery.ts +0 -104
  74. package/src/daemon/collectors/codex/hooks.ts +0 -179
  75. package/src/daemon/collectors/codex/index.ts +0 -7
  76. package/src/daemon/collectors/codex/jsonl.ts +0 -108
  77. package/src/daemon/collectors/codex/transcript.ts +0 -299
  78. package/src/daemon/collectors/git.ts +0 -353
  79. package/src/daemon/collectors/herdr/collector.ts +0 -128
  80. package/src/daemon/collectors/herdr/index.ts +0 -2
  81. package/src/daemon/collectors/herdr/normalization.ts +0 -111
  82. package/src/daemon/collectors/opencode/README.md +0 -106
  83. package/src/daemon/collectors/opencode/collector.ts +0 -545
  84. package/src/daemon/collectors/opencode/discovery.ts +0 -257
  85. package/src/daemon/collectors/opencode/index.ts +0 -5
  86. package/src/daemon/collectors/opencode/session-builder.ts +0 -59
  87. package/src/daemon/collectors/opencode-db.ts +0 -294
  88. package/src/daemon/collectors/process.ts +0 -201
  89. package/src/daemon/collectors/tmux/README.md +0 -128
  90. package/src/daemon/collectors/tmux/collector.ts +0 -492
  91. package/src/daemon/collectors/tmux/enrichment.ts +0 -242
  92. package/src/daemon/collectors/tmux/index.ts +0 -4
  93. package/src/daemon/collectors/tmux/parse.ts +0 -128
  94. package/src/daemon/collectors/usage.ts +0 -259
  95. package/src/daemon/index.ts +0 -209
  96. package/src/daemon/scheduler.ts +0 -86
  97. package/src/daemon/store.ts +0 -630
  98. package/src/detect.ts +0 -143
  99. package/src/hooks/claude.ts +0 -596
  100. package/src/hooks/codex.ts +0 -517
  101. package/src/legacy/classifier.ts +0 -215
  102. package/src/legacy/detect.ts +0 -143
  103. package/src/mcp/client-server.ts +0 -21
  104. package/src/mcp/http-handler.ts +0 -126
  105. package/src/mcp/index.ts +0 -61
  106. package/src/mcp/resources/config-current.ts +0 -19
  107. package/src/mcp/resources/index.ts +0 -11
  108. package/src/mcp/resources/sessions-active.ts +0 -19
  109. package/src/mcp/resources/sessions-all.ts +0 -19
  110. package/src/mcp/schemas/sessions.ts +0 -3
  111. package/src/mcp/server.ts +0 -17
  112. package/src/mcp/services/api-adapter.ts +0 -48
  113. package/src/mcp/services/data-source.ts +0 -22
  114. package/src/mcp/services/store-adapter.ts +0 -40
  115. package/src/mcp/tools/get-active-sessions.ts +0 -16
  116. package/src/mcp/tools/get-session-children.ts +0 -24
  117. package/src/mcp/tools/get-session-messages.ts +0 -24
  118. package/src/mcp/tools/get-session.ts +0 -23
  119. package/src/mcp/tools/index.ts +0 -15
  120. package/src/mcp/tools/list-sessions.ts +0 -16
  121. package/src/oc/index.ts +0 -302
  122. package/src/service/manager.ts +0 -284
  123. package/src/shared/config.ts +0 -511
  124. package/src/shared/ipc.ts +0 -80
  125. package/src/shared/logger.ts +0 -248
  126. package/src/shared/paths.ts +0 -73
  127. package/src/shared/platform.ts +0 -110
  128. package/src/shared/session-exclusions.ts +0 -5
  129. package/src/shared/session-view.ts +0 -302
  130. package/src/shared/terminal-capabilities.ts +0 -130
  131. package/src/shared/types.ts +0 -330
  132. package/src/shared/utils.ts +0 -339
  133. package/src/shared/version.ts +0 -44
  134. package/src/tui/App.tsx +0 -240
  135. package/src/tui/client.ts +0 -163
  136. package/src/tui/components/BindingsModal.tsx +0 -82
  137. package/src/tui/components/DashboardHeader.tsx +0 -256
  138. package/src/tui/components/KeyBar.tsx +0 -67
  139. package/src/tui/components/SessionDetailModal.tsx +0 -169
  140. package/src/tui/components/SessionsView.tsx +0 -184
  141. package/src/tui/components/TabBar.tsx +0 -40
  142. package/src/tui/components/UsageSummaryPane.tsx +0 -272
  143. package/src/tui/components/UsageView.tsx +0 -242
  144. package/src/tui/components/tool-icons.ts +0 -24
  145. package/src/tui/index.tsx +0 -106
  146. package/src/tui/keybindings.ts +0 -49
  147. package/src/tui/model.ts +0 -295
  148. package/src/tui/state.ts +0 -77
  149. package/src/tui/theme.ts +0 -110
  150. package/src/types.ts +0 -113
  151. package/src/usage/README.md +0 -323
  152. package/src/usage/api.ts +0 -99
  153. package/src/usage/client.ts +0 -3
  154. package/src/usage/clients/anthropic-oauth-usage.ts +0 -258
  155. package/src/usage/clients/anthropic-web-usage.ts +0 -329
  156. package/src/usage/clients/claude-cli-probe.ts +0 -513
  157. package/src/usage/clients/codex-app-server.ts +0 -354
  158. package/src/usage/clients/codex-oauth-usage.ts +0 -240
  159. package/src/usage/clients/opencode-go-api.ts +0 -100
  160. package/src/usage/clients/opencode-go-usage.ts +0 -577
  161. package/src/usage/errors.ts +0 -33
  162. package/src/usage/index.ts +0 -20
  163. package/src/usage/local/opencode-go-local.ts +0 -194
  164. package/src/usage/mappers.ts +0 -282
  165. package/src/usage/planner.ts +0 -118
  166. package/src/usage/providers/claude.ts +0 -233
  167. package/src/usage/providers/codex.ts +0 -115
  168. package/src/usage/providers/opencode-go.ts +0 -115
  169. package/src/usage/resolver.ts +0 -4
  170. package/src/usage/resolvers/browser-cookies.ts +0 -808
  171. package/src/usage/resolvers/claude-auth.ts +0 -208
  172. package/src/usage/resolvers/claude-cli.ts +0 -24
  173. package/src/usage/resolvers/claude-desktop-auth.ts +0 -170
  174. package/src/usage/resolvers/claude-web.ts +0 -82
  175. package/src/usage/resolvers/codex-auth.ts +0 -174
  176. package/src/usage/resolvers/keychain-coordinator.ts +0 -397
  177. package/src/usage/resolvers/opencode-go-web.ts +0 -55
  178. package/src/usage/types.ts +0 -225
  179. package/src/usage/web-session-cache.ts +0 -37
  180. /package/{src/tui → dist/cli}/assets/providers/SOURCES.md +0 -0
  181. /package/{src/tui → dist/cli}/assets/providers/claude-terminal.png +0 -0
  182. /package/{src/tui → dist/cli}/assets/providers/claude-terminal.svg +0 -0
  183. /package/{src/tui → dist/cli}/assets/providers/claude.png +0 -0
  184. /package/{src/tui → dist/cli}/assets/providers/copilot.png +0 -0
  185. /package/{src/tui → dist/cli}/assets/providers/copilot.svg +0 -0
  186. /package/{src/tui → dist/cli}/assets/providers/openai-terminal.png +0 -0
  187. /package/{src/tui → dist/cli}/assets/providers/openai-terminal.svg +0 -0
  188. /package/{src/tui → dist/cli}/assets/providers/openai.png +0 -0
  189. /package/{src/tui → dist/cli}/assets/providers/opencode-terminal.png +0 -0
  190. /package/{src/tui → dist/cli}/assets/providers/opencode-terminal.svg +0 -0
  191. /package/{src/tui → dist/cli}/assets/providers/opencode.png +0 -0
  192. /package/{src/tui → dist/cli}/assets/providers/shell.png +0 -0
  193. /package/{src/tui → dist/cli}/assets/providers/shell.svg +0 -0
  194. /package/{src/tui → dist/cli}/assets/providers/unknown.png +0 -0
  195. /package/{src/tui → dist/cli}/assets/providers/unknown.svg +0 -0
package/src/cli/index.ts DELETED
@@ -1,18 +0,0 @@
1
- #!/usr/bin/env bun
2
- import { CommanderError } from "commander";
3
- import { createProgram } from "./program";
4
-
5
- export async function main(argv = process.argv): Promise<void> {
6
- await createProgram().parseAsync(argv);
7
- }
8
-
9
- if (import.meta.main) {
10
- main().catch((error) => {
11
- if (error instanceof CommanderError) {
12
- process.exitCode = error.exitCode;
13
- return;
14
- }
15
- process.stderr.write(`scrylog: fatal: ${error instanceof Error ? error.message : String(error)}\n`);
16
- process.exitCode = 1;
17
- });
18
- }
@@ -1,175 +0,0 @@
1
- import { Command } from "commander";
2
- import { getInstalledVersion } from "../shared/version";
3
- import {
4
- runClaudeHooksInstall,
5
- runCodexHooksInstall,
6
- runConfigCommand,
7
- runDaemonCommand,
8
- runDoctor,
9
- runLogsCommand,
10
- runOpenCodeHooksInstall,
11
- runSetupWizard,
12
- runTokenCommand,
13
- } from "./commands";
14
- import type { GlobalCliOptions } from "./commands";
15
-
16
- export interface CliIO {
17
- writeOut(message: string): void;
18
- writeErr(message: string): void;
19
- }
20
-
21
- export type TuiLauncher = (configPath?: string, includeUnknown?: boolean) => void | Promise<void>;
22
-
23
- interface CliHandlers {
24
- setup(options: GlobalCliOptions): void | Promise<void>;
25
- doctor(options: GlobalCliOptions): void | Promise<void>;
26
- daemon(action: string, options: GlobalCliOptions): void | Promise<void>;
27
- config(action: string, options: GlobalCliOptions): void | Promise<void>;
28
- token(target: "mcp" | "api" | "both", action: string, options: GlobalCliOptions): void | Promise<void>;
29
- logs(options: GlobalCliOptions): void | Promise<void>;
30
- claudeHooksInstall(options: GlobalCliOptions): void | Promise<void>;
31
- codexHooksInstall(options: GlobalCliOptions): void | Promise<void>;
32
- openCodeHooksInstall(options: GlobalCliOptions): void | Promise<void>;
33
- }
34
-
35
- export interface CreateProgramOptions {
36
- io?: CliIO;
37
- launchTui?: TuiLauncher;
38
- handlers?: Partial<CliHandlers>;
39
- }
40
-
41
- interface ProgramOptions {
42
- config?: string;
43
- includeUnknown?: boolean;
44
- }
45
-
46
- const HELP_TEXT = `scrylog
47
-
48
- Usage:
49
- scrylog [--config <path>] [--include-unknown]
50
- scrylog setup [--config <path>]
51
- scrylog doctor [--config <path>]
52
- scrylog daemon <install|uninstall|start|stop|restart|status> [--config <path>]
53
- scrylog config <show|path> [--config <path>]
54
- scrylog token <mcp|api|both> <generate|rotate|clear> [--config <path>]
55
- scrylog claude hooks install [--config <path>]
56
- scrylog codex hooks install [--config <path>]
57
- scrylog opencode hooks install [--config <path>]
58
- scrylog logs [--config <path>]
59
-
60
- Options:
61
- --config <path> Load config from an explicit path
62
- --include-unknown Include sessions whose tool is unidentified
63
- -h, --help Show this help text
64
- -V, --version Show the installed scrylog version
65
-
66
- See also:
67
- scrylogd Background daemon (collects sessions and serves API/MCP)
68
- scrylog-mcp stdio MCP server that proxies daemon data to AI agents
69
- scrylog-claude-hook Claude Code lifecycle hook binary
70
- scrylog-codex-hook Codex CLI lifecycle hook binary
71
-
72
- Notes:
73
- Running scrylog with no subcommand launches the TUI dashboard.
74
- 'scrylog claude hooks install' configures Claude Code to emit lifecycle
75
- hooks that scrylog uses for real-time session state tracking.
76
- 'scrylog codex hooks install' configures Codex CLI to emit lifecycle
77
- hooks that scrylog uses for real-time session state tracking.
78
- 'scrylog opencode hooks install' registers the scrylog plugin in
79
- OpenCode configuration for real-time session state tracking.
80
- `;
81
-
82
- export const TOKEN_USAGE = "Usage: scrylog token <mcp|api|both> <generate|rotate|clear>";
83
-
84
- export function parseTokenArgs(args: Array<string | undefined>): { target: "mcp" | "api" | "both"; action: string } {
85
- const [target, action] = args;
86
- if (!target) throw new Error(`Missing token target (mcp, api, or both). ${TOKEN_USAGE}`);
87
- if (!action) throw new Error(`Missing token action (generate, rotate, or clear). ${TOKEN_USAGE}`);
88
- if (target !== "mcp" && target !== "api" && target !== "both") {
89
- throw new Error(`Invalid token target: ${target}. Must be mcp, api, or both. ${TOKEN_USAGE}`);
90
- }
91
- return { target, action };
92
- }
93
-
94
- function defaultIO(): CliIO {
95
- return {
96
- writeOut: (message) => process.stdout.write(message),
97
- writeErr: (message) => process.stderr.write(message),
98
- };
99
- }
100
-
101
- async function defaultLaunchTui(configPath?: string, includeUnknown = false): Promise<void> {
102
- const tui = await import("../tui/index") as { launchTui: TuiLauncher };
103
- await tui.launchTui(configPath, includeUnknown);
104
- }
105
-
106
- function globalOptions(command: Command): GlobalCliOptions {
107
- const options = command.optsWithGlobals<ProgramOptions>();
108
- return { configPath: options.config };
109
- }
110
-
111
- export function createProgram(options: CreateProgramOptions = {}): Command {
112
- const io = options.io ?? defaultIO();
113
- const launchTui = options.launchTui ?? defaultLaunchTui;
114
- const handlers: CliHandlers = {
115
- setup: runSetupWizard,
116
- doctor: runDoctor,
117
- daemon: runDaemonCommand,
118
- config: runConfigCommand,
119
- token: runTokenCommand,
120
- logs: runLogsCommand,
121
- claudeHooksInstall: runClaudeHooksInstall,
122
- codexHooksInstall: runCodexHooksInstall,
123
- openCodeHooksInstall: runOpenCodeHooksInstall,
124
- ...options.handlers,
125
- };
126
-
127
- const program = new Command();
128
- program
129
- .name("scrylog")
130
- .option("--config <path>", "Load config from an explicit path")
131
- .option("--include-unknown", "Include sessions whose tool is unidentified")
132
- .version(`scrylog ${getInstalledVersion()}`, "-V, --version", "Show the installed scrylog version")
133
- .helpOption("-h, --help", "Show this help text")
134
- .configureOutput({ writeOut: io.writeOut, writeErr: io.writeErr })
135
- .configureHelp({ formatHelp: () => HELP_TEXT })
136
- .showHelpAfterError("(see --help for usage)")
137
- .exitOverride()
138
- .argument("[command]")
139
- .action(async (unknownCommand?: string) => {
140
- if (unknownCommand) {
141
- program.error(`error: unknown command '${unknownCommand}'`, { code: "commander.unknownCommand" });
142
- }
143
- const rootOptions = program.opts<ProgramOptions>();
144
- await launchTui(rootOptions.config ?? process.env.SCRYLOG_CONFIG, rootOptions.includeUnknown ?? false);
145
- });
146
-
147
- const setup = program.command("setup").action(() => handlers.setup(globalOptions(setup)));
148
- const doctor = program.command("doctor").action(() => handlers.doctor(globalOptions(doctor)));
149
- const daemon = program
150
- .command("daemon")
151
- .argument("<action>", "install, uninstall, start, stop, restart, or status")
152
- .action((action: string) => handlers.daemon(action, globalOptions(daemon)));
153
- const config = program
154
- .command("config")
155
- .argument("<action>", "show or path")
156
- .action((action: string) => handlers.config(action, globalOptions(config)));
157
- const token = program
158
- .command("token")
159
- .argument("[target]", "mcp, api, or both")
160
- .argument("[action]", "generate, rotate, or clear")
161
- .action((target: string | undefined, action: string | undefined) => {
162
- const parsed = parseTokenArgs([target, action]);
163
- return handlers.token(parsed.target, parsed.action, globalOptions(token));
164
- });
165
- const logs = program.command("logs").action(() => handlers.logs(globalOptions(logs)));
166
-
167
- const claudeInstall = program.command("claude").command("hooks").command("install");
168
- claudeInstall.action(() => handlers.claudeHooksInstall(globalOptions(claudeInstall)));
169
- const codexInstall = program.command("codex").command("hooks").command("install");
170
- codexInstall.action(() => handlers.codexHooksInstall(globalOptions(codexInstall)));
171
- const openCodeInstall = program.command("opencode").command("hooks").command("install");
172
- openCodeInstall.action(() => handlers.openCodeHooksInstall(globalOptions(openCodeInstall)));
173
-
174
- return program;
175
- }
package/src/cli/prompt.ts DELETED
@@ -1,44 +0,0 @@
1
- import { createInterface } from "node:readline/promises";
2
- import { stdin as input, stdout as output } from "node:process";
3
-
4
- export interface PromptSession {
5
- text(message: string, defaultValue?: string): Promise<string>;
6
- yesNo(message: string, defaultValue?: boolean): Promise<boolean>;
7
- choose(message: string, options: string[], defaultIndex?: number): Promise<string>;
8
- close(): void;
9
- }
10
-
11
- export function createPromptSession(): PromptSession {
12
- const rl = createInterface({ input, output });
13
-
14
- return {
15
- async text(message: string, defaultValue?: string): Promise<string> {
16
- const suffix = defaultValue !== undefined ? ` [${defaultValue}]` : "";
17
- const answer = (await rl.question(`${message}${suffix}: `)).trim();
18
- return answer || defaultValue || "";
19
- },
20
- async yesNo(message: string, defaultValue = true): Promise<boolean> {
21
- const label = defaultValue ? "Y/n" : "y/N";
22
- const answer = (await rl.question(`${message} [${label}]: `)).trim().toLowerCase();
23
- if (!answer) return defaultValue;
24
- return answer === "y" || answer === "yes";
25
- },
26
- async choose(message: string, options: string[], defaultIndex = 0): Promise<string> {
27
- output.write(`${message}\n`);
28
- for (const [index, option] of options.entries()) {
29
- output.write(` ${index + 1}. ${option}\n`);
30
- }
31
- while (true) {
32
- const answer = (await rl.question(`Select [${defaultIndex + 1}]: `)).trim();
33
- const value = answer || String(defaultIndex + 1);
34
- const index = Number.parseInt(value, 10) - 1;
35
- if (!Number.isNaN(index) && index >= 0 && index < options.length) {
36
- return options[index]!;
37
- }
38
- }
39
- },
40
- close(): void {
41
- rl.close();
42
- },
43
- };
44
- }
package/src/daemon/cli.ts DELETED
@@ -1,27 +0,0 @@
1
- export interface DaemonCliOptions {
2
- help: boolean;
3
- configPath?: string;
4
- logLevel?: string;
5
- logFormat?: "pretty" | "json";
6
- logFileEnabled: boolean;
7
- }
8
-
9
- export function parseDaemonArgs(args: string[]): DaemonCliOptions {
10
- const configFlagIndex = args.indexOf("--config");
11
- const logLevelFlagIndex = args.indexOf("--log-level");
12
- const logFormatFlagIndex = args.indexOf("--log-format");
13
- const rawLogFormat = logFormatFlagIndex >= 0 ? args[logFormatFlagIndex + 1] : undefined;
14
- const logFormat = rawLogFormat === "pretty" || rawLogFormat === "json" ? rawLogFormat : undefined;
15
-
16
- if (logFormatFlagIndex >= 0 && rawLogFormat !== "pretty" && rawLogFormat !== "json") {
17
- throw new Error("--log-format must be 'pretty' or 'json'");
18
- }
19
-
20
- return {
21
- help: args.includes("--help") || args.includes("-h"),
22
- configPath: configFlagIndex >= 0 ? args[configFlagIndex + 1] : undefined,
23
- logLevel: logLevelFlagIndex >= 0 ? args[logLevelFlagIndex + 1] : undefined,
24
- logFormat,
25
- logFileEnabled: !args.includes("--no-log-file"),
26
- };
27
- }
@@ -1,108 +0,0 @@
1
- # Claude Collector
2
-
3
- Monitors Claude Code interactive sessions by reading JSONL transcript files and
4
- optional hook files emitted by the `scrylog-claude-hook` binary.
5
-
6
- ## Data Flow
7
-
8
- ```
9
- ~/.claude/projects/<slug>/<sessionId>.jsonl ~/.claude/hooks/<sessionId>.json
10
- │ │
11
- │ │
12
- ▼ ▼
13
- ┌──────────────┐ ┌──────────────┐
14
- │ discovery │ discoverTranscripts() │ hooks │ readHookData()
15
- │ │ │ │
16
- └──────┬───────┘ └──────┬───────┘
17
- │ │
18
- │ │
19
- ▼ │
20
- ┌──────────────┐ │
21
- │ jsonl │ parseJsonlFile() / parseJsonlHead() │
22
- └──────┬───────┘ │
23
- │ │
24
- ▼ │
25
- ┌──────────────┐ │
26
- │ transcript │ inferState() │
27
- │ │ extractSummary() │
28
- │ │ extractTitle() │
29
- │ │ isLocalCommandTranscript() │
30
- └──────┬───────┘ │
31
- │ │
32
- ▼ ▼
33
- ┌──────────────────────────────────────────────────────────────┐
34
- │ collector.ts │
35
- │ │
36
- │ ┌──────────────┐ ┌──────────────┐ ┌──────────┐ │
37
- │ │ 30s poll │ │ watchFile │ │ fs.watch │ │
38
- │ │ run() │ │ (2s interval)│ │ hooksDir │ │
39
- │ └──────┬───────┘ └──────┬───────┘ └────┬─────┘ │
40
- │ │ │ │ │
41
- │ │ │ │ │
42
- │ └────────────┬────────┴────────────────────┘ │
43
- │ │ │
44
- │ ▼ │
45
- │ processTranscript() │
46
- │ │ │
47
- │ │ ┌───────────────────────────────┐ │
48
- │ └──│ mergeHookIntoModel() │ │
49
- │ │ (if hook newer than transcript)│ │
50
- │ └───────────────────────────────┘ │
51
- │ │ │
52
- │ ▼ │
53
- │ store.upsertSession() │
54
- │ store.syncChildSessionIds() │
55
- └──────────────────────────────────────────────────────────────┘
56
- │
57
- ▼
58
- DaemonStore ──► /api/events SSE ──► TUI
59
- ```
60
-
61
- ## Modules
62
-
63
- | File | Responsibility | Key Exports |
64
- |------|-------------|-------------|
65
- | `discovery.ts` | Scan `~/.claude/projects/<slug>/` for `.jsonl` files; decode slug back to absolute path | `discoverTranscripts()`, `decodeClaudeProjectSlug()`, `getClaudeDir()`, `getClaudeProcessPids()` |
66
- | `jsonl.ts` | Read JSONL tail/head with byte-size limits; parse lines into typed entries | `parseJsonlFile()`, `parseJsonlHead()`, `readTextTail()`, `readTextHead()`, `JsonlEntry`, `ContentBlock` |
67
- | `transcript.ts` | Infer session state from the last meaningful turn; extract summary/title; detect headless `claude -p` transcripts | `inferState()`, `extractSummary()`, `extractTitle()`, `isLocalCommandTranscript()`, `isQuestionText()` |
68
- | `hooks.ts` | Read/validate hook JSON files; merge hook data into a session model; merge claude metadata without overwriting existing fields | `readHookData()`, `mergeHookIntoModel()`, `mergeClaudeMeta()`, `isHookNewer()`, `getHookTime()`, `isValidHookData()`, `hasClaudePermissionPrompt()`, `ClaudeHookFileData` |
69
- | `collector.ts` | Orchestrate discovery, transcript watching, hook watching, deduplication, and store writes | `ClaudeCollector` (implements `Collector`) |
70
- | `index.ts` | Public re-exports | `ClaudeCollector`, test-accessible pure functions |
71
-
72
- ## State Inference Rules (`transcript.ts`)
73
-
74
- `inferState()` walks the JSONL entries in reverse order looking for the last
75
- **meaningful** turn, skipping:
76
- 1. Synthetic user entries (tool results, "[Request interrupted by user]")
77
- 2. Thinking-only assistant entries
78
- 3. System/tool events without a role
79
-
80
- | Last meaningful turn | State | Reason |
81
- |----------------------|-------|--------|
82
- | `assistant` with question text | `waiting-input` | Claude is asking the user something |
83
- | `assistant` with visible text, no tool_use | `idle` | Claude has replied |
84
- | `assistant` with tool_use, no visible text | `working` | Claude is executing a tool |
85
- | `user` (non-synthetic) | `working` | Waiting for Claude's reply |
86
- | Empty / only synthetic entries | `idle` | Nothing meaningful happened |
87
-
88
- ## Hook Merge Priority
89
-
90
- When both transcript and hook data exist, the collector uses this priority:
91
-
92
- 1. **Hook newer** (`hookSeq` or `hookEventTime` >= existing): hook data wins for `state`, `hasAttention`, `summary`, `activeTool`
93
- 2. **Hook older**: transcript data wins (except `claude` metadata merged via `mergeClaudeMeta`)
94
- 3. **Hook-managed session** (`detectionSource === "claude-hook"`): transcript can only fill missing metadata (e.g. `transcriptPath`), never override state
95
-
96
- ## Interactions
97
-
98
- | Component | How |
99
- |-----------|-----|
100
- | `GitCollector` | Resolves `currentPath` → `project` when hooks/transcript provide a directory |
101
- | `DaemonStore` | Upserts sessions; clears old bindings via `syncChildSessionIds()` |
102
- | `Scheduler` | Calls `start()` → sets up `30s` discovery interval + `5s` fallback re-read |
103
- | `TUI` | Receives updates via SSE from the store |
104
-
105
- ## Detection Sources Produced
106
-
107
- - `"claude-transcript"` — session discovered from `.jsonl` file, state inferred from transcript content
108
- - `"claude-hook"` — session discovered/enriched from hook JSON, state is authoritative from Claude Code directly