import { join, dirname, basename, sep } from 'path'; import { homedir } from 'os'; import { existsSync, mkdirSync } from 'fs'; import { execSync } from 'child_process'; import { fileURLToPath } from 'url'; /** * Simple path configuration for claude-mem * Standard paths based on Claude Code conventions */ // Base directories export const DATA_DIR = process.env.CLAUDE_MEM_DATA_DIR || join(homedir(), '.claude-mem'); export const CLAUDE_CONFIG_DIR = process.env.CLAUDE_CONFIG_DIR || join(homedir(), '.claude'); // Data subdirectories export const ARCHIVES_DIR = join(DATA_DIR, 'archives'); export const LOGS_DIR = join(DATA_DIR, 'logs'); export const TRASH_DIR = join(DATA_DIR, 'trash'); export const BACKUPS_DIR = join(DATA_DIR, 'backups'); export const USER_SETTINGS_PATH = join(DATA_DIR, 'settings.json'); export const DB_PATH = join(DATA_DIR, 'claude-mem.db'); // Claude integration paths export const CLAUDE_SETTINGS_PATH = join(CLAUDE_CONFIG_DIR, 'settings.json'); export const CLAUDE_COMMANDS_DIR = join(CLAUDE_CONFIG_DIR, 'commands'); export const CLAUDE_MD_PATH = join(CLAUDE_CONFIG_DIR, 'CLAUDE.md'); /** * Get project-specific archive directory */ export function getProjectArchiveDir(projectName: string): string { return join(ARCHIVES_DIR, projectName); } /** * Get worker socket path for a session */ export function getWorkerSocketPath(sessionId: number): string { return join(DATA_DIR, `worker-${sessionId}.sock`); } /** * Ensure a directory exists */ export function ensureDir(dirPath: string): void { mkdirSync(dirPath, { recursive: true }); } /** * Ensure all data directories exist */ export function ensureAllDataDirs(): void { ensureDir(DATA_DIR); ensureDir(ARCHIVES_DIR); ensureDir(LOGS_DIR); ensureDir(TRASH_DIR); ensureDir(BACKUPS_DIR); } /** * Ensure all Claude integration directories exist */ export function ensureAllClaudeDirs(): void { ensureDir(CLAUDE_CONFIG_DIR); ensureDir(CLAUDE_COMMANDS_DIR); } /** * Get current project name from git root or cwd */ export function getCurrentProjectName(): string { try { const gitRoot = execSync('git rev-parse --show-toplevel', { cwd: process.cwd(), encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] }).trim(); return basename(gitRoot); } catch { return basename(process.cwd()); } } /** * Find package root directory (for install command) */ export function getPackageRoot(): string { // Method 1: Try require.resolve for package.json try { const packageJsonPath = require.resolve('claude-mem/package.json'); return dirname(packageJsonPath); } catch { // Continue to next method } // Method 2: Walk up from current module location const currentFile = fileURLToPath(import.meta.url); let currentDir = dirname(currentFile); for (let i = 0; i < 10; i++) { const packageJsonPath = join(currentDir, 'package.json'); if (existsSync(packageJsonPath)) { const packageJson = require(packageJsonPath); if (packageJson.name === 'claude-mem') { return currentDir; } } const parentDir = dirname(currentDir); if (parentDir === currentDir) break; currentDir = parentDir; } throw new Error('Cannot locate claude-mem package root. Ensure claude-mem is properly installed.'); } /** * Find commands directory in the installed package */ export function getPackageCommandsDir(): string { const packageRoot = getPackageRoot(); const commandsDir = join(packageRoot, 'commands'); if (!existsSync(join(commandsDir, 'save.md'))) { throw new Error('Package commands directory missing required files'); } return commandsDir; } /** * Create a timestamped backup filename */ export function createBackupFilename(originalPath: string): string { const timestamp = new Date() .toISOString() .replace(/[:.]/g, '-') .replace('T', '_') .slice(0, 19); return `${originalPath}.backup.${timestamp}`; }