claude-mem 3.2.0 → 3.2.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 (50) hide show
  1. package/claude-mem +0 -0
  2. package/package.json +1 -2
  3. package/dist/bin/cli.d.ts +0 -2
  4. package/dist/bin/cli.js +0 -129
  5. package/dist/commands/compress.d.ts +0 -2
  6. package/dist/commands/compress.js +0 -27
  7. package/dist/commands/hooks.d.ts +0 -19
  8. package/dist/commands/hooks.js +0 -131
  9. package/dist/commands/install.d.ts +0 -2
  10. package/dist/commands/install.js +0 -649
  11. package/dist/commands/load-context.d.ts +0 -2
  12. package/dist/commands/load-context.js +0 -108
  13. package/dist/commands/logs.d.ts +0 -2
  14. package/dist/commands/logs.js +0 -76
  15. package/dist/commands/migrate-to-jsonl.d.ts +0 -5
  16. package/dist/commands/migrate-to-jsonl.js +0 -99
  17. package/dist/commands/status.d.ts +0 -1
  18. package/dist/commands/status.js +0 -136
  19. package/dist/commands/uninstall.d.ts +0 -2
  20. package/dist/commands/uninstall.js +0 -107
  21. package/dist/constants.d.ts +0 -271
  22. package/dist/constants.js +0 -199
  23. package/dist/core/compression/TranscriptCompressor.d.ts +0 -83
  24. package/dist/core/compression/TranscriptCompressor.js +0 -602
  25. package/dist/core/orchestration/PromptOrchestrator.d.ts +0 -165
  26. package/dist/core/orchestration/PromptOrchestrator.js +0 -182
  27. package/dist/lib/time-utils.d.ts +0 -5
  28. package/dist/lib/time-utils.js +0 -70
  29. package/dist/prompts/constants.d.ts +0 -126
  30. package/dist/prompts/constants.js +0 -161
  31. package/dist/prompts/index.d.ts +0 -10
  32. package/dist/prompts/index.js +0 -11
  33. package/dist/prompts/templates/analysis/AnalysisTemplates.d.ts +0 -13
  34. package/dist/prompts/templates/analysis/AnalysisTemplates.js +0 -94
  35. package/dist/prompts/templates/context/ContextTemplates.d.ts +0 -119
  36. package/dist/prompts/templates/context/ContextTemplates.js +0 -399
  37. package/dist/prompts/templates/hooks/HookTemplates.d.ts +0 -175
  38. package/dist/prompts/templates/hooks/HookTemplates.js +0 -394
  39. package/dist/prompts/templates/hooks/HookTemplates.test.d.ts +0 -7
  40. package/dist/prompts/templates/hooks/HookTemplates.test.js +0 -127
  41. package/dist/shared/config.d.ts +0 -4
  42. package/dist/shared/config.js +0 -41
  43. package/dist/shared/error-handler.d.ts +0 -22
  44. package/dist/shared/error-handler.js +0 -142
  45. package/dist/shared/logger.d.ts +0 -19
  46. package/dist/shared/logger.js +0 -51
  47. package/dist/shared/paths.d.ts +0 -28
  48. package/dist/shared/paths.js +0 -100
  49. package/dist/shared/types.d.ts +0 -141
  50. package/dist/shared/types.js +0 -78
