@stackmemoryai/stackmemory 0.5.6 → 0.5.7
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.
- package/dist/cli/commands/auto-background.js +180 -0
- package/dist/cli/commands/auto-background.js.map +7 -0
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +2 -2
- package/dist/hooks/auto-background.js +146 -0
- package/dist/hooks/auto-background.js.map +7 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/index.js.map +2 -2
- package/package.json +1 -1
- package/scripts/install-auto-background-hook.sh +144 -0
- package/templates/claude-hooks/auto-background-hook.js +156 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { fileURLToPath as __fileURLToPath } from 'url';
|
|
2
|
+
import { dirname as __pathDirname } from 'path';
|
|
3
|
+
const __filename = __fileURLToPath(import.meta.url);
|
|
4
|
+
const __dirname = __pathDirname(__filename);
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
import { execSync } from "child_process";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
import {
|
|
10
|
+
loadConfig,
|
|
11
|
+
saveConfig
|
|
12
|
+
} from "../../hooks/auto-background.js";
|
|
13
|
+
function createAutoBackgroundCommand() {
|
|
14
|
+
const cmd = new Command("auto-bg").description("Manage auto-background settings for long-running commands").addHelpText(
|
|
15
|
+
"after",
|
|
16
|
+
`
|
|
17
|
+
Examples:
|
|
18
|
+
stackmemory auto-bg show Show current configuration
|
|
19
|
+
stackmemory auto-bg enable Enable auto-backgrounding
|
|
20
|
+
stackmemory auto-bg disable Disable auto-backgrounding
|
|
21
|
+
stackmemory auto-bg add "npm publish" Add command to always-background list
|
|
22
|
+
stackmemory auto-bg remove "npm test" Remove command from list
|
|
23
|
+
stackmemory auto-bg timeout 10000 Set timeout to 10 seconds
|
|
24
|
+
stackmemory auto-bg install Install Claude Code hook
|
|
25
|
+
`
|
|
26
|
+
);
|
|
27
|
+
cmd.command("show").description("Show current auto-background configuration").action(() => {
|
|
28
|
+
const config = loadConfig();
|
|
29
|
+
console.log(chalk.blue("Auto-Background Configuration:"));
|
|
30
|
+
console.log();
|
|
31
|
+
console.log(
|
|
32
|
+
` ${chalk.gray("Enabled:")} ${config.enabled ? chalk.green("yes") : chalk.red("no")}`
|
|
33
|
+
);
|
|
34
|
+
console.log(` ${chalk.gray("Timeout:")} ${config.timeoutMs}ms`);
|
|
35
|
+
console.log(
|
|
36
|
+
` ${chalk.gray("Verbose:")} ${config.verbose ? "yes" : "no"}`
|
|
37
|
+
);
|
|
38
|
+
console.log();
|
|
39
|
+
console.log(chalk.blue("Always Background:"));
|
|
40
|
+
config.alwaysBackground.forEach((p) => console.log(` - ${p}`));
|
|
41
|
+
console.log();
|
|
42
|
+
console.log(chalk.blue("Never Background:"));
|
|
43
|
+
config.neverBackground.forEach((p) => console.log(` - ${p}`));
|
|
44
|
+
});
|
|
45
|
+
cmd.command("enable").description("Enable auto-backgrounding").action(() => {
|
|
46
|
+
const config = loadConfig();
|
|
47
|
+
config.enabled = true;
|
|
48
|
+
saveConfig(config);
|
|
49
|
+
console.log(chalk.green("Auto-background enabled"));
|
|
50
|
+
});
|
|
51
|
+
cmd.command("disable").description("Disable auto-backgrounding").action(() => {
|
|
52
|
+
const config = loadConfig();
|
|
53
|
+
config.enabled = false;
|
|
54
|
+
saveConfig(config);
|
|
55
|
+
console.log(chalk.yellow("Auto-background disabled"));
|
|
56
|
+
});
|
|
57
|
+
cmd.command("add <pattern>").description("Add command pattern to always-background list").action((pattern) => {
|
|
58
|
+
const config = loadConfig();
|
|
59
|
+
if (!config.alwaysBackground.includes(pattern)) {
|
|
60
|
+
config.alwaysBackground.push(pattern);
|
|
61
|
+
saveConfig(config);
|
|
62
|
+
console.log(chalk.green(`Added: ${pattern}`));
|
|
63
|
+
} else {
|
|
64
|
+
console.log(chalk.yellow(`Already in list: ${pattern}`));
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
cmd.command("remove <pattern>").description("Remove command pattern from always-background list").action((pattern) => {
|
|
68
|
+
const config = loadConfig();
|
|
69
|
+
const idx = config.alwaysBackground.indexOf(pattern);
|
|
70
|
+
if (idx !== -1) {
|
|
71
|
+
config.alwaysBackground.splice(idx, 1);
|
|
72
|
+
saveConfig(config);
|
|
73
|
+
console.log(chalk.green(`Removed: ${pattern}`));
|
|
74
|
+
} else {
|
|
75
|
+
console.log(chalk.yellow(`Not in list: ${pattern}`));
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
cmd.command("timeout <ms>").description("Set timeout threshold in milliseconds").action((ms) => {
|
|
79
|
+
const config = loadConfig();
|
|
80
|
+
const timeout = parseInt(ms, 10);
|
|
81
|
+
if (isNaN(timeout) || timeout < 0) {
|
|
82
|
+
console.log(chalk.red("Invalid timeout value"));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
config.timeoutMs = timeout;
|
|
86
|
+
saveConfig(config);
|
|
87
|
+
console.log(chalk.green(`Timeout set to ${timeout}ms`));
|
|
88
|
+
});
|
|
89
|
+
cmd.command("verbose [on|off]").description("Enable/disable verbose logging").action((value) => {
|
|
90
|
+
const config = loadConfig();
|
|
91
|
+
if (value === void 0) {
|
|
92
|
+
config.verbose = !config.verbose;
|
|
93
|
+
} else {
|
|
94
|
+
config.verbose = value === "on" || value === "true";
|
|
95
|
+
}
|
|
96
|
+
saveConfig(config);
|
|
97
|
+
console.log(
|
|
98
|
+
chalk.green(
|
|
99
|
+
`Verbose logging ${config.verbose ? "enabled" : "disabled"}`
|
|
100
|
+
)
|
|
101
|
+
);
|
|
102
|
+
});
|
|
103
|
+
cmd.command("reset").description("Reset configuration to defaults").action(() => {
|
|
104
|
+
const defaultConfig = {
|
|
105
|
+
enabled: true,
|
|
106
|
+
timeoutMs: 5e3,
|
|
107
|
+
alwaysBackground: [
|
|
108
|
+
"npm install",
|
|
109
|
+
"npm ci",
|
|
110
|
+
"yarn install",
|
|
111
|
+
"pnpm install",
|
|
112
|
+
"bun install",
|
|
113
|
+
"npm run build",
|
|
114
|
+
"yarn build",
|
|
115
|
+
"pnpm build",
|
|
116
|
+
"cargo build",
|
|
117
|
+
"go build",
|
|
118
|
+
"make",
|
|
119
|
+
"npm test",
|
|
120
|
+
"npm run test",
|
|
121
|
+
"yarn test",
|
|
122
|
+
"pytest",
|
|
123
|
+
"jest",
|
|
124
|
+
"vitest",
|
|
125
|
+
"cargo test",
|
|
126
|
+
"docker build",
|
|
127
|
+
"docker-compose up",
|
|
128
|
+
"docker compose up",
|
|
129
|
+
"git clone",
|
|
130
|
+
"git fetch --all",
|
|
131
|
+
"npx tsc",
|
|
132
|
+
"tsc --noEmit",
|
|
133
|
+
"eslint .",
|
|
134
|
+
"npm run lint"
|
|
135
|
+
],
|
|
136
|
+
neverBackground: [
|
|
137
|
+
"vim",
|
|
138
|
+
"nvim",
|
|
139
|
+
"nano",
|
|
140
|
+
"less",
|
|
141
|
+
"more",
|
|
142
|
+
"top",
|
|
143
|
+
"htop",
|
|
144
|
+
"echo",
|
|
145
|
+
"cat",
|
|
146
|
+
"ls",
|
|
147
|
+
"pwd",
|
|
148
|
+
"cd",
|
|
149
|
+
"which",
|
|
150
|
+
"git status",
|
|
151
|
+
"git diff",
|
|
152
|
+
"git log"
|
|
153
|
+
],
|
|
154
|
+
verbose: false
|
|
155
|
+
};
|
|
156
|
+
saveConfig(defaultConfig);
|
|
157
|
+
console.log(chalk.green("Configuration reset to defaults"));
|
|
158
|
+
});
|
|
159
|
+
cmd.command("install").description("Install Claude Code hook for auto-backgrounding").action(() => {
|
|
160
|
+
try {
|
|
161
|
+
const scriptPath = join(
|
|
162
|
+
__dirname,
|
|
163
|
+
"../../../scripts/install-auto-background-hook.sh"
|
|
164
|
+
);
|
|
165
|
+
execSync(`bash "${scriptPath}"`, { stdio: "inherit" });
|
|
166
|
+
} catch {
|
|
167
|
+
console.error(chalk.red("Failed to install hook"));
|
|
168
|
+
console.log(
|
|
169
|
+
chalk.gray(
|
|
170
|
+
"Run manually: bash scripts/install-auto-background-hook.sh"
|
|
171
|
+
)
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
return cmd;
|
|
176
|
+
}
|
|
177
|
+
export {
|
|
178
|
+
createAutoBackgroundCommand
|
|
179
|
+
};
|
|
180
|
+
//# sourceMappingURL=auto-background.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/cli/commands/auto-background.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * CLI command for managing auto-background settings\n */\n\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport { execSync } from 'child_process';\nimport { join } from 'path';\nimport {\n loadConfig,\n saveConfig,\n AutoBackgroundConfig,\n} from '../../hooks/auto-background.js';\n\n// __dirname provided by esbuild banner\n\nexport function createAutoBackgroundCommand(): Command {\n const cmd = new Command('auto-bg')\n .description('Manage auto-background settings for long-running commands')\n .addHelpText(\n 'after',\n `\nExamples:\n stackmemory auto-bg show Show current configuration\n stackmemory auto-bg enable Enable auto-backgrounding\n stackmemory auto-bg disable Disable auto-backgrounding\n stackmemory auto-bg add \"npm publish\" Add command to always-background list\n stackmemory auto-bg remove \"npm test\" Remove command from list\n stackmemory auto-bg timeout 10000 Set timeout to 10 seconds\n stackmemory auto-bg install Install Claude Code hook\n`\n );\n\n cmd\n .command('show')\n .description('Show current auto-background configuration')\n .action(() => {\n const config = loadConfig();\n console.log(chalk.blue('Auto-Background Configuration:'));\n console.log();\n console.log(\n ` ${chalk.gray('Enabled:')} ${config.enabled ? chalk.green('yes') : chalk.red('no')}`\n );\n console.log(` ${chalk.gray('Timeout:')} ${config.timeoutMs}ms`);\n console.log(\n ` ${chalk.gray('Verbose:')} ${config.verbose ? 'yes' : 'no'}`\n );\n console.log();\n console.log(chalk.blue('Always Background:'));\n config.alwaysBackground.forEach((p) => console.log(` - ${p}`));\n console.log();\n console.log(chalk.blue('Never Background:'));\n config.neverBackground.forEach((p) => console.log(` - ${p}`));\n });\n\n cmd\n .command('enable')\n .description('Enable auto-backgrounding')\n .action(() => {\n const config = loadConfig();\n config.enabled = true;\n saveConfig(config);\n console.log(chalk.green('Auto-background enabled'));\n });\n\n cmd\n .command('disable')\n .description('Disable auto-backgrounding')\n .action(() => {\n const config = loadConfig();\n config.enabled = false;\n saveConfig(config);\n console.log(chalk.yellow('Auto-background disabled'));\n });\n\n cmd\n .command('add <pattern>')\n .description('Add command pattern to always-background list')\n .action((pattern: string) => {\n const config = loadConfig();\n if (!config.alwaysBackground.includes(pattern)) {\n config.alwaysBackground.push(pattern);\n saveConfig(config);\n console.log(chalk.green(`Added: ${pattern}`));\n } else {\n console.log(chalk.yellow(`Already in list: ${pattern}`));\n }\n });\n\n cmd\n .command('remove <pattern>')\n .description('Remove command pattern from always-background list')\n .action((pattern: string) => {\n const config = loadConfig();\n const idx = config.alwaysBackground.indexOf(pattern);\n if (idx !== -1) {\n config.alwaysBackground.splice(idx, 1);\n saveConfig(config);\n console.log(chalk.green(`Removed: ${pattern}`));\n } else {\n console.log(chalk.yellow(`Not in list: ${pattern}`));\n }\n });\n\n cmd\n .command('timeout <ms>')\n .description('Set timeout threshold in milliseconds')\n .action((ms: string) => {\n const config = loadConfig();\n const timeout = parseInt(ms, 10);\n if (isNaN(timeout) || timeout < 0) {\n console.log(chalk.red('Invalid timeout value'));\n return;\n }\n config.timeoutMs = timeout;\n saveConfig(config);\n console.log(chalk.green(`Timeout set to ${timeout}ms`));\n });\n\n cmd\n .command('verbose [on|off]')\n .description('Enable/disable verbose logging')\n .action((value?: string) => {\n const config = loadConfig();\n if (value === undefined) {\n config.verbose = !config.verbose;\n } else {\n config.verbose = value === 'on' || value === 'true';\n }\n saveConfig(config);\n console.log(\n chalk.green(\n `Verbose logging ${config.verbose ? 'enabled' : 'disabled'}`\n )\n );\n });\n\n cmd\n .command('reset')\n .description('Reset configuration to defaults')\n .action(() => {\n const defaultConfig: AutoBackgroundConfig = {\n enabled: true,\n timeoutMs: 5000,\n alwaysBackground: [\n 'npm install',\n 'npm ci',\n 'yarn install',\n 'pnpm install',\n 'bun install',\n 'npm run build',\n 'yarn build',\n 'pnpm build',\n 'cargo build',\n 'go build',\n 'make',\n 'npm test',\n 'npm run test',\n 'yarn test',\n 'pytest',\n 'jest',\n 'vitest',\n 'cargo test',\n 'docker build',\n 'docker-compose up',\n 'docker compose up',\n 'git clone',\n 'git fetch --all',\n 'npx tsc',\n 'tsc --noEmit',\n 'eslint .',\n 'npm run lint',\n ],\n neverBackground: [\n 'vim',\n 'nvim',\n 'nano',\n 'less',\n 'more',\n 'top',\n 'htop',\n 'echo',\n 'cat',\n 'ls',\n 'pwd',\n 'cd',\n 'which',\n 'git status',\n 'git diff',\n 'git log',\n ],\n verbose: false,\n };\n saveConfig(defaultConfig);\n console.log(chalk.green('Configuration reset to defaults'));\n });\n\n cmd\n .command('install')\n .description('Install Claude Code hook for auto-backgrounding')\n .action(() => {\n try {\n // Find the install script\n const scriptPath = join(\n __dirname,\n '../../../scripts/install-auto-background-hook.sh'\n );\n execSync(`bash \"${scriptPath}\"`, { stdio: 'inherit' });\n } catch {\n console.error(chalk.red('Failed to install hook'));\n console.log(\n chalk.gray(\n 'Run manually: bash scripts/install-auto-background-hook.sh'\n )\n );\n }\n });\n\n return cmd;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/cli/index.js
CHANGED
|
@@ -46,6 +46,7 @@ import { createHooksCommand } from "./commands/hooks.js";
|
|
|
46
46
|
import { createShellCommand } from "./commands/shell.js";
|
|
47
47
|
import { createAPICommand } from "./commands/api.js";
|
|
48
48
|
import { createCleanupProcessesCommand } from "./commands/cleanup-processes.js";
|
|
49
|
+
import { createAutoBackgroundCommand } from "./commands/auto-background.js";
|
|
49
50
|
import { ProjectManager } from "../core/projects/project-manager.js";
|
|
50
51
|
import Database from "better-sqlite3";
|
|
51
52
|
import { join } from "path";
|
|
@@ -437,6 +438,7 @@ program.addCommand(createHooksCommand());
|
|
|
437
438
|
program.addCommand(createShellCommand());
|
|
438
439
|
program.addCommand(createAPICommand());
|
|
439
440
|
program.addCommand(createCleanupProcessesCommand());
|
|
441
|
+
program.addCommand(createAutoBackgroundCommand());
|
|
440
442
|
program.command("dashboard").description("Display monitoring dashboard in terminal").option("-w, --watch", "Auto-refresh dashboard").option("-i, --interval <seconds>", "Refresh interval in seconds", "5").action(async (options) => {
|
|
441
443
|
const { dashboardCommand } = await import("./commands/dashboard.js");
|
|
442
444
|
await dashboardCommand.handler(options);
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/cli/index.ts"],
|
|
4
|
-
"sourcesContent": ["#!/usr/bin/env node\n/**\n * StackMemory CLI\n * Command-line interface for StackMemory operations\n */\n\n// Set environment flag for CLI usage to skip async context bridge\nprocess.env['STACKMEMORY_CLI'] = 'true';\n\n// Load environment variables\nimport 'dotenv/config';\n\n// Initialize tracing system early\nimport { initializeTracing, trace } from '../core/trace/index.js';\ninitializeTracing();\n\nimport { program } from 'commander';\nimport { logger } from '../core/monitoring/logger.js';\nimport { FrameManager } from '../core/context/frame-manager.js';\nimport { sessionManager, FrameQueryMode } from '../core/session/index.js';\nimport { sharedContextLayer } from '../core/context/shared-context-layer.js';\nimport { UpdateChecker } from '../core/utils/update-checker.js';\nimport { ProgressTracker } from '../core/monitoring/progress-tracker.js';\nimport { registerProjectCommands } from './commands/projects.js';\nimport { registerLinearCommands } from './commands/linear.js';\nimport { createSessionCommands } from './commands/session.js';\nimport { registerWorktreeCommands } from './commands/worktree.js';\nimport { registerOnboardingCommand } from './commands/onboard.js';\nimport { createTaskCommands } from './commands/tasks.js';\nimport { createSearchCommand } from './commands/search.js';\nimport { createLogCommand } from './commands/log.js';\nimport { createContextCommands } from './commands/context.js';\nimport { createConfigCommand } from './commands/config.js';\nimport { createHandoffCommand } from './commands/handoff.js';\nimport {\n createDecisionCommand,\n createMemoryCommand,\n} from './commands/decision.js';\nimport { createStorageCommand } from './commands/storage.js';\nimport { createSkillsCommand } from './commands/skills.js';\nimport { createTestCommand } from './commands/test.js';\nimport clearCommand from './commands/clear.js';\nimport createWorkflowCommand from './commands/workflow.js';\nimport monitorCommand from './commands/monitor.js';\nimport qualityCommand from './commands/quality.js';\nimport createRalphCommand from './commands/ralph.js';\nimport serviceCommand from './commands/service.js';\nimport { registerLoginCommand } from './commands/login.js';\nimport { registerSignupCommand } from './commands/signup.js';\nimport { registerLogoutCommand, registerDbCommands } from './commands/db.js';\nimport { createSweepCommand } from './commands/sweep.js';\nimport { createHooksCommand } from './commands/hooks.js';\nimport { createShellCommand } from './commands/shell.js';\nimport { createAPICommand } from './commands/api.js';\nimport { createCleanupProcessesCommand } from './commands/cleanup-processes.js';\nimport { ProjectManager } from '../core/projects/project-manager.js';\nimport Database from 'better-sqlite3';\nimport { join } from 'path';\nimport { existsSync, mkdirSync } from 'fs';\nimport inquirer from 'inquirer';\nimport chalk from 'chalk';\nimport {\n loadStorageConfig,\n enableChromaDB,\n getStorageModeDescription,\n} from '../core/config/storage-config.js';\n\nconst VERSION = '0.5.5';\n\n// Check for updates on CLI startup\nUpdateChecker.checkForUpdates(VERSION, true).catch(() => {\n // Silently ignore errors\n});\n\nprogram\n .name('stackmemory')\n .description(\n 'Lossless memory runtime for AI coding tools - organizes context as a call stack instead of linear chat logs, with team collaboration and infinite retention'\n )\n .version(VERSION);\n\nprogram\n .command('init')\n .description(\n `Initialize StackMemory in current project\n\nStorage Modes:\n SQLite (default): Local only, fast, no setup required\n ChromaDB (hybrid): Adds semantic search and cloud backup, requires API key`\n )\n .option('--sqlite', 'Use SQLite-only storage (default, skip prompts)')\n .option(\n '--chromadb',\n 'Enable ChromaDB for semantic search (prompts for API key)'\n )\n .option('--skip-storage-prompt', 'Skip storage configuration prompt')\n .action(async (options) => {\n try {\n const projectRoot = process.cwd();\n const dbDir = join(projectRoot, '.stackmemory');\n\n if (!existsSync(dbDir)) {\n mkdirSync(dbDir, { recursive: true });\n }\n\n // Handle storage configuration\n let storageConfig = loadStorageConfig();\n const isFirstTimeSetup =\n !storageConfig.chromadb.enabled && storageConfig.mode === 'sqlite';\n\n // Skip prompts if --sqlite flag or --skip-storage-prompt\n if (options.sqlite || options.skipStoragePrompt) {\n // Use SQLite-only (default)\n console.log(chalk.gray('Using SQLite-only storage mode.'));\n } else if (options.chromadb) {\n // User explicitly requested ChromaDB, prompt for API key\n await promptAndEnableChromaDB();\n } else if (isFirstTimeSetup && process.stdin.isTTY) {\n // Interactive mode - ask user about ChromaDB\n console.log(chalk.cyan('\\nStorage Configuration'));\n console.log(chalk.gray('StackMemory supports two storage modes:\\n'));\n console.log(chalk.white(' SQLite (default):'));\n console.log(chalk.gray(' - Local storage only'));\n console.log(chalk.gray(' - Fast and simple'));\n console.log(chalk.gray(' - No external dependencies\\n'));\n console.log(chalk.white(' ChromaDB (hybrid):'));\n console.log(chalk.gray(' - Semantic search across your context'));\n console.log(chalk.gray(' - Cloud backup capability'));\n console.log(chalk.gray(' - Requires ChromaDB API key\\n'));\n\n const { enableChroma } = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'enableChroma',\n message: 'Enable ChromaDB for semantic search? (requires API key)',\n default: false,\n },\n ]);\n\n if (enableChroma) {\n await promptAndEnableChromaDB();\n } else {\n console.log(chalk.gray('Using SQLite-only storage mode.'));\n }\n }\n\n // Initialize SQLite database\n const dbPath = join(dbDir, 'context.db');\n const db = new Database(dbPath);\n new FrameManager(db, 'cli-project');\n\n logger.info('StackMemory initialized successfully', { projectRoot });\n console.log(\n chalk.green('\\n[OK] StackMemory initialized in'),\n projectRoot\n );\n\n // Show current storage mode\n storageConfig = loadStorageConfig();\n console.log(chalk.gray(`Storage mode: ${getStorageModeDescription()}`));\n\n db.close();\n } catch (error: unknown) {\n logger.error('Failed to initialize StackMemory', error as Error);\n console.error(\n chalk.red('[ERROR] Initialization failed:'),\n (error as Error).message\n );\n process.exit(1);\n }\n });\n\n/**\n * Prompt user for ChromaDB configuration and enable it\n */\nasync function promptAndEnableChromaDB(): Promise<void> {\n const answers = await inquirer.prompt([\n {\n type: 'password',\n name: 'apiKey',\n message: 'Enter your ChromaDB API key:',\n validate: (input: string) => {\n if (!input || input.trim().length === 0) {\n return 'API key is required for ChromaDB';\n }\n return true;\n },\n },\n {\n type: 'input',\n name: 'apiUrl',\n message: 'ChromaDB API URL (press Enter for default):',\n default: 'https://api.trychroma.com',\n },\n ]);\n\n enableChromaDB({\n apiKey: answers.apiKey,\n apiUrl: answers.apiUrl,\n });\n\n console.log(chalk.green('[OK] ChromaDB enabled for semantic search.'));\n console.log(\n chalk.gray('API key saved to ~/.stackmemory/storage-config.json')\n );\n}\n\nprogram\n .command('status')\n .description('Show current StackMemory status')\n .option('--all', 'Show all active frames across sessions')\n .option('--project', 'Show all active frames in current project')\n .option('--session <id>', 'Show frames for specific session')\n .action(async (options) => {\n return trace.command('stackmemory-status', options, async () => {\n try {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n '\u274C StackMemory not initialized. Run \"stackmemory init\" first.'\n );\n return;\n }\n\n // Check for updates and display if available\n await UpdateChecker.checkForUpdates(VERSION);\n\n // Initialize session manager and shared context\n await sessionManager.initialize();\n await sharedContextLayer.initialize();\n\n const session = await sessionManager.getOrCreateSession({\n projectPath: projectRoot,\n sessionId: options.session,\n });\n\n // Auto-discover shared context on startup\n const contextDiscovery = await sharedContextLayer.autoDiscoverContext();\n\n // Show context hints if available\n if (\n contextDiscovery.hasSharedContext &&\n contextDiscovery.sessionCount > 1\n ) {\n console.log(`\\n\uD83D\uDCA1 Shared Context Available:`);\n console.log(\n ` ${contextDiscovery.sessionCount} sessions with shared context`\n );\n\n if (contextDiscovery.recentPatterns.length > 0) {\n console.log(` Recent patterns:`);\n contextDiscovery.recentPatterns.slice(0, 3).forEach((p) => {\n console.log(\n ` \u2022 ${p.type}: ${p.pattern.slice(0, 50)} (${p.frequency}x)`\n );\n });\n }\n\n if (contextDiscovery.lastDecisions.length > 0) {\n console.log(\n ` Last decision: ${contextDiscovery.lastDecisions[0].decision.slice(0, 60)}`\n );\n }\n }\n\n const db = new Database(dbPath);\n const frameManager = new FrameManager(db, session.projectId);\n\n // Set query mode based on options\n if (options.all) {\n frameManager.setQueryMode(FrameQueryMode.ALL_ACTIVE);\n } else if (options.project) {\n frameManager.setQueryMode(FrameQueryMode.PROJECT_ACTIVE);\n }\n\n const activeFrames = frameManager.getActiveFramePath();\n const stackDepth = frameManager.getStackDepth();\n\n // Always get total counts across all sessions\n const totalStats = db\n .prepare(\n `\n SELECT \n COUNT(*) as total_frames,\n SUM(CASE WHEN state = 'active' THEN 1 ELSE 0 END) as active_frames,\n SUM(CASE WHEN state = 'closed' THEN 1 ELSE 0 END) as closed_frames,\n COUNT(DISTINCT run_id) as total_sessions\n FROM frames\n WHERE project_id = ?\n `\n )\n .get(session.projectId) as {\n total_frames: number;\n active_frames: number;\n closed_frames: number;\n total_sessions: number;\n };\n\n const contextCount = db\n .prepare(\n `\n SELECT COUNT(*) as count FROM contexts\n `\n )\n .get() as { count: number };\n\n const eventCount = db\n .prepare(\n `\n SELECT COUNT(*) as count FROM events e\n JOIN frames f ON e.frame_id = f.frame_id\n WHERE f.project_id = ?\n `\n )\n .get(session.projectId) as { count: number };\n\n console.log('\uD83D\uDCCA StackMemory Status:');\n console.log(\n ` Session: ${session.sessionId.slice(0, 8)} (${session.state}, ${Math.round((Date.now() - session.startedAt) / 1000 / 60)}min old)`\n );\n console.log(` Project: ${session.projectId}`);\n if (session.branch) {\n console.log(` Branch: ${session.branch}`);\n }\n\n // Show total database statistics\n console.log(`\\n Database Statistics (this project):`);\n console.log(\n ` Frames: ${totalStats.total_frames || 0} (${totalStats.active_frames || 0} active, ${totalStats.closed_frames || 0} closed)`\n );\n console.log(` Events: ${eventCount.count || 0}`);\n console.log(` Sessions: ${totalStats.total_sessions || 0}`);\n console.log(\n ` Cached contexts: ${contextCount.count || 0} (global)`\n );\n\n // Show recent activity\n const recentFrames = db\n .prepare(\n `\n SELECT name, type, state, datetime(created_at, 'unixepoch') as created\n FROM frames\n WHERE project_id = ?\n ORDER BY created_at DESC\n LIMIT 3\n `\n )\n .all(session.projectId) as Array<{\n name: string;\n type: string;\n state: string;\n created: string;\n }>;\n\n if (recentFrames.length > 0) {\n console.log(`\\n Recent Activity:`);\n recentFrames.forEach((f) => {\n const stateIcon = f.state === 'active' ? '\uD83D\uDFE2' : '\u26AB';\n console.log(\n ` ${stateIcon} ${f.name} [${f.type}] - ${f.created}`\n );\n });\n }\n\n console.log(`\\n Current Session:`);\n console.log(` Stack depth: ${stackDepth}`);\n console.log(` Active frames: ${activeFrames.length}`);\n\n if (activeFrames.length > 0) {\n activeFrames.forEach((frame, i) => {\n const indent = ' ' + ' '.repeat(frame.depth || i);\n const prefix = i === 0 ? '\u2514\u2500' : ' \u2514\u2500';\n console.log(`${indent}${prefix} ${frame.name} [${frame.type}]`);\n });\n }\n\n // Show other sessions if in default mode\n if (!options.all && !options.project) {\n const otherSessions = await sessionManager.listSessions({\n projectId: session.projectId,\n state: 'active',\n });\n\n const otherActive = otherSessions.filter(\n (s) => s.sessionId !== session.sessionId\n );\n if (otherActive.length > 0) {\n console.log(`\\n Other Active Sessions (same project):`);\n otherActive.forEach((s) => {\n const age = Math.round(\n (Date.now() - s.lastActiveAt) / 1000 / 60 / 60\n );\n console.log(\n ` - ${s.sessionId.slice(0, 8)}: ${s.branch || 'main'}, ${age}h old`\n );\n });\n console.log(`\\n Tip: Use --all to see frames across sessions`);\n }\n }\n\n db.close();\n } catch (error: unknown) {\n logger.error('Failed to get status', error as Error);\n console.error('\u274C Status check failed:', (error as Error).message);\n process.exit(1);\n }\n });\n });\n\nprogram\n .command('update-check')\n .description('Check for StackMemory updates')\n .action(async () => {\n try {\n console.log('\uD83D\uDD0D Checking for updates...');\n await UpdateChecker.forceCheck(VERSION);\n } catch (error: unknown) {\n logger.error('Update check failed', error as Error);\n console.error('\u274C Update check failed:', (error as Error).message);\n process.exit(1);\n }\n });\n\nprogram\n .command('progress')\n .description('Show current progress and recent changes')\n .action(async () => {\n try {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n '\u274C StackMemory not initialized. Run \"stackmemory init\" first.'\n );\n return;\n }\n\n const progress = new ProgressTracker(projectRoot);\n console.log(progress.getSummary());\n } catch (error: unknown) {\n logger.error('Failed to show progress', error as Error);\n console.error('\u274C Failed to show progress:', (error as Error).message);\n process.exit(1);\n }\n });\n\nprogram\n .command('mcp-server')\n .description('Start StackMemory MCP server for Claude Desktop')\n .option('-p, --project <path>', 'Project root directory', process.cwd())\n .action(async (options) => {\n try {\n const { runMCPServer } = await import('../integrations/mcp/server.js');\n\n // Set project root\n process.env['PROJECT_ROOT'] = options.project;\n\n console.log('\uD83D\uDE80 Starting StackMemory MCP Server...');\n console.log(` Project: ${options.project}`);\n console.log(` Version: ${VERSION}`);\n\n // Check for updates silently\n UpdateChecker.checkForUpdates(VERSION, true).catch(() => {});\n\n // Start the MCP server\n await runMCPServer();\n } catch (error: unknown) {\n logger.error('Failed to start MCP server', error as Error);\n console.error('\u274C MCP server failed:', (error as Error).message);\n process.exit(1);\n }\n });\n\n// Add test context command\nprogram\n .command('context:test')\n .description('Test context persistence by creating sample frames')\n .action(async () => {\n try {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n '\u274C StackMemory not initialized. Run \"stackmemory init\" first.'\n );\n return;\n }\n\n const db = new Database(dbPath);\n const frameManager = new FrameManager(db, 'cli-project');\n\n // Create test frames\n console.log('\uD83D\uDCDD Creating test context frames...');\n\n const rootFrame = frameManager.createFrame({\n type: 'task',\n name: 'Test Session',\n inputs: { test: true, timestamp: new Date().toISOString() },\n });\n\n const taskFrame = frameManager.createFrame({\n type: 'subtask',\n name: 'Sample Task',\n inputs: { description: 'Testing context persistence' },\n parentFrameId: rootFrame,\n });\n\n const commandFrame = frameManager.createFrame({\n type: 'tool_scope',\n name: 'test-command',\n inputs: { args: ['--test'] },\n parentFrameId: taskFrame,\n });\n\n // Add some events\n frameManager.addEvent(\n 'observation',\n {\n message: 'Test event recorded',\n },\n commandFrame\n );\n\n console.log('\u2705 Test frames created!');\n console.log(`\uD83D\uDCCA Stack depth: ${frameManager.getStackDepth()}`);\n console.log(\n `\uD83D\uDD04 Active frames: ${frameManager.getActiveFramePath().length}`\n );\n\n // Close one frame to test state changes\n frameManager.closeFrame(commandFrame);\n console.log(\n `\uD83D\uDCCA After closing command frame: depth = ${frameManager.getStackDepth()}`\n );\n\n db.close();\n } catch (error: unknown) {\n logger.error('Test context failed', error as Error);\n console.error('\u274C Test failed:', (error as Error).message);\n process.exit(1);\n }\n });\n\n// Register project management commands\n// Register command modules\nregisterOnboardingCommand(program);\nregisterSignupCommand(program);\nregisterLoginCommand(program);\nregisterLogoutCommand(program);\nregisterDbCommands(program);\nregisterProjectCommands(program);\nregisterWorktreeCommands(program);\n\n// Register Linear integration commands\nregisterLinearCommands(program);\n\n// Register session management commands\nprogram.addCommand(createSessionCommands());\n\n// Register enhanced CLI commands\nprogram.addCommand(createTaskCommands());\nprogram.addCommand(createSearchCommand());\nprogram.addCommand(createLogCommand());\nprogram.addCommand(createContextCommands());\nprogram.addCommand(createConfigCommand());\nprogram.addCommand(createHandoffCommand());\nprogram.addCommand(createDecisionCommand());\nprogram.addCommand(createMemoryCommand());\nprogram.addCommand(createStorageCommand());\nprogram.addCommand(createSkillsCommand());\nprogram.addCommand(createTestCommand());\nprogram.addCommand(clearCommand);\nprogram.addCommand(createWorkflowCommand());\nprogram.addCommand(monitorCommand);\nprogram.addCommand(qualityCommand);\nprogram.addCommand(createRalphCommand());\nprogram.addCommand(serviceCommand);\nprogram.addCommand(createSweepCommand());\nprogram.addCommand(createHooksCommand());\nprogram.addCommand(createShellCommand());\nprogram.addCommand(createAPICommand());\nprogram.addCommand(createCleanupProcessesCommand());\n\n// Register dashboard command\nprogram\n .command('dashboard')\n .description('Display monitoring dashboard in terminal')\n .option('-w, --watch', 'Auto-refresh dashboard')\n .option('-i, --interval <seconds>', 'Refresh interval in seconds', '5')\n .action(async (options) => {\n const { dashboardCommand } = await import('./commands/dashboard.js');\n await dashboardCommand.handler(options);\n });\n\n// Auto-detect current project on startup\nif (process.argv.length > 2) {\n const manager = ProjectManager.getInstance();\n manager.detectProject().catch(() => {\n // Silently fail if not in a project directory\n });\n}\n\n// Only parse when running as main module (not when imported for testing)\nconst isMainModule =\n import.meta.url === `file://${process.argv[1]}` ||\n process.argv[1]?.endsWith('/stackmemory') ||\n process.argv[1]?.endsWith('index.ts') ||\n process.argv[1]?.includes('tsx');\n\nif (isMainModule) {\n program.parse();\n}\n\nexport { program };\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["#!/usr/bin/env node\n/**\n * StackMemory CLI\n * Command-line interface for StackMemory operations\n */\n\n// Set environment flag for CLI usage to skip async context bridge\nprocess.env['STACKMEMORY_CLI'] = 'true';\n\n// Load environment variables\nimport 'dotenv/config';\n\n// Initialize tracing system early\nimport { initializeTracing, trace } from '../core/trace/index.js';\ninitializeTracing();\n\nimport { program } from 'commander';\nimport { logger } from '../core/monitoring/logger.js';\nimport { FrameManager } from '../core/context/frame-manager.js';\nimport { sessionManager, FrameQueryMode } from '../core/session/index.js';\nimport { sharedContextLayer } from '../core/context/shared-context-layer.js';\nimport { UpdateChecker } from '../core/utils/update-checker.js';\nimport { ProgressTracker } from '../core/monitoring/progress-tracker.js';\nimport { registerProjectCommands } from './commands/projects.js';\nimport { registerLinearCommands } from './commands/linear.js';\nimport { createSessionCommands } from './commands/session.js';\nimport { registerWorktreeCommands } from './commands/worktree.js';\nimport { registerOnboardingCommand } from './commands/onboard.js';\nimport { createTaskCommands } from './commands/tasks.js';\nimport { createSearchCommand } from './commands/search.js';\nimport { createLogCommand } from './commands/log.js';\nimport { createContextCommands } from './commands/context.js';\nimport { createConfigCommand } from './commands/config.js';\nimport { createHandoffCommand } from './commands/handoff.js';\nimport {\n createDecisionCommand,\n createMemoryCommand,\n} from './commands/decision.js';\nimport { createStorageCommand } from './commands/storage.js';\nimport { createSkillsCommand } from './commands/skills.js';\nimport { createTestCommand } from './commands/test.js';\nimport clearCommand from './commands/clear.js';\nimport createWorkflowCommand from './commands/workflow.js';\nimport monitorCommand from './commands/monitor.js';\nimport qualityCommand from './commands/quality.js';\nimport createRalphCommand from './commands/ralph.js';\nimport serviceCommand from './commands/service.js';\nimport { registerLoginCommand } from './commands/login.js';\nimport { registerSignupCommand } from './commands/signup.js';\nimport { registerLogoutCommand, registerDbCommands } from './commands/db.js';\nimport { createSweepCommand } from './commands/sweep.js';\nimport { createHooksCommand } from './commands/hooks.js';\nimport { createShellCommand } from './commands/shell.js';\nimport { createAPICommand } from './commands/api.js';\nimport { createCleanupProcessesCommand } from './commands/cleanup-processes.js';\nimport { createAutoBackgroundCommand } from './commands/auto-background.js';\nimport { ProjectManager } from '../core/projects/project-manager.js';\nimport Database from 'better-sqlite3';\nimport { join } from 'path';\nimport { existsSync, mkdirSync } from 'fs';\nimport inquirer from 'inquirer';\nimport chalk from 'chalk';\nimport {\n loadStorageConfig,\n enableChromaDB,\n getStorageModeDescription,\n} from '../core/config/storage-config.js';\n\nconst VERSION = '0.5.5';\n\n// Check for updates on CLI startup\nUpdateChecker.checkForUpdates(VERSION, true).catch(() => {\n // Silently ignore errors\n});\n\nprogram\n .name('stackmemory')\n .description(\n 'Lossless memory runtime for AI coding tools - organizes context as a call stack instead of linear chat logs, with team collaboration and infinite retention'\n )\n .version(VERSION);\n\nprogram\n .command('init')\n .description(\n `Initialize StackMemory in current project\n\nStorage Modes:\n SQLite (default): Local only, fast, no setup required\n ChromaDB (hybrid): Adds semantic search and cloud backup, requires API key`\n )\n .option('--sqlite', 'Use SQLite-only storage (default, skip prompts)')\n .option(\n '--chromadb',\n 'Enable ChromaDB for semantic search (prompts for API key)'\n )\n .option('--skip-storage-prompt', 'Skip storage configuration prompt')\n .action(async (options) => {\n try {\n const projectRoot = process.cwd();\n const dbDir = join(projectRoot, '.stackmemory');\n\n if (!existsSync(dbDir)) {\n mkdirSync(dbDir, { recursive: true });\n }\n\n // Handle storage configuration\n let storageConfig = loadStorageConfig();\n const isFirstTimeSetup =\n !storageConfig.chromadb.enabled && storageConfig.mode === 'sqlite';\n\n // Skip prompts if --sqlite flag or --skip-storage-prompt\n if (options.sqlite || options.skipStoragePrompt) {\n // Use SQLite-only (default)\n console.log(chalk.gray('Using SQLite-only storage mode.'));\n } else if (options.chromadb) {\n // User explicitly requested ChromaDB, prompt for API key\n await promptAndEnableChromaDB();\n } else if (isFirstTimeSetup && process.stdin.isTTY) {\n // Interactive mode - ask user about ChromaDB\n console.log(chalk.cyan('\\nStorage Configuration'));\n console.log(chalk.gray('StackMemory supports two storage modes:\\n'));\n console.log(chalk.white(' SQLite (default):'));\n console.log(chalk.gray(' - Local storage only'));\n console.log(chalk.gray(' - Fast and simple'));\n console.log(chalk.gray(' - No external dependencies\\n'));\n console.log(chalk.white(' ChromaDB (hybrid):'));\n console.log(chalk.gray(' - Semantic search across your context'));\n console.log(chalk.gray(' - Cloud backup capability'));\n console.log(chalk.gray(' - Requires ChromaDB API key\\n'));\n\n const { enableChroma } = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'enableChroma',\n message: 'Enable ChromaDB for semantic search? (requires API key)',\n default: false,\n },\n ]);\n\n if (enableChroma) {\n await promptAndEnableChromaDB();\n } else {\n console.log(chalk.gray('Using SQLite-only storage mode.'));\n }\n }\n\n // Initialize SQLite database\n const dbPath = join(dbDir, 'context.db');\n const db = new Database(dbPath);\n new FrameManager(db, 'cli-project');\n\n logger.info('StackMemory initialized successfully', { projectRoot });\n console.log(\n chalk.green('\\n[OK] StackMemory initialized in'),\n projectRoot\n );\n\n // Show current storage mode\n storageConfig = loadStorageConfig();\n console.log(chalk.gray(`Storage mode: ${getStorageModeDescription()}`));\n\n db.close();\n } catch (error: unknown) {\n logger.error('Failed to initialize StackMemory', error as Error);\n console.error(\n chalk.red('[ERROR] Initialization failed:'),\n (error as Error).message\n );\n process.exit(1);\n }\n });\n\n/**\n * Prompt user for ChromaDB configuration and enable it\n */\nasync function promptAndEnableChromaDB(): Promise<void> {\n const answers = await inquirer.prompt([\n {\n type: 'password',\n name: 'apiKey',\n message: 'Enter your ChromaDB API key:',\n validate: (input: string) => {\n if (!input || input.trim().length === 0) {\n return 'API key is required for ChromaDB';\n }\n return true;\n },\n },\n {\n type: 'input',\n name: 'apiUrl',\n message: 'ChromaDB API URL (press Enter for default):',\n default: 'https://api.trychroma.com',\n },\n ]);\n\n enableChromaDB({\n apiKey: answers.apiKey,\n apiUrl: answers.apiUrl,\n });\n\n console.log(chalk.green('[OK] ChromaDB enabled for semantic search.'));\n console.log(\n chalk.gray('API key saved to ~/.stackmemory/storage-config.json')\n );\n}\n\nprogram\n .command('status')\n .description('Show current StackMemory status')\n .option('--all', 'Show all active frames across sessions')\n .option('--project', 'Show all active frames in current project')\n .option('--session <id>', 'Show frames for specific session')\n .action(async (options) => {\n return trace.command('stackmemory-status', options, async () => {\n try {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n '\u274C StackMemory not initialized. Run \"stackmemory init\" first.'\n );\n return;\n }\n\n // Check for updates and display if available\n await UpdateChecker.checkForUpdates(VERSION);\n\n // Initialize session manager and shared context\n await sessionManager.initialize();\n await sharedContextLayer.initialize();\n\n const session = await sessionManager.getOrCreateSession({\n projectPath: projectRoot,\n sessionId: options.session,\n });\n\n // Auto-discover shared context on startup\n const contextDiscovery = await sharedContextLayer.autoDiscoverContext();\n\n // Show context hints if available\n if (\n contextDiscovery.hasSharedContext &&\n contextDiscovery.sessionCount > 1\n ) {\n console.log(`\\n\uD83D\uDCA1 Shared Context Available:`);\n console.log(\n ` ${contextDiscovery.sessionCount} sessions with shared context`\n );\n\n if (contextDiscovery.recentPatterns.length > 0) {\n console.log(` Recent patterns:`);\n contextDiscovery.recentPatterns.slice(0, 3).forEach((p) => {\n console.log(\n ` \u2022 ${p.type}: ${p.pattern.slice(0, 50)} (${p.frequency}x)`\n );\n });\n }\n\n if (contextDiscovery.lastDecisions.length > 0) {\n console.log(\n ` Last decision: ${contextDiscovery.lastDecisions[0].decision.slice(0, 60)}`\n );\n }\n }\n\n const db = new Database(dbPath);\n const frameManager = new FrameManager(db, session.projectId);\n\n // Set query mode based on options\n if (options.all) {\n frameManager.setQueryMode(FrameQueryMode.ALL_ACTIVE);\n } else if (options.project) {\n frameManager.setQueryMode(FrameQueryMode.PROJECT_ACTIVE);\n }\n\n const activeFrames = frameManager.getActiveFramePath();\n const stackDepth = frameManager.getStackDepth();\n\n // Always get total counts across all sessions\n const totalStats = db\n .prepare(\n `\n SELECT \n COUNT(*) as total_frames,\n SUM(CASE WHEN state = 'active' THEN 1 ELSE 0 END) as active_frames,\n SUM(CASE WHEN state = 'closed' THEN 1 ELSE 0 END) as closed_frames,\n COUNT(DISTINCT run_id) as total_sessions\n FROM frames\n WHERE project_id = ?\n `\n )\n .get(session.projectId) as {\n total_frames: number;\n active_frames: number;\n closed_frames: number;\n total_sessions: number;\n };\n\n const contextCount = db\n .prepare(\n `\n SELECT COUNT(*) as count FROM contexts\n `\n )\n .get() as { count: number };\n\n const eventCount = db\n .prepare(\n `\n SELECT COUNT(*) as count FROM events e\n JOIN frames f ON e.frame_id = f.frame_id\n WHERE f.project_id = ?\n `\n )\n .get(session.projectId) as { count: number };\n\n console.log('\uD83D\uDCCA StackMemory Status:');\n console.log(\n ` Session: ${session.sessionId.slice(0, 8)} (${session.state}, ${Math.round((Date.now() - session.startedAt) / 1000 / 60)}min old)`\n );\n console.log(` Project: ${session.projectId}`);\n if (session.branch) {\n console.log(` Branch: ${session.branch}`);\n }\n\n // Show total database statistics\n console.log(`\\n Database Statistics (this project):`);\n console.log(\n ` Frames: ${totalStats.total_frames || 0} (${totalStats.active_frames || 0} active, ${totalStats.closed_frames || 0} closed)`\n );\n console.log(` Events: ${eventCount.count || 0}`);\n console.log(` Sessions: ${totalStats.total_sessions || 0}`);\n console.log(\n ` Cached contexts: ${contextCount.count || 0} (global)`\n );\n\n // Show recent activity\n const recentFrames = db\n .prepare(\n `\n SELECT name, type, state, datetime(created_at, 'unixepoch') as created\n FROM frames\n WHERE project_id = ?\n ORDER BY created_at DESC\n LIMIT 3\n `\n )\n .all(session.projectId) as Array<{\n name: string;\n type: string;\n state: string;\n created: string;\n }>;\n\n if (recentFrames.length > 0) {\n console.log(`\\n Recent Activity:`);\n recentFrames.forEach((f) => {\n const stateIcon = f.state === 'active' ? '\uD83D\uDFE2' : '\u26AB';\n console.log(\n ` ${stateIcon} ${f.name} [${f.type}] - ${f.created}`\n );\n });\n }\n\n console.log(`\\n Current Session:`);\n console.log(` Stack depth: ${stackDepth}`);\n console.log(` Active frames: ${activeFrames.length}`);\n\n if (activeFrames.length > 0) {\n activeFrames.forEach((frame, i) => {\n const indent = ' ' + ' '.repeat(frame.depth || i);\n const prefix = i === 0 ? '\u2514\u2500' : ' \u2514\u2500';\n console.log(`${indent}${prefix} ${frame.name} [${frame.type}]`);\n });\n }\n\n // Show other sessions if in default mode\n if (!options.all && !options.project) {\n const otherSessions = await sessionManager.listSessions({\n projectId: session.projectId,\n state: 'active',\n });\n\n const otherActive = otherSessions.filter(\n (s) => s.sessionId !== session.sessionId\n );\n if (otherActive.length > 0) {\n console.log(`\\n Other Active Sessions (same project):`);\n otherActive.forEach((s) => {\n const age = Math.round(\n (Date.now() - s.lastActiveAt) / 1000 / 60 / 60\n );\n console.log(\n ` - ${s.sessionId.slice(0, 8)}: ${s.branch || 'main'}, ${age}h old`\n );\n });\n console.log(`\\n Tip: Use --all to see frames across sessions`);\n }\n }\n\n db.close();\n } catch (error: unknown) {\n logger.error('Failed to get status', error as Error);\n console.error('\u274C Status check failed:', (error as Error).message);\n process.exit(1);\n }\n });\n });\n\nprogram\n .command('update-check')\n .description('Check for StackMemory updates')\n .action(async () => {\n try {\n console.log('\uD83D\uDD0D Checking for updates...');\n await UpdateChecker.forceCheck(VERSION);\n } catch (error: unknown) {\n logger.error('Update check failed', error as Error);\n console.error('\u274C Update check failed:', (error as Error).message);\n process.exit(1);\n }\n });\n\nprogram\n .command('progress')\n .description('Show current progress and recent changes')\n .action(async () => {\n try {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n '\u274C StackMemory not initialized. Run \"stackmemory init\" first.'\n );\n return;\n }\n\n const progress = new ProgressTracker(projectRoot);\n console.log(progress.getSummary());\n } catch (error: unknown) {\n logger.error('Failed to show progress', error as Error);\n console.error('\u274C Failed to show progress:', (error as Error).message);\n process.exit(1);\n }\n });\n\nprogram\n .command('mcp-server')\n .description('Start StackMemory MCP server for Claude Desktop')\n .option('-p, --project <path>', 'Project root directory', process.cwd())\n .action(async (options) => {\n try {\n const { runMCPServer } = await import('../integrations/mcp/server.js');\n\n // Set project root\n process.env['PROJECT_ROOT'] = options.project;\n\n console.log('\uD83D\uDE80 Starting StackMemory MCP Server...');\n console.log(` Project: ${options.project}`);\n console.log(` Version: ${VERSION}`);\n\n // Check for updates silently\n UpdateChecker.checkForUpdates(VERSION, true).catch(() => {});\n\n // Start the MCP server\n await runMCPServer();\n } catch (error: unknown) {\n logger.error('Failed to start MCP server', error as Error);\n console.error('\u274C MCP server failed:', (error as Error).message);\n process.exit(1);\n }\n });\n\n// Add test context command\nprogram\n .command('context:test')\n .description('Test context persistence by creating sample frames')\n .action(async () => {\n try {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n '\u274C StackMemory not initialized. Run \"stackmemory init\" first.'\n );\n return;\n }\n\n const db = new Database(dbPath);\n const frameManager = new FrameManager(db, 'cli-project');\n\n // Create test frames\n console.log('\uD83D\uDCDD Creating test context frames...');\n\n const rootFrame = frameManager.createFrame({\n type: 'task',\n name: 'Test Session',\n inputs: { test: true, timestamp: new Date().toISOString() },\n });\n\n const taskFrame = frameManager.createFrame({\n type: 'subtask',\n name: 'Sample Task',\n inputs: { description: 'Testing context persistence' },\n parentFrameId: rootFrame,\n });\n\n const commandFrame = frameManager.createFrame({\n type: 'tool_scope',\n name: 'test-command',\n inputs: { args: ['--test'] },\n parentFrameId: taskFrame,\n });\n\n // Add some events\n frameManager.addEvent(\n 'observation',\n {\n message: 'Test event recorded',\n },\n commandFrame\n );\n\n console.log('\u2705 Test frames created!');\n console.log(`\uD83D\uDCCA Stack depth: ${frameManager.getStackDepth()}`);\n console.log(\n `\uD83D\uDD04 Active frames: ${frameManager.getActiveFramePath().length}`\n );\n\n // Close one frame to test state changes\n frameManager.closeFrame(commandFrame);\n console.log(\n `\uD83D\uDCCA After closing command frame: depth = ${frameManager.getStackDepth()}`\n );\n\n db.close();\n } catch (error: unknown) {\n logger.error('Test context failed', error as Error);\n console.error('\u274C Test failed:', (error as Error).message);\n process.exit(1);\n }\n });\n\n// Register project management commands\n// Register command modules\nregisterOnboardingCommand(program);\nregisterSignupCommand(program);\nregisterLoginCommand(program);\nregisterLogoutCommand(program);\nregisterDbCommands(program);\nregisterProjectCommands(program);\nregisterWorktreeCommands(program);\n\n// Register Linear integration commands\nregisterLinearCommands(program);\n\n// Register session management commands\nprogram.addCommand(createSessionCommands());\n\n// Register enhanced CLI commands\nprogram.addCommand(createTaskCommands());\nprogram.addCommand(createSearchCommand());\nprogram.addCommand(createLogCommand());\nprogram.addCommand(createContextCommands());\nprogram.addCommand(createConfigCommand());\nprogram.addCommand(createHandoffCommand());\nprogram.addCommand(createDecisionCommand());\nprogram.addCommand(createMemoryCommand());\nprogram.addCommand(createStorageCommand());\nprogram.addCommand(createSkillsCommand());\nprogram.addCommand(createTestCommand());\nprogram.addCommand(clearCommand);\nprogram.addCommand(createWorkflowCommand());\nprogram.addCommand(monitorCommand);\nprogram.addCommand(qualityCommand);\nprogram.addCommand(createRalphCommand());\nprogram.addCommand(serviceCommand);\nprogram.addCommand(createSweepCommand());\nprogram.addCommand(createHooksCommand());\nprogram.addCommand(createShellCommand());\nprogram.addCommand(createAPICommand());\nprogram.addCommand(createCleanupProcessesCommand());\nprogram.addCommand(createAutoBackgroundCommand());\n\n// Register dashboard command\nprogram\n .command('dashboard')\n .description('Display monitoring dashboard in terminal')\n .option('-w, --watch', 'Auto-refresh dashboard')\n .option('-i, --interval <seconds>', 'Refresh interval in seconds', '5')\n .action(async (options) => {\n const { dashboardCommand } = await import('./commands/dashboard.js');\n await dashboardCommand.handler(options);\n });\n\n// Auto-detect current project on startup\nif (process.argv.length > 2) {\n const manager = ProjectManager.getInstance();\n manager.detectProject().catch(() => {\n // Silently fail if not in a project directory\n });\n}\n\n// Only parse when running as main module (not when imported for testing)\nconst isMainModule =\n import.meta.url === `file://${process.argv[1]}` ||\n process.argv[1]?.endsWith('/stackmemory') ||\n process.argv[1]?.endsWith('index.ts') ||\n process.argv[1]?.includes('tsx');\n\nif (isMainModule) {\n program.parse();\n}\n\nexport { program };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { fileURLToPath as __fileURLToPath } from 'url';
|
|
2
|
+
import { dirname as __pathDirname } from 'path';
|
|
3
|
+
const __filename = __fileURLToPath(import.meta.url);
|
|
4
|
+
const __dirname = __pathDirname(__filename);
|
|
5
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
6
|
+
import { join } from "path";
|
|
7
|
+
import { homedir } from "os";
|
|
8
|
+
const DEFAULT_CONFIG = {
|
|
9
|
+
enabled: true,
|
|
10
|
+
timeoutMs: 5e3,
|
|
11
|
+
// 5 seconds
|
|
12
|
+
alwaysBackground: [
|
|
13
|
+
// Package managers
|
|
14
|
+
"npm install",
|
|
15
|
+
"npm ci",
|
|
16
|
+
"yarn install",
|
|
17
|
+
"pnpm install",
|
|
18
|
+
"bun install",
|
|
19
|
+
// Builds
|
|
20
|
+
"npm run build",
|
|
21
|
+
"yarn build",
|
|
22
|
+
"pnpm build",
|
|
23
|
+
"cargo build",
|
|
24
|
+
"go build",
|
|
25
|
+
"make",
|
|
26
|
+
"cmake",
|
|
27
|
+
// Tests
|
|
28
|
+
"npm test",
|
|
29
|
+
"npm run test",
|
|
30
|
+
"yarn test",
|
|
31
|
+
"pnpm test",
|
|
32
|
+
"pytest",
|
|
33
|
+
"jest",
|
|
34
|
+
"vitest",
|
|
35
|
+
"cargo test",
|
|
36
|
+
"go test",
|
|
37
|
+
// Docker
|
|
38
|
+
"docker build",
|
|
39
|
+
"docker-compose up",
|
|
40
|
+
"docker compose up",
|
|
41
|
+
// Git operations that can be slow
|
|
42
|
+
"git clone",
|
|
43
|
+
"git fetch --all",
|
|
44
|
+
"git pull --all",
|
|
45
|
+
// Type checking
|
|
46
|
+
"npx tsc",
|
|
47
|
+
"tsc --noEmit",
|
|
48
|
+
// Linting large codebases
|
|
49
|
+
"eslint .",
|
|
50
|
+
"npm run lint"
|
|
51
|
+
],
|
|
52
|
+
neverBackground: [
|
|
53
|
+
// Interactive commands
|
|
54
|
+
"vim",
|
|
55
|
+
"nvim",
|
|
56
|
+
"nano",
|
|
57
|
+
"less",
|
|
58
|
+
"more",
|
|
59
|
+
"top",
|
|
60
|
+
"htop",
|
|
61
|
+
// Quick commands
|
|
62
|
+
"echo",
|
|
63
|
+
"cat",
|
|
64
|
+
"ls",
|
|
65
|
+
"pwd",
|
|
66
|
+
"cd",
|
|
67
|
+
"which",
|
|
68
|
+
"git status",
|
|
69
|
+
"git diff",
|
|
70
|
+
"git log"
|
|
71
|
+
],
|
|
72
|
+
verbose: false
|
|
73
|
+
};
|
|
74
|
+
const CONFIG_PATH = join(homedir(), ".stackmemory", "auto-background.json");
|
|
75
|
+
function loadConfig() {
|
|
76
|
+
try {
|
|
77
|
+
if (existsSync(CONFIG_PATH)) {
|
|
78
|
+
const data = readFileSync(CONFIG_PATH, "utf8");
|
|
79
|
+
return { ...DEFAULT_CONFIG, ...JSON.parse(data) };
|
|
80
|
+
}
|
|
81
|
+
} catch {
|
|
82
|
+
}
|
|
83
|
+
return DEFAULT_CONFIG;
|
|
84
|
+
}
|
|
85
|
+
function saveConfig(config) {
|
|
86
|
+
try {
|
|
87
|
+
const dir = join(homedir(), ".stackmemory");
|
|
88
|
+
if (!existsSync(dir)) {
|
|
89
|
+
mkdirSync(dir, { recursive: true });
|
|
90
|
+
}
|
|
91
|
+
writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
92
|
+
} catch {
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function shouldAutoBackground(command, config) {
|
|
96
|
+
const cfg = config || loadConfig();
|
|
97
|
+
if (!cfg.enabled) return false;
|
|
98
|
+
const normalizedCmd = command.trim().toLowerCase();
|
|
99
|
+
for (const pattern of cfg.neverBackground) {
|
|
100
|
+
if (normalizedCmd.startsWith(pattern.toLowerCase())) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
for (const pattern of cfg.alwaysBackground) {
|
|
105
|
+
if (normalizedCmd.startsWith(pattern.toLowerCase())) {
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
function processToolUse(toolName, toolInput) {
|
|
112
|
+
if (toolName !== "Bash") {
|
|
113
|
+
return { decision: "allow" };
|
|
114
|
+
}
|
|
115
|
+
const command = toolInput.command;
|
|
116
|
+
if (!command) {
|
|
117
|
+
return { decision: "allow" };
|
|
118
|
+
}
|
|
119
|
+
if (toolInput.run_in_background === true) {
|
|
120
|
+
return { decision: "allow" };
|
|
121
|
+
}
|
|
122
|
+
const config = loadConfig();
|
|
123
|
+
if (shouldAutoBackground(command, config)) {
|
|
124
|
+
if (config.verbose) {
|
|
125
|
+
console.error(
|
|
126
|
+
`[auto-background] Backgrounding: ${command.substring(0, 50)}...`
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
decision: "modify",
|
|
131
|
+
modifiedInput: {
|
|
132
|
+
...toolInput,
|
|
133
|
+
run_in_background: true
|
|
134
|
+
},
|
|
135
|
+
reason: `Auto-backgrounded: matches pattern`
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
return { decision: "allow" };
|
|
139
|
+
}
|
|
140
|
+
export {
|
|
141
|
+
loadConfig,
|
|
142
|
+
processToolUse,
|
|
143
|
+
saveConfig,
|
|
144
|
+
shouldAutoBackground
|
|
145
|
+
};
|
|
146
|
+
//# sourceMappingURL=auto-background.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/hooks/auto-background.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Auto-background hook for Claude Code\n * Automatically backgrounds long-running or specific commands\n */\n\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\n\nexport interface AutoBackgroundConfig {\n enabled: boolean;\n // Time-based: background if command runs longer than this (ms)\n timeoutMs: number;\n // Pattern-based: always background these commands\n alwaysBackground: string[];\n // Never background these (override)\n neverBackground: string[];\n // Log backgrounded commands\n verbose: boolean;\n}\n\nconst DEFAULT_CONFIG: AutoBackgroundConfig = {\n enabled: true,\n timeoutMs: 5000, // 5 seconds\n alwaysBackground: [\n // Package managers\n 'npm install',\n 'npm ci',\n 'yarn install',\n 'pnpm install',\n 'bun install',\n // Builds\n 'npm run build',\n 'yarn build',\n 'pnpm build',\n 'cargo build',\n 'go build',\n 'make',\n 'cmake',\n // Tests\n 'npm test',\n 'npm run test',\n 'yarn test',\n 'pnpm test',\n 'pytest',\n 'jest',\n 'vitest',\n 'cargo test',\n 'go test',\n // Docker\n 'docker build',\n 'docker-compose up',\n 'docker compose up',\n // Git operations that can be slow\n 'git clone',\n 'git fetch --all',\n 'git pull --all',\n // Type checking\n 'npx tsc',\n 'tsc --noEmit',\n // Linting large codebases\n 'eslint .',\n 'npm run lint',\n ],\n neverBackground: [\n // Interactive commands\n 'vim',\n 'nvim',\n 'nano',\n 'less',\n 'more',\n 'top',\n 'htop',\n // Quick commands\n 'echo',\n 'cat',\n 'ls',\n 'pwd',\n 'cd',\n 'which',\n 'git status',\n 'git diff',\n 'git log',\n ],\n verbose: false,\n};\n\nconst CONFIG_PATH = join(homedir(), '.stackmemory', 'auto-background.json');\n\nexport function loadConfig(): AutoBackgroundConfig {\n try {\n if (existsSync(CONFIG_PATH)) {\n const data = readFileSync(CONFIG_PATH, 'utf8');\n return { ...DEFAULT_CONFIG, ...JSON.parse(data) };\n }\n } catch {\n // Use defaults\n }\n return DEFAULT_CONFIG;\n}\n\nexport function saveConfig(config: AutoBackgroundConfig): void {\n try {\n const dir = join(homedir(), '.stackmemory');\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));\n } catch {\n // Silently fail\n }\n}\n\nexport function shouldAutoBackground(\n command: string,\n config?: AutoBackgroundConfig\n): boolean {\n const cfg = config || loadConfig();\n\n if (!cfg.enabled) return false;\n\n const normalizedCmd = command.trim().toLowerCase();\n\n // Check never-background list first (highest priority)\n for (const pattern of cfg.neverBackground) {\n if (normalizedCmd.startsWith(pattern.toLowerCase())) {\n return false;\n }\n }\n\n // Check always-background list\n for (const pattern of cfg.alwaysBackground) {\n if (normalizedCmd.startsWith(pattern.toLowerCase())) {\n return true;\n }\n }\n\n // Default: don't auto-background (let timeout handle it)\n return false;\n}\n\n/**\n * Hook response format for Claude Code\n * Returns modified tool input if command should be backgrounded\n */\nexport interface HookResponse {\n decision: 'allow' | 'modify' | 'block';\n modifiedInput?: Record<string, unknown>;\n reason?: string;\n}\n\nexport function processToolUse(\n toolName: string,\n toolInput: Record<string, unknown>\n): HookResponse {\n // Only process Bash tool\n if (toolName !== 'Bash') {\n return { decision: 'allow' };\n }\n\n const command = toolInput.command as string;\n if (!command) {\n return { decision: 'allow' };\n }\n\n // Skip if already backgrounded\n if (toolInput.run_in_background === true) {\n return { decision: 'allow' };\n }\n\n const config = loadConfig();\n\n if (shouldAutoBackground(command, config)) {\n if (config.verbose) {\n console.error(\n `[auto-background] Backgrounding: ${command.substring(0, 50)}...`\n );\n }\n\n return {\n decision: 'modify',\n modifiedInput: {\n ...toolInput,\n run_in_background: true,\n },\n reason: `Auto-backgrounded: matches pattern`,\n };\n }\n\n return { decision: 'allow' };\n}\n\n// CLI entry point removed - use stackmemory auto-bg command instead\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/hooks/index.js
CHANGED
package/dist/hooks/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/hooks/index.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * StackMemory Hooks Module\n * User-configurable hook system for automation and suggestions\n */\n\nexport * from './events.js';\nexport * from './config.js';\nexport * from './daemon.js';\n"],
|
|
5
|
-
"mappings": ";;;;AAKA,cAAc;AACd,cAAc;AACd,cAAc;",
|
|
4
|
+
"sourcesContent": ["/**\n * StackMemory Hooks Module\n * User-configurable hook system for automation and suggestions\n */\n\nexport * from './events.js';\nexport * from './config.js';\nexport * from './daemon.js';\nexport * from './auto-background.js';\n"],
|
|
5
|
+
"mappings": ";;;;AAKA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackmemoryai/stackmemory",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.7",
|
|
4
4
|
"description": "Lossless memory runtime for AI coding tools - organizes context as a call stack instead of linear chat logs, with team collaboration and infinite retention",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=20.0.0",
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Install auto-background hook for Claude Code
|
|
3
|
+
|
|
4
|
+
set -e
|
|
5
|
+
|
|
6
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
7
|
+
HOOK_SOURCE="$SCRIPT_DIR/../templates/claude-hooks/auto-background-hook.js"
|
|
8
|
+
CLAUDE_DIR="$HOME/.claude"
|
|
9
|
+
HOOKS_DIR="$CLAUDE_DIR/hooks"
|
|
10
|
+
SETTINGS_FILE="$CLAUDE_DIR/settings.json"
|
|
11
|
+
CONFIG_DIR="$HOME/.stackmemory"
|
|
12
|
+
|
|
13
|
+
echo "Installing auto-background hook for Claude Code..."
|
|
14
|
+
|
|
15
|
+
# Create directories
|
|
16
|
+
mkdir -p "$HOOKS_DIR"
|
|
17
|
+
mkdir -p "$CONFIG_DIR"
|
|
18
|
+
|
|
19
|
+
# Copy hook script
|
|
20
|
+
HOOK_DEST="$HOOKS_DIR/auto-background-hook.js"
|
|
21
|
+
cp "$HOOK_SOURCE" "$HOOK_DEST"
|
|
22
|
+
chmod +x "$HOOK_DEST"
|
|
23
|
+
echo "Installed hook to $HOOK_DEST"
|
|
24
|
+
|
|
25
|
+
# Create default config if not exists
|
|
26
|
+
CONFIG_FILE="$CONFIG_DIR/auto-background.json"
|
|
27
|
+
if [ ! -f "$CONFIG_FILE" ]; then
|
|
28
|
+
cat > "$CONFIG_FILE" << 'EOF'
|
|
29
|
+
{
|
|
30
|
+
"enabled": true,
|
|
31
|
+
"timeoutMs": 5000,
|
|
32
|
+
"alwaysBackground": [
|
|
33
|
+
"npm install",
|
|
34
|
+
"npm ci",
|
|
35
|
+
"yarn install",
|
|
36
|
+
"pnpm install",
|
|
37
|
+
"bun install",
|
|
38
|
+
"npm run build",
|
|
39
|
+
"yarn build",
|
|
40
|
+
"pnpm build",
|
|
41
|
+
"cargo build",
|
|
42
|
+
"go build",
|
|
43
|
+
"make",
|
|
44
|
+
"npm test",
|
|
45
|
+
"npm run test",
|
|
46
|
+
"yarn test",
|
|
47
|
+
"pytest",
|
|
48
|
+
"jest",
|
|
49
|
+
"vitest",
|
|
50
|
+
"cargo test",
|
|
51
|
+
"docker build",
|
|
52
|
+
"docker-compose up",
|
|
53
|
+
"docker compose up",
|
|
54
|
+
"git clone",
|
|
55
|
+
"git fetch --all",
|
|
56
|
+
"npx tsc",
|
|
57
|
+
"tsc --noEmit",
|
|
58
|
+
"eslint .",
|
|
59
|
+
"npm run lint"
|
|
60
|
+
],
|
|
61
|
+
"neverBackground": [
|
|
62
|
+
"vim",
|
|
63
|
+
"nvim",
|
|
64
|
+
"nano",
|
|
65
|
+
"less",
|
|
66
|
+
"more",
|
|
67
|
+
"top",
|
|
68
|
+
"htop",
|
|
69
|
+
"echo",
|
|
70
|
+
"cat",
|
|
71
|
+
"ls",
|
|
72
|
+
"pwd",
|
|
73
|
+
"cd",
|
|
74
|
+
"which",
|
|
75
|
+
"git status",
|
|
76
|
+
"git diff",
|
|
77
|
+
"git log"
|
|
78
|
+
],
|
|
79
|
+
"verbose": false
|
|
80
|
+
}
|
|
81
|
+
EOF
|
|
82
|
+
echo "Created config at $CONFIG_FILE"
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
# Update Claude Code settings
|
|
86
|
+
if [ -f "$SETTINGS_FILE" ]; then
|
|
87
|
+
# Check if jq is available
|
|
88
|
+
if command -v jq &> /dev/null; then
|
|
89
|
+
# Backup existing settings
|
|
90
|
+
cp "$SETTINGS_FILE" "$SETTINGS_FILE.bak"
|
|
91
|
+
|
|
92
|
+
# Add hook to settings
|
|
93
|
+
HOOK_CMD="node $HOOK_DEST"
|
|
94
|
+
|
|
95
|
+
# Check if hooks.pre_tool_use exists
|
|
96
|
+
if jq -e '.hooks.pre_tool_use' "$SETTINGS_FILE" > /dev/null 2>&1; then
|
|
97
|
+
# Check if hook already added
|
|
98
|
+
if ! jq -e ".hooks.pre_tool_use | index(\"$HOOK_CMD\")" "$SETTINGS_FILE" > /dev/null 2>&1; then
|
|
99
|
+
jq ".hooks.pre_tool_use += [\"$HOOK_CMD\"]" "$SETTINGS_FILE" > "$SETTINGS_FILE.tmp"
|
|
100
|
+
mv "$SETTINGS_FILE.tmp" "$SETTINGS_FILE"
|
|
101
|
+
echo "Added hook to existing pre_tool_use array"
|
|
102
|
+
else
|
|
103
|
+
echo "Hook already configured"
|
|
104
|
+
fi
|
|
105
|
+
else
|
|
106
|
+
# Create hooks.pre_tool_use array
|
|
107
|
+
jq ".hooks = (.hooks // {}) | .hooks.pre_tool_use = [\"$HOOK_CMD\"]" "$SETTINGS_FILE" > "$SETTINGS_FILE.tmp"
|
|
108
|
+
mv "$SETTINGS_FILE.tmp" "$SETTINGS_FILE"
|
|
109
|
+
echo "Created hooks.pre_tool_use with auto-background hook"
|
|
110
|
+
fi
|
|
111
|
+
else
|
|
112
|
+
echo ""
|
|
113
|
+
echo "jq not found. Please manually add to $SETTINGS_FILE:"
|
|
114
|
+
echo ""
|
|
115
|
+
echo ' "hooks": {'
|
|
116
|
+
echo ' "pre_tool_use": ["node '$HOOK_DEST'"]'
|
|
117
|
+
echo ' }'
|
|
118
|
+
fi
|
|
119
|
+
else
|
|
120
|
+
# Create new settings file
|
|
121
|
+
cat > "$SETTINGS_FILE" << EOF
|
|
122
|
+
{
|
|
123
|
+
"hooks": {
|
|
124
|
+
"pre_tool_use": ["node $HOOK_DEST"]
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
EOF
|
|
128
|
+
echo "Created settings file with hook"
|
|
129
|
+
fi
|
|
130
|
+
|
|
131
|
+
echo ""
|
|
132
|
+
echo "Auto-background hook installed!"
|
|
133
|
+
echo ""
|
|
134
|
+
echo "Configuration: $CONFIG_FILE"
|
|
135
|
+
echo " - Edit to customize which commands auto-background"
|
|
136
|
+
echo " - Set 'enabled': false to disable"
|
|
137
|
+
echo " - Set 'verbose': true for debug logging"
|
|
138
|
+
echo ""
|
|
139
|
+
echo "Commands that will auto-background:"
|
|
140
|
+
echo " - npm install/build/test"
|
|
141
|
+
echo " - yarn/pnpm/bun install"
|
|
142
|
+
echo " - docker build"
|
|
143
|
+
echo " - cargo/go build/test"
|
|
144
|
+
echo " - And more (see config)"
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Claude Code pre-tool-use hook for auto-backgrounding commands
|
|
4
|
+
*
|
|
5
|
+
* Install: Add to ~/.claude/settings.json hooks.pre_tool_use
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const os = require('os');
|
|
11
|
+
|
|
12
|
+
const CONFIG_PATH = path.join(
|
|
13
|
+
os.homedir(),
|
|
14
|
+
'.stackmemory',
|
|
15
|
+
'auto-background.json'
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
const DEFAULT_CONFIG = {
|
|
19
|
+
enabled: true,
|
|
20
|
+
timeoutMs: 5000,
|
|
21
|
+
alwaysBackground: [
|
|
22
|
+
'npm install',
|
|
23
|
+
'npm ci',
|
|
24
|
+
'yarn install',
|
|
25
|
+
'pnpm install',
|
|
26
|
+
'bun install',
|
|
27
|
+
'npm run build',
|
|
28
|
+
'yarn build',
|
|
29
|
+
'pnpm build',
|
|
30
|
+
'cargo build',
|
|
31
|
+
'go build',
|
|
32
|
+
'make',
|
|
33
|
+
'npm test',
|
|
34
|
+
'npm run test',
|
|
35
|
+
'yarn test',
|
|
36
|
+
'pytest',
|
|
37
|
+
'jest',
|
|
38
|
+
'vitest',
|
|
39
|
+
'cargo test',
|
|
40
|
+
'docker build',
|
|
41
|
+
'docker-compose up',
|
|
42
|
+
'docker compose up',
|
|
43
|
+
'git clone',
|
|
44
|
+
'git fetch --all',
|
|
45
|
+
'npx tsc',
|
|
46
|
+
'tsc --noEmit',
|
|
47
|
+
'eslint .',
|
|
48
|
+
'npm run lint',
|
|
49
|
+
],
|
|
50
|
+
neverBackground: [
|
|
51
|
+
'vim',
|
|
52
|
+
'nvim',
|
|
53
|
+
'nano',
|
|
54
|
+
'less',
|
|
55
|
+
'more',
|
|
56
|
+
'top',
|
|
57
|
+
'htop',
|
|
58
|
+
'echo',
|
|
59
|
+
'cat',
|
|
60
|
+
'ls',
|
|
61
|
+
'pwd',
|
|
62
|
+
'cd',
|
|
63
|
+
'which',
|
|
64
|
+
'git status',
|
|
65
|
+
'git diff',
|
|
66
|
+
'git log',
|
|
67
|
+
],
|
|
68
|
+
verbose: false,
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
function loadConfig() {
|
|
72
|
+
try {
|
|
73
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
74
|
+
return {
|
|
75
|
+
...DEFAULT_CONFIG,
|
|
76
|
+
...JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8')),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
} catch {}
|
|
80
|
+
return DEFAULT_CONFIG;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function shouldAutoBackground(command, config) {
|
|
84
|
+
if (!config.enabled) return false;
|
|
85
|
+
|
|
86
|
+
const cmd = command.trim().toLowerCase();
|
|
87
|
+
|
|
88
|
+
// Never background these
|
|
89
|
+
for (const pattern of config.neverBackground) {
|
|
90
|
+
if (cmd.startsWith(pattern.toLowerCase())) return false;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Always background these
|
|
94
|
+
for (const pattern of config.alwaysBackground) {
|
|
95
|
+
if (cmd.startsWith(pattern.toLowerCase())) return true;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Read hook input from stdin
|
|
102
|
+
let input = '';
|
|
103
|
+
process.stdin.setEncoding('utf8');
|
|
104
|
+
process.stdin.on('data', (chunk) => (input += chunk));
|
|
105
|
+
process.stdin.on('end', () => {
|
|
106
|
+
try {
|
|
107
|
+
const hookData = JSON.parse(input);
|
|
108
|
+
const { tool_name, tool_input } = hookData;
|
|
109
|
+
|
|
110
|
+
// Only process Bash tool
|
|
111
|
+
if (tool_name !== 'Bash') {
|
|
112
|
+
// Allow other tools through unchanged
|
|
113
|
+
console.log(JSON.stringify({ decision: 'allow' }));
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const command = tool_input?.command;
|
|
118
|
+
if (!command) {
|
|
119
|
+
console.log(JSON.stringify({ decision: 'allow' }));
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Already backgrounded
|
|
124
|
+
if (tool_input.run_in_background === true) {
|
|
125
|
+
console.log(JSON.stringify({ decision: 'allow' }));
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const config = loadConfig();
|
|
130
|
+
|
|
131
|
+
if (shouldAutoBackground(command, config)) {
|
|
132
|
+
if (config.verbose) {
|
|
133
|
+
console.error(
|
|
134
|
+
`[auto-bg] Backgrounding: ${command.substring(0, 60)}...`
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Modify the tool input to add run_in_background
|
|
139
|
+
console.log(
|
|
140
|
+
JSON.stringify({
|
|
141
|
+
decision: 'modify',
|
|
142
|
+
tool_input: {
|
|
143
|
+
...tool_input,
|
|
144
|
+
run_in_background: true,
|
|
145
|
+
},
|
|
146
|
+
})
|
|
147
|
+
);
|
|
148
|
+
} else {
|
|
149
|
+
console.log(JSON.stringify({ decision: 'allow' }));
|
|
150
|
+
}
|
|
151
|
+
} catch (err) {
|
|
152
|
+
// On error, allow the command through unchanged
|
|
153
|
+
console.error('[auto-bg] Error:', err.message);
|
|
154
|
+
console.log(JSON.stringify({ decision: 'allow' }));
|
|
155
|
+
}
|
|
156
|
+
});
|