@peekdev/cli 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/NOTICE +8 -0
  2. package/dist/commands/audit.d.ts +3 -0
  3. package/dist/commands/audit.d.ts.map +1 -0
  4. package/dist/commands/audit.js +96 -0
  5. package/dist/commands/audit.js.map +1 -0
  6. package/dist/commands/init.d.ts +3 -0
  7. package/dist/commands/init.d.ts.map +1 -0
  8. package/dist/commands/init.js +180 -0
  9. package/dist/commands/init.js.map +1 -0
  10. package/dist/commands/sessions.d.ts +3 -0
  11. package/dist/commands/sessions.d.ts.map +1 -0
  12. package/dist/commands/sessions.js +214 -0
  13. package/dist/commands/sessions.js.map +1 -0
  14. package/dist/commands/status.d.ts +2 -0
  15. package/dist/commands/status.d.ts.map +1 -0
  16. package/dist/commands/status.js +88 -0
  17. package/dist/commands/status.js.map +1 -0
  18. package/dist/index.d.ts +3 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +78 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/lib/audit.d.ts +47 -0
  23. package/dist/lib/audit.d.ts.map +1 -0
  24. package/dist/lib/audit.js +68 -0
  25. package/dist/lib/audit.js.map +1 -0
  26. package/dist/lib/db.d.ts +86 -0
  27. package/dist/lib/db.d.ts.map +1 -0
  28. package/dist/lib/db.js +117 -0
  29. package/dist/lib/db.js.map +1 -0
  30. package/dist/lib/duration.d.ts +14 -0
  31. package/dist/lib/duration.d.ts.map +1 -0
  32. package/dist/lib/duration.js +41 -0
  33. package/dist/lib/duration.js.map +1 -0
  34. package/dist/lib/format/index.d.ts +16 -0
  35. package/dist/lib/format/index.d.ts.map +1 -0
  36. package/dist/lib/format/index.js +43 -0
  37. package/dist/lib/format/index.js.map +1 -0
  38. package/dist/lib/format/json.d.ts +35 -0
  39. package/dist/lib/format/json.d.ts.map +1 -0
  40. package/dist/lib/format/json.js +41 -0
  41. package/dist/lib/format/json.js.map +1 -0
  42. package/dist/lib/format/markdown.d.ts +4 -0
  43. package/dist/lib/format/markdown.d.ts.map +1 -0
  44. package/dist/lib/format/markdown.js +76 -0
  45. package/dist/lib/format/markdown.js.map +1 -0
  46. package/dist/lib/fs-atomic.d.ts +10 -0
  47. package/dist/lib/fs-atomic.d.ts.map +1 -0
  48. package/dist/lib/fs-atomic.js +32 -0
  49. package/dist/lib/fs-atomic.js.map +1 -0
  50. package/dist/lib/init-config.d.ts +81 -0
  51. package/dist/lib/init-config.d.ts.map +1 -0
  52. package/dist/lib/init-config.js +152 -0
  53. package/dist/lib/init-config.js.map +1 -0
  54. package/dist/lib/output.d.ts +5 -0
  55. package/dist/lib/output.d.ts.map +1 -0
  56. package/dist/lib/output.js +23 -0
  57. package/dist/lib/output.js.map +1 -0
  58. package/dist/lib/peek-home.d.ts +5 -0
  59. package/dist/lib/peek-home.d.ts.map +1 -0
  60. package/dist/lib/peek-home.js +11 -0
  61. package/dist/lib/peek-home.js.map +1 -0
  62. package/dist/lib/prompt.d.ts +25 -0
  63. package/dist/lib/prompt.d.ts.map +1 -0
  64. package/dist/lib/prompt.js +62 -0
  65. package/dist/lib/prompt.js.map +1 -0
  66. package/dist/lib/status.d.ts +54 -0
  67. package/dist/lib/status.d.ts.map +1 -0
  68. package/dist/lib/status.js +62 -0
  69. package/dist/lib/status.js.map +1 -0
  70. package/dist/version.d.ts +2 -0
  71. package/dist/version.d.ts.map +1 -0
  72. package/dist/version.js +6 -0
  73. package/dist/version.js.map +1 -0
  74. package/package.json +42 -0
