@stackmemoryai/stackmemory 0.5.30 → 0.5.33

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.
Files changed (64) hide show
  1. package/README.md +44 -44
  2. package/dist/cli/claude-sm.js +199 -16
  3. package/dist/cli/claude-sm.js.map +2 -2
  4. package/dist/cli/commands/context.js +0 -11
  5. package/dist/cli/commands/context.js.map +2 -2
  6. package/dist/cli/commands/linear.js +1 -14
  7. package/dist/cli/commands/linear.js.map +2 -2
  8. package/dist/cli/commands/login.js +32 -10
  9. package/dist/cli/commands/login.js.map +2 -2
  10. package/dist/cli/commands/migrate.js +80 -22
  11. package/dist/cli/commands/migrate.js.map +2 -2
  12. package/dist/cli/commands/model.js +533 -0
  13. package/dist/cli/commands/model.js.map +7 -0
  14. package/dist/cli/commands/ralph.js +93 -28
  15. package/dist/cli/commands/ralph.js.map +2 -2
  16. package/dist/cli/commands/service.js +10 -3
  17. package/dist/cli/commands/service.js.map +2 -2
  18. package/dist/cli/commands/skills.js +60 -10
  19. package/dist/cli/commands/skills.js.map +2 -2
  20. package/dist/cli/commands/sms-notify.js +342 -22
  21. package/dist/cli/commands/sms-notify.js.map +3 -3
  22. package/dist/cli/index.js +2 -0
  23. package/dist/cli/index.js.map +2 -2
  24. package/dist/core/context/dual-stack-manager.js +23 -7
  25. package/dist/core/context/dual-stack-manager.js.map +2 -2
  26. package/dist/core/context/frame-database.js +33 -5
  27. package/dist/core/context/frame-database.js.map +2 -2
  28. package/dist/core/context/frame-digest.js +6 -1
  29. package/dist/core/context/frame-digest.js.map +2 -2
  30. package/dist/core/context/frame-manager.js +56 -9
  31. package/dist/core/context/frame-manager.js.map +2 -2
  32. package/dist/core/context/permission-manager.js +0 -11
  33. package/dist/core/context/permission-manager.js.map +2 -2
  34. package/dist/core/context/recursive-context-manager.js +15 -9
  35. package/dist/core/context/recursive-context-manager.js.map +2 -2
  36. package/dist/core/context/shared-context-layer.js +0 -11
  37. package/dist/core/context/shared-context-layer.js.map +2 -2
  38. package/dist/core/context/validation.js +6 -1
  39. package/dist/core/context/validation.js.map +2 -2
  40. package/dist/core/models/fallback-monitor.js +229 -0
  41. package/dist/core/models/fallback-monitor.js.map +7 -0
  42. package/dist/core/models/model-router.js +331 -0
  43. package/dist/core/models/model-router.js.map +7 -0
  44. package/dist/hooks/claude-code-whatsapp-hook.js +197 -0
  45. package/dist/hooks/claude-code-whatsapp-hook.js.map +7 -0
  46. package/dist/hooks/linear-task-picker.js +1 -1
  47. package/dist/hooks/linear-task-picker.js.map +2 -2
  48. package/dist/hooks/schemas.js +55 -1
  49. package/dist/hooks/schemas.js.map +2 -2
  50. package/dist/hooks/session-summary.js +5 -1
  51. package/dist/hooks/session-summary.js.map +2 -2
  52. package/dist/hooks/sms-action-runner.js +12 -1
  53. package/dist/hooks/sms-action-runner.js.map +2 -2
  54. package/dist/hooks/sms-notify.js +4 -2
  55. package/dist/hooks/sms-notify.js.map +2 -2
  56. package/dist/hooks/sms-webhook.js +23 -2
  57. package/dist/hooks/sms-webhook.js.map +2 -2
  58. package/dist/hooks/whatsapp-commands.js +376 -0
  59. package/dist/hooks/whatsapp-commands.js.map +7 -0
  60. package/dist/hooks/whatsapp-scheduler.js +317 -0
  61. package/dist/hooks/whatsapp-scheduler.js.map +7 -0
  62. package/dist/hooks/whatsapp-sync.js +375 -0
  63. package/dist/hooks/whatsapp-sync.js.map +7 -0
  64. package/package.json +2 -3
