coder-config 0.45.5 → 0.45.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/lib/cli.js CHANGED
@@ -318,133 +318,152 @@ function runCli(manager) {
318
318
  }
319
319
 
320
320
  /**
321
- * Print help message
321
+ * Print help message with nice TUI formatting
322
322
  */
323
323
  function printHelp() {
324
324
  const showLoops = isRalphLoopsEnabled();
325
325
 
326
- const loopHelp = showLoops ? `
327
- Loop Commands (Ralph Loop - autonomous development):
328
- loop List all loops
329
- loop create "Task" Create new loop with task description
330
- loop create "Task" --workstream <name> Create loop in workstream context
331
- loop start <id> Start/resume a loop
332
- loop pause <id> Pause loop at next safe point
333
- loop resume <id> Resume paused loop
334
- loop cancel <id> Cancel loop
335
- loop delete <id> Delete loop and its data
336
- loop approve <id> Approve plan (when in plan phase)
337
- loop complete <id> Mark loop as complete
338
- loop status [id] Show status (active loop if no id)
339
- loop active Show current active loop
340
- loop history Show completed loops
341
- loop config Show loop configuration
342
- loop config --max-iterations 50 Set max iterations
343
- loop config --auto-approve-plan Skip manual plan approval
344
- loop inject [--silent] Output loop context (for hooks)
345
-
346
- Running a loop with Claude Code:
347
- export CODER_LOOP_ID=<id>
348
- claude --continue "Your task"
349
- ` : '';
326
+ // ANSI color codes
327
+ const c = {
328
+ reset: '\x1b[0m',
329
+ bold: '\x1b[1m',
330
+ dim: '\x1b[2m',
331
+ cyan: '\x1b[36m',
332
+ green: '\x1b[32m',
333
+ yellow: '\x1b[33m',
334
+ blue: '\x1b[34m',
335
+ magenta: '\x1b[35m',
336
+ white: '\x1b[37m',
337
+ };
338
+
339
+ // Check if colors should be disabled
340
+ const noColor = process.env.NO_COLOR || process.env.TERM === 'dumb';
341
+ if (noColor) {
342
+ Object.keys(c).forEach(k => c[k] = '');
343
+ }
350
344
 
345
+ // Helper to format a command line
346
+ const cmd = (name, desc) => {
347
+ const paddedName = name.padEnd(32);
348
+ return `${c.cyan}${paddedName}${c.reset}${desc}`;
349
+ };
350
+
351
+ // Helper to create a boxed section
352
+ const box = (title, lines) => {
353
+ const maxLen = Math.max(...lines.map(l => l.replace(/\x1b\[[0-9;]*m/g, '').length), title.length + 4);
354
+ const width = Math.min(maxLen + 2, 80);
355
+ const top = `┌─ ${c.bold}${title}${c.reset} ${'─'.repeat(Math.max(0, width - title.length - 5))}┐`;
356
+ const bot = `└${'─'.repeat(width)}┘`;
357
+ const content = lines.map(l => {
358
+ const stripped = l.replace(/\x1b\[[0-9;]*m/g, '');
359
+ const padding = Math.max(0, width - stripped.length - 1);
360
+ return `│ ${l}${' '.repeat(padding)}│`;
361
+ }).join('\n');
362
+ return `${top}\n${content}\n${bot}`;
363
+ };
364
+
365
+ // Header
351
366
  console.log(`
352
- coder-config v${VERSION}
353
- Configuration manager for AI coding tools
354
-
355
- Usage:
356
- coder-config <command> [args]
357
- claude-config <command> [args] (alias)
358
-
359
- Project Commands:
360
- init Initialize project with .claude/mcps.json
361
- apply Generate .mcp.json from config
362
- show Show current project config
363
- list List available MCPs (✓ = active)
364
- add <mcp> [mcp...] Add MCP(s) to project
365
- remove <mcp> [mcp...] Remove MCP(s) from project
366
-
367
- Memory Commands:
368
- memory Show memory status
369
- memory init Initialize project memory
370
- memory add <type> <content> Add entry (types: preference, correction, fact,
371
- context, pattern, decision, issue, history)
372
- memory search <query> Search all memory files
373
-
374
- Environment Commands:
375
- env List environment variables
376
- env set <KEY> <value> Set variable in .claude/.env
377
- env unset <KEY> Remove variable
378
-
379
- Project Commands (for UI):
380
- project List registered projects
381
- project add [path] Add project (defaults to cwd)
382
- project add [path] --name X Add with custom display name
383
- project remove <name|path> Remove project from registry
384
-
385
- Workstream Commands:
386
- workstream List all workstreams
387
- workstream create "Name" Create new workstream
388
- workstream delete <name> Delete workstream
389
- workstream use <name> Set active workstream (global)
390
- workstream active Show current active workstream
391
- workstream deactivate Show how to deactivate workstream
392
- workstream add <ws> <path> Add project to workstream
393
- workstream remove <ws> <path> Remove project from workstream
394
- workstream inject [--silent] Output restriction + context (for hooks)
395
- workstream detect [path] Detect workstream for directory
396
- workstream install-hook Install pre-prompt hook for Claude Code
397
- workstream install-hook --gemini Install for Gemini CLI
398
- workstream install-hook --codex Install for Codex CLI
399
- workstream install-hook --all Install for all supported tools
400
-
401
- Folder Auto-Activation:
402
- workstream add-trigger <ws> <folder> Add trigger folder
403
- workstream remove-trigger <ws> <folder> Remove trigger folder
404
- workstream auto-activate <ws> [on|off|default] Set auto-activate
405
- workstream check-folder [path] [--json] Check folder for matches
406
- workstream install-cd-hook Install cd hook for auto-activation
407
- workstream uninstall-cd-hook Remove cd hook
408
- workstream cd-hook-status Check if cd hook is installed
409
-
410
- Per-session activation (enables parallel work):
411
- export CODER_WORKSTREAM=<name-or-id>
412
- ${loopHelp}
413
- Session Persistence:
414
- session Show session status (saved context)
415
- session install Install hooks and /flush command
416
- session clear Clear saved session context
417
-
418
- Registry Commands:
419
- registry List MCPs in global registry
420
- registry add <name> '<json>' Add MCP to global registry
421
- registry remove <name> Remove MCP from registry
422
-
423
- Maintenance:
424
- migrate Migrate from ~/.claude-config to ~/.coder-config
425
- migrate --force Overwrite existing files in new location
426
- migrate --remove Remove legacy directory after migration
427
- update Check npm for updates and install if available
428
- update --check Check for updates without installing
429
- update /path/to/source Update from local development source
430
- ui [--port=3333] Start web UI (daemon mode by default)
431
- ui install Auto-start on login (macOS LaunchAgent)
432
- ui uninstall Remove auto-start
433
- ui status Check if UI daemon is running
434
- ui stop Stop the UI daemon
435
- version Show version info
436
-
437
- Plugins (Claude Code CLI):
438
- claude plugin marketplace add regression-io/coder-config-plugins
439
- claude plugin install <name>@coder-config-plugins
440
-
441
- Examples:
442
- coder-config init
443
- coder-config add postgres github
444
- coder-config memory add preference "Use TypeScript for new files"
445
- coder-config env set GITHUB_TOKEN ghp_xxx
446
- coder-config apply
367
+ ${c.yellow}Usage:${c.reset} ${c.bold}coder-config${c.reset} [OPTIONS] ${c.cyan}COMMAND${c.reset} [ARGS]...
368
+
369
+ ${c.dim}Configuration manager for AI coding tools (Claude Code, Gemini CLI, Codex CLI)${c.reset}
447
370
  `);
371
+
372
+ // Options section
373
+ console.log(box('Options', [
374
+ `${c.green}--version${c.reset} ${c.dim}-v${c.reset} Show version and exit`,
375
+ `${c.green}--help${c.reset} ${c.dim}-h${c.reset} Show this message and exit`,
376
+ ]));
377
+ console.log();
378
+
379
+ // Project Commands
380
+ console.log(box('Project', [
381
+ cmd('init', 'Initialize project with .claude/mcps.json'),
382
+ cmd('apply', 'Generate .mcp.json from config'),
383
+ cmd('show', 'Show current project config'),
384
+ cmd('list', 'List available MCPs (✓ = active)'),
385
+ cmd('add <mcp> [mcp...]', 'Add MCP(s) to project'),
386
+ cmd('remove <mcp> [mcp...]', 'Remove MCP(s) from project'),
387
+ ]));
388
+ console.log();
389
+
390
+ // Memory Commands
391
+ console.log(box('Memory', [
392
+ cmd('memory', 'Show memory status'),
393
+ cmd('memory init', 'Initialize project memory'),
394
+ cmd('memory add <type> <text>', 'Add entry to memory'),
395
+ cmd('memory search <query>', 'Search all memory files'),
396
+ ]));
397
+ console.log();
398
+
399
+ // Environment Commands
400
+ console.log(box('Environment', [
401
+ cmd('env', 'List environment variables'),
402
+ cmd('env set <KEY> <value>', 'Set variable in .claude/.env'),
403
+ cmd('env unset <KEY>', 'Remove variable'),
404
+ ]));
405
+ console.log();
406
+
407
+ // Registry Commands
408
+ console.log(box('Registry', [
409
+ cmd('registry', 'List MCPs in global registry'),
410
+ cmd('registry add <name> \'<json>\'', 'Add MCP to registry'),
411
+ cmd('registry remove <name>', 'Remove MCP from registry'),
412
+ ]));
413
+ console.log();
414
+
415
+ // Workstream Commands
416
+ console.log(box('Workstreams', [
417
+ cmd('workstream', 'List all workstreams'),
418
+ cmd('workstream create "Name"', 'Create new workstream'),
419
+ cmd('workstream delete <name>', 'Delete workstream'),
420
+ cmd('workstream use <name>', 'Set active workstream'),
421
+ cmd('workstream add <ws> <path>', 'Add project to workstream'),
422
+ cmd('workstream remove <ws> <path>', 'Remove from workstream'),
423
+ cmd('workstream install-hook', 'Install pre-prompt hook'),
424
+ ]));
425
+ console.log();
426
+
427
+ // Loop Commands (if enabled)
428
+ if (showLoops) {
429
+ console.log(box('Loops (Ralph Loop)', [
430
+ cmd('loop', 'List all loops'),
431
+ cmd('loop create "Task"', 'Create new loop'),
432
+ cmd('loop start <id>', 'Start/resume a loop'),
433
+ cmd('loop pause <id>', 'Pause loop'),
434
+ cmd('loop cancel <id>', 'Cancel loop'),
435
+ cmd('loop status [id]', 'Show loop status'),
436
+ cmd('loop config', 'Show/set loop config'),
437
+ ]));
438
+ console.log();
439
+ }
440
+
441
+ // Session Commands
442
+ console.log(box('Sessions', [
443
+ cmd('session', 'Show session status'),
444
+ cmd('session install', 'Install hooks and /flush'),
445
+ cmd('session clear', 'Clear saved context'),
446
+ ]));
447
+ console.log();
448
+
449
+ // UI & Maintenance
450
+ console.log(box('UI & Maintenance', [
451
+ cmd('ui', 'Start web UI (daemon mode)'),
452
+ cmd('ui install', 'Auto-start on login'),
453
+ cmd('ui status', 'Check daemon status'),
454
+ cmd('ui stop', 'Stop the daemon'),
455
+ cmd('update', 'Check and install updates'),
456
+ cmd('version', 'Show version info'),
457
+ ]));
458
+ console.log();
459
+
460
+ // Examples
461
+ console.log(`${c.yellow}Examples:${c.reset}`);
462
+ console.log(` ${c.dim}$${c.reset} coder-config init`);
463
+ console.log(` ${c.dim}$${c.reset} coder-config add postgres github`);
464
+ console.log(` ${c.dim}$${c.reset} coder-config memory add preference "Use TypeScript"`);
465
+ console.log(` ${c.dim}$${c.reset} coder-config ui`);
466
+ console.log();
448
467
  }
449
468
 
450
469
  module.exports = {
package/lib/constants.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * Constants and tool path configurations
3
3
  */
4
4
 
5
- const VERSION = '0.45.5';
5
+ const VERSION = '0.45.7';
6
6
 
7
7
  // Tool-specific path configurations
8
8
  const TOOL_PATHS = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coder-config",
3
- "version": "0.45.5",
3
+ "version": "0.45.7",
4
4
  "description": "Configuration manager for AI coding tools - Claude Code, Gemini CLI, Codex CLI, Antigravity. Manage MCPs, rules, permissions, memory, and workstreams.",
5
5
  "author": "regression.io",
6
6
  "main": "config-loader.js",
package/ui/server.cjs CHANGED
@@ -263,6 +263,32 @@ class ConfigUIServer {
263
263
  console.log(`📁 Project: ${this.projectDir}`);
264
264
  console.log(`💻 Terminal WebSocket: ws://localhost:${this.port}/ws/terminal\n`);
265
265
  });
266
+
267
+ // Watchdog: detect suspend/resume and restart if event loop was blocked
268
+ this.startSuspendWatchdog();
269
+ }
270
+
271
+ /**
272
+ * Watchdog to detect system suspend/resume
273
+ * If the event loop was blocked for too long (suspend), restart the server
274
+ */
275
+ startSuspendWatchdog() {
276
+ const HEARTBEAT_INTERVAL = 5000; // Check every 5 seconds
277
+ const SUSPEND_THRESHOLD = 30000; // 30 seconds gap = likely suspended
278
+ let lastHeartbeat = Date.now();
279
+
280
+ setInterval(() => {
281
+ const now = Date.now();
282
+ const elapsed = now - lastHeartbeat;
283
+
284
+ if (elapsed > SUSPEND_THRESHOLD) {
285
+ console.log(`[Watchdog] System resumed after ${Math.round(elapsed / 1000)}s suspend, restarting server...`);
286
+ // Exit with code 0 - launchd will restart us
287
+ process.exit(0);
288
+ }
289
+
290
+ lastHeartbeat = now;
291
+ }, HEARTBEAT_INTERVAL);
266
292
  }
267
293
 
268
294
  /**