UNPKG

@stackmemoryai/stackmemory

Version:

Project-scoped memory for AI coding tools. Durable context across sessions with MCP integration, frames, smart retrieval, Claude Code skills, and automatic hooks.

156 lines (155 loc) 5.02 kB
#!/usr/bin/env tsx import { fileURLToPath as __fileURLToPath } from 'url'; import { dirname as __pathDirname } from 'path'; const __filename = __fileURLToPath(import.meta.url); const __dirname = __pathDirname(__filename); import Database from "better-sqlite3"; import { existsSync, readFileSync } from "fs"; import { join } from "path"; import chalk from "chalk"; const projectRoot = process.cwd(); const stackDir = join(projectRoot, ".stackmemory"); const dbPath = join(stackDir, "context.db"); const configPath = join(stackDir, "config.json"); console.log(chalk.blue.bold("\n[StackMemory Status]\n")); if (!existsSync(stackDir)) { console.log(chalk.red("[X] .stackmemory directory not found")); console.log(chalk.gray(" Run: stackmemory init")); process.exit(1); } console.log(chalk.green("[OK] .stackmemory directory exists")); if (existsSync(configPath)) { try { const config = JSON.parse(readFileSync(configPath, "utf-8")); console.log(chalk.green("[OK] config.json found")); console.log(chalk.gray(` version: ${config.version || "unknown"}`)); console.log(chalk.gray(` project: ${config.project || "unknown"}`)); console.log( chalk.gray(` initialized: ${config.initialized || "unknown"}`) ); } catch { console.log(chalk.yellow("[!] config.json exists but failed to parse")); } } else { console.log(chalk.yellow("[!] config.json not found")); } if (!existsSync(dbPath)) { console.log(chalk.red("[X] context.db not found")); process.exit(1); } console.log(chalk.green("[OK] context.db exists")); const db = new Database(dbPath, { readonly: true }); const stats = { contexts: db.prepare("SELECT COUNT(*) as count FROM contexts").get(), frames: db.prepare("SELECT COUNT(*) as count FROM frames").get(), attention: db.prepare("SELECT COUNT(*) as count FROM attention_log").get() }; console.log(chalk.cyan("\n[Database Stats]")); console.log(` Contexts: ${stats.contexts.count}`); console.log(` Frames: ${stats.frames.count}`); console.log(` Attention logs: ${stats.attention.count}`); if (stats.contexts.count > 0) { console.log(chalk.cyan("\n[Top Contexts by Importance]")); const topContexts = db.prepare( ` SELECT type, substr(content, 1, 60) as preview, importance, access_count FROM contexts ORDER BY importance DESC, access_count DESC LIMIT 5 ` ).all(); topContexts.forEach((ctx, i) => { const importance = "*".repeat(Math.round(ctx.importance * 5)); console.log( chalk.white(` ${i + 1}.`) + ` [${ctx.type}] ` + chalk.gray(`(${ctx.access_count} uses)`) + ` ${importance}` ); console.log(chalk.gray(` ${ctx.preview}...`)); }); } const activeFrames = db.prepare( ` SELECT name, type, datetime(created_at, 'unixepoch') as started FROM frames WHERE state = 'active' ORDER BY created_at DESC LIMIT 3 ` ).all(); if (activeFrames.length > 0) { console.log(chalk.cyan("\n[Active Frames]")); activeFrames.forEach((frame) => { console.log(chalk.green(" *") + ` ${frame.name} (${frame.type})`); console.log(chalk.gray(` Started: ${frame.started}`)); }); } const recentAttention = db.prepare( ` SELECT substr(query, 1, 50) as query_preview, COUNT(*) as count FROM attention_log WHERE timestamp > unixepoch() - 86400 GROUP BY query_preview ORDER BY count DESC LIMIT 3 ` ).all(); if (recentAttention.length > 0) { console.log(chalk.cyan("\n[Recent Query Patterns]")); recentAttention.forEach((pattern) => { console.log( chalk.yellow(" ?") + ` "${pattern.query_preview}..." (${pattern.count}x)` ); }); } const oldContexts = db.prepare( ` SELECT COUNT(*) as count FROM contexts WHERE last_accessed < unixepoch() - 86400 * 7 ` ).get(); if (oldContexts.count > 0) { console.log( chalk.yellow( ` [!] ${oldContexts.count} contexts haven't been accessed in 7+ days` ) ); } console.log(chalk.cyan("\n[MCP Configuration]")); const mcpConfigPaths = [ join( process.env.HOME || "", "Library/Application Support/Claude/claude_desktop_config.json" ), join(process.env.HOME || "", ".config/claude/claude_desktop_config.json") ]; let mcpFound = false; for (const mcpPath of mcpConfigPaths) { if (existsSync(mcpPath)) { try { const mcpConfig = JSON.parse(readFileSync(mcpPath, "utf-8")); const hasStackMemory = mcpConfig.mcpServers?.stackmemory || mcpConfig.mcpServers?.["stackmemory-mcp"]; if (hasStackMemory) { console.log(chalk.green(" [OK] MCP server configured")); mcpFound = true; } else { console.log( chalk.yellow(" [!] MCP config exists but stackmemory not configured") ); } } catch { console.log(chalk.yellow(` [!] Failed to parse ${mcpPath}`)); } break; } } if (!mcpFound) { console.log(chalk.gray(" [--] No MCP configuration found")); } console.log( chalk.gray('\nTip: Run "npm run analyze" for detailed attention analysis\n') ); db.close(); //# sourceMappingURL=status.js.map