package/README.md CHANGED
@@ -1,19 +1,19 @@
1
1
  # StackMemory
2
2
 
3
- **Lossless, project-scoped memory for AI tools** • v0.5.29
3
+ **Lossless, project-scoped memory for AI tools** • v0.5.30
4
4
 
5
5
  StackMemory is a **production-ready memory runtime** for AI coding tools that preserves full project context across sessions. With **Phases 1-4 complete**, it delivers:
6
6
 
7
- - **89-98% faster** task operations than manual tracking
8
- - **10,000+ frame depth** support with hierarchical organization
9
- - **Full Linear integration** with bidirectional sync
10
- - **20+ MCP tools** for Claude Code
11
- - **Context persistence** that survives /clear operations
12
- - **Two-tier storage system** with local tiers and infinite remote storage
13
- - **Smart compression** (LZ4/ZSTD) with 2.5-3.5x ratios
14
- - **Background migration** with configurable triggers
15
- - **396 tests passing** with standardized error handling
16
- - **npm v0.5.29** published with WhatsApp notifications and improved integrations
7
+ - **89-98% faster** task operations than manual tracking
8
+ - **10,000+ frame depth** support with hierarchical organization
9
+ - **Full Linear integration** with bidirectional sync
10
+ - **20+ MCP tools** for Claude Code
11
+ - **Context persistence** that survives /clear operations
12
+ - **Two-tier storage system** with local tiers and infinite remote storage
13
+ - **Smart compression** (LZ4/ZSTD) with 2.5-3.5x ratios
14
+ - **Background migration** with configurable triggers
15
+ - **396 tests passing** with standardized error handling
16
+ - **npm v0.5.30** published with WhatsApp notifications and improved integrations
17
17
 
18
18
  Instead of a linear chat log, StackMemory organizes memory as a **call stack** of scoped work (frames), with intelligent LLM-driven retrieval and team collaboration features.
19
19
 
@@ -96,16 +96,16 @@ The editor never manages memory directly; it asks StackMemory for the **context
96
96
 
97
97
  ## Product Health Metrics
98
98
 
99
- ### Current Status (v0.5.29)
99
+ ### Current Status (v0.5.30)
100
100
 
101
101
  | Metric | Current | Target | Status |
102
102
  |--------|---------|--------|--------|
103
- | **Test Coverage** | 85% | 90% | 🟡 |
104
- | **Performance (p50)** | TBD | <50ms | 🔄 |
105
- | **Documentation** | 70% | 100% | 🟡 |
106
- | **Active Issues** | 5 high | 0 high | 🟡 |
107
- | **Code Quality** | 396 tests | 400+ | |
108
- | **npm Downloads** | Growing | 1K+/week | 🚀 |
103
+ | **Test Coverage** | 85% | 90% | In Progress |
104
+ | **Performance (p50)** | TBD | <50ms | Pending |
105
+ | **Documentation** | 70% | 100% | In Progress |
106
+ | **Active Issues** | 5 high | 0 high | In Progress |
107
+ | **Code Quality** | 396 tests | 400+ | Done |
108
+ | **npm Downloads** | Growing | 1K+/week | On Track |
109
109
 
110
110
  ### Quality Score: 78/100
111
111
 
@@ -136,7 +136,7 @@ This creates a **project-scoped memory space** tied to the repo.
136
136
  ### Step 2: Install StackMemory
137
137
 
138
138
  ```bash
139
- npm install -g @stackmemoryai/stackmemory@0.5.29
139
+ npm install -g @stackmemoryai/stackmemory@0.5.30
140
140
  # or latest
141
141
  npm install -g @stackmemoryai/stackmemory@latest
142
142
  ```
@@ -455,7 +455,7 @@ stackmemory mcp-server [--port 3001]
455
455
  - Hosted: **Private beta**
456
456
  - OSS mirror: **Production ready**
457
457
  - MCP integration: **Stable**
