@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.
- package/dist/assets/highlights-eq9cgrbb.scm +604 -0
- package/dist/assets/highlights-ghv9g403.scm +205 -0
- package/dist/assets/highlights-hk7bwhj4.scm +284 -0
- package/dist/assets/highlights-r812a2qc.scm +150 -0
- package/dist/assets/highlights-x6tmsnaa.scm +115 -0
- package/dist/assets/injections-73j83es3.scm +27 -0
- package/dist/assets/parser.worker-xyhf83rf.js +4563 -0
- package/dist/assets/tree-sitter-3jzf13jk.wasm +0 -0
- package/dist/assets/tree-sitter-javascript-nd0q4pe9.wasm +0 -0
- package/dist/assets/tree-sitter-markdown-411r6y9b.wasm +0 -0
- package/dist/assets/tree-sitter-markdown_inline-j5349f42.wasm +0 -0
- package/dist/assets/tree-sitter-typescript-zxjzwt75.wasm +0 -0
- package/dist/assets/tree-sitter-zig-e78zbjpm.wasm +0 -0
- package/dist/cli/index.js +499 -0
- package/dist/cli/index.js.map +61 -0
- package/dist/daemon/index.js +670 -0
- package/dist/daemon/index.js.map +1475 -0
- package/dist/hooks/claude.js +6 -0
- package/dist/hooks/claude.js.map +11 -0
- package/dist/hooks/codex.js +10 -0
- package/dist/hooks/codex.js.map +11 -0
- package/dist/mcp/index.js +100 -0
- package/dist/mcp/index.js.map +231 -0
- package/dist/oc/index.js +21 -0
- package/dist/oc/index.js.map +10 -0
- package/package.json +16 -13
- package/src/api/docs/sessions.keys.ts +0 -6
- package/src/api/docs/sessions.ts +0 -82
- package/src/api/docs/system.keys.ts +0 -5
- package/src/api/docs/system.ts +0 -69
- package/src/api/docs/usage.keys.ts +0 -3
- package/src/api/docs/usage.ts +0 -24
- package/src/api/docs/webhooks.keys.ts +0 -5
- package/src/api/docs/webhooks.ts +0 -78
- package/src/api/index.ts +0 -18
- package/src/api/lib/auth.ts +0 -43
- package/src/api/lib/errors.ts +0 -28
- package/src/api/lib/route.ts +0 -18
- package/src/api/models/claude.ts +0 -4
- package/src/api/models/codex.ts +0 -4
- package/src/api/models/opencode.ts +0 -11
- package/src/api/routes/sessions.ts +0 -51
- package/src/api/routes/system.ts +0 -106
- package/src/api/routes/usage.ts +0 -15
- package/src/api/routes/webhooks/claude.ts +0 -149
- package/src/api/routes/webhooks/codex.ts +0 -175
- package/src/api/routes/webhooks/opencode.ts +0 -112
- package/src/api/routes.ts +0 -93
- package/src/api/schemas/common.ts +0 -29
- package/src/api/schemas/sessions.ts +0 -86
- package/src/api/schemas/usage.ts +0 -51
- package/src/api/schemas/webhooks/claude.ts +0 -32
- package/src/api/schemas/webhooks/codex.ts +0 -34
- package/src/api/schemas/webhooks/opencode.ts +0 -29
- package/src/api/services/claude-session.ts +0 -9
- package/src/api/services/codex-session.ts +0 -8
- package/src/api/services/opencode-session.ts +0 -73
- package/src/classifier.ts +0 -206
- package/src/cli/commands.ts +0 -714
- package/src/cli/index.ts +0 -18
- package/src/cli/program.ts +0 -175
- package/src/cli/prompt.ts +0 -44
- package/src/daemon/cli.ts +0 -27
- package/src/daemon/collectors/claude/README.md +0 -108
- package/src/daemon/collectors/claude/collector.ts +0 -423
- package/src/daemon/collectors/claude/discovery.ts +0 -127
- package/src/daemon/collectors/claude/hooks.ts +0 -181
- package/src/daemon/collectors/claude/index.ts +0 -8
- package/src/daemon/collectors/claude/jsonl.ts +0 -85
- package/src/daemon/collectors/claude/transcript.ts +0 -246
- package/src/daemon/collectors/codex/README.md +0 -147
- package/src/daemon/collectors/codex/collector.ts +0 -661
- package/src/daemon/collectors/codex/discovery.ts +0 -104
- package/src/daemon/collectors/codex/hooks.ts +0 -179
- package/src/daemon/collectors/codex/index.ts +0 -7
- package/src/daemon/collectors/codex/jsonl.ts +0 -108
- package/src/daemon/collectors/codex/transcript.ts +0 -299
- package/src/daemon/collectors/git.ts +0 -353
- package/src/daemon/collectors/herdr/collector.ts +0 -128
- package/src/daemon/collectors/herdr/index.ts +0 -2
- package/src/daemon/collectors/herdr/normalization.ts +0 -111
- package/src/daemon/collectors/opencode/README.md +0 -106
- package/src/daemon/collectors/opencode/collector.ts +0 -545
- package/src/daemon/collectors/opencode/discovery.ts +0 -257
- package/src/daemon/collectors/opencode/index.ts +0 -5
- package/src/daemon/collectors/opencode/session-builder.ts +0 -59
- package/src/daemon/collectors/opencode-db.ts +0 -294
- package/src/daemon/collectors/process.ts +0 -201
- package/src/daemon/collectors/tmux/README.md +0 -128
- package/src/daemon/collectors/tmux/collector.ts +0 -492
- package/src/daemon/collectors/tmux/enrichment.ts +0 -242
- package/src/daemon/collectors/tmux/index.ts +0 -4
- package/src/daemon/collectors/tmux/parse.ts +0 -128
- package/src/daemon/collectors/usage.ts +0 -259
- package/src/daemon/index.ts +0 -209
- package/src/daemon/scheduler.ts +0 -86
- package/src/daemon/store.ts +0 -630
- package/src/detect.ts +0 -143
- package/src/hooks/claude.ts +0 -596
- package/src/hooks/codex.ts +0 -517
- package/src/legacy/classifier.ts +0 -215
- package/src/legacy/detect.ts +0 -143
- package/src/mcp/client-server.ts +0 -21
- package/src/mcp/http-handler.ts +0 -126
- package/src/mcp/index.ts +0 -61
- package/src/mcp/resources/config-current.ts +0 -19
- package/src/mcp/resources/index.ts +0 -11
- package/src/mcp/resources/sessions-active.ts +0 -19
- package/src/mcp/resources/sessions-all.ts +0 -19
- package/src/mcp/schemas/sessions.ts +0 -3
- package/src/mcp/server.ts +0 -17
- package/src/mcp/services/api-adapter.ts +0 -48
- package/src/mcp/services/data-source.ts +0 -22
- package/src/mcp/services/store-adapter.ts +0 -40
- package/src/mcp/tools/get-active-sessions.ts +0 -16
- package/src/mcp/tools/get-session-children.ts +0 -24
- package/src/mcp/tools/get-session-messages.ts +0 -24
- package/src/mcp/tools/get-session.ts +0 -23
- package/src/mcp/tools/index.ts +0 -15
- package/src/mcp/tools/list-sessions.ts +0 -16
- package/src/oc/index.ts +0 -302
- package/src/service/manager.ts +0 -284
- package/src/shared/config.ts +0 -511
- package/src/shared/ipc.ts +0 -80
- package/src/shared/logger.ts +0 -248
- package/src/shared/paths.ts +0 -73
- package/src/shared/platform.ts +0 -110
- package/src/shared/session-exclusions.ts +0 -5
- package/src/shared/session-view.ts +0 -302
- package/src/shared/terminal-capabilities.ts +0 -130
- package/src/shared/types.ts +0 -330
- package/src/shared/utils.ts +0 -339
- package/src/shared/version.ts +0 -44
- package/src/tui/App.tsx +0 -240
- package/src/tui/client.ts +0 -163
- package/src/tui/components/BindingsModal.tsx +0 -82
- package/src/tui/components/DashboardHeader.tsx +0 -256
- package/src/tui/components/KeyBar.tsx +0 -67
- package/src/tui/components/SessionDetailModal.tsx +0 -169
- package/src/tui/components/SessionsView.tsx +0 -184
- package/src/tui/components/TabBar.tsx +0 -40
- package/src/tui/components/UsageSummaryPane.tsx +0 -272
- package/src/tui/components/UsageView.tsx +0 -242
- package/src/tui/components/tool-icons.ts +0 -24
- package/src/tui/index.tsx +0 -106
- package/src/tui/keybindings.ts +0 -49
- package/src/tui/model.ts +0 -295
- package/src/tui/state.ts +0 -77
- package/src/tui/theme.ts +0 -110
- package/src/types.ts +0 -113
- package/src/usage/README.md +0 -323
- package/src/usage/api.ts +0 -99
- package/src/usage/client.ts +0 -3
- package/src/usage/clients/anthropic-oauth-usage.ts +0 -258
- package/src/usage/clients/anthropic-web-usage.ts +0 -329
- package/src/usage/clients/claude-cli-probe.ts +0 -513
- package/src/usage/clients/codex-app-server.ts +0 -354
- package/src/usage/clients/codex-oauth-usage.ts +0 -240
- package/src/usage/clients/opencode-go-api.ts +0 -100
- package/src/usage/clients/opencode-go-usage.ts +0 -577
- package/src/usage/errors.ts +0 -33
- package/src/usage/index.ts +0 -20
- package/src/usage/local/opencode-go-local.ts +0 -194
- package/src/usage/mappers.ts +0 -282
- package/src/usage/planner.ts +0 -118
- package/src/usage/providers/claude.ts +0 -233
- package/src/usage/providers/codex.ts +0 -115
- package/src/usage/providers/opencode-go.ts +0 -115
- package/src/usage/resolver.ts +0 -4
- package/src/usage/resolvers/browser-cookies.ts +0 -808
- package/src/usage/resolvers/claude-auth.ts +0 -208
- package/src/usage/resolvers/claude-cli.ts +0 -24
- package/src/usage/resolvers/claude-desktop-auth.ts +0 -170
- package/src/usage/resolvers/claude-web.ts +0 -82
- package/src/usage/resolvers/codex-auth.ts +0 -174
- package/src/usage/resolvers/keychain-coordinator.ts +0 -397
- package/src/usage/resolvers/opencode-go-web.ts +0 -55
- package/src/usage/types.ts +0 -225
- package/src/usage/web-session-cache.ts +0 -37
- /package/{src/tui → dist/cli}/assets/providers/SOURCES.md +0 -0
- /package/{src/tui → dist/cli}/assets/providers/claude-terminal.png +0 -0
- /package/{src/tui → dist/cli}/assets/providers/claude-terminal.svg +0 -0
- /package/{src/tui → dist/cli}/assets/providers/claude.png +0 -0
- /package/{src/tui → dist/cli}/assets/providers/copilot.png +0 -0
- /package/{src/tui → dist/cli}/assets/providers/copilot.svg +0 -0
- /package/{src/tui → dist/cli}/assets/providers/openai-terminal.png +0 -0
- /package/{src/tui → dist/cli}/assets/providers/openai-terminal.svg +0 -0
- /package/{src/tui → dist/cli}/assets/providers/openai.png +0 -0
- /package/{src/tui → dist/cli}/assets/providers/opencode-terminal.png +0 -0
- /package/{src/tui → dist/cli}/assets/providers/opencode-terminal.svg +0 -0
- /package/{src/tui → dist/cli}/assets/providers/opencode.png +0 -0
- /package/{src/tui → dist/cli}/assets/providers/shell.png +0 -0
- /package/{src/tui → dist/cli}/assets/providers/shell.svg +0 -0
- /package/{src/tui → dist/cli}/assets/providers/unknown.png +0 -0
- /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
|
-
}
|
package/src/cli/program.ts
DELETED
|
@@ -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
|