|
| 1 | +/** |
| 2 | + * CLI command for managing auto-background settings |
| 3 | + */ |
| 4 | + |
| 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 | + AutoBackgroundConfig, |
| 13 | +} from '../../hooks/auto-background.js'; |
| 14 | + |
| 15 | +// __dirname provided by esbuild banner |
| 16 | + |
| 17 | +export function createAutoBackgroundCommand(): Command { |
| 18 | + const cmd = new Command('auto-bg') |
| 19 | + .description('Manage auto-background settings for long-running commands') |
| 20 | + .addHelpText( |
| 21 | + 'after', |
| 22 | + ` |
| 23 | +Examples: |
| 24 | + stackmemory auto-bg show Show current configuration |
| 25 | + stackmemory auto-bg enable Enable auto-backgrounding |
| 26 | + stackmemory auto-bg disable Disable auto-backgrounding |
| 27 | + stackmemory auto-bg add "npm publish" Add command to always-background list |
| 28 | + stackmemory auto-bg remove "npm test" Remove command from list |
| 29 | + stackmemory auto-bg timeout 10000 Set timeout to 10 seconds |
| 30 | + stackmemory auto-bg install Install Claude Code hook |
| 31 | +` |
| 32 | + ); |
| 33 | + |
| 34 | + cmd |
| 35 | + .command('show') |
| 36 | + .description('Show current auto-background configuration') |
| 37 | + .action(() => { |
| 38 | + const config = loadConfig(); |
| 39 | + console.log(chalk.blue('Auto-Background Configuration:')); |
| 40 | + console.log(); |
| 41 | + console.log( |
| 42 | + ` ${chalk.gray('Enabled:')} ${config.enabled ? chalk.green('yes') : chalk.red('no')}` |
| 43 | + ); |
| 44 | + console.log(` ${chalk.gray('Timeout:')} ${config.timeoutMs}ms`); |
| 45 | + console.log( |
| 46 | + ` ${chalk.gray('Verbose:')} ${config.verbose ? 'yes' : 'no'}` |
| 47 | + ); |
| 48 | + console.log(); |
| 49 | + console.log(chalk.blue('Always Background:')); |
| 50 | + config.alwaysBackground.forEach((p) => console.log(` - ${p}`)); |
| 51 | + console.log(); |
| 52 | + console.log(chalk.blue('Never Background:')); |
| 53 | + config.neverBackground.forEach((p) => console.log(` - ${p}`)); |
| 54 | + }); |
| 55 | + |
| 56 | + cmd |
| 57 | + .command('enable') |
| 58 | + .description('Enable auto-backgrounding') |
| 59 | + .action(() => { |
| 60 | + const config = loadConfig(); |
| 61 | + config.enabled = true; |
| 62 | + saveConfig(config); |
| 63 | + console.log(chalk.green('Auto-background enabled')); |
| 64 | + }); |
| 65 | + |
| 66 | + cmd |
| 67 | + .command('disable') |
| 68 | + .description('Disable auto-backgrounding') |
| 69 | + .action(() => { |
| 70 | + const config = loadConfig(); |
| 71 | + config.enabled = false; |
| 72 | + saveConfig(config); |
| 73 | + console.log(chalk.yellow('Auto-background disabled')); |
| 74 | + }); |
| 75 | + |
| 76 | + cmd |
| 77 | + .command('add <pattern>') |
| 78 | + .description('Add command pattern to always-background list') |
| 79 | + .action((pattern: string) => { |
| 80 | + const config = loadConfig(); |
| 81 | + if (!config.alwaysBackground.includes(pattern)) { |
| 82 | + config.alwaysBackground.push(pattern); |
| 83 | + saveConfig(config); |
| 84 | + console.log(chalk.green(`Added: ${pattern}`)); |
| 85 | + } else { |
| 86 | + console.log(chalk.yellow(`Already in list: ${pattern}`)); |
| 87 | + } |
| 88 | + }); |
| 89 | + |
| 90 | + cmd |
| 91 | + .command('remove <pattern>') |
| 92 | + .description('Remove command pattern from always-background list') |
| 93 | + .action((pattern: string) => { |
| 94 | + const config = loadConfig(); |
| 95 | + const idx = config.alwaysBackground.indexOf(pattern); |
| 96 | + if (idx !== -1) { |
| 97 | + config.alwaysBackground.splice(idx, 1); |
| 98 | + saveConfig(config); |
| 99 | + console.log(chalk.green(`Removed: ${pattern}`)); |
| 100 | + } else { |
| 101 | + console.log(chalk.yellow(`Not in list: ${pattern}`)); |
| 102 | + } |
| 103 | + }); |
| 104 | + |
| 105 | + cmd |
| 106 | + .command('timeout <ms>') |
| 107 | + .description('Set timeout threshold in milliseconds') |
| 108 | + .action((ms: string) => { |
| 109 | + const config = loadConfig(); |
| 110 | + const timeout = parseInt(ms, 10); |
| 111 | + if (isNaN(timeout) || timeout < 0) { |
| 112 | + console.log(chalk.red('Invalid timeout value')); |
| 113 | + return; |
| 114 | + } |
| 115 | + config.timeoutMs = timeout; |
| 116 | + saveConfig(config); |
| 117 | + console.log(chalk.green(`Timeout set to ${timeout}ms`)); |
| 118 | + }); |
| 119 | + |
| 120 | + cmd |
| 121 | + .command('verbose [on|off]') |
| 122 | + .description('Enable/disable verbose logging') |
| 123 | + .action((value?: string) => { |
| 124 | + const config = loadConfig(); |
| 125 | + if (value === undefined) { |
| 126 | + config.verbose = !config.verbose; |
| 127 | + } else { |
| 128 | + config.verbose = value === 'on' || value === 'true'; |
| 129 | + } |
| 130 | + saveConfig(config); |
| 131 | + console.log( |
| 132 | + chalk.green( |
| 133 | + `Verbose logging ${config.verbose ? 'enabled' : 'disabled'}` |
| 134 | + ) |
| 135 | + ); |
| 136 | + }); |
| 137 | + |
| 138 | + cmd |
| 139 | + .command('reset') |
| 140 | + .description('Reset configuration to defaults') |
| 141 | + .action(() => { |
| 142 | + const defaultConfig: AutoBackgroundConfig = { |
| 143 | + enabled: true, |
| 144 | + timeoutMs: 5000, |
| 145 | + alwaysBackground: [ |
| 146 | + 'npm install', |
| 147 | + 'npm ci', |
| 148 | + 'yarn install', |
| 149 | + 'pnpm install', |
| 150 | + 'bun install', |
| 151 | + 'npm run build', |
| 152 | + 'yarn build', |
| 153 | + 'pnpm build', |
| 154 | + 'cargo build', |
| 155 | + 'go build', |
| 156 | + 'make', |
| 157 | + 'npm test', |
| 158 | + 'npm run test', |
| 159 | + 'yarn test', |
| 160 | + 'pytest', |
| 161 | + 'jest', |
| 162 | + 'vitest', |
| 163 | + 'cargo test', |
| 164 | + 'docker build', |
| 165 | + 'docker-compose up', |
| 166 | + 'docker compose up', |
| 167 | + 'git clone', |
| 168 | + 'git fetch --all', |
| 169 | + 'npx tsc', |
| 170 | + 'tsc --noEmit', |
| 171 | + 'eslint .', |
| 172 | + 'npm run lint', |
| 173 | + ], |
| 174 | + neverBackground: [ |
| 175 | + 'vim', |
| 176 | + 'nvim', |
| 177 | + 'nano', |
| 178 | + 'less', |
| 179 | + 'more', |
| 180 | + 'top', |
| 181 | + 'htop', |
| 182 | + 'echo', |
| 183 | + 'cat', |
| 184 | + 'ls', |
| 185 | + 'pwd', |
| 186 | + 'cd', |
| 187 | + 'which', |
| 188 | + 'git status', |
| 189 | + 'git diff', |
| 190 | + 'git log', |
| 191 | + ], |
| 192 | + verbose: false, |
| 193 | + }; |
| 194 | + saveConfig(defaultConfig); |
| 195 | + console.log(chalk.green('Configuration reset to defaults')); |
| 196 | + }); |
| 197 | + |
| 198 | + cmd |
| 199 | + .command('install') |
| 200 | + .description('Install Claude Code hook for auto-backgrounding') |
| 201 | + .action(() => { |
| 202 | + try { |
| 203 | + // Find the install script |
| 204 | + const scriptPath = join( |
| 205 | + __dirname, |
| 206 | + '../../../scripts/install-auto-background-hook.sh' |
| 207 | + ); |
| 208 | + execSync(`bash "${scriptPath}"`, { stdio: 'inherit' }); |
| 209 | + } catch { |
| 210 | + console.error(chalk.red('Failed to install hook')); |
| 211 | + console.log( |
| 212 | + chalk.gray( |
| 213 | + 'Run manually: bash scripts/install-auto-background-hook.sh' |
| 214 | + ) |
| 215 | + ); |
| 216 | + } |
| 217 | + }); |
| 218 | + |
| 219 | + return cmd; |
| 220 | +} |
0 commit comments