458
- - CLI: **v0.5.29** - Full task, context, Linear, and storage management
458
+ - CLI: **v0.5.30** - Full task, context, Linear, and storage management
459
459
  - Two-tier storage: **Complete**
460
460
  - Test Suite: **396 tests passing**
461
461
 
@@ -463,40 +463,40 @@ stackmemory mcp-server [--port 3001]
463
463
 
464
464
  ## Changelog
465
465
 
466
- ### v0.5.29 (2026-01-26)
467
- - Standardized error handling with `IntegrationError`, `DatabaseError`, `ValidationError`
468
- - Adopted error classes across Linear integration (12 files)
469
- - Adopted error classes across database layer (6 files)
470
- - WhatsApp notifications with session ID and interactive options
471
- - 396 tests passing with improved code quality
466
+ ### v0.5.30 (2026-01-26)
467
+ - Standardized error handling with `IntegrationError`, `DatabaseError`, `ValidationError`
468
+ - Adopted error classes across Linear integration (12 files)
469
+ - Adopted error classes across database layer (6 files)
470
+ - WhatsApp notifications with session ID and interactive options
471
+ - 396 tests passing with improved code quality
472
472
 
473
473
  ### v0.5.28 (2026-01-25)
474
- - WhatsApp flag for claude-sm automatic notifications
475
- - Incoming request queue for WhatsApp triggers
476
- - SMS webhook /send endpoint for outgoing notifications
474
+ - WhatsApp flag for claude-sm automatic notifications
475
+ - Incoming request queue for WhatsApp triggers
476
+ - SMS webhook /send endpoint for outgoing notifications
477
477
 
478
478
  ### v0.5.26 (2026-01-24)
479
- - OpenCode wrapper (opencode-sm) with context integration
480
- - Discovery CLI and MCP tools
481
- - Real LLM provider and retrieval audit system
482
- - Linear issue management and task picker
479
+ - OpenCode wrapper (opencode-sm) with context integration
480
+ - Discovery CLI and MCP tools
481
+ - Real LLM provider and retrieval audit system
482
+ - Linear issue management and task picker
483
483
 
484
484
  ### v0.5.21 (2026-01-23)
485
- - Claude-sm remote mode and configurable defaults
486
- - Context loading command improvements
487
- - Session summary features
485
+ - Claude-sm remote mode and configurable defaults
486
+ - Context loading command improvements
487
+ - Session summary features
488
488
 
489
489
  ### v0.3.16 (2026-01-15)
490
- - Fixed critical error handling - getFrame() returns undefined instead of throwing
491
- - Improved test coverage and fixed StackMemoryError constructor usage
492
- - Removed dangerous secret-cleaning scripts from repository
493
- - All tests passing, lint clean, build successful
490
+ - Fixed critical error handling - getFrame() returns undefined instead of throwing
491
+ - Improved test coverage and fixed StackMemoryError constructor usage
492
+ - Removed dangerous secret-cleaning scripts from repository
493
+ - All tests passing, lint clean, build successful
494
494
 
495
495
  ### v0.3.15 (2026-01-14)
496
- - Two-tier storage system implementation complete
497
- - Smart compression with LZ4/ZSTD support
498
- - Background migration with configurable triggers
499
- - Improved Linear integration with bidirectional sync
496
+ - Two-tier storage system implementation complete
497
+ - Smart compression with LZ4/ZSTD support
498
+ - Background migration with configurable triggers
499
+ - Improved Linear integration with bidirectional sync
500
500
 
501
501
  ---
502
502
 
@@ -17,7 +17,15 @@ import {
17
17
  generateSessionSummary,
18
18
  formatSummaryMessage
19
19
  } from "../hooks/session-summary.js";
