@tyroneross/bookmark 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/.claude-plugin/marketplace.json +15 -0
- package/.claude-plugin/plugin.json +13 -0
- package/CLAUDE.md +69 -0
- package/LICENSE +21 -0
- package/README.md +178 -0
- package/agents/snapshot-analyst.md +41 -0
- package/commands/activate.md +20 -0
- package/commands/list.md +15 -0
- package/commands/restore.md +30 -0
- package/commands/snapshot.md +26 -0
- package/commands/status.md +19 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +437 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +86 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/restore/index.d.ts +13 -0
- package/dist/restore/index.d.ts.map +1 -0
- package/dist/restore/index.js +94 -0
- package/dist/restore/index.js.map +1 -0
- package/dist/setup/auto-setup.d.ts +16 -0
- package/dist/setup/auto-setup.d.ts.map +1 -0
- package/dist/setup/auto-setup.js +192 -0
- package/dist/setup/auto-setup.js.map +1 -0
- package/dist/setup/configure-hooks.d.ts +10 -0
- package/dist/setup/configure-hooks.d.ts.map +1 -0
- package/dist/setup/configure-hooks.js +97 -0
- package/dist/setup/configure-hooks.js.map +1 -0
- package/dist/snapshot/capture.d.ts +21 -0
- package/dist/snapshot/capture.d.ts.map +1 -0
- package/dist/snapshot/capture.js +134 -0
- package/dist/snapshot/capture.js.map +1 -0
- package/dist/snapshot/compress.d.ts +8 -0
- package/dist/snapshot/compress.d.ts.map +1 -0
- package/dist/snapshot/compress.js +93 -0
- package/dist/snapshot/compress.js.map +1 -0
- package/dist/snapshot/storage.d.ts +13 -0
- package/dist/snapshot/storage.d.ts.map +1 -0
- package/dist/snapshot/storage.js +151 -0
- package/dist/snapshot/storage.js.map +1 -0
- package/dist/threshold/adaptive.d.ts +23 -0
- package/dist/threshold/adaptive.d.ts.map +1 -0
- package/dist/threshold/adaptive.js +29 -0
- package/dist/threshold/adaptive.js.map +1 -0
- package/dist/threshold/state.d.ts +8 -0
- package/dist/threshold/state.d.ts.map +1 -0
- package/dist/threshold/state.js +83 -0
- package/dist/threshold/state.js.map +1 -0
- package/dist/threshold/time-based.d.ts +13 -0
- package/dist/threshold/time-based.d.ts.map +1 -0
- package/dist/threshold/time-based.js +24 -0
- package/dist/threshold/time-based.js.map +1 -0
- package/dist/transcript/estimator.d.ts +20 -0
- package/dist/transcript/estimator.d.ts.map +1 -0
- package/dist/transcript/estimator.js +95 -0
- package/dist/transcript/estimator.js.map +1 -0
- package/dist/transcript/extractor.d.ts +7 -0
- package/dist/transcript/extractor.d.ts.map +1 -0
- package/dist/transcript/extractor.js +237 -0
- package/dist/transcript/extractor.js.map +1 -0
- package/dist/transcript/parser.d.ts +16 -0
- package/dist/transcript/parser.d.ts.map +1 -0
- package/dist/transcript/parser.js +120 -0
- package/dist/transcript/parser.js.map +1 -0
- package/dist/types.d.ts +156 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/hooks/hooks.json +54 -0
- package/package.json +77 -0
- package/scripts/install-plugin.sh +38 -0
- package/skills/context-continuity/SKILL.md +49 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { readLatestMd, loadLatestSnapshot, getSnapshotCount } from '../snapshot/storage.js';
|
|
3
|
+
import { loadState, saveState, resetForNewSession, incrementCompaction } from '../threshold/state.js';
|
|
4
|
+
import { loadConfig, getStoragePath } from '../config.js';
|
|
5
|
+
/**
|
|
6
|
+
* Generate restoration context for a SessionStart hook.
|
|
7
|
+
* Returns a HookOutput with systemMessage containing the LATEST.md content.
|
|
8
|
+
*/
|
|
9
|
+
export function restoreContext(options) {
|
|
10
|
+
const config = loadConfig(options.cwd);
|
|
11
|
+
const storagePath = getStoragePath(options.cwd, config);
|
|
12
|
+
const state = loadState(storagePath);
|
|
13
|
+
// Handle session state transitions
|
|
14
|
+
handleSessionTransition(storagePath, state, options, config.thresholds);
|
|
15
|
+
// Check if restoration is needed
|
|
16
|
+
if (!config.restoreOnSessionStart) {
|
|
17
|
+
return {};
|
|
18
|
+
}
|
|
19
|
+
// On resume, context is likely intact — skip restoration
|
|
20
|
+
if (options.source === 'resume') {
|
|
21
|
+
return {};
|
|
22
|
+
}
|
|
23
|
+
// Check for existing snapshots
|
|
24
|
+
const snapshotCount = getSnapshotCount(storagePath);
|
|
25
|
+
if (snapshotCount === 0) {
|
|
26
|
+
// First run — tell Claude that bookmark is active
|
|
27
|
+
return {
|
|
28
|
+
systemMessage: '[Bookmark: Active — no snapshots yet. Snapshots will be captured automatically ' +
|
|
29
|
+
'before compaction, on 20-minute intervals, and at session end.]\n\n' +
|
|
30
|
+
'Briefly let the user know that Bookmark is active and will start capturing context snapshots automatically.',
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
// Read LATEST.md
|
|
34
|
+
const latestMd = readLatestMd(storagePath);
|
|
35
|
+
if (!latestMd) {
|
|
36
|
+
return {};
|
|
37
|
+
}
|
|
38
|
+
if (options.format === 'json') {
|
|
39
|
+
const snapshot = loadLatestSnapshot(storagePath);
|
|
40
|
+
return {
|
|
41
|
+
systemMessage: JSON.stringify(snapshot, null, 2),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
if (options.format === 'markdown') {
|
|
45
|
+
return {
|
|
46
|
+
systemMessage: latestMd,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
// Default: system_message format
|
|
50
|
+
const systemMessage = buildRestorationMessage(latestMd, snapshotCount);
|
|
51
|
+
return { systemMessage };
|
|
52
|
+
}
|
|
53
|
+
function buildRestorationMessage(latestMd, snapshotCount) {
|
|
54
|
+
const lines = [];
|
|
55
|
+
lines.push('[Bookmark: Context recovered from previous session]');
|
|
56
|
+
lines.push('');
|
|
57
|
+
lines.push('Briefly notify the user that their prior session context has been recovered by Bookmark.');
|
|
58
|
+
lines.push('');
|
|
59
|
+
lines.push('## Prior Session Context (Bookmark)');
|
|
60
|
+
lines.push('');
|
|
61
|
+
lines.push(latestMd);
|
|
62
|
+
lines.push('');
|
|
63
|
+
if (snapshotCount > 1) {
|
|
64
|
+
lines.push(`> ${snapshotCount} snapshots available. Use \`/bookmark:list\` for history or \`/bookmark:restore\` for a specific snapshot.`);
|
|
65
|
+
}
|
|
66
|
+
return lines.join('\n');
|
|
67
|
+
}
|
|
68
|
+
function handleSessionTransition(storagePath, state, options, thresholds) {
|
|
69
|
+
const source = options.source ?? 'startup';
|
|
70
|
+
const sessionId = options.sessionId ?? `session_${Date.now()}`;
|
|
71
|
+
let updatedState;
|
|
72
|
+
switch (source) {
|
|
73
|
+
case 'startup':
|
|
74
|
+
case 'clear':
|
|
75
|
+
// New session — reset compaction count
|
|
76
|
+
updatedState = resetForNewSession(state, sessionId, thresholds);
|
|
77
|
+
break;
|
|
78
|
+
case 'compact':
|
|
79
|
+
// After compaction — increment compaction count
|
|
80
|
+
updatedState = incrementCompaction(state, thresholds);
|
|
81
|
+
updatedState.session_id = sessionId;
|
|
82
|
+
break;
|
|
83
|
+
case 'resume':
|
|
84
|
+
// Resuming — keep state, just update session ID if different
|
|
85
|
+
updatedState = { ...state, session_id: sessionId, last_event_time: Date.now() };
|
|
86
|
+
break;
|
|
87
|
+
default:
|
|
88
|
+
updatedState = state;
|
|
89
|
+
}
|
|
90
|
+
if (!existsSync(storagePath))
|
|
91
|
+
return;
|
|
92
|
+
saveState(storagePath, updatedState);
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/restore/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if bookmark hooks are already configured in a project.
|
|
3
|
+
*/
|
|
4
|
+
export declare function isProjectConfigured(cwd: string): boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Set up bookmark in a project directory.
|
|
7
|
+
* Creates storage dirs, configures hooks, injects gitignore and CLAUDE.md.
|
|
8
|
+
* Returns list of steps completed. Silent (no console output) — caller decides output.
|
|
9
|
+
*/
|
|
10
|
+
export declare function setupProject(cwd: string): string[];
|
|
11
|
+
/**
|
|
12
|
+
* Auto-bootstrap: silently configure hooks if bookmark CLI runs in an unconfigured project.
|
|
13
|
+
* Called at the top of CLI commands. No-op if already configured.
|
|
14
|
+
*/
|
|
15
|
+
export declare function ensureProjectBootstrapped(cwd: string): void;
|
|
16
|
+
//# sourceMappingURL=auto-setup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-setup.d.ts","sourceRoot":"","sources":["../../src/setup/auto-setup.ts"],"names":[],"mappings":"AAqBA;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CASxD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAgClD;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAW3D"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { configureHooks } from './configure-hooks.js';
|
|
4
|
+
const GREEN = '\x1b[32m';
|
|
5
|
+
const CYAN = '\x1b[36m';
|
|
6
|
+
const DIM = '\x1b[2m';
|
|
7
|
+
const RESET = '\x1b[0m';
|
|
8
|
+
/**
|
|
9
|
+
* Find the project root — npm sets INIT_CWD to the original working directory.
|
|
10
|
+
*/
|
|
11
|
+
function findProjectRoot() {
|
|
12
|
+
if (process.env.INIT_CWD) {
|
|
13
|
+
return process.env.INIT_CWD;
|
|
14
|
+
}
|
|
15
|
+
return process.cwd();
|
|
16
|
+
}
|
|
17
|
+
// ─── Core Setup (reusable) ───
|
|
18
|
+
/**
|
|
19
|
+
* Check if bookmark hooks are already configured in a project.
|
|
20
|
+
*/
|
|
21
|
+
export function isProjectConfigured(cwd) {
|
|
22
|
+
const settingsPath = join(cwd, '.claude', 'settings.json');
|
|
23
|
+
if (!existsSync(settingsPath))
|
|
24
|
+
return false;
|
|
25
|
+
try {
|
|
26
|
+
const content = readFileSync(settingsPath, 'utf-8');
|
|
27
|
+
return content.includes('@tyroneross/bookmark');
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Set up bookmark in a project directory.
|
|
35
|
+
* Creates storage dirs, configures hooks, injects gitignore and CLAUDE.md.
|
|
36
|
+
* Returns list of steps completed. Silent (no console output) — caller decides output.
|
|
37
|
+
*/
|
|
38
|
+
export function setupProject(cwd) {
|
|
39
|
+
const steps = [];
|
|
40
|
+
// 1. Ensure storage directories
|
|
41
|
+
const bookmarkPath = join(cwd, '.claude', 'bookmarks');
|
|
42
|
+
mkdirSync(join(bookmarkPath, 'snapshots'), { recursive: true });
|
|
43
|
+
mkdirSync(join(bookmarkPath, 'archive'), { recursive: true });
|
|
44
|
+
steps.push('Created .claude/bookmarks/ directories');
|
|
45
|
+
// 2. Configure hooks in settings.json
|
|
46
|
+
try {
|
|
47
|
+
configureHooks(cwd);
|
|
48
|
+
steps.push('Configured 4 hooks (PreCompact, SessionStart, UserPromptSubmit, Stop)');
|
|
49
|
+
}
|
|
50
|
+
catch { /* silently skip */ }
|
|
51
|
+
// 3. Add .claude/bookmarks/ to .gitignore
|
|
52
|
+
try {
|
|
53
|
+
const added = injectGitignore(cwd);
|
|
54
|
+
if (added) {
|
|
55
|
+
steps.push('Added .claude/bookmarks/ to .gitignore');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch { /* silently skip */ }
|
|
59
|
+
// 4. Inject CLAUDE.md section
|
|
60
|
+
try {
|
|
61
|
+
const updated = injectClaudeMd(cwd);
|
|
62
|
+
if (updated) {
|
|
63
|
+
steps.push('Updated .claude/CLAUDE.md with bookmark docs');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch { /* silently skip */ }
|
|
67
|
+
return steps;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Auto-bootstrap: silently configure hooks if bookmark CLI runs in an unconfigured project.
|
|
71
|
+
* Called at the top of CLI commands. No-op if already configured.
|
|
72
|
+
*/
|
|
73
|
+
export function ensureProjectBootstrapped(cwd) {
|
|
74
|
+
if (isProjectConfigured(cwd))
|
|
75
|
+
return;
|
|
76
|
+
// Skip if no package.json (not a real project)
|
|
77
|
+
if (!existsSync(join(cwd, 'package.json')))
|
|
78
|
+
return;
|
|
79
|
+
try {
|
|
80
|
+
setupProject(cwd);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// Silent — don't break the command
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// ─── Postinstall Entry Point ───
|
|
87
|
+
/**
|
|
88
|
+
* Auto-setup runs on npm postinstall.
|
|
89
|
+
* Sets up hooks, CLAUDE.md injection, and storage directories.
|
|
90
|
+
* Shows visible output so users know setup succeeded.
|
|
91
|
+
*/
|
|
92
|
+
function autoSetup() {
|
|
93
|
+
// Skip in CI or when disabled
|
|
94
|
+
if (process.env.CI || process.env.BOOKMARK_SKIP_SETUP === 'true') {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const projectRoot = findProjectRoot();
|
|
98
|
+
const isGlobal = process.env.npm_config_global === 'true';
|
|
99
|
+
const hasProject = projectRoot !== '/' && existsSync(join(projectRoot, 'package.json'));
|
|
100
|
+
// Global install with no project context
|
|
101
|
+
if (isGlobal && !hasProject) {
|
|
102
|
+
console.log(`\n ${GREEN}Bookmark${RESET} installed globally.`);
|
|
103
|
+
console.log(` Hooks will auto-configure when you use ${CYAN}/bookmark:activate${RESET} in a Claude Code session.\n`);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
// No project found
|
|
107
|
+
if (!hasProject) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
// Skip if this is our own package (development mode)
|
|
111
|
+
try {
|
|
112
|
+
const pkg = JSON.parse(readFileSync(join(projectRoot, 'package.json'), 'utf-8'));
|
|
113
|
+
if (pkg.name === '@tyroneross/bookmark')
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
catch { /* ignore */ }
|
|
117
|
+
// Global install FROM a project directory — configure that project
|
|
118
|
+
// Local install — configure the project
|
|
119
|
+
console.log(`\n ${GREEN}Bookmark${RESET} — Setting up context snapshots\n`);
|
|
120
|
+
try {
|
|
121
|
+
const steps = setupProject(projectRoot);
|
|
122
|
+
for (const step of steps) {
|
|
123
|
+
console.log(` ${GREEN}+${RESET} ${step}`);
|
|
124
|
+
}
|
|
125
|
+
console.log();
|
|
126
|
+
console.log(` ${GREEN}Ready.${RESET} Context snapshots are now active.`);
|
|
127
|
+
console.log();
|
|
128
|
+
console.log(` ${DIM}How it works:${RESET}`);
|
|
129
|
+
console.log(` ${DIM} - Snapshots captured automatically before compaction and on intervals${RESET}`);
|
|
130
|
+
console.log(` ${DIM} - Context restored when you start a new session${RESET}`);
|
|
131
|
+
console.log(` ${DIM} - Use${RESET} ${CYAN}/bookmark:snapshot${RESET} ${DIM}for manual snapshots${RESET}`);
|
|
132
|
+
console.log();
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
// Don't fail npm install
|
|
136
|
+
console.warn(` Setup skipped: ${error.message}\n`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// ─── Inject Helpers ───
|
|
140
|
+
function injectGitignore(cwd) {
|
|
141
|
+
const gitignorePath = join(cwd, '.gitignore');
|
|
142
|
+
const entry = '.claude/bookmarks/';
|
|
143
|
+
let content = '';
|
|
144
|
+
if (existsSync(gitignorePath)) {
|
|
145
|
+
content = readFileSync(gitignorePath, 'utf-8');
|
|
146
|
+
if (content.includes(entry))
|
|
147
|
+
return false;
|
|
148
|
+
if (!content.endsWith('\n'))
|
|
149
|
+
content += '\n';
|
|
150
|
+
}
|
|
151
|
+
content += `\n# Bookmark snapshot data\n${entry}\n`;
|
|
152
|
+
writeFileSync(gitignorePath, content, 'utf-8');
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
function injectClaudeMd(cwd) {
|
|
156
|
+
const claudeMdPath = join(cwd, '.claude', 'CLAUDE.md');
|
|
157
|
+
const marker = '## Bookmark — Context Snapshots';
|
|
158
|
+
let content = '';
|
|
159
|
+
if (existsSync(claudeMdPath)) {
|
|
160
|
+
content = readFileSync(claudeMdPath, 'utf-8');
|
|
161
|
+
// Don't duplicate
|
|
162
|
+
if (content.includes(marker))
|
|
163
|
+
return false;
|
|
164
|
+
content += '\n\n';
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
// Ensure .claude dir exists
|
|
168
|
+
mkdirSync(join(cwd, '.claude'), { recursive: true });
|
|
169
|
+
}
|
|
170
|
+
content += `${marker}
|
|
171
|
+
|
|
172
|
+
This project uses @tyroneross/bookmark for context snapshots.
|
|
173
|
+
|
|
174
|
+
**Automatic behavior:**
|
|
175
|
+
- Snapshots captured before compaction and on session end
|
|
176
|
+
- Context restored automatically on session start
|
|
177
|
+
- Adaptive thresholds increase snapshot frequency with compaction count
|
|
178
|
+
- Time-based snapshots every 20 minutes (configurable)
|
|
179
|
+
|
|
180
|
+
**Commands:**
|
|
181
|
+
- \`/bookmark:snapshot\` — Manual snapshot
|
|
182
|
+
- \`/bookmark:restore\` — Restore from a snapshot
|
|
183
|
+
- \`/bookmark:status\` — Show snapshot stats
|
|
184
|
+
- \`/bookmark:list\` — List all snapshots
|
|
185
|
+
|
|
186
|
+
The system operates with zero context window tax — all processing runs externally.
|
|
187
|
+
`;
|
|
188
|
+
writeFileSync(claudeMdPath, content, 'utf-8');
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
autoSetup();
|
|
192
|
+
//# sourceMappingURL=auto-setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-setup.js","sourceRoot":"","sources":["../../src/setup/auto-setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configure hooks in the project's .claude/settings.json.
|
|
3
|
+
* Adds bookmark hooks without duplicating or overwriting existing hooks.
|
|
4
|
+
*/
|
|
5
|
+
export declare function configureHooks(cwd: string): void;
|
|
6
|
+
/**
|
|
7
|
+
* Remove bookmark hooks from settings.json.
|
|
8
|
+
*/
|
|
9
|
+
export declare function removeHooks(cwd: string): void;
|
|
10
|
+
//# sourceMappingURL=configure-hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configure-hooks.d.ts","sourceRoot":"","sources":["../../src/setup/configure-hooks.ts"],"names":[],"mappings":"AA2DA;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAqChD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAqB7C"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
const BOOKMARK_HOOKS = {
|
|
4
|
+
PreCompact: {
|
|
5
|
+
matcher: '',
|
|
6
|
+
hooks: [{
|
|
7
|
+
type: 'command',
|
|
8
|
+
command: 'npx @tyroneross/bookmark snapshot --trigger pre_compact 2>/dev/null || true',
|
|
9
|
+
timeout: 30000,
|
|
10
|
+
async: true,
|
|
11
|
+
}],
|
|
12
|
+
},
|
|
13
|
+
SessionStart: {
|
|
14
|
+
matcher: '',
|
|
15
|
+
hooks: [{
|
|
16
|
+
type: 'command',
|
|
17
|
+
command: 'npx @tyroneross/bookmark restore 2>/dev/null || echo \'{}\'',
|
|
18
|
+
timeout: 5000,
|
|
19
|
+
}],
|
|
20
|
+
},
|
|
21
|
+
UserPromptSubmit: {
|
|
22
|
+
matcher: '',
|
|
23
|
+
hooks: [{
|
|
24
|
+
type: 'command',
|
|
25
|
+
command: 'npx @tyroneross/bookmark check 2>/dev/null || true',
|
|
26
|
+
timeout: 3000,
|
|
27
|
+
async: true,
|
|
28
|
+
}],
|
|
29
|
+
},
|
|
30
|
+
Stop: {
|
|
31
|
+
matcher: '',
|
|
32
|
+
hooks: [{
|
|
33
|
+
type: 'command',
|
|
34
|
+
command: 'npx @tyroneross/bookmark snapshot --trigger session_end 2>/dev/null || true',
|
|
35
|
+
timeout: 15000,
|
|
36
|
+
}],
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
const BOOKMARK_MARKER = '@tyroneross/bookmark';
|
|
40
|
+
/**
|
|
41
|
+
* Configure hooks in the project's .claude/settings.json.
|
|
42
|
+
* Adds bookmark hooks without duplicating or overwriting existing hooks.
|
|
43
|
+
*/
|
|
44
|
+
export function configureHooks(cwd) {
|
|
45
|
+
const settingsDir = join(cwd, '.claude');
|
|
46
|
+
const settingsPath = join(settingsDir, 'settings.json');
|
|
47
|
+
if (!existsSync(settingsDir)) {
|
|
48
|
+
mkdirSync(settingsDir, { recursive: true });
|
|
49
|
+
}
|
|
50
|
+
let settings = {};
|
|
51
|
+
if (existsSync(settingsPath)) {
|
|
52
|
+
try {
|
|
53
|
+
settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
settings = {};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (!settings.hooks) {
|
|
60
|
+
settings.hooks = {};
|
|
61
|
+
}
|
|
62
|
+
for (const [event, hookConfig] of Object.entries(BOOKMARK_HOOKS)) {
|
|
63
|
+
if (!settings.hooks[event]) {
|
|
64
|
+
settings.hooks[event] = [];
|
|
65
|
+
}
|
|
66
|
+
// Check if bookmark hook already exists
|
|
67
|
+
const exists = settings.hooks[event].some(h => h.hooks.some(hh => hh.command?.includes(BOOKMARK_MARKER)));
|
|
68
|
+
if (!exists) {
|
|
69
|
+
settings.hooks[event].push(hookConfig);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf-8');
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Remove bookmark hooks from settings.json.
|
|
76
|
+
*/
|
|
77
|
+
export function removeHooks(cwd) {
|
|
78
|
+
const settingsPath = join(cwd, '.claude', 'settings.json');
|
|
79
|
+
if (!existsSync(settingsPath))
|
|
80
|
+
return;
|
|
81
|
+
try {
|
|
82
|
+
const settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
|
|
83
|
+
if (!settings.hooks)
|
|
84
|
+
return;
|
|
85
|
+
for (const event of Object.keys(settings.hooks)) {
|
|
86
|
+
settings.hooks[event] = settings.hooks[event].filter(h => !h.hooks.some(hh => hh.command?.includes(BOOKMARK_MARKER)));
|
|
87
|
+
if (settings.hooks[event].length === 0) {
|
|
88
|
+
delete settings.hooks[event];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf-8');
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// Silent
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=configure-hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configure-hooks.js","sourceRoot":"","sources":["../../src/setup/configure-hooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Snapshot, SnapshotTrigger } from '../types.js';
|
|
2
|
+
export interface CaptureOptions {
|
|
3
|
+
trigger: SnapshotTrigger;
|
|
4
|
+
transcriptPath: string;
|
|
5
|
+
cwd: string;
|
|
6
|
+
sessionId?: string;
|
|
7
|
+
smart?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Full snapshot capture pipeline:
|
|
11
|
+
* 1. Parse transcript
|
|
12
|
+
* 2. Estimate token usage
|
|
13
|
+
* 3. Extract decisions/status/files/errors
|
|
14
|
+
* 4. Optionally enhance with LLM (--smart)
|
|
15
|
+
* 5. Build snapshot object
|
|
16
|
+
* 6. Store snapshot JSON
|
|
17
|
+
* 7. Generate and write LATEST.md
|
|
18
|
+
* 8. Update state
|
|
19
|
+
*/
|
|
20
|
+
export declare function captureSnapshot(options: CaptureOptions): Promise<Snapshot>;
|
|
21
|
+
//# sourceMappingURL=capture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../src/snapshot/capture.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE7D,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,eAAe,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC,CAyDhF"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { parseTranscript } from '../transcript/parser.js';
|
|
2
|
+
import { estimateFromTranscript } from '../transcript/estimator.js';
|
|
3
|
+
import { extractFromEntries } from '../transcript/extractor.js';
|
|
4
|
+
import { storeSnapshot, writeLatestMd, loadLatestSnapshot } from './storage.js';
|
|
5
|
+
import { compressToMarkdown } from './compress.js';
|
|
6
|
+
import { loadState, saveState, updateSnapshotTime } from '../threshold/state.js';
|
|
7
|
+
import { loadConfig, getStoragePath } from '../config.js';
|
|
8
|
+
/**
|
|
9
|
+
* Full snapshot capture pipeline:
|
|
10
|
+
* 1. Parse transcript
|
|
11
|
+
* 2. Estimate token usage
|
|
12
|
+
* 3. Extract decisions/status/files/errors
|
|
13
|
+
* 4. Optionally enhance with LLM (--smart)
|
|
14
|
+
* 5. Build snapshot object
|
|
15
|
+
* 6. Store snapshot JSON
|
|
16
|
+
* 7. Generate and write LATEST.md
|
|
17
|
+
* 8. Update state
|
|
18
|
+
*/
|
|
19
|
+
export async function captureSnapshot(options) {
|
|
20
|
+
const config = loadConfig(options.cwd);
|
|
21
|
+
const storagePath = getStoragePath(options.cwd, config);
|
|
22
|
+
const state = loadState(storagePath);
|
|
23
|
+
// 1. Parse transcript
|
|
24
|
+
const { entries } = parseTranscript(options.transcriptPath);
|
|
25
|
+
// 2. Estimate token usage
|
|
26
|
+
const estimate = estimateFromTranscript(options.transcriptPath, {
|
|
27
|
+
contextLimit: config.contextLimitTokens,
|
|
28
|
+
charsPerToken: config.charsPerToken,
|
|
29
|
+
});
|
|
30
|
+
// 3. Extract structured content
|
|
31
|
+
let extraction = extractFromEntries(entries);
|
|
32
|
+
// 4. Optional LLM enhancement
|
|
33
|
+
if (options.smart ?? config.smartDefault) {
|
|
34
|
+
extraction = await enhanceWithLLM(extraction, entries);
|
|
35
|
+
}
|
|
36
|
+
// 5. Build snapshot
|
|
37
|
+
const snapshotId = generateSnapshotId();
|
|
38
|
+
const priorSnapshot = loadLatestSnapshot(storagePath);
|
|
39
|
+
const snapshot = {
|
|
40
|
+
snapshot_id: snapshotId,
|
|
41
|
+
timestamp: Date.now(),
|
|
42
|
+
session_id: options.sessionId ?? state.session_id ?? 'unknown',
|
|
43
|
+
project_path: options.cwd,
|
|
44
|
+
trigger: options.trigger,
|
|
45
|
+
compaction_cycle: state.compaction_count,
|
|
46
|
+
context_remaining_pct: estimate.remaining_pct,
|
|
47
|
+
token_estimate: estimate.total_tokens,
|
|
48
|
+
current_status: extraction.current_status,
|
|
49
|
+
decisions: extraction.decisions,
|
|
50
|
+
open_items: extraction.open_items,
|
|
51
|
+
unknowns: extraction.unknowns,
|
|
52
|
+
files_changed: extraction.files_changed,
|
|
53
|
+
errors_encountered: extraction.errors_encountered,
|
|
54
|
+
tools_summary: extraction.tools_summary,
|
|
55
|
+
prior_snapshot_id: priorSnapshot?.snapshot_id,
|
|
56
|
+
};
|
|
57
|
+
// 6. Store snapshot
|
|
58
|
+
storeSnapshot(storagePath, snapshot);
|
|
59
|
+
// 7. Generate LATEST.md
|
|
60
|
+
const markdown = compressToMarkdown(snapshot);
|
|
61
|
+
writeLatestMd(storagePath, markdown);
|
|
62
|
+
// 8. Update state
|
|
63
|
+
const updatedState = updateSnapshotTime(state);
|
|
64
|
+
saveState(storagePath, updatedState);
|
|
65
|
+
return snapshot;
|
|
66
|
+
}
|
|
67
|
+
function generateSnapshotId() {
|
|
68
|
+
const now = new Date();
|
|
69
|
+
const pad = (n, len = 2) => String(n).padStart(len, '0');
|
|
70
|
+
const date = `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}`;
|
|
71
|
+
const time = `${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
|
|
72
|
+
return `SNAP_${date}_${time}`;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Enhance extraction with Claude Haiku for higher-quality summaries.
|
|
76
|
+
* Falls back to original extraction if SDK not available or API key missing.
|
|
77
|
+
*/
|
|
78
|
+
async function enhanceWithLLM(extraction, entries) {
|
|
79
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
80
|
+
if (!apiKey)
|
|
81
|
+
return extraction;
|
|
82
|
+
try {
|
|
83
|
+
// Dynamic import — @anthropic-ai/sdk is an optional dependency
|
|
84
|
+
const { default: Anthropic } = await import('@anthropic-ai/sdk');
|
|
85
|
+
const client = new Anthropic({ apiKey });
|
|
86
|
+
// Build a compressed transcript excerpt (last ~2000 tokens worth)
|
|
87
|
+
const recentEntries = entries.slice(-50); // Last 50 entries
|
|
88
|
+
const transcript = recentEntries
|
|
89
|
+
.filter(e => e.type === 'assistant' || e.type === 'user')
|
|
90
|
+
.map(e => `[${e.type}]: ${typeof e.content === 'string' ? e.content.slice(0, 200) : ''}`)
|
|
91
|
+
.join('\n')
|
|
92
|
+
.slice(-4000);
|
|
93
|
+
const response = await client.messages.create({
|
|
94
|
+
model: 'claude-haiku-4-5-20251001',
|
|
95
|
+
max_tokens: 1000,
|
|
96
|
+
messages: [{
|
|
97
|
+
role: 'user',
|
|
98
|
+
content: `Analyze this coding session transcript and extract:
|
|
99
|
+
1. Key decisions made (with brief rationale)
|
|
100
|
+
2. Current status (1-2 sentences)
|
|
101
|
+
3. Open items/TODOs (with priority: high/medium/low)
|
|
102
|
+
4. Unknowns or blockers
|
|
103
|
+
|
|
104
|
+
Transcript excerpt:
|
|
105
|
+
${transcript}
|
|
106
|
+
|
|
107
|
+
Respond in JSON format:
|
|
108
|
+
{
|
|
109
|
+
"current_status": "...",
|
|
110
|
+
"decisions": [{"description": "...", "rationale": "..."}],
|
|
111
|
+
"open_items": [{"description": "...", "priority": "high|medium|low"}],
|
|
112
|
+
"unknowns": ["..."]
|
|
113
|
+
}`,
|
|
114
|
+
}],
|
|
115
|
+
});
|
|
116
|
+
const text = response.content[0]?.type === 'text' ? response.content[0].text : '';
|
|
117
|
+
const jsonMatch = text.match(/\{[\s\S]*\}/);
|
|
118
|
+
if (jsonMatch) {
|
|
119
|
+
const enhanced = JSON.parse(jsonMatch[0]);
|
|
120
|
+
return {
|
|
121
|
+
...extraction,
|
|
122
|
+
current_status: enhanced.current_status ?? extraction.current_status,
|
|
123
|
+
decisions: enhanced.decisions?.length ? enhanced.decisions : extraction.decisions,
|
|
124
|
+
open_items: enhanced.open_items?.length ? enhanced.open_items : extraction.open_items,
|
|
125
|
+
unknowns: enhanced.unknowns?.length ? enhanced.unknowns : extraction.unknowns,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
// Fall back silently to pattern-based extraction
|
|
131
|
+
}
|
|
132
|
+
return extraction;
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=capture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/snapshot/capture.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Snapshot } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Compress a full snapshot into a concise markdown summary.
|
|
4
|
+
* Target: <150 lines, <1000 tokens.
|
|
5
|
+
* This becomes LATEST.md — the hot context tier.
|
|
6
|
+
*/
|
|
7
|
+
export declare function compressToMarkdown(snapshot: Snapshot): string;
|
|
8
|
+
//# sourceMappingURL=compress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compress.d.ts","sourceRoot":"","sources":["../../src/snapshot/compress.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CA2F7D"}
|