@tyroneross/bookmark 0.2.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/.claude-plugin/marketplace.json +29 -12
- package/.claude-plugin/plugin.json +12 -8
- package/.codex-plugin/plugin.json +31 -0
- package/.mcp.json +8 -0
- package/CLAUDE.md +82 -38
- package/LICENSE +202 -21
- package/README.md +150 -57
- package/agents/snapshot-analyst.md +1 -1
- package/commands/bookmark.md +29 -0
- package/commands/feedback.md +37 -0
- package/commands/restore.md +14 -4
- package/commands/snapshot.md +19 -7
- package/commands/status.md +1 -1
- package/dist/cli/index.js +600 -66
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/snapshot-resolution.d.ts +15 -0
- package/dist/cli/snapshot-resolution.d.ts.map +1 -0
- package/dist/cli/snapshot-resolution.js +21 -0
- package/dist/cli/snapshot-resolution.js.map +1 -0
- package/dist/config.d.ts +19 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +150 -19
- package/dist/config.js.map +1 -1
- package/dist/context/freshness.d.ts +3 -0
- package/dist/context/freshness.d.ts.map +1 -0
- package/dist/context/freshness.js +29 -0
- package/dist/context/freshness.js.map +1 -0
- package/dist/context/handoff-prompt.d.ts +12 -0
- package/dist/context/handoff-prompt.d.ts.map +1 -0
- package/dist/context/handoff-prompt.js +29 -0
- package/dist/context/handoff-prompt.js.map +1 -0
- package/dist/index.d.ts +7 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts +9 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +85 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +97 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +304 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/registry.d.ts +40 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +134 -0
- package/dist/registry.js.map +1 -0
- package/dist/restore/index.d.ts +13 -1
- package/dist/restore/index.d.ts.map +1 -1
- package/dist/restore/index.js +154 -256
- package/dist/restore/index.js.map +1 -1
- package/dist/setup/auto-setup.d.ts +8 -2
- package/dist/setup/auto-setup.d.ts.map +1 -1
- package/dist/setup/auto-setup.js +281 -66
- package/dist/setup/auto-setup.js.map +1 -1
- package/dist/setup/configure-hooks.d.ts +14 -3
- package/dist/setup/configure-hooks.d.ts.map +1 -1
- package/dist/setup/configure-hooks.js +156 -24
- package/dist/setup/configure-hooks.js.map +1 -1
- package/dist/snapshot/capture.d.ts +12 -10
- package/dist/snapshot/capture.d.ts.map +1 -1
- package/dist/snapshot/capture.js +36 -48
- package/dist/snapshot/capture.js.map +1 -1
- package/dist/snapshot/compress.d.ts +3 -3
- package/dist/snapshot/compress.d.ts.map +1 -1
- package/dist/snapshot/compress.js +16 -51
- package/dist/snapshot/compress.js.map +1 -1
- package/dist/snapshot/storage.d.ts +1 -0
- package/dist/snapshot/storage.d.ts.map +1 -1
- package/dist/snapshot/storage.js +7 -6
- package/dist/snapshot/storage.js.map +1 -1
- package/dist/threshold/state.d.ts +5 -0
- package/dist/threshold/state.d.ts.map +1 -1
- package/dist/threshold/state.js +28 -2
- package/dist/threshold/state.js.map +1 -1
- package/dist/threshold/token-usage.d.ts +29 -0
- package/dist/threshold/token-usage.d.ts.map +1 -0
- package/dist/threshold/token-usage.js +128 -0
- package/dist/threshold/token-usage.js.map +1 -0
- package/dist/trails/identity.d.ts +76 -0
- package/dist/trails/identity.d.ts.map +1 -0
- package/dist/trails/identity.js +117 -0
- package/dist/trails/identity.js.map +1 -0
- package/dist/trails/reader.d.ts +1 -1
- package/dist/trails/reader.js +2 -2
- package/dist/trails/reader.js.map +1 -1
- package/dist/trails/writer.d.ts +2 -8
- package/dist/trails/writer.d.ts.map +1 -1
- package/dist/trails/writer.js +33 -191
- package/dist/trails/writer.js.map +1 -1
- package/dist/transcript/extractor.d.ts +8 -9
- package/dist/transcript/extractor.d.ts.map +1 -1
- package/dist/transcript/extractor.js +97 -360
- package/dist/transcript/extractor.js.map +1 -1
- package/dist/types.d.ts +34 -41
- package/dist/types.d.ts.map +1 -1
- package/hooks/hooks.json +12 -14
- package/package.json +13 -7
- package/scripts/install-plugin.sh +48 -0
- package/skills/context-continuity/SKILL.md +43 -24
- package/commands/activate.md +0 -20
- package/dist/transcript/estimator.d.ts +0 -20
- package/dist/transcript/estimator.d.ts.map +0 -1
- package/dist/transcript/estimator.js +0 -95
- package/dist/transcript/estimator.js.map +0 -1
package/dist/types.d.ts
CHANGED
|
@@ -5,21 +5,24 @@ export interface Snapshot {
|
|
|
5
5
|
project_path: string;
|
|
6
6
|
trigger: SnapshotTrigger;
|
|
7
7
|
compaction_cycle: number;
|
|
8
|
-
context_remaining_pct: number;
|
|
9
|
-
token_estimate: number;
|
|
10
|
-
intent: string;
|
|
11
|
-
progress: string;
|
|
12
|
-
current_status: string;
|
|
13
|
-
decisions: Decision[];
|
|
14
|
-
open_items: OpenItem[];
|
|
15
|
-
unknowns: string[];
|
|
16
8
|
files_changed: FileActivity[];
|
|
17
|
-
errors_encountered: ErrorEntry[];
|
|
18
9
|
tools_summary: Record<string, number>;
|
|
10
|
+
context_remaining_pct?: number;
|
|
11
|
+
context_used_pct?: number;
|
|
12
|
+
token_estimate?: number;
|
|
13
|
+
context_limit_tokens?: number;
|
|
14
|
+
model?: string;
|
|
15
|
+
intent?: string;
|
|
16
|
+
progress?: string;
|
|
17
|
+
current_status?: string;
|
|
18
|
+
decisions?: Decision[];
|
|
19
|
+
open_items?: OpenItem[];
|
|
20
|
+
unknowns?: string[];
|
|
21
|
+
errors_encountered?: ErrorEntry[];
|
|
19
22
|
user_sentiment?: 'positive' | 'neutral' | 'negative';
|
|
20
23
|
prior_snapshot_id?: string;
|
|
21
24
|
}
|
|
22
|
-
export type SnapshotTrigger = 'pre_compact' | 'time_interval' | 'manual' | 'session_end';
|
|
25
|
+
export type SnapshotTrigger = 'pre_compact' | 'token_threshold' | 'time_interval' | 'manual' | 'session_end';
|
|
23
26
|
export interface Decision {
|
|
24
27
|
description: string;
|
|
25
28
|
rationale?: string;
|
|
@@ -61,11 +64,11 @@ export interface SnapshotEntry {
|
|
|
61
64
|
timestamp: number;
|
|
62
65
|
trigger: SnapshotTrigger;
|
|
63
66
|
compaction_cycle: number;
|
|
64
|
-
context_remaining_pct: number;
|
|
65
|
-
token_estimate: number;
|
|
66
|
-
decisions_count: number;
|
|
67
67
|
files_changed_count: number;
|
|
68
|
-
|
|
68
|
+
context_remaining_pct?: number;
|
|
69
|
+
token_estimate?: number;
|
|
70
|
+
decisions_count?: number;
|
|
71
|
+
open_items_count?: number;
|
|
69
72
|
}
|
|
70
73
|
export interface BookmarkState {
|
|
71
74
|
version: string;
|
|
@@ -76,6 +79,17 @@ export interface BookmarkState {
|
|
|
76
79
|
last_event_time: number;
|
|
77
80
|
snapshot_interval_minutes: number;
|
|
78
81
|
session_history: SessionEntry[];
|
|
82
|
+
restores_performed?: number;
|
|
83
|
+
tokens_injected?: number;
|
|
84
|
+
quality_blocks?: number;
|
|
85
|
+
boilerplate_caught?: number;
|
|
86
|
+
latest_model?: string;
|
|
87
|
+
latest_context_tokens?: number;
|
|
88
|
+
latest_context_limit_tokens?: number;
|
|
89
|
+
latest_context_used_pct?: number;
|
|
90
|
+
latest_context_observed_at?: number;
|
|
91
|
+
unknown_context_limit_notified_model?: string;
|
|
92
|
+
token_thresholds_triggered?: number[];
|
|
79
93
|
}
|
|
80
94
|
export interface SessionEntry {
|
|
81
95
|
session_id: string;
|
|
@@ -101,29 +115,6 @@ export interface TranscriptContent {
|
|
|
101
115
|
input?: Record<string, unknown>;
|
|
102
116
|
content?: string | TranscriptContent[];
|
|
103
117
|
}
|
|
104
|
-
export interface TokenEstimate {
|
|
105
|
-
total_tokens: number;
|
|
106
|
-
message_count: number;
|
|
107
|
-
user_tokens: number;
|
|
108
|
-
assistant_tokens: number;
|
|
109
|
-
tool_tokens: number;
|
|
110
|
-
system_tokens: number;
|
|
111
|
-
context_limit: number;
|
|
112
|
-
remaining_pct: number;
|
|
113
|
-
remaining_tokens: number;
|
|
114
|
-
}
|
|
115
|
-
export interface ExtractionResult {
|
|
116
|
-
intent?: string;
|
|
117
|
-
progress?: string;
|
|
118
|
-
current_status: string;
|
|
119
|
-
decisions: Decision[];
|
|
120
|
-
open_items: OpenItem[];
|
|
121
|
-
unknowns: string[];
|
|
122
|
-
files_changed: FileActivity[];
|
|
123
|
-
errors_encountered: ErrorEntry[];
|
|
124
|
-
tools_summary: Record<string, number>;
|
|
125
|
-
user_sentiment?: 'positive' | 'neutral' | 'negative';
|
|
126
|
-
}
|
|
127
118
|
export interface HookInput {
|
|
128
119
|
session_id: string;
|
|
129
120
|
transcript_path: string;
|
|
@@ -133,6 +124,7 @@ export interface HookInput {
|
|
|
133
124
|
trigger?: 'manual' | 'auto';
|
|
134
125
|
source?: 'startup' | 'resume' | 'compact' | 'clear';
|
|
135
126
|
custom_instructions?: string;
|
|
127
|
+
prompt?: string;
|
|
136
128
|
}
|
|
137
129
|
export interface HookOutput {
|
|
138
130
|
systemMessage?: string;
|
|
@@ -143,20 +135,21 @@ export interface BookmarkConfig {
|
|
|
143
135
|
thresholds: number[];
|
|
144
136
|
maxThreshold: number;
|
|
145
137
|
intervalMinutes: number;
|
|
146
|
-
contextLimitTokens: number;
|
|
147
|
-
charsPerToken: number;
|
|
148
138
|
maxDecisions: number;
|
|
149
139
|
maxOpenItems: number;
|
|
150
140
|
maxFilesTracked: number;
|
|
151
141
|
maxErrorsTracked: number;
|
|
152
|
-
summaryTokenBudget: number;
|
|
153
142
|
maxActiveSnapshots: number;
|
|
154
143
|
archiveAfterDays: number;
|
|
155
144
|
snapshotOnSessionEnd: boolean;
|
|
156
145
|
restoreOnSessionStart: boolean;
|
|
146
|
+
tokenThresholds: number[];
|
|
147
|
+
contextLimitTokens?: number;
|
|
157
148
|
verboseLogging: boolean;
|
|
158
149
|
}
|
|
159
150
|
export interface SetupPreferences {
|
|
160
|
-
intervalMinutes
|
|
151
|
+
intervalMinutes?: number;
|
|
152
|
+
tokenThresholds?: number[];
|
|
153
|
+
contextLimitTokens?: number;
|
|
161
154
|
}
|
|
162
155
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,QAAQ;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IAGrB,OAAO,EAAE,eAAe,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/hooks/hooks.json
CHANGED
|
@@ -1,51 +1,49 @@
|
|
|
1
1
|
{
|
|
2
2
|
"hooks": {
|
|
3
|
-
"
|
|
3
|
+
"Stop": [
|
|
4
4
|
{
|
|
5
5
|
"matcher": "",
|
|
6
6
|
"hooks": [
|
|
7
7
|
{
|
|
8
8
|
"type": "command",
|
|
9
|
-
"command": "npx @tyroneross/bookmark
|
|
10
|
-
"timeout":
|
|
11
|
-
"async": true
|
|
9
|
+
"command": "npx @tyroneross/bookmark stop 2>/dev/null || echo '{\"decision\": \"approve\"}'",
|
|
10
|
+
"timeout": 10000
|
|
12
11
|
}
|
|
13
12
|
]
|
|
14
13
|
}
|
|
15
14
|
],
|
|
16
|
-
"
|
|
15
|
+
"PreCompact": [
|
|
17
16
|
{
|
|
18
17
|
"matcher": "",
|
|
19
18
|
"hooks": [
|
|
20
19
|
{
|
|
21
20
|
"type": "command",
|
|
22
|
-
"command": "npx @tyroneross/bookmark
|
|
23
|
-
"timeout":
|
|
21
|
+
"command": "npx @tyroneross/bookmark precompact 2>/dev/null || echo '{}'",
|
|
22
|
+
"timeout": 10000
|
|
24
23
|
}
|
|
25
24
|
]
|
|
26
25
|
}
|
|
27
26
|
],
|
|
28
|
-
"
|
|
27
|
+
"SessionStart": [
|
|
29
28
|
{
|
|
30
29
|
"matcher": "",
|
|
31
30
|
"hooks": [
|
|
32
31
|
{
|
|
33
32
|
"type": "command",
|
|
34
|
-
"command": "npx @tyroneross/bookmark
|
|
35
|
-
"timeout":
|
|
36
|
-
"async": true
|
|
33
|
+
"command": "npx @tyroneross/bookmark restore 2>/dev/null || echo '{}'",
|
|
34
|
+
"timeout": 5000
|
|
37
35
|
}
|
|
38
36
|
]
|
|
39
37
|
}
|
|
40
38
|
],
|
|
41
|
-
"
|
|
39
|
+
"UserPromptSubmit": [
|
|
42
40
|
{
|
|
43
41
|
"matcher": "",
|
|
44
42
|
"hooks": [
|
|
45
43
|
{
|
|
46
44
|
"type": "command",
|
|
47
|
-
"command": "npx @tyroneross/bookmark
|
|
48
|
-
"timeout":
|
|
45
|
+
"command": "npx @tyroneross/bookmark context-check 2>/dev/null || echo '{}'",
|
|
46
|
+
"timeout": 10000
|
|
49
47
|
}
|
|
50
48
|
]
|
|
51
49
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tyroneross/bookmark",
|
|
3
|
-
"version": "0.2
|
|
4
|
-
"description": "Context snapshots for
|
|
3
|
+
"version": "0.3.2",
|
|
4
|
+
"description": "Context snapshots for agent sessions, compactions, and terminal workflows",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
"hooks",
|
|
26
26
|
"agents",
|
|
27
27
|
".claude-plugin",
|
|
28
|
+
".codex-plugin",
|
|
29
|
+
".mcp.json",
|
|
28
30
|
"scripts/install-plugin.sh",
|
|
29
31
|
"CLAUDE.md",
|
|
30
32
|
"README.md"
|
|
@@ -38,10 +40,10 @@
|
|
|
38
40
|
"clean": "rm -rf dist",
|
|
39
41
|
"prepublishOnly": "npm run clean && npm run build",
|
|
40
42
|
"postinstall": "node dist/setup/auto-setup.js || true",
|
|
41
|
-
"install-plugin": "bash scripts/install-plugin.sh --global"
|
|
43
|
+
"install-plugin": "bash scripts/install-plugin.sh --global",
|
|
44
|
+
"mcp": "node dist/mcp/server.js"
|
|
42
45
|
},
|
|
43
46
|
"keywords": [
|
|
44
|
-
"claude-code",
|
|
45
47
|
"context",
|
|
46
48
|
"snapshots",
|
|
47
49
|
"session-continuity",
|
|
@@ -49,11 +51,11 @@
|
|
|
49
51
|
"memory",
|
|
50
52
|
"devtools"
|
|
51
53
|
],
|
|
52
|
-
"author": "Tyrone Ross",
|
|
53
|
-
"license": "
|
|
54
|
+
"author": "Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com>",
|
|
55
|
+
"license": "Apache-2.0",
|
|
54
56
|
"repository": {
|
|
55
57
|
"type": "git",
|
|
56
|
-
"url": "https://github.com/tyroneross/bookmark"
|
|
58
|
+
"url": "git+https://github.com/tyroneross/bookmark.git"
|
|
57
59
|
},
|
|
58
60
|
"homepage": "https://github.com/tyroneross/bookmark#readme",
|
|
59
61
|
"bugs": {
|
|
@@ -62,6 +64,10 @@
|
|
|
62
64
|
"engines": {
|
|
63
65
|
"node": ">=20.0.0"
|
|
64
66
|
},
|
|
67
|
+
"publishConfig": {
|
|
68
|
+
"access": "public",
|
|
69
|
+
"provenance": true
|
|
70
|
+
},
|
|
65
71
|
"dependencies": {
|
|
66
72
|
"commander": "^14.0.0",
|
|
67
73
|
"glob": "^13.0.0"
|
|
@@ -6,6 +6,41 @@ set -e
|
|
|
6
6
|
|
|
7
7
|
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
8
8
|
PLUGIN_DIR="$SCRIPT_DIR"
|
|
9
|
+
INSTALLED_PLUGINS="$HOME/.claude/plugins/installed_plugins.json"
|
|
10
|
+
|
|
11
|
+
register_plugin() {
|
|
12
|
+
# Register bookmark in installed_plugins.json for Claude Code discovery
|
|
13
|
+
node -e "
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
const path = '$INSTALLED_PLUGINS';
|
|
16
|
+
const installPath = '$1';
|
|
17
|
+
const now = new Date().toISOString();
|
|
18
|
+
|
|
19
|
+
let data = { version: 2, plugins: {} };
|
|
20
|
+
try {
|
|
21
|
+
if (fs.existsSync(path)) {
|
|
22
|
+
data = JSON.parse(fs.readFileSync(path, 'utf-8'));
|
|
23
|
+
}
|
|
24
|
+
} catch {}
|
|
25
|
+
|
|
26
|
+
const key = 'bookmark@local';
|
|
27
|
+
if (data.plugins[key]) {
|
|
28
|
+
data.plugins[key][0].installPath = installPath;
|
|
29
|
+
data.plugins[key][0].lastUpdated = now;
|
|
30
|
+
} else {
|
|
31
|
+
data.plugins[key] = [{
|
|
32
|
+
scope: 'user',
|
|
33
|
+
installPath: installPath,
|
|
34
|
+
version: '0.2.1',
|
|
35
|
+
installedAt: now,
|
|
36
|
+
lastUpdated: now
|
|
37
|
+
}];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
fs.mkdirSync(require('path').dirname(path), { recursive: true });
|
|
41
|
+
fs.writeFileSync(path, JSON.stringify(data, null, 2));
|
|
42
|
+
"
|
|
43
|
+
}
|
|
9
44
|
|
|
10
45
|
if [[ "$1" == "--global" ]]; then
|
|
11
46
|
# Global install — link plugin for all projects
|
|
@@ -19,12 +54,25 @@ if [[ "$1" == "--global" ]]; then
|
|
|
19
54
|
fi
|
|
20
55
|
ln -sf "$PLUGIN_DIR" "$LINK_PATH"
|
|
21
56
|
echo "Bookmark plugin linked globally: $LINK_PATH -> $PLUGIN_DIR"
|
|
57
|
+
|
|
58
|
+
# Register in installed_plugins.json
|
|
59
|
+
register_plugin "$PLUGIN_DIR"
|
|
60
|
+
echo "Registered bookmark in Claude Code plugin registry"
|
|
22
61
|
else
|
|
23
62
|
# Project-level install
|
|
24
63
|
CWD="${2:-$(pwd)}"
|
|
25
64
|
CLAUDE_DIR="$CWD/.claude"
|
|
26
65
|
mkdir -p "$CLAUDE_DIR"
|
|
27
66
|
|
|
67
|
+
# Register globally (commands/skills need global registration)
|
|
68
|
+
CLAUDE_PLUGINS_DIR="$HOME/.claude/plugins"
|
|
69
|
+
mkdir -p "$CLAUDE_PLUGINS_DIR"
|
|
70
|
+
LINK_PATH="$CLAUDE_PLUGINS_DIR/bookmark"
|
|
71
|
+
if [ ! -L "$LINK_PATH" ] && [ ! -d "$LINK_PATH" ]; then
|
|
72
|
+
ln -sf "$PLUGIN_DIR" "$LINK_PATH"
|
|
73
|
+
fi
|
|
74
|
+
register_plugin "$PLUGIN_DIR"
|
|
75
|
+
|
|
28
76
|
echo "Bookmark plugin installed for project: $CWD"
|
|
29
77
|
echo ""
|
|
30
78
|
echo "Commands available:"
|
|
@@ -1,49 +1,68 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: context-continuity
|
|
3
|
-
description:
|
|
4
|
-
version: 0.
|
|
3
|
+
description: Use when the user asks "what was I working on", "continue from last session", "restore context", "pick up where I left off", or after compaction/lost context. Restores session via bookmark snapshots.
|
|
4
|
+
version: 0.2.0
|
|
5
|
+
user-invocable: false
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
# Context Continuity Workflow
|
|
8
9
|
|
|
9
|
-
This skill
|
|
10
|
+
This skill restores and maintains context across Claude Code sessions and compactions using the Bookmark MCP tools.
|
|
10
11
|
|
|
11
12
|
## When to Activate
|
|
12
13
|
|
|
13
|
-
- User asks about prior session work
|
|
14
|
+
- User asks about prior session work or decisions
|
|
14
15
|
- User wants to continue a previous task
|
|
15
16
|
- After compaction when context was compressed
|
|
16
17
|
- User reports "losing" context or decisions
|
|
18
|
+
- Session start when prior context exists
|
|
17
19
|
|
|
18
20
|
## Restoration Flow
|
|
19
21
|
|
|
20
|
-
1. Check
|
|
21
|
-
```bash
|
|
22
|
-
npx @tyroneross/bookmark status
|
|
23
|
-
```
|
|
22
|
+
### 1. Check snapshot inventory
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
npx @tyroneross/bookmark show --latest
|
|
28
|
-
```
|
|
24
|
+
Use the `bookmark status` MCP tool to check if snapshots exist and how fresh they are.
|
|
29
25
|
|
|
30
|
-
|
|
31
|
-
- **Current Status**: What was being worked on
|
|
32
|
-
- **Decisions Made**: Key choices with rationale
|
|
33
|
-
- **Open Items**: What still needs doing
|
|
34
|
-
- **Unknowns**: Blockers or questions
|
|
26
|
+
The status tool returns: snapshot count, last capture time, freshness, compaction count, configured new-session threshold, and the latest measured model/context usage when available.
|
|
35
27
|
|
|
36
|
-
|
|
28
|
+
### 2. Restore context
|
|
37
29
|
|
|
38
|
-
|
|
30
|
+
Use the `bookmark restore` MCP tool to load the latest session context. This returns a structured summary optimized for continuation:
|
|
31
|
+
- **Current Status**: What was being worked on
|
|
32
|
+
- **Decisions Made**: Key choices with rationale
|
|
33
|
+
- **Open Items**: What still needs doing
|
|
34
|
+
- **Unknowns**: Blockers or questions
|
|
35
|
+
- **Files Changed**: What was modified
|
|
36
|
+
|
|
37
|
+
### 3. Present and continue
|
|
38
|
+
|
|
39
|
+
Summarize the restored context to the user. Ask which open item to continue with, or if the user has a new direction.
|
|
39
40
|
|
|
40
|
-
|
|
41
|
+
## Browsing History
|
|
42
|
+
|
|
43
|
+
To list available snapshots and view a specific one:
|
|
44
|
+
|
|
45
|
+
1. Use the `bookmark list` MCP tool to see all snapshots with timestamps and triggers
|
|
46
|
+
2. Use the `bookmark show` MCP tool with a snapshot_id to view full content of a specific snapshot
|
|
41
47
|
|
|
42
48
|
## Manual Snapshot
|
|
43
49
|
|
|
44
50
|
If the user wants to explicitly save context before a break:
|
|
45
|
-
```bash
|
|
46
|
-
npx @tyroneross/bookmark snapshot --trigger manual
|
|
47
|
-
```
|
|
48
51
|
|
|
49
|
-
|
|
52
|
+
Use the `bookmark snapshot` MCP tool with trigger "manual" to capture current session state.
|
|
53
|
+
|
|
54
|
+
## After Restoration
|
|
55
|
+
|
|
56
|
+
Once context is restored, continue working normally. The automatic hooks handle future snapshots — no manual intervention needed.
|
|
57
|
+
|
|
58
|
+
## MCP Tools Reference
|
|
59
|
+
|
|
60
|
+
| Tool | Purpose |
|
|
61
|
+
|------|---------|
|
|
62
|
+
| `status` | Snapshot inventory — count, freshness, thresholds |
|
|
63
|
+
| `restore` | Load latest or specific snapshot context for continuation |
|
|
64
|
+
| `list` | Browse all snapshots with metadata |
|
|
65
|
+
| `show` | View full content of a specific snapshot |
|
|
66
|
+
| `snapshot` | Capture a manual snapshot of current session |
|
|
67
|
+
|
|
68
|
+
*bookmark — session continuity*
|
package/commands/activate.md
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "Activate Bookmark context snapshots for this project"
|
|
3
|
-
allowed-tools: Bash
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
Activate Bookmark (context snapshots) for the current project. This configures hooks, creates storage directories, and sets up automatic context capture.
|
|
7
|
-
|
|
8
|
-
Run the setup command:
|
|
9
|
-
|
|
10
|
-
```bash
|
|
11
|
-
npx @tyroneross/bookmark setup --defaults
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
After activation, confirm to the user:
|
|
15
|
-
- Bookmark is now active for this project
|
|
16
|
-
- Snapshots will be captured automatically before compaction, on 20-minute intervals, and at session end
|
|
17
|
-
- Context will be restored automatically when starting a new session
|
|
18
|
-
- Available commands: `/bookmark:snapshot`, `/bookmark:status`, `/bookmark:list`, `/bookmark:restore`
|
|
19
|
-
|
|
20
|
-
*bookmark — context snapshot*
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { TokenEstimate } from '../types.js';
|
|
2
|
-
export interface EstimateOptions {
|
|
3
|
-
contextLimit?: number;
|
|
4
|
-
charsPerToken?: number;
|
|
5
|
-
startOffset?: number;
|
|
6
|
-
}
|
|
7
|
-
/**
|
|
8
|
-
* Estimate token usage from a transcript file.
|
|
9
|
-
* Uses a simple chars/4 heuristic — accurate enough for threshold comparison.
|
|
10
|
-
*/
|
|
11
|
-
export declare function estimateFromTranscript(transcriptPath: string, options?: EstimateOptions): TokenEstimate;
|
|
12
|
-
/**
|
|
13
|
-
* Quick file-size-based estimation without parsing.
|
|
14
|
-
* Much faster for threshold checks — reads only file metadata.
|
|
15
|
-
*/
|
|
16
|
-
export declare function quickEstimate(transcriptPath: string, contextLimit?: number, charsPerToken?: number): {
|
|
17
|
-
estimatedTokens: number;
|
|
18
|
-
remainingPct: number;
|
|
19
|
-
};
|
|
20
|
-
//# sourceMappingURL=estimator.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"estimator.d.ts","sourceRoot":"","sources":["../../src/transcript/estimator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAmB,MAAM,aAAa,CAAC;AAMlE,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,cAAc,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE,eAAe,GACxB,aAAa,CA2Df;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,cAAc,EAAE,MAAM,EACtB,YAAY,SAAwB,EACpC,aAAa,SAAkB,GAC9B;IAAE,eAAe,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAiBnD"}
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { existsSync, statSync } from 'node:fs';
|
|
2
|
-
import { parseTranscript } from './parser.js';
|
|
3
|
-
const DEFAULT_CONTEXT_LIMIT = 200_000;
|
|
4
|
-
const CHARS_PER_TOKEN = 4;
|
|
5
|
-
/**
|
|
6
|
-
* Estimate token usage from a transcript file.
|
|
7
|
-
* Uses a simple chars/4 heuristic — accurate enough for threshold comparison.
|
|
8
|
-
*/
|
|
9
|
-
export function estimateFromTranscript(transcriptPath, options) {
|
|
10
|
-
const contextLimit = options?.contextLimit ?? DEFAULT_CONTEXT_LIMIT;
|
|
11
|
-
const charsPerToken = options?.charsPerToken ?? CHARS_PER_TOKEN;
|
|
12
|
-
if (!existsSync(transcriptPath)) {
|
|
13
|
-
return emptyEstimate(contextLimit);
|
|
14
|
-
}
|
|
15
|
-
const { entries } = parseTranscript(transcriptPath, {
|
|
16
|
-
startOffset: options?.startOffset,
|
|
17
|
-
});
|
|
18
|
-
let userChars = 0;
|
|
19
|
-
let assistantChars = 0;
|
|
20
|
-
let toolChars = 0;
|
|
21
|
-
let systemChars = 0;
|
|
22
|
-
for (const entry of entries) {
|
|
23
|
-
const text = typeof entry.content === 'string' ? entry.content : '';
|
|
24
|
-
const len = text.length;
|
|
25
|
-
switch (entry.type) {
|
|
26
|
-
case 'user':
|
|
27
|
-
userChars += len;
|
|
28
|
-
break;
|
|
29
|
-
case 'assistant':
|
|
30
|
-
assistantChars += len;
|
|
31
|
-
break;
|
|
32
|
-
case 'tool_use':
|
|
33
|
-
case 'tool_result':
|
|
34
|
-
toolChars += len;
|
|
35
|
-
break;
|
|
36
|
-
case 'system':
|
|
37
|
-
systemChars += len;
|
|
38
|
-
break;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
const totalChars = userChars + assistantChars + toolChars + systemChars;
|
|
42
|
-
const totalTokens = Math.ceil(totalChars / charsPerToken);
|
|
43
|
-
const userTokens = Math.ceil(userChars / charsPerToken);
|
|
44
|
-
const assistantTokens = Math.ceil(assistantChars / charsPerToken);
|
|
45
|
-
const toolTokens = Math.ceil(toolChars / charsPerToken);
|
|
46
|
-
const systemTokens = Math.ceil(systemChars / charsPerToken);
|
|
47
|
-
const remainingTokens = Math.max(0, contextLimit - totalTokens);
|
|
48
|
-
const remainingPct = contextLimit > 0 ? remainingTokens / contextLimit : 1;
|
|
49
|
-
return {
|
|
50
|
-
total_tokens: totalTokens,
|
|
51
|
-
message_count: entries.length,
|
|
52
|
-
user_tokens: userTokens,
|
|
53
|
-
assistant_tokens: assistantTokens,
|
|
54
|
-
tool_tokens: toolTokens,
|
|
55
|
-
system_tokens: systemTokens,
|
|
56
|
-
context_limit: contextLimit,
|
|
57
|
-
remaining_pct: Math.round(remainingPct * 100) / 100,
|
|
58
|
-
remaining_tokens: remainingTokens,
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Quick file-size-based estimation without parsing.
|
|
63
|
-
* Much faster for threshold checks — reads only file metadata.
|
|
64
|
-
*/
|
|
65
|
-
export function quickEstimate(transcriptPath, contextLimit = DEFAULT_CONTEXT_LIMIT, charsPerToken = CHARS_PER_TOKEN) {
|
|
66
|
-
if (!existsSync(transcriptPath)) {
|
|
67
|
-
return { estimatedTokens: 0, remainingPct: 1 };
|
|
68
|
-
}
|
|
69
|
-
try {
|
|
70
|
-
const stat = statSync(transcriptPath);
|
|
71
|
-
// File size in bytes ≈ chars for ASCII-heavy content
|
|
72
|
-
// JSON overhead adds ~30%, so adjust
|
|
73
|
-
const estimatedContentChars = stat.size * 0.7;
|
|
74
|
-
const estimatedTokens = Math.ceil(estimatedContentChars / charsPerToken);
|
|
75
|
-
const remainingPct = Math.max(0, Math.round((1 - estimatedTokens / contextLimit) * 100) / 100);
|
|
76
|
-
return { estimatedTokens, remainingPct };
|
|
77
|
-
}
|
|
78
|
-
catch {
|
|
79
|
-
return { estimatedTokens: 0, remainingPct: 1 };
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
function emptyEstimate(contextLimit) {
|
|
83
|
-
return {
|
|
84
|
-
total_tokens: 0,
|
|
85
|
-
message_count: 0,
|
|
86
|
-
user_tokens: 0,
|
|
87
|
-
assistant_tokens: 0,
|
|
88
|
-
tool_tokens: 0,
|
|
89
|
-
system_tokens: 0,
|
|
90
|
-
context_limit: contextLimit,
|
|
91
|
-
remaining_pct: 1,
|
|
92
|
-
remaining_tokens: contextLimit,
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
//# sourceMappingURL=estimator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"estimator.js","sourceRoot":"","sources":["../../src/transcript/estimator.ts"],"names":[],"mappings":"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"}
|