package/NOTICE ADDED
@@ -0,0 +1,8 @@
1
+ @peekdev/cli
2
+ Copyright 2026 Cubenest
3
+
4
+ This product includes software developed by:
5
+ - WiseLibs — better-sqlite3 (MIT License)
6
+
7
+ This product is licensed under the Apache License, Version 2.0.
8
+ See the LICENSE file for details.
@@ -0,0 +1,3 @@
1
+ /** Entry for `peek audit ...`; `argv` excludes the `audit` token. */
2
+ export declare function runAudit(argv: string[]): number;
3
+ //# sourceMappingURL=audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/commands/audit.ts"],"names":[],"mappings":"AA8CA,qEAAqE;AACrE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CA6D/C"}
@@ -0,0 +1,96 @@
1
+ // `peek audit log [--since <dur>] [--tool <name>] [--client <name>]` command
2
+ // shell (Task 3.10, ADR-0010 / P2 PRD §H3). Reads ~/.peek/audit.log (JSONL),
3
+ // runs the pure parse + filter, and prints. The native host / extension write
4
+ // the log; the CLI only reads it.
5
+ import { readFileSync } from 'node:fs';
6
+ import { parseArgs } from 'node:util';
7
+ import { filterAuditEntries, parseAuditLog, } from '../lib/audit.js';
8
+ import { cutoffBefore } from '../lib/duration.js';
9
+ import { auditLogPath } from '../lib/peek-home.js';
10
+ function printUsage() {
11
+ process.stdout.write([
12
+ 'Usage: peek audit log [options]',
13
+ '',
14
+ 'Options:',
15
+ ' --since <dur> Only entries newer than e.g. 1h, 30m, 7d',
16
+ ' --tool <name> Filter by tool (e.g. execute_action)',
17
+ ' --client <name> Filter by MCP client (e.g. cursor, claude-code)',
18
+ ' --json Emit matching entries as JSON instead of a table',
19
+ '',
20
+ ].join('\n'));
21
+ }
22
+ function renderEntry(e) {
23
+ const parts = [
24
+ e.ts,
25
+ e.tool ?? '(no tool)',
26
+ e.client ? `client=${e.client}` : '',
27
+ e.result ? `result=${e.result}` : '',
28
+ e.sessionId ? `session=${e.sessionId}` : '',
29
+ ].filter(Boolean);
30
+ let line = parts.join(' ');
31
+ if (e.args !== undefined) {
32
+ line += ` args=${JSON.stringify(e.args)}`;
33
+ }
34
+ return line;
35
+ }
36
+ /** Entry for `peek audit ...`; `argv` excludes the `audit` token. */
37
+ export function runAudit(argv) {
38
+ const sub = argv[0];
39
+ if (sub !== 'log') {
40
+ if (sub === undefined || sub === 'help' || sub === '--help' || sub === '-h') {
41
+ printUsage();
42
+ return sub === undefined ? 1 : 0;
43
+ }
44
+ process.stderr.write(`peek audit: unknown subcommand '${sub}' (did you mean 'log'?)\n`);
45
+ return 1;
46
+ }
47
+ const { values } = parseArgs({
48
+ args: argv.slice(1),
49
+ options: {
50
+ since: { type: 'string' },
51
+ tool: { type: 'string' },
52
+ client: { type: 'string' },
53
+ json: { type: 'boolean' },
54
+ },
55
+ allowPositionals: false,
56
+ });
57
+ const filter = {
58
+ ...(values.tool !== undefined ? { tool: values.tool } : {}),
59
+ ...(values.client !== undefined ? { client: values.client } : {}),
60
+ };
61
+ if (values.since !== undefined) {
62
+ try {
63
+ filter.sinceMs = cutoffBefore(values.since);
64
+ }
65
+ catch (err) {
66
+ process.stderr.write(`peek audit log: ${err instanceof Error ? err.message : String(err)}\n`);
67
+ return 1;
68
+ }
69
+ }
70
+ const path = auditLogPath();
71
+ let contents;
72
+ try {
73
+ contents = readFileSync(path, 'utf8');
74
+ }
75
+ catch {
76
+ process.stdout.write(`No audit log yet (${path}).\n`);
77
+ return 0;
78
+ }
79
+ const { entries, errors } = parseAuditLog(contents);
80
+ const matched = filterAuditEntries(entries, filter);
81
+ if (values.json) {
82
+ process.stdout.write(`${JSON.stringify(matched, null, 2)}\n`);
83
+ }
84
+ else if (matched.length === 0) {
85
+ process.stdout.write('No matching audit entries.\n');
86
+ }
87
+ else {
88
+ for (const e of matched)
89
+ process.stdout.write(`${renderEntry(e)}\n`);
90
+ }
91
+ if (errors.length > 0) {
92
+ process.stderr.write(`\npeek audit log: skipped ${errors.length} malformed line(s) (first at line ${errors[0]?.line}).\n`);
93
+ }
94
+ return 0;
95
+ }
96
+ //# sourceMappingURL=audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/commands/audit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** Entry for `peek init`; `argv` excludes the `init` token. */
2
+ export declare function runInit(argv: string[]): Promise<number>;
3
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAsMA,+DAA+D;AAC/D,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAgC7D"}
@@ -0,0 +1,180 @@
1
+ // `peek init` interactive wizard (Task 3.9, P2 PRD §K.5). This is the
2
+ // SIDE-EFFECTFUL shell: it detects MCP-capable clients (pure: init-config.ts),
3
+ // prompts which to configure, writes the merged `mcpServers.peek` block into
4
+ // each (merge is pure + tested), and then offers to register the native
5
+ // messaging host — the consent step the Phase 3a postinstall deliberately
6
+ // defers to (it dry-runs unless PEEK_INSTALL_NATIVE_HOST is set; here the user
7
+ // affirmatively opts in, so we call the installer directly with realSink).
8
+ import { existsSync, readFileSync } from 'node:fs';
9
+ import { homedir } from 'node:os';
10
+ import { parseArgs } from 'node:util';
11
+ import { buildManifest, hostBinaryPath, installManifests, loadExtensionIds, realSink, resolveInstallTargets, } from '@peekdev/mcp/native-host';
12
+ import { atomicWriteFileSync } from '../lib/fs-atomic.js';
13
+ import { PEEK_BLOCK_SNIPPET, containsJsonComments, detectClients, hasPeekServer, mergePeekConfig, serializeConfig, } from '../lib/init-config.js';
14
+ import { confirm, multiSelect } from '../lib/prompt.js';
15
+ const SUPPORTED = ['darwin', 'linux', 'win32'];
16
+ /** Thrown by `readConfig` when the file is JSONC (comments) — we won't rewrite it. */
17
+ class JsoncConfigError extends Error {
18
+ constructor() {
19
+ super('config contains comments (JSONC)');
20
+ this.name = 'JsoncConfigError';
21
+ }
22
+ }
23
+ /**
24
+ * Read + parse a client config file, or undefined if absent/empty. Throws
25
+ * `JsoncConfigError` if the file is JSONC (comments) so the caller can route to
26
+ * the "add the block manually" path rather than corrupt it; throws on other
27
+ * invalid JSON.
28
+ */
29
+ function readConfig(path) {
30
+ if (!existsSync(path))
31
+ return undefined;
32
+ const raw = readFileSync(path, 'utf8').trim();
33
+ if (raw.length === 0)
34
+ return undefined;
35
+ if (containsJsonComments(raw))
36
+ throw new JsoncConfigError();
37
+ return JSON.parse(raw);
38
+ }
39
+ /** Merge the peek block into a client's config and write it atomically. */
40
+ function writeClientConfig(client) {
41
+ let existing;
42
+ try {
43
+ existing = readConfig(client.configPath);
44
+ }
45
+ catch (err) {
46
+ if (err instanceof JsoncConfigError)
47
+ return { ok: false, jsonc: true };
48
+ return { ok: false, jsonc: false, error: err instanceof Error ? err.message : String(err) };
49
+ }
50
+ try {
51
+ atomicWriteFileSync(client.configPath, serializeConfig(mergePeekConfig(existing)));
52
+ return { ok: true };
53
+ }
54
+ catch (err) {
55
+ return { ok: false, jsonc: false, error: err instanceof Error ? err.message : String(err) };
56
+ }
57
+ }
58
+ async function configureClients(homeDir, cwd) {
59
+ const detected = detectClients(homeDir, cwd, existsSync);
60
+ const present = detected.filter((c) => c.exists);
61
+ process.stdout.write(present.length > 0
62
+ ? `Detected MCP-capable clients: ${present.map((c) => c.label).join(', ')}\n`
63
+ : 'No MCP client configs detected — you can still create them below.\n');
64
+ const chosen = await multiSelect('Which clients would you like to configure? (peek will be added to each)', detected.map((c) => ({
65
+ value: c,
66
+ label: c.label,
67
+ // Default-check clients whose config already exists and that aren't
68
+ // manual-only (matches the §K.5 transcript's pre-checked rows).
69
+ checked: c.exists && !c.manualOnly,
70
+ disabled: c.manualOnly,
71
+ hint: c.manualOnly ? 'manual config required' : c.configPath,
72
+ })));
73
+ if (chosen.length === 0) {
74
+ process.stdout.write('No clients selected; skipping MCP config.\n');
75
+ return;
76
+ }
77
+ for (const client of chosen) {
78
+ const already = (() => {
79
+ try {
80
+ return hasPeekServer(readConfig(client.configPath));
81
+ }
82
+ catch {
83
+ return false;
84
+ }
85
+ })();
86
+ const res = writeClientConfig(client);
87
+ if (res.ok) {
88
+ process.stdout.write(` ${already ? 'Updated' : 'Wrote'} ${client.label}: ${client.configPath}\n`);
89
+ }
90
+ else if (res.jsonc) {
91
+ // JSONC (comments): don't rewrite — JSON.stringify would strip the
92
+ // comments. Tell the user exactly what to add.
93
+ const snippet = PEEK_BLOCK_SNIPPET.split('\n')
94
+ .map((l) => ` ${l}`)
95
+ .join('\n');
96
+ process.stdout.write([
97
+ ` ! ${client.label}: ${client.configPath} contains comments (JSONC); not modified.`,
98
+ ' Add the peek server manually:',
99
+ `${snippet}\n`,
100
+ ].join('\n'));
101
+ }
102
+ else {
103
+ process.stdout.write(` ✗ ${client.label}: ${client.configPath} — ${res.error}\n`);
104
+ }
105
+ }
106
+ }
107
+ async function registerNativeHost(platform, homeDir) {
108
+ const proceed = await confirm('\nRegister the native messaging host now? (writes a manifest into your browser dirs, with your consent)', true);
109
+ if (!proceed) {
110
+ process.stdout.write('Skipped native-host registration. Re-run `peek init`, or set PEEK_INSTALL_NATIVE_HOST=1 and reinstall @peekdev/mcp.\n');
111
+ return;
112
+ }
113
+ let extensionIds;
114
+ try {
115
+ extensionIds = loadExtensionIds();
116
+ }
117
+ catch (err) {
118
+ process.stdout.write(`Could not load extension IDs (${err instanceof Error ? err.message : String(err)}); skipping native-host registration.\n`);
119
+ return;
120
+ }
121
+ const allTargets = resolveInstallTargets(platform, homeDir);
122
+ const chosen = await multiSelect('Register native messaging host for:', allTargets.map((t) => ({
123
+ value: t,
124
+ label: t.browser,
125
+ checked: true,
126
+ hint: t.manifestPath ?? t.registryKey,
127
+ })));
128
+ if (chosen.length === 0) {
129
+ process.stdout.write('No browsers selected; skipping native-host registration.\n');
130
+ return;
131
+ }
132
+ const manifest = buildManifest(hostBinaryPath(), extensionIds);
133
+ const results = installManifests([...chosen], manifest, { sink: realSink });
134
+ for (const r of results) {
135
+ const where = r.manifestPath ?? r.registryKey ?? '(unknown)';
136
+ if (r.error)
137
+ process.stdout.write(` ✗ ${r.browser}: ${where} — ${r.error}\n`);
138
+ else
139
+ process.stdout.write(` ✔ Wrote ${r.browser}: ${where}\n`);
140
+ }
141
+ }
142
+ function nextSteps() {
143
+ process.stdout.write([
144
+ '',
145
+ 'Next steps:',
146
+ ' 1. Install the peek Chrome extension (see the repo README for the store link).',
147
+ ' 2. Open Chrome → click the peek icon → enable recording on a site.',
148
+ ' 3. In your AI client: ask "what\'s in my last Peek session?"',
149
+ '',
150
+ ].join('\n'));
151
+ }
152
+ /** Entry for `peek init`; `argv` excludes the `init` token. */
153
+ export async function runInit(argv) {
154
+ const { values } = parseArgs({
155
+ args: argv,
156
+ options: {
157
+ 'skip-native-host': { type: 'boolean' },
158
+ 'skip-clients': { type: 'boolean' },
159
+ },
160
+ allowPositionals: false,
161
+ });
162
+ const platform = process.platform;
163
+ const homeDir = homedir();
164
+ const cwd = process.cwd();
165
+ process.stdout.write('peek init — configure MCP clients + the native messaging host.\n\n');
166
+ if (!values['skip-clients']) {
167
+ await configureClients(homeDir, cwd);
168
+ }
169
+ if (!values['skip-native-host']) {
170
+ if (SUPPORTED.includes(platform)) {
171
+ await registerNativeHost(platform, homeDir);
172
+ }
173
+ else {
174
+ process.stdout.write(`\nNative-host registration is not supported on '${platform}'; skipping.\n`);
175
+ }
176
+ }
177
+ nextSteps();
178
+ return 0;
179
+ }
180
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** Entry for `peek sessions ...`; `argv` excludes the `sessions` token. */
2
+ export declare function runSessions(argv: string[]): number;
3
+ //# sourceMappingURL=sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/commands/sessions.ts"],"names":[],"mappings":"AAyNA,2EAA2E;AAC3E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAuBlD"}
@@ -0,0 +1,214 @@
1
+ // `peek sessions <list|show|export|delete>` command shell (Task 3.8, P2 PRD
2
+ // §C.1). Opens the shared DB read-mostly via @peekdev/mcp's openDb, runs the
3
+ // pure query/format helpers, and prints / writes. Arg parsing uses the built-in
4
+ // node:util parseArgs (no dependency).
5
+ import { writeFileSync } from 'node:fs';
6
+ import { parseArgs } from 'node:util';
7
+ import { openDb } from '@peekdev/mcp/db';
8
+ import { deleteSession, deleteSessionsOlderThan, getSessionDetail, listSessions, } from '../lib/db.js';
9
+ import { cutoffBefore } from '../lib/duration.js';
10
+ import { EXPORT_FORMATS, formatSession, isExportFormat, } from '../lib/format/index.js';
11
+ import { formatBytes, pad } from '../lib/output.js';
12
+ import { defaultDbPath } from '../lib/peek-home.js';
13
+ /** Open the shared DB for reading (migrations applied so a fresh DB is valid). */
14
+ function open() {
15
+ return openDb({ path: defaultDbPath() });
16
+ }
17
+ function printUsage() {
18
+ process.stdout.write([
19
+ 'Usage: peek sessions <command>',
20
+ '',
21
+ 'Commands:',
22
+ ' list [--origin <url>] [--limit 20] List recent sessions (newest first)',
23
+ ' show <session-id> Show one session (metadata + errors)',
24
+ ` export <session-id> --format <${EXPORT_FORMATS.join('|')}> [--out <file>]`,
25
+ ' delete <session-id> Delete one session',
26
+ ' delete --all-older-than <dur> Delete sessions older than e.g. 7d',
27
+ '',
28
+ ].join('\n'));
29
+ }
30
+ function runList(argv) {
31
+ const { values } = parseArgs({
32
+ args: argv,
33
+ options: {
34
+ origin: { type: 'string' },
35
+ limit: { type: 'string' },
36
+ },
37
+ allowPositionals: false,
38
+ });
39
+ const limit = values.limit !== undefined ? Number(values.limit) : 20;
40
+ if (!Number.isInteger(limit) || limit <= 0) {
41
+ process.stderr.write('peek sessions list: --limit must be a positive integer\n');
42
+ return 1;
43
+ }
44
+ const db = open();
45
+ try {
46
+ const rows = listSessions(db, {
47
+ limit,
48
+ ...(values.origin !== undefined ? { origin: values.origin } : {}),
49
+ });
50
+ if (rows.length === 0) {
51
+ process.stdout.write('No sessions recorded yet.\n');
52
+ return 0;
53
+ }
54
+ process.stdout.write(`${pad('ID', 22)}${pad('UPDATED', 26)}${pad('EVENTS', 9)}${pad('SIZE', 11)}ORIGIN\n`);
55
+ for (const s of rows) {
56
+ process.stdout.write(`${pad(s.id, 22)}${pad(s.updatedAt, 26)}${pad(String(s.eventCount), 9)}${pad(formatBytes(s.bytes), 11)}${s.origin ?? '(unknown)'}\n`);
57
+ }
58
+ return 0;
59
+ }
60
+ finally {
61
+ db.close();
62
+ }
63
+ }
64
+ function runShow(argv) {
65
+ const { positionals } = parseArgs({ args: argv, allowPositionals: true, options: {} });
66
+ const id = positionals[0];
67
+ if (!id) {
68
+ process.stderr.write('peek sessions show: missing <session-id>\n');
69
+ return 1;
70
+ }
71
+ const db = open();
72
+ try {
73
+ const detail = getSessionDetail(db, id);
74
+ if (!detail) {
75
+ process.stderr.write(`peek sessions show: no session with id '${id}'\n`);
76
+ return 1;
77
+ }
78
+ // `show` reuses the markdown formatter — it's the human + AI-readable view.
79
+ const result = formatSession(detail, 'markdown');
80
+ if (result.ok)
81
+ process.stdout.write(result.content);
82
+ return 0;
83
+ }
84
+ finally {
85
+ db.close();
86
+ }
87
+ }
88
+ function runExport(argv) {
89
+ const { values, positionals } = parseArgs({
90
+ args: argv,
91
+ options: {
92
+ format: { type: 'string' },
93
+ out: { type: 'string' },
94
+ },
95
+ allowPositionals: true,
96
+ });
97
+ const id = positionals[0];
98
+ if (!id) {
99
+ process.stderr.write('peek sessions export: missing <session-id>\n');
100
+ return 1;
101
+ }
102
+ const formatRaw = values.format ?? 'markdown';
103
+ if (!isExportFormat(formatRaw)) {
104
+ process.stderr.write(`peek sessions export: invalid --format '${formatRaw}' (expected ${EXPORT_FORMATS.join('|')})\n`);
105
+ return 1;
106
+ }
107
+ const format = formatRaw;
108
+ const db = open();
109
+ try {
110
+ const detail = getSessionDetail(db, id);
111
+ if (!detail) {
112
+ process.stderr.write(`peek sessions export: no session with id '${id}'\n`);
113
+ return 1;
114
+ }
115
+ const result = formatSession(detail, format);
116
+ if (!result.ok) {
117
+ // html / playwright stubs: clear message, non-zero exit (never write a
118
+ // partial file).
119
+ process.stderr.write(`peek sessions export: ${result.message}\n`);
120
+ return 2;
121
+ }
122
+ if (values.out !== undefined) {
123
+ writeFileSync(values.out, result.content, 'utf8');
124
+ process.stdout.write(`Wrote ${format} export to ${values.out}\n`);
125
+ }
126
+ else {
127
+ process.stdout.write(result.content);
128
+ }
129
+ return 0;
130
+ }
131
+ finally {
132
+ db.close();
133
+ }
134
+ }
135
+ function runDelete(argv) {
136
+ const { values, positionals } = parseArgs({
137
+ args: argv,
138
+ options: {
139
+ 'all-older-than': { type: 'string' },
140
+ },
141
+ allowPositionals: true,
142
+ });
143
+ const olderThan = values['all-older-than'];
144
+ const id = positionals[0];
145
+ if (olderThan !== undefined && id !== undefined) {
146
+ process.stderr.write('peek sessions delete: pass either <session-id> OR --all-older-than\n');
147
+ return 1;
148
+ }
149
+ const db = open();
150
+ try {
151
+ if (olderThan !== undefined) {
152
+ let cutoffIso;
153
+ try {
154
+ const cutoffMs = cutoffBefore(olderThan);
155
+ // parseDuration accepts any integer, so a huge duration (e.g. `17200000w`)
156
+ // yields a finite-but-out-of-range cutoff; `new Date(...).toISOString()`
157
+ // would throw RangeError. Guard before converting (the JS Date floor is
158
+ // -8.64e15 ms) so the failure is a clean message, not a stack trace.
159
+ if (!Number.isFinite(cutoffMs) || cutoffMs < -8_640_000_000_000_000) {
160
+ process.stderr.write(`peek sessions delete: duration '${olderThan}' is too large\n`);
161
+ return 1;
162
+ }
163
+ cutoffIso = new Date(cutoffMs).toISOString();
164
+ }
165
+ catch (err) {
166
+ process.stderr.write(`peek sessions delete: ${err instanceof Error ? err.message : String(err)}\n`);
167
+ return 1;
168
+ }
169
+ const removed = deleteSessionsOlderThan(db, cutoffIso);
170
+ process.stdout.write(`Deleted ${removed} session(s) older than ${olderThan}.\n`);
171
+ return 0;
172
+ }
173
+ if (id === undefined) {
174
+ process.stderr.write('peek sessions delete: missing <session-id> or --all-older-than\n');
175
+ return 1;
176
+ }
177
+ const removed = deleteSession(db, id);
178
+ if (removed === 0) {
179
+ process.stderr.write(`peek sessions delete: no session with id '${id}'\n`);
180
+ return 1;
181
+ }
182
+ process.stdout.write(`Deleted session ${id}.\n`);
183
+ return 0;
184
+ }
185
+ finally {
186
+ db.close();
187
+ }
188
+ }
189
+ /** Entry for `peek sessions ...`; `argv` excludes the `sessions` token. */
190
+ export function runSessions(argv) {
191
+ const sub = argv[0];
192
+ const rest = argv.slice(1);
193
+ switch (sub) {
194
+ case 'list':
195
+ return runList(rest);
196
+ case 'show':
197
+ return runShow(rest);
198
+ case 'export':
199
+ return runExport(rest);
200
+ case 'delete':
201
+ return runDelete(rest);
202
+ case undefined:
203
+ case 'help':
204
+ case '--help':
205
+ case '-h':
206
+ printUsage();
207
+ return sub === undefined ? 1 : 0;
208
+ default:
209
+ process.stderr.write(`peek sessions: unknown subcommand '${sub}'\n`);
210
+ printUsage();
211
+ return 1;
212
+ }
213
+ }
214
+ //# sourceMappingURL=sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/commands/sessions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function runStatus(): number;
2
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAkEA,wBAAgB,SAAS,IAAI,MAAM,CAoClC"}
@@ -0,0 +1,88 @@
1
+ // `peek status` command shell (Task 3.7). Wires the real filesystem/platform
2
+ // probes into the pure `gatherStatus`, then prints. Reports native-host
3
+ // manifest install state, DB path + size + schema version, and the (best-effort)
4
+ // extension connection state.
5
+ import { existsSync, statSync } from 'node:fs';
6
+ import { homedir } from 'node:os';
7
+ import { openDb } from '@peekdev/mcp/db';
8
+ import { loadExtensionIds, resolveInstallTargets, } from '@peekdev/mcp/native-host';
9
+ import { formatBytes } from '../lib/output.js';
10
+ import { defaultDbPath } from '../lib/peek-home.js';
11
+ import { gatherStatus } from '../lib/status.js';
12
+ const SUPPORTED = ['darwin', 'linux', 'win32'];
13
+ function fileSize(path) {
14
+ try {
15
+ return statSync(path).size;
16
+ }
17
+ catch {
18
+ return null;
19
+ }
20
+ }
21
+ function renderStatus(report) {
22
+ const lines = [];
23
+ lines.push('peek status');
24
+ lines.push('');
25
+ lines.push('Database (~/.peek/sessions.db):');
26
+ lines.push(` path: ${report.dbPath}`);
27
+ if (report.dbExists) {
28
+ lines.push(` size: ${formatBytes(report.dbBytes)}`);
29
+ lines.push(` schema: v${report.schemaVersion ?? '?'}`);
30
+ lines.push(` sessions: ${report.sessionCount ?? '?'}`);
31
+ }
32
+ else {
33
+ lines.push(' size: (not created yet — record a session to initialize)');
34
+ }
35
+ lines.push('');
36
+ lines.push('Native messaging host:');
37
+ lines.push(` binary: ${report.hostBinaryPath}`);
38
+ lines.push(report.anyManifestInstalled
39
+ ? ' status: registered'
40
+ : ' status: not registered (run `peek init` to register with consent)');
41
+ for (const t of report.manifestTargets) {
42
+ const mark = t.installed ? '✔' : '·';
43
+ lines.push(` ${mark} ${t.browser}: ${t.location}`);
44
+ }
45
+ lines.push('');
46
+ lines.push('Browser extension:');
47
+ const conn = report.extensionConnection === 'unknown'
48
+ ? 'unknown (connection check requires the extension; see https://github.com/Cubenest/rrweb-stack)'
49
+ : report.extensionConnection;
50
+ lines.push(` connection: ${conn}`);
51
+ return lines.join('\n');
52
+ }
53
+ export function runStatus() {
54
+ const platform = process.platform;
55
+ if (!SUPPORTED.includes(platform)) {
56
+ process.stdout.write(`peek status: unsupported platform '${platform}'.\n`);
57
+ return 0;
58
+ }
59
+ const home = homedir();
60
+ const dbPath = defaultDbPath();
61
+ let extensionIds;
62
+ try {
63
+ extensionIds = loadExtensionIds();
64
+ }
65
+ catch {
66
+ // The published extension-ids.json may be unreadable in a partial install;
67
+ // fall back to placeholders so status still renders the rest.
68
+ extensionIds = { chromeWebStore: '', edgeAddons: '', dev: '' };
69
+ }
70
+ const report = gatherStatus({
71
+ dbPath,
72
+ fileSize,
73
+ fileExists: existsSync,
74
+ manifestTargets: resolveInstallTargets(platform, home),
75
+ extensionIds,
76
+ openDb: () => {
77
+ try {
78
+ return openDb({ path: dbPath, skipMigrations: true });
79
+ }
80
+ catch {
81
+ return null;
82
+ }
83
+ },
84
+ });
85
+ process.stdout.write(`${renderStatus(report)}\n`);
86
+ return 0;
87
+ }
88
+ //# sourceMappingURL=status.js.map