20
- import { sendNotification } from "../hooks/sms-notify.js";
20
+ import { sendNotification, loadSMSConfig } from "../hooks/sms-notify.js";
21
+ import { enableAutoSync } from "../hooks/whatsapp-sync.js";
22
+ import { enableCommands } from "../hooks/whatsapp-commands.js";
23
+ import { startScheduler, listSchedules } from "../hooks/whatsapp-scheduler.js";
24
+ import {
25
+ getModelRouter,
26
+ loadModelRouterConfig
27
+ } from "../core/models/model-router.js";
28
+ import { FallbackMonitor } from "../core/models/fallback-monitor.js";
21
29
  const DEFAULT_SM_CONFIG = {
22
30
  defaultWorktree: false,
23
31
  defaultSandbox: false,
@@ -25,7 +33,8 @@ const DEFAULT_SM_CONFIG = {
25
33
  defaultTracing: true,
26
34
  defaultRemote: false,
27
35
  defaultNotifyOnDone: true,
28
- defaultWhatsApp: false
36
+ defaultWhatsApp: false,
37
+ defaultModelRouting: false
29
38
  };
30
39
  function getConfigPath() {
31
40
  return path.join(os.homedir(), ".stackmemory", "claude-sm.json");
@@ -68,7 +77,9 @@ class ClaudeSM {
68
77
  contextEnabled: true,
69
78
  tracingEnabled: this.smConfig.defaultTracing,
70
79
  verboseTracing: false,
71
- sessionStartTime: Date.now()
80
+ sessionStartTime: Date.now(),
81
+ useModelRouting: this.smConfig.defaultModelRouting,
82
+ useThinkingMode: false
72
83
  };
73
84
  this.stackmemoryPath = this.findStackMemory();
74
85
  this.worktreeScriptPath = path.join(
@@ -249,7 +260,41 @@ class ClaudeSM {
249
260
  }
250
261
  async startWhatsAppServices() {
251
262
  const WEBHOOK_PORT = 3456;
252
- console.log(chalk.cyan("Starting WhatsApp services..."));
263
+ console.log(chalk.cyan("\n\u{1F4F1} WhatsApp Mode - Full Integration"));
264
+ console.log(chalk.gray("\u2500".repeat(42)));
265
+ const smsConfig = loadSMSConfig();
266
+ if (!smsConfig.enabled) {
267
+ console.log(
268
+ chalk.yellow(" Notifications disabled. Run: stackmemory notify enable")
269
+ );
270
+ }
271
+ try {
272
+ enableAutoSync();
273
+ console.log(
274
+ chalk.green(" \u2713 Auto-sync enabled (digests on frame close)")
275
+ );
276
+ } catch {
277
+ console.log(chalk.gray(" Auto-sync: skipped"));
278
+ }
279
+ try {
280
+ enableCommands();
281
+ console.log(chalk.green(" \u2713 Command processing enabled"));
282
+ console.log(
283
+ chalk.gray(" Reply: status, tasks, context, help, build, test, lint")
284
+ );
285
+ } catch {
286
+ console.log(chalk.gray(" Command processing: skipped"));
287
+ }
288
+ try {
289
+ const schedules = listSchedules();
290
+ if (schedules.length > 0) {
291
+ startScheduler();
292
+ console.log(
293
+ chalk.green(` \u2713 Scheduler started (${schedules.length} schedules)`)
294
+ );
295
+ }
296
+ } catch {
297
+ }
253
298
  const webhookRunning = await fetch(
254
299
  `http://localhost:${WEBHOOK_PORT}/health`
255
300
  ).then((r) => r.ok).catch(() => false);
@@ -262,11 +307,11 @@ class ClaudeSM {
262
307
  });
263
308
  webhookProcess.unref();
264
309
  console.log(
265
- chalk.gray(` Webhook server starting on port ${WEBHOOK_PORT}`)
310
+ chalk.green(` \u2713 Webhook server started (port ${WEBHOOK_PORT})`)
266
311
  );
267
312
  } else {
268
313
  console.log(
269
- chalk.gray(` Webhook already running on port ${WEBHOOK_PORT}`)
314
+ chalk.green(` \u2713 Webhook already running (port ${WEBHOOK_PORT})`)
270
315
  );
271
316
  }
272
317
  const ngrokRunning = await fetch("http://localhost:4040/api/tunnels").then((r) => r.ok).catch(() => false);
@@ -276,7 +321,7 @@ class ClaudeSM {
276
321
  stdio: "ignore"
277
322
  });
278
323
  ngrokProcess.unref();
279
- console.log(chalk.gray(" ngrok tunnel starting..."));
324
+ console.log(chalk.gray(" Starting ngrok tunnel..."));
280
325
  await new Promise((resolve) => setTimeout(resolve, 3e3));
281
326
  }
