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.

250 lines (248 loc) 8.9 kB
import { fileURLToPath as __fileURLToPath } from 'url'; import { dirname as __pathDirname } from 'path'; const __filename = __fileURLToPath(import.meta.url); const __dirname = __pathDirname(__filename); import { Command } from "commander"; import chalk from "chalk"; import ora from "ora"; import { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync, chmodSync, appendFileSync } from "fs"; import { join } from "path"; function getShellType() { const shell = process.env.SHELL || ""; if (shell.includes("zsh")) return "zsh"; if (shell.includes("bash")) return "bash"; return "unknown"; } function getShellRcFile() { const home = process.env.HOME || ""; const shell = getShellType(); if (shell === "zsh") { return join(home, ".zshrc"); } else if (shell === "bash") { const bashrc = join(home, ".bashrc"); const profile = join(home, ".bash_profile"); return existsSync(bashrc) ? bashrc : profile; } return join(home, ".profile"); } function findTemplateFile(filename) { const locations = [ join(process.cwd(), "templates", "shell", filename), join( process.cwd(), "node_modules", "@stackmemoryai", "stackmemory", "templates", "shell", filename ), join(dirname(dirname(dirname(__dirname))), "templates", "shell", filename) ]; for (const loc of locations) { if (existsSync(loc)) { return loc; } } return null; } function createShellCommand() { const cmd = new Command("shell").description("Shell integration for Sweep-powered completions").addHelpText( "after", ` Examples: stackmemory shell install Install shell completions stackmemory shell status Check installation status stackmemory shell uninstall Remove shell integration After installation: - Ctrl+] Request suggestion - Shift+Tab Accept suggestion - sweep_status Check status - sweep_toggle Enable/disable ` ); cmd.command("install").description("Install Sweep-powered shell completions").option("--shell <type>", "Shell type (zsh or bash)", getShellType()).action(async (options) => { const spinner = ora("Installing shell integration...").start(); const home = process.env.HOME || ""; const shellDir = join(home, ".stackmemory", "shell"); const shell = options.shell; if (shell === "unknown") { spinner.fail(chalk.red("Could not detect shell type")); console.log(chalk.gray("Use --shell zsh or --shell bash")); process.exit(1); } try { mkdirSync(shellDir, { recursive: true }); const zshSource = findTemplateFile("sweep-complete.zsh"); const suggestSource = findTemplateFile("sweep-suggest.js"); if (!zshSource || !suggestSource) { spinner.fail(chalk.red("Template files not found")); console.log(chalk.gray("Ensure stackmemory is installed correctly")); process.exit(1); } const zshDest = join(shellDir, "sweep-complete.zsh"); const suggestDest = join(shellDir, "sweep-suggest.js"); copyFileSync(zshSource, zshDest); copyFileSync(suggestSource, suggestDest); chmodSync(suggestDest, "755"); spinner.text = "Updating shell configuration..."; const rcFile = getShellRcFile(); const sourceCmd = shell === "zsh" ? `source "${zshDest}"` : `source "${shellDir}/sweep-complete.bash"`; const marker = "# StackMemory Sweep Completion"; if (existsSync(rcFile)) { const content = readFileSync(rcFile, "utf-8"); if (content.includes(marker)) { spinner.succeed(chalk.green("Shell integration already installed")); console.log( chalk.gray("Restart your shell or run: source " + rcFile) ); return; } const addition = ` ${marker} if [[ -f "${zshDest}" ]]; then ${sourceCmd} fi `; appendFileSync(rcFile, addition); } else { writeFileSync( rcFile, `${marker} if [[ -f "${zshDest}" ]]; then ${sourceCmd} fi ` ); } spinner.succeed(chalk.green("Shell integration installed")); console.log(""); console.log(chalk.bold("Files installed:")); console.log(chalk.gray(` ${zshDest}`)); console.log(chalk.gray(` ${suggestDest}`)); console.log(""); console.log(chalk.bold("To activate:")); console.log(` source ${rcFile}`); console.log(" OR restart your terminal"); console.log(""); console.log(chalk.bold("Usage:")); console.log(" Ctrl+] Request suggestion"); console.log(" Shift+Tab Accept suggestion"); console.log(" sweep_status Check status"); console.log(" sweep_toggle Enable/disable"); } catch (error) { spinner.fail(chalk.red("Installation failed")); console.log(chalk.gray(error.message)); process.exit(1); } }); cmd.command("status").description("Check shell integration status").action(() => { const home = process.env.HOME || ""; const shellDir = join(home, ".stackmemory", "shell"); const zshFile = join(shellDir, "sweep-complete.zsh"); const suggestFile = join(shellDir, "sweep-suggest.js"); const rcFile = getShellRcFile(); console.log(chalk.bold("\nShell Integration Status\n")); console.log(`Shell: ${chalk.cyan(getShellType())}`); console.log(`RC file: ${chalk.gray(rcFile)}`); console.log(""); const zshInstalled = existsSync(zshFile); const suggestInstalled = existsSync(suggestFile); console.log( `Completion script: ${zshInstalled ? chalk.green("Installed") : chalk.yellow("Not installed")}` ); console.log( `Suggest script: ${suggestInstalled ? chalk.green("Installed") : chalk.yellow("Not installed")}` ); if (existsSync(rcFile)) { const content = readFileSync(rcFile, "utf-8"); const configured = content.includes("StackMemory Sweep Completion"); console.log( `RC configured: ${configured ? chalk.green("Yes") : chalk.yellow("No")}` ); } else { console.log(`RC configured: ${chalk.yellow("No RC file")}`); } const sweepState = join(home, ".stackmemory", "sweep-state.json"); if (existsSync(sweepState)) { try { const state = JSON.parse(readFileSync(sweepState, "utf-8")); console.log(""); console.log(chalk.bold("Sweep Context:")); console.log( chalk.gray(` Recent diffs: ${state.recentDiffs?.length || 0}`) ); if (state.lastPrediction) { const age = Date.now() - state.lastPrediction.timestamp; const ageStr = age < 6e4 ? `${Math.round(age / 1e3)}s ago` : `${Math.round(age / 6e4)}m ago`; console.log(chalk.gray(` Last prediction: ${ageStr}`)); } } catch { } } if (!zshInstalled || !suggestInstalled) { console.log(""); console.log(chalk.bold("To install: stackmemory shell install")); } }); cmd.command("uninstall").description("Remove shell integration").action(() => { const rcFile = getShellRcFile(); if (existsSync(rcFile)) { let content = readFileSync(rcFile, "utf-8"); const marker = "# StackMemory Sweep Completion"; const markerIndex = content.indexOf(marker); if (markerIndex !== -1) { const endPattern = /\nfi\n/; const afterMarker = content.slice(markerIndex); const endMatch = afterMarker.match(endPattern); if (endMatch && endMatch.index !== void 0) { const endIndex = markerIndex + endMatch.index + endMatch[0].length; content = content.slice(0, markerIndex) + content.slice(endIndex); writeFileSync(rcFile, content); console.log( chalk.green("Shell integration removed from " + rcFile) ); } } else { console.log(chalk.yellow("No shell integration found in " + rcFile)); } } console.log( chalk.gray("\nRestart your shell to complete uninstallation") ); }); cmd.action(() => { const home = process.env.HOME || ""; const zshFile = join(home, ".stackmemory", "shell", "sweep-complete.zsh"); const installed = existsSync(zshFile); console.log(chalk.bold("\nStackMemory Shell Integration\n")); console.log( `Status: ${installed ? chalk.green("Installed") : chalk.yellow("Not installed")}` ); if (!installed) { console.log(""); console.log(chalk.bold("Install with:")); console.log(" stackmemory shell install"); } else { console.log(""); console.log(chalk.bold("Commands:")); console.log(" stackmemory shell status Check status"); console.log(" stackmemory shell uninstall Remove integration"); } }); return cmd; } var shell_default = createShellCommand(); export { createShellCommand, shell_default as default }; //# sourceMappingURL=shell.js.map