claude-mem 2.1.2 → 3.0.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.
@@ -1,75 +1,190 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * Claude Memory System - Session-Start Hook (Refactored)
5
- * Uses shared utilities to eliminate code duplication
4
+ * 🔒 LOCKED by @docs-agent | Change to 🔑 to allow @docs-agent edits
6
5
  *
7
- * Always loads context regardless of source (startup/compact/vscode/web)
6
+ * OFFICIAL DOCS: Claude Code SessionStart Hook v2025
7
+ * Last Verified: 2025-08-31
8
+ * @see https://docs.anthropic.com/en/docs/claude-code/hooks
9
+ *
10
+ * SessionStart Hook Payload:
11
+ * {
12
+ * "session_id": "string",
13
+ * "transcript_path": "string",
14
+ * "hook_event_name": "SessionStart",
15
+ * "source": "startup" | "compact" | "vscode" | "web"
16
+ * }
17
+ *
18
+ * The 'source' field indicates how the session was initiated:
19
+ * - "startup": New session started normally
20
+ * - "compact": Session started after compaction
21
+ * - "vscode": Session initiated from VS Code
22
+ * - "web": Session initiated from web interface
23
+ *
24
+ * Valid Response Format:
25
+ * Success without context: { "continue": true }
26
+ * Success with context: {
27
+ * "continue": true,
28
+ * "hookSpecificOutput": {
29
+ * "hookEventName": "SessionStart",
30
+ * "additionalContext": "string" // Context to add to session
31
+ * }
32
+ * }
33
+ * Failure: { "continue": false, "stopReason": "error message" }
34
+ *
35
+ * @docs-ref: SessionStart supports hookSpecificOutput.additionalContext
36
+ * @see https://docs.anthropic.com/claude-code/hooks#sessionstart
8
37
  */
9
38
 
10
- import { loadHookConfig, readStdinJson, HookResponse, spawnCLI } from './hook-utils.js';
11
- import { dirname, basename } from 'path';
39
+ import { spawn } from 'child_process';
40
+ import { join, dirname, basename } from 'path';
41
+ import { fileURLToPath } from 'url';
42
+ import { readFileSync, existsSync } from 'fs';
12
43
 