282
327
  try {
@@ -291,15 +336,34 @@ class ClaudeSM {
291
336
  fs.mkdirSync(configDir, { recursive: true });
292
337
  }
293
338
  fs.writeFileSync(configPath, publicUrl);
294
- console.log(
295
- chalk.green(` WhatsApp webhook: ${publicUrl}/sms/incoming`)
296
- );
339
+ console.log(chalk.green(` \u2713 ngrok tunnel: ${publicUrl}/sms/incoming`));
297
340
  }
298
341
  } catch {
342
+ console.log(chalk.yellow(" ngrok: waiting for tunnel..."));
343
+ }
344
+ if (smsConfig.pendingPrompts.length > 0) {
345
+ console.log();
299
346
  console.log(
300
- chalk.yellow(" Waiting for ngrok... URL will be available shortly")
347
+ chalk.yellow(
348
+ ` \u23F3 ${smsConfig.pendingPrompts.length} pending prompt(s) awaiting response:`
349
+ )
301
350
  );
351
+ smsConfig.pendingPrompts.slice(0, 3).forEach((p, i) => {
352
+ const msg = p.message.length > 40 ? p.message.slice(0, 40) + "..." : p.message;
353
+ console.log(chalk.gray(` ${i + 1}. [${p.id}] ${msg}`));
354
+ });
355
+ if (smsConfig.pendingPrompts.length > 3) {
356
+ console.log(
357
+ chalk.gray(` ... and ${smsConfig.pendingPrompts.length - 3} more`)
358
+ );
359
+ }
302
360
  }
361
+ console.log();
362
+ console.log(chalk.gray(" Quick actions from WhatsApp:"));
363
+ console.log(chalk.gray(' "status" - session status'));
364
+ console.log(chalk.gray(' "context" - current frame digest'));
365
+ console.log(chalk.gray(' "1", "2" - respond to prompts'));
366
+ console.log(chalk.gray("\u2500".repeat(42)));
303
367
  }
304
368
  async sendDoneNotification(exitCode) {
305
369
  try {
@@ -430,6 +494,31 @@ class ClaudeSM {
430
494
  this.config.useWorktree = this.hasUncommittedChanges() || this.detectMultipleInstances();
431
495
  }
432
496
  break;
497
+ case "--think":
498
+ case "--think-hard":
499
+ case "--ultrathink":
500
+ this.config.useThinkingMode = true;
501
+ this.config.useModelRouting = true;
502
+ this.config.forceProvider = "qwen";
503
+ break;
504
+ case "--qwen":
505
+ this.config.useModelRouting = true;
506
+ this.config.forceProvider = "qwen";
507
+ break;
508
+ case "--openai":
509
+ this.config.useModelRouting = true;
510
+ this.config.forceProvider = "openai";
511
+ break;
512
+ case "--ollama":
513
+ this.config.useModelRouting = true;
514
+ this.config.forceProvider = "ollama";
515
+ break;
516
+ case "--model-routing":
517
+ this.config.useModelRouting = true;
518
+ break;
519
+ case "--no-model-routing":
520
+ this.config.useModelRouting = false;
521
+ break;
433
522
  default:
434
523
  claudeArgs.push(arg);
435
524
  }
@@ -517,6 +606,45 @@ class ClaudeSM {
517
606
  );
518
607
  }
519
608
  }