@@ -1,108 +0,0 @@
1
- import fs from 'fs';
2
- import { PathResolver } from '../shared/paths.js';
3
- import { createCompletionMessage, createContextualError, createUserFriendlyError, formatTimeAgo, outputSessionStartContent } from '../prompts/templates/context/ContextTemplates.js';
4
- export async function loadContext(options = {}) {
5
- const pathResolver = new PathResolver();
6
- const indexPath = pathResolver.getIndexPath();
7
- try {
8
- // Check if index file exists
9
- if (!fs.existsSync(indexPath)) {
10
- if (options.format === 'session-start') {
11
- console.log(createContextualError('NO_MEMORIES', options.project || 'this project'));
12
- }
13
- return;
14
- }
15
- const content = fs.readFileSync(indexPath, 'utf-8');
16
- const lines = content.trim().split('\n').filter(line => line.trim());
17
- if (lines.length === 0) {
18
- if (options.format === 'session-start') {
19
- console.log(createContextualError('NO_MEMORIES', options.project || 'this project'));
20
- }
21
- return;
22
- }
23
- // Parse JSONL format - each line is a JSON object
24
- const jsonObjects = [];
25
- for (const line of lines) {
26
- try {
27
- // Skip lines that don't look like JSON (could be legacy format)
28
- if (!line.trim().startsWith('{')) {
29
- continue;
30
- }
31
- const obj = JSON.parse(line);
32
- jsonObjects.push(obj);
33
- }
34
- catch (e) {
35
- // Skip malformed JSON lines
36
- continue;
37
- }
38
- }
39
- if (jsonObjects.length === 0) {
40
- if (options.format === 'session-start') {
41
- console.log(createContextualError('NO_MEMORIES', options.project || 'this project'));
42
- }
43
- return;
44
- }
45
- // Filter by project if specified
46
- let filteredObjects = jsonObjects;
47
- if (options.project) {
48
- // Sanitize project name to match how it's stored (replace hyphens with underscores)
49
- const sanitizedProject = options.project.replace(/-/g, '_');
50
- // Filter objects by project field
51
- filteredObjects = jsonObjects.filter(obj => obj.project === sanitizedProject || obj.project === options.project);
52
- }
53
- // Take more entries for session-start to get multiple overviews
54
- const count = options.format === 'session-start' ? 30 : 10;
55
- const recentObjects = filteredObjects.slice(-count);
56
- if (options.format === 'session-start') {
57
- // Find most recent timestamp for last session info
58
- let lastSessionTime = 'recently';
59
- const timestamps = recentObjects
60
- .map(obj => {
61
- // Get timestamp from JSON object
62
- return obj.timestamp ? new Date(obj.timestamp) : null;
63
- })
64
- .filter(date => date !== null)
65
- .sort((a, b) => b.getTime() - a.getTime());
66
- if (timestamps.length > 0) {
67
- lastSessionTime = formatTimeAgo(timestamps[0]);
68
- }
69
- // Use dual-stream output for session start formatting
70
- outputSessionStartContent({
71
- projectName: options.project || 'your project',
72
- memoryCount: recentObjects.length,
73
- lastSessionTime,
74
- recentObjects
75
- });
76
- }
77
- else if (options.format === 'json') {
78
- console.log(JSON.stringify(recentObjects));
79
- }
80
- else {
81
- // Default format - show completion message and entries
82
- console.log(createCompletionMessage('Context loading', recentObjects.length, 'recent memories found'));
83
- recentObjects.forEach((obj) => {
84
- if (obj.type === 'memory') {
85
- console.log(`${obj.text} | ${obj.document_id} | ${obj.keywords}`);
86
- }
87
- else if (obj.type === 'overview') {
88
- console.log(`**Overview:** ${obj.content}`);
89
- }
90
- else if (obj.type === 'session') {
91
- console.log(`# Session: ${obj.session_id} [${obj.timestamp}]`);
92
- }
93
- else {
94
- console.log(JSON.stringify(obj));
95
- }
96
- });
97
- }
98
- }
99
- catch (error) {
100
- const errorMessage = error instanceof Error ? error.message : String(error);
101
- if (options.format === 'session-start') {
102
- console.log(createContextualError('CONNECTION_FAILED', errorMessage));
103
- }
104
- else {
105
- console.log(createUserFriendlyError('Context loading', errorMessage, 'Check file permissions and try again'));
106
- }
107
- }
108
- }
@@ -1,2 +0,0 @@
1
- import { OptionValues } from 'commander';
2
- export declare function logs(options?: OptionValues): Promise<void>;
@@ -1,76 +0,0 @@
1
- import { readFileSync, readdirSync, statSync } from 'fs';
2
- import { join } from 'path';
3
- import { homedir } from 'os';
4
- // <Block> 1.1 ====================================
5
- async function showLog(logPath, logType, tail) {
6
- // <Block> 1.2 ====================================
7
- try {
8
- const content = readFileSync(logPath, 'utf8');
9
- const lines = content.split('\n').filter(line => line.trim());
10
- const displayLines = lines.slice(-tail);
11
- console.log(`📋 ${logType} Logs (last ${tail} lines):`);
12
- console.log(` File: ${logPath}`);
13
- console.log('');
14
- // <Block> 1.3 ====================================
15
- if (displayLines.length === 0) {
16
- console.log(' No log entries found');
17
- // </Block> =======================================
18
- }
19
- else {
20
- displayLines.forEach(line => {
21
- console.log(` ${line}`);
22
- });
23
- }
24
- // </Block> =======================================
25
- console.log('');
26
- // </Block> =======================================
27
- }
28
- catch (error) {
29
- // <Block> 1.4 ====================================
30
- console.log(`❌ Could not read ${logType.toLowerCase()} log: ${logPath}`);
31
- // </Block> =======================================
32
- }
33
- // </Block> =======================================
34
- }
35
- // <Block> 2.1 ====================================
36
- export async function logs(options = {}) {
37
- // <Block> 2.2 ====================================
38
- const logsDir = join(homedir(), '.claude-mem', 'logs');
39
- const tail = parseInt(options.tail) || 20;
40
- // </Block> =======================================
41
- // Find most recent log file
42
- try {
43
- const files = readdirSync(logsDir);
44
- const logFiles = files
45
- .filter(f => f.startsWith('claude-mem-') && f.endsWith('.log'))
46
- .map(f => ({
47
- name: f,
48
- path: join(logsDir, f),
49
- mtime: statSync(join(logsDir, f)).mtime
50
- }))
51
- .sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
52
- if (logFiles.length === 0) {
53
- console.log('❌ No log files found in ~/.claude-mem/logs/');
54
- return;
55
- }
56
- // Show most recent log
57
- await showLog(logFiles[0].path, 'Most Recent', tail);
58
- if (options.all && logFiles.length > 1) {
59
- console.log(`📚 Found ${logFiles.length} total log files`);
60
- }
61
- }
62
- catch (error) {
63
- console.log('❌ Could not read logs directory: ~/.claude-mem/logs/');
64
- console.log(' Run a compression first to generate logs');
65
- }
66
- // <Block> 2.5 ====================================
67
- if (options.follow) {
68
- console.log('Following logs... (Press Ctrl+C to stop)');
69
- // Basic follow implementation - would need more sophisticated watching in real usage
70
- setInterval(() => {
71
- // This would need proper file watching implementation
72
- }, 1000);
73
- }
74
- // </Block> =======================================
75
- // </Block> =======================================
76
- }
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * One-time migration script to convert claude-mem-index.md to claude-mem-index.jsonl
4
- */
5
- export declare function migrateToJSONL(): void;
@@ -1,99 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * One-time migration script to convert claude-mem-index.md to claude-mem-index.jsonl
4
- */
5
- import fs from 'fs';
6
- import path from 'path';
7
- import { PathResolver } from '../shared/paths.js';
8
- export function migrateToJSONL() {
9
- const pathResolver = new PathResolver();
10
- const oldIndexPath = path.join(pathResolver.getConfigDir(), 'claude-mem-index.md');
11
- const newIndexPath = path.join(pathResolver.getConfigDir(), 'claude-mem-index.jsonl');
12
- // Check if old index exists
13
- if (!fs.existsSync(oldIndexPath)) {
14
- console.log('No markdown index found to migrate');
15
- return;
16
- }
17
- // Check if new index already exists
18
- if (fs.existsSync(newIndexPath)) {
19
- console.log('JSONL index already exists, skipping migration');
20
- return;
21
- }
22
- console.log('Starting migration from MD to JSONL...');
23
- const content = fs.readFileSync(oldIndexPath, 'utf-8');
24
- const lines = content.split('\n').filter(line => line.trim());
25
- const jsonlLines = [];
26
- let currentSessionId = '';
27
- let currentSessionTimestamp = '';
28
- for (const line of lines) {
29
- // Parse session headers: # Session: <id> [<timestamp>]
30
- const sessionMatch = line.match(/^# Session:\s*([^\[]+)(?:\s*\[([^\]]+)\])?/);
31
- if (sessionMatch) {
32
- currentSessionId = sessionMatch[1].trim();
33
- currentSessionTimestamp = sessionMatch[2]?.trim() || new Date().toISOString();
34
- // Extract project from session ID (assuming format like <project>_<uuid>)
35
- const projectMatch = currentSessionId.match(/^([^_]+)_/);
36
- const project = projectMatch ? projectMatch[1] : 'unknown';
37
- jsonlLines.push(JSON.stringify({
38
- type: 'session',
39
- session_id: currentSessionId,
40
- timestamp: currentSessionTimestamp,
41
- project
42
- }));
43
- continue;
44
- }
45
- // Parse overviews: **Overview:** <text>
46
- const overviewMatch = line.match(/^\*\*Overview:\*\*\s*(.+)/);
47
- if (overviewMatch) {
48
- const overviewText = overviewMatch[1].trim();
49
- // Extract project from current session ID
50
- const projectMatch = currentSessionId.match(/^([^_]+)_/);
51
- const project = projectMatch ? projectMatch[1] : 'unknown';
52
- jsonlLines.push(JSON.stringify({
53
- type: 'overview',
54
- content: overviewText,
55
- session_id: currentSessionId,
56
- project,
57
- timestamp: currentSessionTimestamp
58
- }));
59
- continue;
60
- }
61
- // Skip certain lines
62
- if (line.startsWith('# NO SUMMARIES EXTRACTED')) {
63
- continue;
64
- }
65
- // Parse memory entries (pipe-separated)
66
- if (line.includes(' | ')) {
67
- const parts = line.split(' | ').map(p => p.trim());
68
- if (parts.length >= 3) {
69
- const [text, document_id, keywords, timestamp, archive] = parts;
70
- // Extract project from document_id (format: <project>_<session>_<number>)
71
- const projectMatch = document_id?.match(/^([^_]+)_/);
72
- const project = projectMatch ? projectMatch[1] : 'unknown';
73
- jsonlLines.push(JSON.stringify({
74
- type: 'memory',
75
- text,
76
- document_id: document_id || `${currentSessionId}_${Date.now()}`,
77
- keywords: keywords || '',
78
- session_id: currentSessionId,
79
- project,
80
- timestamp: timestamp || currentSessionTimestamp,
81
- archive: archive || `${currentSessionId}.jsonl.archive`
82
- }));
83
- }
84
- }
85
- }
86
- // Write JSONL file
87
- fs.writeFileSync(newIndexPath, jsonlLines.join('\n') + '\n');
88
- // Backup old index
89
- const backupPath = oldIndexPath + '.backup';
90
- fs.renameSync(oldIndexPath, backupPath);
91
- console.log(`✅ Migration complete!`);
92
- console.log(` - Converted ${jsonlLines.length} entries`);
93
- console.log(` - New index: ${newIndexPath}`);
94
- console.log(` - Backup: ${backupPath}`);
95
- }
96
- // Run if called directly
97
- if (import.meta.url === `file://${process.argv[1]}`) {
98
- migrateToJSONL();
99
- }
@@ -1 +0,0 @@
1
- export declare function status(): Promise<void>;
@@ -1,136 +0,0 @@
1
- import { readFileSync, existsSync, readdirSync, statSync } from 'fs';
2
- import { join, dirname } from 'path';
3
- import { homedir } from 'os';
4
- import { execSync } from 'child_process';
5
- import { fileURLToPath } from 'url';
6
- const __dirname = dirname(fileURLToPath(import.meta.url));
7
- export async function status() {
8
- console.log('🔍 Claude Memory System Status Check');
9
- console.log('=====================================\n');
10
- console.log('📂 Installed Hook Scripts:');
11
- const claudeMemHooksDir = join(homedir(), '.claude-mem', 'hooks');
12
- const preCompactScript = join(claudeMemHooksDir, 'pre-compact.js');
13
- const sessionStartScript = join(claudeMemHooksDir, 'session-start.js');
14
- const sessionEndScript = join(claudeMemHooksDir, 'session-end.js');
15
- const checkScript = (path, name) => {
16
- if (existsSync(path)) {
17
- console.log(` ✅ ${name}: Found at ${path}`);
18
- }
19
- else {
20
- console.log(` ❌ ${name}: Not found at ${path}`);
21
- }
22
- };
23
- checkScript(preCompactScript, 'pre-compact.js');
24
- checkScript(sessionStartScript, 'session-start.js');
25
- checkScript(sessionEndScript, 'session-end.js');
26
- console.log('');
27
- console.log('âš™ī¸ Settings Configuration:');
28
- const checkSettings = (name, path) => {
29
- if (!existsSync(path)) {
30
- console.log(` â­ī¸ ${name}: No settings file`);
31
- return;
32
- }
33
- console.log(` 📋 ${name}: ${path}`);
34
- try {
35
- const settings = JSON.parse(readFileSync(path, 'utf8'));
36
- const hasPreCompact = settings.hooks?.PreCompact?.some((matcher) => matcher.hooks?.some((hook) => hook.command?.includes('pre-compact.js') || hook.command?.includes('claude-mem')));
37
- const hasSessionStart = settings.hooks?.SessionStart?.some((matcher) => matcher.hooks?.some((hook) => hook.command?.includes('session-start.js') || hook.command?.includes('claude-mem')));
38
- const hasSessionEnd = settings.hooks?.SessionEnd?.some((matcher) => matcher.hooks?.some((hook) => hook.command?.includes('session-end.js') || hook.command?.includes('claude-mem')));
39
- console.log(` PreCompact: ${hasPreCompact ? '✅' : '❌'}`);
40
- console.log(` SessionStart: ${hasSessionStart ? '✅' : '❌'}`);
41
- console.log(` SessionEnd: ${hasSessionEnd ? '✅' : '❌'}`);
42
- }
43
- catch (error) {
44
- console.log(` âš ī¸ Could not parse settings`);
45
- }
46
- };
47
- checkSettings('Global', join(homedir(), '.claude', 'settings.json'));
48
- checkSettings('Project', join(process.cwd(), '.claude', 'settings.json'));
49
- console.log('');
50
- console.log('đŸ“Ļ Compressed Transcripts:');
51
- const claudeProjectsDir = join(homedir(), '.claude', 'projects');
52
- if (existsSync(claudeProjectsDir)) {
53
- try {
54
- let compressedCount = 0;
55
- let archiveCount = 0;
56
- const searchDir = (dir, depth = 0) => {
57
- if (depth > 3)
58
- return;
59
- const files = readdirSync(dir);
60
- for (const file of files) {
61
- const fullPath = join(dir, file);
62
- const stats = statSync(fullPath);
63
- if (stats.isDirectory() && !file.startsWith('.')) {
64
- searchDir(fullPath, depth + 1);
65
- }
66
- else if (file.endsWith('.jsonl.compressed')) {
67
- compressedCount++;
68
- }
69
- else if (file.endsWith('.jsonl.archive')) {
70
- archiveCount++;
71
- }
72
- }
73
- };
74
- searchDir(claudeProjectsDir);
75
- console.log(` Compressed files: ${compressedCount}`);
76
- console.log(` Archive files: ${archiveCount}`);
77
- }
78
- catch (error) {
79
- console.log(` âš ī¸ Could not scan projects directory`);
80
- }
81
- }
82
- else {
83
- console.log(` â„šī¸ No Claude projects directory found`);
84
- }
85
- console.log('');
86
- console.log('🔧 Runtime Environment:');
87
- const checkCommand = (cmd, name) => {
88
- try {
89
- const version = execSync(`${cmd} --version`, { encoding: 'utf8' }).trim();
90
- console.log(` ✅ ${name}: ${version}`);
91
- }
92
- catch {
93
- console.log(` ❌ ${name}: Not found`);
94
- }
95
- };
96
- checkCommand('node', 'Node.js');
97
- checkCommand('bun', 'Bun');
98
- console.log('');
99
- console.log('🧠 Chroma Storage Status:');
100
- console.log(' ✅ Storage backend: Chroma MCP');
101
- console.log(' 📍 Data location: ~/.claude-mem/chroma');
102
- console.log(' 🔍 Features: Vector search, semantic similarity, document storage');
103
- console.log('');
104
- console.log('📊 Summary:');
105
- const globalPath = join(homedir(), '.claude', 'settings.json');
106
- const projectPath = join(process.cwd(), '.claude', 'settings.json');
107
- let isInstalled = false;
108
- let installLocation = 'Not installed';
109
- try {
110
- if (existsSync(globalPath)) {
111
- const settings = JSON.parse(readFileSync(globalPath, 'utf8'));
112
- if (settings.hooks?.PreCompact || settings.hooks?.SessionStart || settings.hooks?.SessionEnd) {
113
- isInstalled = true;
114
- installLocation = 'Global';
115
- }
116
- }
117
- if (existsSync(projectPath)) {
118
- const settings = JSON.parse(readFileSync(projectPath, 'utf8'));
119
- if (settings.hooks?.PreCompact || settings.hooks?.SessionStart || settings.hooks?.SessionEnd) {
120
- isInstalled = true;
121
- installLocation = installLocation === 'Global' ? 'Global + Project' : 'Project';
122
- }
123
- }
124
- }
125
- catch { }
126
- if (isInstalled) {
127
- console.log(` ✅ Claude Memory System is installed (${installLocation})`);
128
- console.log('');
129
- console.log('💡 To test: Use /compact in Claude Code');
130
- }
131
- else {
132
- console.log(` ❌ Claude Memory System is not installed`);
133
- console.log('');
134
- console.log('💡 To install: claude-mem install');
135
- }
136
- }
@@ -1,2 +0,0 @@
1
- import { OptionValues } from 'commander';
2
- export declare function uninstall(options?: OptionValues): Promise<void>;
@@ -1,107 +0,0 @@
1
- import { readFileSync, writeFileSync, existsSync } from 'fs';
2
- import { join } from 'path';
3
- import { homedir } from 'os';
4
- export async function uninstall(options = {}) {
5
- console.log('🔄 Uninstalling Claude Memory System hooks...');
6
- const locations = [];
7
- if (options.all) {
8
- locations.push({
9
- name: 'User',
10
- path: join(homedir(), '.claude', 'settings.json')
11
- });
12
- locations.push({
13
- name: 'Project',
14
- path: join(process.cwd(), '.claude', 'settings.json')
15
- });
16
- }
17
- else {
18
- const isProject = options.project;
19
- locations.push({
20
- name: isProject ? 'Project' : 'User',
21
- path: join(isProject ? process.cwd() : homedir(), '.claude', 'settings.json')
22
- });
23
- }
24
- const claudeMemHooksDir = join(homedir(), '.claude-mem', 'hooks');
25
- const preCompactScript = join(claudeMemHooksDir, 'pre-compact.js');
26
- const sessionStartScript = join(claudeMemHooksDir, 'session-start.js');
27
- const sessionEndScript = join(claudeMemHooksDir, 'session-end.js');
28
- let removedCount = 0;
29
- for (const location of locations) {
30
- if (!existsSync(location.path)) {
31
- console.log(`â­ī¸ No settings found at ${location.name} location`);
32
- continue;
33
- }
34
- try {
35
- const content = readFileSync(location.path, 'utf8');
36
- const settings = JSON.parse(content);
37
- if (!settings.hooks) {
38
- console.log(`â­ī¸ No hooks configured in ${location.name} settings`);
39
- continue;
40
- }
41
- let modified = false;
42
- if (settings.hooks.PreCompact) {
43
- const filteredPreCompact = settings.hooks.PreCompact.filter((matcher) => !matcher.hooks?.some((hook) => hook.command === preCompactScript ||
44
- hook.command?.includes('pre-compact.js') ||
45
- hook.command?.includes('claude-mem')));
46
- if (filteredPreCompact.length !== settings.hooks.PreCompact.length) {
47
- settings.hooks.PreCompact = filteredPreCompact.length ? filteredPreCompact : undefined;
48
- modified = true;
49
- console.log(`✅ Removed PreCompact hook from ${location.name} settings`);
50
- }
51
- }
52
- if (settings.hooks.SessionStart) {
53
- const filteredSessionStart = settings.hooks.SessionStart.filter((matcher) => !matcher.hooks?.some((hook) => hook.command === sessionStartScript ||
54
- hook.command?.includes('session-start.js') ||
55
- hook.command?.includes('claude-mem')));
56
- if (filteredSessionStart.length !== settings.hooks.SessionStart.length) {
57
- settings.hooks.SessionStart = filteredSessionStart.length ? filteredSessionStart : undefined;
58
- modified = true;
59
- console.log(`✅ Removed SessionStart hook from ${location.name} settings`);
60
- }
61
- }
62
- if (settings.hooks.SessionEnd) {
63
- const filteredSessionEnd = settings.hooks.SessionEnd.filter((matcher) => !matcher.hooks?.some((hook) => hook.command === sessionEndScript ||
64
- hook.command?.includes('session-end.js') ||
65
- hook.command?.includes('claude-mem')));
66
- if (filteredSessionEnd.length !== settings.hooks.SessionEnd.length) {
67
- settings.hooks.SessionEnd = filteredSessionEnd.length ? filteredSessionEnd : undefined;
68
- modified = true;
69
- console.log(`✅ Removed SessionEnd hook from ${location.name} settings`);
70
- }
71
- }
72
- if (settings.hooks.PreCompact === undefined)
73
- delete settings.hooks.PreCompact;
74
- if (settings.hooks.SessionStart === undefined)
75
- delete settings.hooks.SessionStart;
76
- if (settings.hooks.SessionEnd === undefined)
77
- delete settings.hooks.SessionEnd;
78
- if (!Object.keys(settings.hooks).length)
79
- delete settings.hooks;
80
- if (modified) {
81
- const backupPath = location.path + '.backup.' + Date.now();
82
- writeFileSync(backupPath, content);
83
- console.log(`📋 Created backup: ${backupPath}`);
84
- writeFileSync(location.path, JSON.stringify(settings, null, 2));
85
- removedCount++;
86
- console.log(`✅ Updated ${location.name} settings: ${location.path}`);
87
- }
88
- else {
89
- console.log(`â„šī¸ No Claude Memory System hooks found in ${location.name} settings`);
90
- }
91
- }
92
- catch (error) {
93
- console.log(`âš ī¸ Could not process ${location.name} settings: ${error.message}`);
94
- }
95
- }
96
- console.log('');
97
- if (removedCount > 0) {
98
- console.log('✨ Uninstallation complete!');
99
- console.log('The Claude Memory System hooks have been removed from your settings.');
100
- console.log('');
101
- console.log('Note: Your compressed transcripts and archives are preserved.');
102
- console.log('To reinstall: claude-mem install');
103
- }
104
- else {
105
- console.log('â„šī¸ No Claude Memory System hooks were found to remove.');
106
- }
107
- }