13
- async function sessionStartHook() {
44
+ const __dirname = dirname(fileURLToPath(import.meta.url));
45
+
46
+ // Load configuration to get the CLI command name
47
+ let cliCommand = 'claude-mem'; // Default fallback
48
+ const configPath = join(__dirname, 'config.json');
49
+ if (existsSync(configPath)) {
14
50
  try {
15
- // Load config and read input using utilities
16
- const config = loadHookConfig();
17
- const data = await readStdinJson();
18
-
19
- // Extract project name from transcript path if available
20
- let projectName = null;
21
- if (data.transcript_path) {
22
- const dir = dirname(data.transcript_path);
23
- const dirName = basename(dir);
51
+ const config = JSON.parse(readFileSync(configPath, 'utf-8'));
52
+ cliCommand = config.cliCommand || 'claude-mem';
53
+ } catch (e) {
54
+ // Fallback to default if config read fails
55
+ }
56
+ }
57
+
58
+ async function sessionStartHook() {
59
+ let input = '';
60
+
61
+ // Read JSON input from stdin
62
+ process.stdin.on('data', chunk => {
63
+ input += chunk;
64
+ });
65
+
66
+ process.stdin.on('end', async () => {
67
+ try {
68
+ const data = JSON.parse(input);
69
+
70
+ /**
71
+ * @docs-ref: SessionStart payload includes 'source' field
72
+ * See: https://docs.anthropic.com/en/docs/claude-code/hooks#sessionstart
73
+ *
74
+ * The 'source' field indicates the session start context:
75
+ * - 'startup': New session (load context)
76
+ * - 'compact': Session after compaction (SHOULD load context)
77
+ * - 'vscode': VS Code initiated session
78
+ * - 'web': Web interface initiated session
79
+ *
80
+ * IMPORTANT: We always load context regardless of source.
81
+ * After compaction, users expect to see their compressed memories loaded.
82
+ * The session after compact is effectively a new session with compressed context.
83
+ *
84
+ * There is no specific indicator for /continue command in the payload,
85
+ * so we treat all session starts equally and load available context.
86
+ */
87
+ // Always proceed to load context for all session types
24
88
 
25
- // Extract project name from directory pattern
26
- if (dirName.includes('-Scripts-')) {
27
- const parts = dirName.split('-Scripts-');
28
- if (parts.length > 1) {
29
- projectName = parts[1];
89
+ // Extract project name from transcript path if available
90
+ let projectName = null;
91
+ if (data.transcript_path) {
92
+ const dir = dirname(data.transcript_path);
93
+ const dirName = basename(dir);
94
+
95
+ // Extract project name from directory pattern
96
+ if (dirName.includes('-Scripts-')) {
97
+ const parts = dirName.split('-Scripts-');
98
+ if (parts.length > 1) {
99
+ projectName = parts[1];
100
+ }
101
+ } else {
102
+ projectName = dirName;
103
+ }
104
+
105
+ // Sanitize project name to match what compression uses
106
+ // This ensures we match the exact project name in the index
107
+ if (projectName) {
108
+ projectName = projectName.replace(/[^a-zA-Z0-9]/g, '_');
30
109
  }
31
- } else {
32
- projectName = dirName;
33
110
  }
34
111
 
35
- // Sanitize project name to match what compression uses
112
+ // Build command to run
113
+ const args = ['load-context', '--format', 'session-start'];
114
+
115
+ // Add project filter if we have a project name
36
116
  if (projectName) {
37
- projectName = projectName.replace(/[^a-zA-Z0-9]/g, '_');
117
+ args.push('--project', projectName);
38
118
  }
39
- }
40
-
41
- // Build command to run
42
- const args = ['load-context', '--format', 'session-start'];
43
- if (projectName) {
44
- args.push('--project', projectName);
45
- }
46
-
47
- // Use spawnCLI utility for loading context
48
- const cliCommand = config.cliCommand || 'claude-mem';
49
-
50
- try {
51
- const result = await spawnCLI(cliCommand, args);
52
119
 
53
- // Output the formatted context if we have any
54
- if (result.stdout && result.stdout.trim()) {
55
- console.log(JSON.stringify(HookResponse.success("SessionStart", result.stdout)));
56
- } else {
57
- console.log(JSON.stringify({ continue: true }));
58
- }
120
+ // Call the CLI load-context command directly
121
+ // Use the configured CLI command name (claude-mem)
122
+ // This ensures we use the correct version with full summaries
123
+ const loader = spawn(cliCommand, args, {
124
+ stdio: ['ignore', 'pipe', 'pipe']
125
+ });
126
+
127
+ let stdout = '';
128
+ let stderr = '';
129
+
130
+ loader.stdout.on('data', (data) => {
131
+ stdout += data.toString();
132
+ });
133
+
134
+ loader.stderr.on('data', (data) => {
135
+ stderr += data.toString();
136
+ });
137
+
138
+ loader.on('close', (code) => {
139
+ if (code !== 0) {
140
+ // If load-context fails, just continue without context
141
+ // This could happen if no index exists yet
142
+ // @docs-ref: Always return valid response format
143
+ console.log(JSON.stringify({
144
+ continue: true
145
+ }));
146
+ process.exit(0);
147
+ }
148
+
149
+ // Output the formatted context for Claude to see using proper JSON format
150
+ // @docs-ref: SessionStart supports hookSpecificOutput.additionalContext
151
+ if (stdout && stdout.trim()) {
152
+ console.log(JSON.stringify({
153
+ continue: true,
154
+ hookSpecificOutput: {
155
+ hookEventName: "SessionStart",
156
+ additionalContext: stdout
157
+ }
158
+ }));
159
+ } else {
160
+ // No context to add, just continue
161
+ console.log(JSON.stringify({
162
+ continue: true
163
+ }));
164
+ }
165
+
166
+ process.exit(0);
167
+ });
168
+
169
+ loader.on('error', () => {
170
+ // If there's an error running the command, continue without context
171
+ // We don't want to break the session start
172
+ // @docs-ref: Always return valid response format
173
+ console.log(JSON.stringify({
174
+ continue: true
175
+ }));
176
+ process.exit(0);
177
+ });
59
178
 
60
179
  } catch (error) {
61
- // If load-context fails, just continue without context
62
- // This could happen if no index exists yet
63
- console.log(JSON.stringify({ continue: true }));
180
+ // Any errors, just continue without additional context
181
+ // @docs-ref: Always return valid response format
182
+ console.log(JSON.stringify({
183
+ continue: true
184
+ }));
185
+ process.exit(0);
64
186
  }
65
-
66
- process.exit(0);
67
-
68
- } catch (error) {
69
- // Any errors, just continue without additional context
70
- console.log(JSON.stringify({ continue: true }));
71
- process.exit(0);
72
- }
187
+ });
73
188
  }
74
189
 
75
190
  sessionStartHook();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mem",
3
- "version": "2.1.2",
3
+ "version": "3.0.2",
4
4
  "description": "Memory compression system for Claude Code - persist context across sessions",
5
5
  "keywords": [
6
6
  "claude",