Files
claude-mem/src/commands/uninstall.ts
T
Alex Newman 85ed7c3d2f Release v3.9.9
Published from npm package build
Source: https://github.com/thedotmack/claude-mem-source
2025-10-03 18:20:47 -04:00

198 lines
6.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { OptionValues } from 'commander';
import { readFileSync, writeFileSync, existsSync } from 'fs';
import { join } from 'path';
import { homedir } from 'os';
import { PathDiscovery } from '../services/path-discovery.js';
async function removeSmartTrashAlias(): Promise<boolean> {
const homeDir = homedir();
const shellConfigs = [
join(homeDir, '.bashrc'),
join(homeDir, '.zshrc'),
join(homeDir, '.bash_profile')
];
const aliasLine = 'alias rm="claude-mem trash"';
// Handle both variations of the comment line
const commentPatterns = [
'# claude-mem smart trash alias',
'# claude-mem trash bin alias'
];
let removedFromAny = false;
for (const configPath of shellConfigs) {
if (!existsSync(configPath)) continue;
let content = readFileSync(configPath, 'utf8');
// Check if alias exists
if (!content.includes(aliasLine)) {
continue; // Not configured in this file
}
// Remove the alias and its comment
const lines = content.split('\n');
const filteredLines = lines.filter((line, index) => {
// Skip the alias line
if (line.trim() === aliasLine) return false;
// Skip any claude-mem comment line if it's right before the alias
for (const commentPattern of commentPatterns) {
if (line.trim() === commentPattern &&
index + 1 < lines.length &&
lines[index + 1].trim() === aliasLine) {
return false;
}
}
return true;
});
const newContent = filteredLines.join('\n');
// Only write if content actually changed
if (newContent !== content) {
// Create backup
const backupPath = configPath + '.backup.' + Date.now();
writeFileSync(backupPath, content);
// Write updated content
writeFileSync(configPath, newContent);
console.log(`✅ Removed Smart Trash alias from ${configPath.replace(homeDir, '~')}`);
removedFromAny = true;
}
}
return removedFromAny;
}
export async function uninstall(options: OptionValues = {}): Promise<void> {
console.log('🔄 Uninstalling Claude Memory System hooks...');
const locations = [];
if (options.all) {
locations.push({
name: 'User',
path: PathDiscovery.getInstance().getClaudeSettingsPath()
});
locations.push({
name: 'Project',
path: join(process.cwd(), '.claude', 'settings.json')
});
} else {
const isProject = options.project;
const pathDiscovery = PathDiscovery.getInstance();
locations.push({
name: isProject ? 'Project' : 'User',
path: isProject ? join(process.cwd(), '.claude', 'settings.json') : pathDiscovery.getClaudeSettingsPath()
});
}
const pathDiscovery = PathDiscovery.getInstance();
const runtimeHooksDir = pathDiscovery.getHooksDirectory();
const preCompactScript = join(runtimeHooksDir, 'pre-compact.js');
const sessionStartScript = join(runtimeHooksDir, 'session-start.js');
const sessionEndScript = join(runtimeHooksDir, 'session-end.js');
let removedCount = 0;
for (const location of locations) {
if (!existsSync(location.path)) {
console.log(`⏭️ No settings found at ${location.name} location`);
continue;
}
const content = readFileSync(location.path, 'utf8');
const settings = JSON.parse(content);
if (!settings.hooks) {
console.log(`⏭️ No hooks configured in ${location.name} settings`);
continue;
}
let modified = false;
if (settings.hooks.PreCompact) {
const filteredPreCompact = settings.hooks.PreCompact.filter((matcher: any) =>
!matcher.hooks?.some((hook: any) =>
hook.command === preCompactScript ||
hook.command?.includes('pre-compact.js') ||
hook.command?.includes('claude-mem')
)
);
if (filteredPreCompact.length !== settings.hooks.PreCompact.length) {
settings.hooks.PreCompact = filteredPreCompact.length ? filteredPreCompact : undefined;
modified = true;
console.log(`✅ Removed PreCompact hook from ${location.name} settings`);
}
}
if (settings.hooks.SessionStart) {
const filteredSessionStart = settings.hooks.SessionStart.filter((matcher: any) =>
!matcher.hooks?.some((hook: any) =>
hook.command === sessionStartScript ||
hook.command?.includes('session-start.js') ||
hook.command?.includes('claude-mem')
)
);
if (filteredSessionStart.length !== settings.hooks.SessionStart.length) {
settings.hooks.SessionStart = filteredSessionStart.length ? filteredSessionStart : undefined;
modified = true;
console.log(`✅ Removed SessionStart hook from ${location.name} settings`);
}
}
if (settings.hooks.SessionEnd) {
const filteredSessionEnd = settings.hooks.SessionEnd.filter((matcher: any) =>
!matcher.hooks?.some((hook: any) =>
hook.command === sessionEndScript ||
hook.command?.includes('session-end.js') ||
hook.command?.includes('claude-mem')
)
);
if (filteredSessionEnd.length !== settings.hooks.SessionEnd.length) {
settings.hooks.SessionEnd = filteredSessionEnd.length ? filteredSessionEnd : undefined;
modified = true;
console.log(`✅ Removed SessionEnd hook from ${location.name} settings`);
}
}
if (settings.hooks.PreCompact === undefined) delete settings.hooks.PreCompact;
if (settings.hooks.SessionStart === undefined) delete settings.hooks.SessionStart;
if (settings.hooks.SessionEnd === undefined) delete settings.hooks.SessionEnd;
if (!Object.keys(settings.hooks).length) delete settings.hooks;
if (modified) {
const backupPath = location.path + '.backup.' + Date.now();
writeFileSync(backupPath, content);
console.log(`📋 Created backup: ${backupPath}`);
writeFileSync(location.path, JSON.stringify(settings, null, 2));
removedCount++;
console.log(`✅ Updated ${location.name} settings: ${location.path}`);
} else {
console.log(`️ No Claude Memory System hooks found in ${location.name} settings`);
}
}
// Remove Smart Trash alias from shell configs
const removedAlias = await removeSmartTrashAlias();
console.log('');
if (removedCount > 0 || removedAlias) {
console.log('✨ Uninstallation complete!');
if (removedCount > 0) {
console.log('The Claude Memory System hooks have been removed from your settings.');
}
if (removedAlias) {
console.log('The Smart Trash alias has been removed from your shell configuration.');
console.log('⚠️ Restart your terminal for the alias removal to take effect.');
}
console.log('');
console.log('Note: Your compressed transcripts and archives are preserved.');
console.log('To reinstall: claude-mem install');
} else {
console.log('️ No Claude Memory System hooks or aliases were found to remove.');
}
}