609
+ if (this.config.useModelRouting) {
610
+ const routerConfig = loadModelRouterConfig();
611
+ if (routerConfig.enabled || this.config.forceProvider) {
612
+ const router = getModelRouter();
613
+ let routeResult;
614
+ if (this.config.forceProvider) {
615
+ const env = router.switchTo(this.config.forceProvider);
616
+ Object.assign(process.env, env);
617
+ console.log(
618
+ chalk.magenta(`\u{1F500} Model: ${this.config.forceProvider} (forced)`)
619
+ );
620
+ if (this.config.forceProvider === "qwen" && this.config.useThinkingMode) {
621
+ const qwenConfig = routerConfig.providers.qwen;
622
+ if (qwenConfig?.params?.enable_thinking) {
623
+ console.log(
624
+ chalk.gray(
625
+ ` Thinking mode: budget ${qwenConfig.params.thinking_budget || 1e4} tokens`
626
+ )
627
+ );
628
+ }
629
+ }
630
+ } else {
631
+ const taskType = this.config.useThinkingMode ? "think" : "default";
632
+ routeResult = router.route(taskType, this.config.task);
633
+ Object.assign(process.env, routeResult.env);
634
+ if (routeResult.switched) {
635
+ console.log(
636
+ chalk.magenta(`\u{1F500} Model routed to: ${routeResult.provider}`)
637
+ );
638
+ }
639
+ }
640
+ } else {
641
+ console.log(
642
+ chalk.gray(
643
+ " Model routing: disabled (run: stackmemory model enable)"
644
+ )
645
+ );
646
+ }
647
+ }
520
648
  if (this.config.useWhatsApp) {
521
649
  console.log(
522
650
  chalk.cyan("\u{1F4F1} WhatsApp mode: notifications + webhook enabled")
@@ -537,10 +665,36 @@ class ClaudeSM {
537
665
  process.exit(1);
538
666
  return;
539
667
  }
540
- const claude = spawn(claudeBin, claudeArgs, {
541
- stdio: "inherit",
542
- env: process.env
668
+ const fallbackMonitor = new FallbackMonitor({
669
+ enabled: true,
670
+ maxRestarts: 2,
671
+ restartDelayMs: 1500,
672
+ onFallback: (provider, reason) => {
673
+ console.log(chalk.yellow(`
674
+ [auto-fallback] Switching to ${provider}`));
675
+ console.log(chalk.gray(` Reason: ${reason}`));
676
+ console.log(chalk.gray(` Session will continue on ${provider}...`));
677
+ if (this.config.notifyOnDone || this.config.useWhatsApp) {
678
+ sendNotification({
679
+ type: "custom",
680
+ title: "Model Fallback",
681
+ message: `Claude unavailable (${reason}). Switched to ${provider}.`
682
+ }).catch(() => {
683
+ });
684
+ }
685
+ }
543
686
  });
687
+ const fallbackAvailable = fallbackMonitor.isFallbackAvailable();
688
+ if (fallbackAvailable) {
689
+ console.log(
690
+ chalk.gray(` Auto-fallback: Qwen ready (on rate limit/error)`)
691
+ );
692
+ }
693
+ const wrapper = fallbackMonitor.wrapProcess(claudeBin, claudeArgs, {
694
+ env: process.env,
695
+ cwd: process.cwd()
696
+ });
697
+ const claude = wrapper.start();
544
698
  claude.on("error", (err) => {
545
699
  console.error(chalk.red("\u274C Failed to launch Claude CLI."));
546
700
  if (err.code === "ENOENT") {
@@ -559,6 +713,15 @@ class ClaudeSM {
559
713
  process.exit(1);
560
714
  });
561
715
  claude.on("exit", async (code) => {
716
+ const status = fallbackMonitor.getStatus();
717
+ if (status.inFallback) {
718
+ console.log(
719
+ chalk.yellow(
720
+ `
721
+ Session completed on fallback provider: ${status.currentProvider}`
722
+ )
723
+ );
724
+ }
562
725
  this.saveContext("Claude session ended", {
563
726
  action: "session_end",
564
727
  exitCode: code
@@ -624,6 +787,9 @@ configCmd.command("show").description("Show current default settings").action(()
624
787
  console.log(
625
788
  ` defaultWhatsApp: ${config.defaultWhatsApp ? chalk.green("true") : chalk.gray("false")}`
626
789
  );
790
+ console.log(
791
+ ` defaultModelRouting: ${config.defaultModelRouting ? chalk.green("true") : chalk.gray("false")}`
792
+ );
627
793
  console.log(chalk.gray(`
628
794
  Config: ${getConfigPath()}`));
629
795
  });
@@ -638,7 +804,9 @@ configCmd.command("set <key> <value>").description("Set a default (e.g., set wor
638
804
  remote: "defaultRemote",
639
805
  "notify-done": "defaultNotifyOnDone",
640
806
  notifyondone: "defaultNotifyOnDone",
641
- whatsapp: "defaultWhatsApp"
807
+ whatsapp: "defaultWhatsApp",
808
+ "model-routing": "defaultModelRouting",
809
+ modelrouting: "defaultModelRouting"
642
810
  };
643
811
  const configKey = keyMap[key];
644
812
  if (!configKey) {
@@ -704,10 +872,25 @@ configCmd.command("whatsapp-off").description("Disable WhatsApp mode by default"
704
872
  saveSMConfig(config);
705
873
  console.log(chalk.green("WhatsApp mode disabled by default"));
706
874
  });
875
+ configCmd.command("model-routing-on").description(
876
+ "Enable model routing by default (route tasks to Qwen/other models)"
877
+ ).action(() => {
878
+ const config = loadSMConfig();
879
+ config.defaultModelRouting = true;
880
+ saveSMConfig(config);
881
+ console.log(chalk.green("Model routing enabled by default"));
882
+ console.log(chalk.gray("Configure with: stackmemory model setup-qwen"));
883
+ });
884
+ configCmd.command("model-routing-off").description("Disable model routing by default (use Claude only)").action(() => {
885
+ const config = loadSMConfig();
886
+ config.defaultModelRouting = false;
887
+ saveSMConfig(config);
888
+ console.log(chalk.green("Model routing disabled by default"));
889
+ });
707
890
  program.option("-w, --worktree", "Create isolated worktree for this instance").option("-W, --no-worktree", "Disable worktree (override default)").option("-r, --remote", "Enable remote mode (WhatsApp for all questions)").option("--no-remote", "Disable remote mode (override default)").option("-n, --notify-done", "Send WhatsApp notification when session ends").option("--no-notify-done", "Disable notification when session ends").option(
708
891
  "--whatsapp",
709
892
  "Enable WhatsApp mode (auto-start webhook + ngrok + notifications)"
710
- ).option("--no-whatsapp", "Disable WhatsApp mode (override default)").option("-s, --sandbox", "Enable sandbox mode (file/network restrictions)").option("-c, --chrome", "Enable Chrome automation").option("-a, --auto", "Automatically detect and apply best settings").option("-b, --branch <name>", "Specify branch name for worktree").option("-t, --task <desc>", "Task description for context").option("--claude-bin <path>", "Path to claude CLI (or use CLAUDE_BIN)").option("--no-context", "Disable StackMemory context integration").option("--no-trace", "Disable debug tracing (enabled by default)").option("--verbose-trace", "Enable verbose debug tracing with full details").helpOption("-h, --help", "Display help").allowUnknownOption(true).action(async (_options) => {
893
+ ).option("--no-whatsapp", "Disable WhatsApp mode (override default)").option("-s, --sandbox", "Enable sandbox mode (file/network restrictions)").option("-c, --chrome", "Enable Chrome automation").option("-a, --auto", "Automatically detect and apply best settings").option("-b, --branch <name>", "Specify branch name for worktree").option("-t, --task <desc>", "Task description for context").option("--claude-bin <path>", "Path to claude CLI (or use CLAUDE_BIN)").option("--no-context", "Disable StackMemory context integration").option("--no-trace", "Disable debug tracing (enabled by default)").option("--verbose-trace", "Enable verbose debug tracing with full details").option("--think", "Enable thinking mode with Qwen (deep reasoning)").option("--think-hard", "Alias for --think").option("--ultrathink", "Alias for --think").option("--qwen", "Force Qwen provider for this session").option("--openai", "Force OpenAI provider for this session").option("--ollama", "Force Ollama provider for this session").option("--model-routing", "Enable model routing").option("--no-model-routing", "Disable model routing").helpOption("-h, --help", "Display help").allowUnknownOption(true).action(async (_options) => {
711
894
  const claudeSM = new ClaudeSM();
712
895
  const args = process.argv.slice(2);
713
896
  await claudeSM.run(args);