#!/usr/bin/env node
import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
import { config as loadDotenv } from "dotenv";
loadDotenv({ override: true, debug: false });
import { spawn, execSync, execFileSync } from "child_process";
import * as fs from "fs";
import * as path from "path";
import * as os from "os";
import { program } from "commander";
import { v4 as uuidv4 } from "uuid";
import chalk from "chalk";
import { initializeTracing, trace } from "../core/trace/index.js";
import {
  generateSessionSummary,
  formatSummaryMessage
} from "../hooks/session-summary.js";
import { sendNotification, loadSMSConfig } from "../hooks/sms-notify.js";
import { enableAutoSync } from "../hooks/whatsapp-sync.js";
import { enableCommands } from "../hooks/whatsapp-commands.js";
import { startScheduler, listSchedules } from "../hooks/whatsapp-scheduler.js";
import {
  getModelRouter,
  loadModelRouterConfig
} from "../core/models/model-router.js";
import { launchWrapper } from "../features/sweep/pty-wrapper.js";
import { FallbackMonitor } from "../core/models/fallback-monitor.js";
import {
  ensureWorkerStateDir,
  saveRegistry,
  loadRegistry,
  clearRegistry
} from "../features/workers/worker-registry.js";
import {
  isTmuxAvailable,
  createTmuxSession,
  sendToPane,
  killTmuxSession,
  attachToSession,
  listPanes,
  sendCtrlC,
  sessionExists
} from "../features/workers/tmux-manager.js";
const DEFAULT_SM_CONFIG = {
  defaultWorktree: false,
  defaultSandbox: false,
  defaultChrome: false,
  defaultTracing: true,
  defaultRemote: false,
  defaultNotifyOnDone: true,
  defaultWhatsApp: false,
  defaultModelRouting: false,
  defaultSweep: true,
  defaultGreptile: true,
  defaultGEPA: false
};
function getConfigPath() {
  return path.join(os.homedir(), ".stackmemory", "claude-sm.json");
}
function loadSMConfig() {
  try {
    const configPath = getConfigPath();
    if (fs.existsSync(configPath)) {
      const content = fs.readFileSync(configPath, "utf8");
      return { ...DEFAULT_SM_CONFIG, ...JSON.parse(content) };
    }
  } catch {
  }
  return { ...DEFAULT_SM_CONFIG };
}
function saveSMConfig(config) {
  const configPath = getConfigPath();
  const dir = path.dirname(configPath);
  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir, { recursive: true });
  }
  fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
}
class ClaudeSM {
  config;
  stackmemoryPath;
  worktreeScriptPath;
  claudeConfigDir;
  smConfig;
  constructor() {
    this.smConfig = loadSMConfig();
    this.config = {
      instanceId: this.generateInstanceId(),
      useSandbox: this.smConfig.defaultSandbox,
      useChrome: this.smConfig.defaultChrome,
      useWorktree: this.smConfig.defaultWorktree,
      useRemote: this.smConfig.defaultRemote,
      notifyOnDone: this.smConfig.defaultNotifyOnDone,
      useWhatsApp: this.smConfig.defaultWhatsApp,
      contextEnabled: true,
      tracingEnabled: this.smConfig.defaultTracing,
      verboseTracing: false,
      sessionStartTime: Date.now(),
      useModelRouting: this.smConfig.defaultModelRouting,
      useThinkingMode: false,
      useSweep: this.smConfig.defaultSweep,
      useGreptile: this.smConfig.defaultGreptile,
      useGEPA: this.smConfig.defaultGEPA
    };
    this.stackmemoryPath = this.findStackMemory();
    this.worktreeScriptPath = path.join(
      __dirname,
      "../../scripts/claude-worktree-manager.sh"
    );
    this.claudeConfigDir = path.join(os.homedir(), ".claude");
    if (!fs.existsSync(this.claudeConfigDir)) {
      fs.mkdirSync(this.claudeConfigDir, { recursive: true });
    }
  }
  generateInstanceId() {
    return uuidv4().substring(0, 8);
  }
  findStackMemory() {
    const possiblePaths = [
      path.join(os.homedir(), ".stackmemory", "bin", "stackmemory"),
      "/usr/local/bin/stackmemory",
      "/opt/homebrew/bin/stackmemory",
      "stackmemory"
      // Rely on PATH
    ];
    for (const smPath of possiblePaths) {
      try {
        execFileSync("which", [smPath], { stdio: "ignore" });
        return smPath;
      } catch {
      }
    }
    return "stackmemory";
  }
  isGitRepo() {
    try {
      execSync("git rev-parse --git-dir", { stdio: "ignore" });
      return true;
    } catch {
      return false;
    }
  }
  getCurrentBranch() {
    try {
      return execSync("git rev-parse --abbrev-ref HEAD", {
        encoding: "utf8"
      }).trim();
    } catch {
      return "main";
    }
  }
  hasUncommittedChanges() {
    try {
      const status = execSync("git status --porcelain", { encoding: "utf8" });
      return status.length > 0;
    } catch {
      return false;
    }
  }
  resolveClaudeBin() {
    if (this.config.claudeBin && this.config.claudeBin.trim()) {
      return this.config.claudeBin.trim();
    }
    const envBin = process.env["CLAUDE_BIN"];
    if (envBin && envBin.trim()) return envBin.trim();
    try {
      execSync("which claude", { stdio: "ignore" });
      return "claude";
    } catch {
    }
    return null;
  }
  gepaProcesses = [];
  startGEPAWatcher() {
    const watchFiles = ["CLAUDE.md", "AGENT.md", "AGENTS.md"].map((f) => path.join(process.cwd(), f)).filter((p) => fs.existsSync(p));
    if (watchFiles.length === 0) {
      console.log(
        chalk.gray(
          "   Prompt Forge: disabled (no CLAUDE.md, AGENT.md, or AGENTS.md found)"
        )
      );
      return;
    }
    const gepaPaths = [
      // From dist/src/cli -> scripts/gepa (3 levels up)
      path.join(__dirname, "../../../scripts/gepa/hooks/auto-optimize.js"),
      // From src/cli -> scripts/gepa (2 levels up, for dev mode)
      path.join(__dirname, "../../scripts/gepa/hooks/auto-optimize.js"),
      // Global install location
      path.join(
        os.homedir(),
        ".stackmemory",
        "scripts",
        "gepa",
        "hooks",
        "auto-optimize.js"
      ),
      // npm global install
      path.join(
        __dirname,
        "..",
        "..",
        "scripts",
        "gepa",
        "hooks",
        "auto-optimize.js"
      )
    ];
    const gepaScript = gepaPaths.find((p) => fs.existsSync(p));
    if (!gepaScript) {
      console.log(chalk.gray("   Prompt Forge: disabled (scripts not found)"));
      return;
    }
    for (const filePath of watchFiles) {
      const gepaProcess = spawn("node", [gepaScript, "watch", filePath], {
        detached: true,
        stdio: ["ignore", "pipe", "pipe"],
        env: { ...process.env, GEPA_SILENT: "1" }
      });
      gepaProcess.unref();
      this.gepaProcesses.push(gepaProcess);
      gepaProcess.stdout?.on("data", (data) => {
        const output = data.toString().trim();
        if (output && !output.includes("Watching")) {
          console.log(chalk.magenta(`[GEPA] ${output}`));
        }
      });
    }
    const fileNames = watchFiles.map((f) => path.basename(f)).join(", ");
    console.log(
      chalk.cyan(`   Prompt Forge: watching ${fileNames} for optimization`)
    );
  }
  stopGEPAWatcher() {
    for (const proc of this.gepaProcesses) {
      proc.kill("SIGTERM");
    }
    this.gepaProcesses = [];
  }
  ensureGreptileMcp() {
    const apiKey = process.env["GREPTILE_API_KEY"];
    const ghToken = process.env["GITHUB_TOKEN"];
    if (!apiKey) {
      console.log(
        chalk.gray("   Greptile: disabled (set GREPTILE_API_KEY in .env)")
      );
      return;
    }
    try {
      const result = execSync("claude mcp list 2>/dev/null", {
        encoding: "utf-8"
      });
      if (result.includes("greptile")) {
        console.log(chalk.gray("   Greptile: MCP server registered"));
        return;
      }
    } catch {
    }
    try {
      const cmd = [
        "claude mcp add",
        "--transport http",
        "greptile",
        "https://api.greptile.com/mcp",
        `--header "Authorization: Bearer ${apiKey}"`
      ];
      if (ghToken) {
        cmd.push(`--header "X-GitHub-Token: ${ghToken}"`);
      }
      execSync(cmd.join(" "), { stdio: "ignore" });
      console.log(chalk.cyan("   Greptile: MCP server registered"));
    } catch {
      try {
        const envArgs = [`GREPTILE_API_KEY=${apiKey}`];
        if (ghToken) envArgs.push(`GITHUB_TOKEN=${ghToken}`);
        execSync(
          `claude mcp add greptile -- env ${envArgs.join(" ")} npx greptile-mcp-server`,
          { stdio: "ignore" }
        );
        console.log(chalk.cyan("   Greptile: MCP server registered (stdio)"));
      } catch {
        console.log(chalk.gray("   Greptile: failed to register MCP server"));
      }
    }
  }
  setupWorktree() {
    if (!this.config.useWorktree || !this.isGitRepo()) {
      return null;
    }
    console.log(chalk.blue("\u{1F333} Setting up isolated worktree..."));
    const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").substring(0, 19);
    const branch = this.config.branch || `claude-${this.config.task || "work"}-${timestamp}-${this.config.instanceId}`;
    const repoName = path.basename(process.cwd());
    const worktreePath = path.join(
      path.dirname(process.cwd()),
      `${repoName}--${branch}`
    );
    try {
      const flags = [];
      if (this.config.useSandbox) flags.push("--sandbox");
      if (this.config.useChrome) flags.push("--chrome");
      const cmd = `git worktree add -b "${branch}" "${worktreePath}"`;
      execSync(cmd, { stdio: "inherit" });
      console.log(chalk.green(`\u2705 Worktree created: ${worktreePath}`));
      console.log(chalk.gray(`   Branch: ${branch}`));
      const configPath = path.join(worktreePath, ".claude-instance.json");
      const configData = {
        instanceId: this.config.instanceId,
        worktreePath,
        branch,
        task: this.config.task,
        sandboxEnabled: this.config.useSandbox,
        chromeEnabled: this.config.useChrome,
        created: (/* @__PURE__ */ new Date()).toISOString(),
        parentRepo: process.cwd()
      };
      fs.writeFileSync(configPath, JSON.stringify(configData, null, 2));
      const envFiles = [".env", ".env.local", ".mise.toml", ".tool-versions"];
      for (const file of envFiles) {
        const srcPath = path.join(process.cwd(), file);
        if (fs.existsSync(srcPath)) {
          fs.copyFileSync(srcPath, path.join(worktreePath, file));
        }
      }
      return worktreePath;
    } catch (err) {
      console.error(chalk.red("\u274C Failed to create worktree:"), err);
      return null;
    }
  }
  saveContext(message, metadata = {}) {
    if (!this.config.contextEnabled) return;
    try {
      const contextData = {
        message,
        metadata: {
          ...metadata,
          instanceId: this.config.instanceId,
          worktree: this.config.worktreePath,
          timestamp: (/* @__PURE__ */ new Date()).toISOString()
        }
      };
      const cmd = `${this.stackmemoryPath} context save --json '${JSON.stringify(contextData)}'`;
      execSync(cmd, { stdio: "ignore" });
    } catch {
    }
  }
  loadContext() {
    if (!this.config.contextEnabled) return;
    try {
      console.log(chalk.blue("\u{1F4DA} Loading previous context..."));
      const cmd = `${this.stackmemoryPath} context show`;
      const output = execSync(cmd, {
        encoding: "utf8",
        stdio: ["pipe", "pipe", "pipe"]
        // Capture stderr to suppress errors
      });
      const lines = output.trim().split("\n").filter((l) => l.trim());
      if (lines.length > 3) {
        console.log(chalk.gray("Context stack loaded"));
      }
    } catch {
    }
  }
  detectMultipleInstances() {
    try {
      const lockDir = path.join(process.cwd(), ".claude-worktree-locks");
      if (!fs.existsSync(lockDir)) return false;
      const locks = fs.readdirSync(lockDir).filter((f) => f.endsWith(".lock"));
      const activeLocks = locks.filter((lockFile) => {
        const lockPath = path.join(lockDir, lockFile);
        const lockData = JSON.parse(fs.readFileSync(lockPath, "utf8"));
        const lockAge = Date.now() - new Date(lockData.created).getTime();
        return lockAge < 24 * 60 * 60 * 1e3;
      });
      return activeLocks.length > 0;
    } catch {
      return false;
    }
  }
  suggestWorktreeMode() {
    if (this.hasUncommittedChanges()) {
      console.log(chalk.yellow("\u26A0\uFE0F  Uncommitted changes detected"));
      console.log(
        chalk.gray("   Consider using --worktree to work in isolation")
      );
    }
    if (this.detectMultipleInstances()) {
      console.log(chalk.yellow("\u26A0\uFE0F  Other Claude instances detected"));
      console.log(
        chalk.gray("   Using --worktree is recommended to avoid conflicts")
      );
    }
  }
  async startWhatsAppServices() {
    const WEBHOOK_PORT = 3456;
    console.log(chalk.cyan("\n\u{1F4F1} WhatsApp Mode - Full Integration"));
    console.log(chalk.gray("\u2500".repeat(42)));
    const smsConfig = loadSMSConfig();
    if (!smsConfig.enabled) {
      console.log(
        chalk.yellow("  Notifications disabled. Run: stackmemory notify enable")
      );
    }
    try {
      enableAutoSync();
      console.log(
        chalk.green("  \u2713 Auto-sync enabled (digests on frame close)")
      );
    } catch {
      console.log(chalk.gray("  Auto-sync: skipped"));
    }
    try {
      enableCommands();
      console.log(chalk.green("  \u2713 Command processing enabled"));
      console.log(
        chalk.gray("    Reply: status, tasks, context, help, build, test, lint")
      );
    } catch {
      console.log(chalk.gray("  Command processing: skipped"));
    }
    try {
      const schedules = listSchedules();
      if (schedules.length > 0) {
        startScheduler();
        console.log(
          chalk.green(`  \u2713 Scheduler started (${schedules.length} schedules)`)
        );
      }
    } catch {
    }
    const webhookRunning = await fetch(
      `http://localhost:${WEBHOOK_PORT}/health`
    ).then((r) => r.ok).catch(() => false);
    if (!webhookRunning) {
      const webhookPath = path.join(__dirname, "../hooks/sms-webhook.js");
      const webhookProcess = spawn("node", [webhookPath], {
        detached: true,
        stdio: "ignore",
        env: { ...process.env, SMS_WEBHOOK_PORT: String(WEBHOOK_PORT) }
      });
      webhookProcess.unref();
      console.log(
        chalk.green(`  \u2713 Webhook server started (port ${WEBHOOK_PORT})`)
      );
    } else {
      console.log(
        chalk.green(`  \u2713 Webhook already running (port ${WEBHOOK_PORT})`)
      );
    }
    const ngrokRunning = await fetch("http://localhost:4040/api/tunnels").then((r) => r.ok).catch(() => false);
    if (!ngrokRunning) {
      const ngrokProcess = spawn("ngrok", ["http", String(WEBHOOK_PORT)], {
        detached: true,
        stdio: "ignore"
      });
      ngrokProcess.unref();
      console.log(chalk.gray("  Starting ngrok tunnel..."));
      await new Promise((resolve) => setTimeout(resolve, 3e3));
    }
    try {
      const tunnels = await fetch("http://localhost:4040/api/tunnels").then(
        (r) => r.json()
      );
      const publicUrl = tunnels?.tunnels?.[0]?.public_url;
      if (publicUrl) {
        const configDir = path.join(os.homedir(), ".stackmemory");
        const configPath = path.join(configDir, "ngrok-url.txt");
        if (!fs.existsSync(configDir)) {
          fs.mkdirSync(configDir, { recursive: true });
        }
        fs.writeFileSync(configPath, publicUrl);
        console.log(chalk.green(`  \u2713 ngrok tunnel: ${publicUrl}/sms/incoming`));
      }
    } catch {
      console.log(chalk.yellow("  ngrok: waiting for tunnel..."));
    }
    if (smsConfig.pendingPrompts.length > 0) {
      console.log();
      console.log(
        chalk.yellow(
          `  \u23F3 ${smsConfig.pendingPrompts.length} pending prompt(s) awaiting response:`
        )
      );
      smsConfig.pendingPrompts.slice(0, 3).forEach((p, i) => {
        const msg = p.message.length > 40 ? p.message.slice(0, 40) + "..." : p.message;
        console.log(chalk.gray(`     ${i + 1}. [${p.id}] ${msg}`));
      });
      if (smsConfig.pendingPrompts.length > 3) {
        console.log(
          chalk.gray(`     ... and ${smsConfig.pendingPrompts.length - 3} more`)
        );
      }
    }
    console.log();
    console.log(chalk.gray("  Quick actions from WhatsApp:"));
    console.log(chalk.gray('    "status"  - session status'));
    console.log(chalk.gray('    "context" - current frame digest'));
    console.log(chalk.gray('    "1", "2"  - respond to prompts'));
    console.log(chalk.gray("\u2500".repeat(42)));
  }
  async sendDoneNotification(exitCode) {
    try {
      const context = {
        instanceId: this.config.instanceId,
        exitCode,
        sessionStartTime: this.config.sessionStartTime,
        worktreePath: this.config.worktreePath,
        branch: this.config.branch,
        task: this.config.task
      };
      const summary = await generateSessionSummary(context);
      const message = formatSummaryMessage(summary, this.config.instanceId);
      console.log(chalk.cyan("\nSending session summary via WhatsApp..."));
      let options = summary.suggestions.slice(0, 4).map((s) => ({
        key: s.key,
        label: s.label,
        action: s.action
      }));
      if (options.length < 2) {
        const defaults = [
          { key: "1", label: "Start new session", action: "claude-sm" },
          {
            key: "2",
            label: "View logs",
            action: "tail -30 ~/.claude/logs/*.log"
          }
        ];
        options = defaults.slice(0, 2 - options.length).concat(options);
        options.forEach((o, i) => o.key = String(i + 1));
      }
      const result = await sendNotification({
        type: "task_complete",
        title: `Claude Session ${this.config.instanceId}`,
        message,
        prompt: {
          type: "options",
          options
        }
      });
      if (result.success) {
        console.log(chalk.green("Notification sent successfully"));
      } else {
        console.log(
          chalk.yellow(`Notification not sent: ${result.error || "unknown"}`)
        );
      }
    } catch (error) {
      console.log(
        chalk.yellow(
          `Could not send notification: ${error instanceof Error ? error.message : "unknown"}`
        )
      );
    }
  }
  async run(args) {
    const claudeArgs = [];
    let i = 0;
    while (i < args.length) {
      const arg = args[i];
      switch (arg) {
        case "--worktree":
        case "-w":
          this.config.useWorktree = true;
          break;
        case "--no-worktree":
        case "-W":
          this.config.useWorktree = false;
          break;
        case "--remote":
        case "-r":
          this.config.useRemote = true;
          break;
        case "--no-remote":
          this.config.useRemote = false;
          break;
        case "--notify-done":
        case "-n":
          this.config.notifyOnDone = true;
          break;
        case "--no-notify-done":
          this.config.notifyOnDone = false;
          break;
        case "--whatsapp":
          this.config.useWhatsApp = true;
          this.config.notifyOnDone = true;
          break;
        case "--no-whatsapp":
          this.config.useWhatsApp = false;
          break;
        case "--sandbox":
        case "-s":
          this.config.useSandbox = true;
          claudeArgs.push("--sandbox");
          break;
        case "--chrome":
        case "-c":
          this.config.useChrome = true;
          claudeArgs.push("--chrome");
          break;
        case "--no-context":
          this.config.contextEnabled = false;
          break;
        case "--no-trace":
          this.config.tracingEnabled = false;
          break;
        case "--verbose-trace":
          this.config.verboseTracing = true;
          break;
        case "--branch":
        case "-b":
          i++;
          this.config.branch = args[i];
          break;
        case "--task":
        case "-t":
          i++;
          this.config.task = args[i];
          break;
        case "--claude-bin":
          i++;
          this.config.claudeBin = args[i];
          process.env["CLAUDE_BIN"] = this.config.claudeBin;
          break;
        case "--auto":
        case "-a":
          if (this.isGitRepo()) {
            this.config.useWorktree = this.hasUncommittedChanges() || this.detectMultipleInstances();
          }
          break;
        case "--think":
        case "--think-hard":
        case "--ultrathink":
          this.config.useThinkingMode = true;
          this.config.useModelRouting = true;
          this.config.forceProvider = "qwen";
          break;
        case "--qwen":
          this.config.useModelRouting = true;
          this.config.forceProvider = "qwen";
          break;
        case "--openai":
          this.config.useModelRouting = true;
          this.config.forceProvider = "openai";
          break;
        case "--ollama":
          this.config.useModelRouting = true;
          this.config.forceProvider = "ollama";
          break;
        case "--model-routing":
          this.config.useModelRouting = true;
          break;
        case "--no-model-routing":
          this.config.useModelRouting = false;
          break;
        case "--sweep":
          this.config.useSweep = true;
          break;
        case "--no-sweep":
          this.config.useSweep = false;
          break;
        case "--greptile":
          this.config.useGreptile = true;
          break;
        case "--no-greptile":
          this.config.useGreptile = false;
          break;
        case "--gepa":
          this.config.useGEPA = true;
          break;
        case "--no-gepa":
          this.config.useGEPA = false;
          break;
        default:
          claudeArgs.push(arg);
      }
      i++;
    }
    const printIndex = claudeArgs.findIndex(
      (a) => a === "-p" || a === "--print"
    );
    if (printIndex !== -1) {
      const nextArg = claudeArgs[printIndex + 1];
      const hasStdin = !process.stdin.isTTY;
      const hasPromptArg = nextArg && !nextArg.startsWith("-");
      if (!hasStdin && !hasPromptArg) {
        console.error(
          chalk.red("Error: --print/-p requires a prompt argument.")
        );
        console.log(chalk.gray('Usage: claude-smd -p "your prompt here"'));
        console.log(chalk.gray('       echo "prompt" | claude-smd -p'));
        process.exit(1);
      }
    }
    if (this.config.tracingEnabled) {
      process.env["DEBUG_TRACE"] = "true";
      process.env["STACKMEMORY_DEBUG"] = "true";
      process.env["TRACE_OUTPUT"] = "file";
      process.env["TRACE_MASK_SENSITIVE"] = "true";
      if (this.config.verboseTracing) {
        process.env["TRACE_VERBOSITY"] = "full";
        process.env["TRACE_PARAMS"] = "true";
        process.env["TRACE_RESULTS"] = "true";
        process.env["TRACE_MEMORY"] = "true";
      } else {
        process.env["TRACE_VERBOSITY"] = "summary";
        process.env["TRACE_PARAMS"] = "true";
        process.env["TRACE_RESULTS"] = "false";
      }
      initializeTracing();
      trace.command(
        "claude-sm",
        {
          instanceId: this.config.instanceId,
          worktree: this.config.useWorktree,
          sandbox: this.config.useSandbox,
          task: this.config.task
        },
        async () => {
        }
      );
    }
    console.log(chalk.blue("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
    console.log(chalk.blue("\u2551     Claude + StackMemory + Worktree   \u2551"));
    console.log(chalk.blue("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
    console.log();
    if (this.isGitRepo()) {
      const branch = this.getCurrentBranch();
      console.log(chalk.gray(`\u{1F4CD} Current branch: ${branch}`));
      if (!this.config.useWorktree) {
        this.suggestWorktreeMode();
      }
    }
    if (this.config.useWorktree) {
      const worktreePath = this.setupWorktree();
      if (worktreePath) {
        this.config.worktreePath = worktreePath;
        process.chdir(worktreePath);
        this.saveContext("Created worktree for Claude instance", {
          action: "worktree_created",
          path: worktreePath,
          branch: this.config.branch
        });
      }
    }
    this.loadContext();
    process.env["CLAUDE_INSTANCE_ID"] = this.config.instanceId;
    if (this.config.worktreePath) {
      process.env["CLAUDE_WORKTREE_PATH"] = this.config.worktreePath;
    }
    if (this.config.useRemote) {
      process.env["CLAUDE_REMOTE"] = "1";
    }
    console.log(chalk.gray(`\u{1F916} Instance ID: ${this.config.instanceId}`));
    console.log(chalk.gray(`\u{1F4C1} Working in: ${process.cwd()}`));
    if (this.config.useSandbox) {
      console.log(chalk.yellow("\u{1F512} Sandbox mode enabled"));
    }
    if (this.config.useRemote) {
      console.log(
        chalk.cyan("\u{1F4F1} Remote mode: WhatsApp notifications for all questions")
      );
    }
    if (this.config.useChrome) {
      console.log(chalk.yellow("\u{1F310} Chrome automation enabled"));
    }
    if (this.config.tracingEnabled) {
      console.log(
        chalk.gray(`\u{1F50D} Debug tracing enabled (logs to ~/.stackmemory/traces/)`)
      );
      if (this.config.verboseTracing) {
        console.log(
          chalk.gray(`   Verbose mode: capturing all execution details`)
        );
      }
    }
    if (this.config.useModelRouting) {
      const routerConfig = loadModelRouterConfig();
      if (routerConfig.enabled || this.config.forceProvider) {
        const router = getModelRouter();
        let routeResult;
        if (this.config.forceProvider) {
          const env = router.switchTo(this.config.forceProvider);
          Object.assign(process.env, env);
          console.log(
            chalk.magenta(`\u{1F500} Model: ${this.config.forceProvider} (forced)`)
          );
          if (this.config.forceProvider === "qwen" && this.config.useThinkingMode) {
            const qwenConfig = routerConfig.providers.qwen;
            if (qwenConfig?.params?.enable_thinking) {
              console.log(
                chalk.gray(
                  `   Thinking mode: budget ${qwenConfig.params.thinking_budget || 1e4} tokens`
                )
              );
            }
          }
        } else {
          const taskType = this.config.useThinkingMode ? "think" : "default";
          routeResult = router.route(taskType, this.config.task);
          Object.assign(process.env, routeResult.env);
          if (routeResult.switched) {
            console.log(
              chalk.magenta(`\u{1F500} Model routed to: ${routeResult.provider}`)
            );
          }
        }
      } else {
        console.log(
          chalk.gray(
            "   Model routing: disabled (run: stackmemory model enable)"
          )
        );
      }
    }
    if (this.config.useGreptile) {
      this.ensureGreptileMcp();
    }
    if (this.config.useGEPA) {
      this.startGEPAWatcher();
    }
    if (this.config.useWhatsApp) {
      console.log(
        chalk.cyan("\u{1F4F1} WhatsApp mode: notifications + webhook enabled")
      );
      await this.startWhatsAppServices();
    }
    console.log();
    if (this.config.useSweep) {
      const claudeBin2 = this.resolveClaudeBin();
      if (!claudeBin2) {
        console.error(chalk.red("Claude CLI not found."));
        process.exit(1);
        return;
      }
      console.log(
        chalk.cyan("[Sweep] Launching Claude with prediction bar...")
      );
      console.log(chalk.gray("\u2500".repeat(42)));
      try {
        await launchWrapper({
          claudeBin: claudeBin2,
          claudeArgs
        });
        return;
      } catch (error) {
        const msg = error.message || "Unknown PTY error";
        console.error(chalk.yellow(`[Sweep disabled] ${msg}`));
        console.log(
          chalk.gray(
            "Falling back to direct Claude launch (no prediction bar)..."
          )
        );
        this.config.useSweep = false;
      }
    }
    console.log(chalk.gray("Starting Claude..."));
    console.log(chalk.gray("\u2500".repeat(42)));
    const claudeBin = this.resolveClaudeBin();
    if (!claudeBin) {
      console.error(chalk.red("\u274C Claude CLI not found."));
      console.log(
        chalk.gray(
          "   Install Claude CLI or set an override:\n     export CLAUDE_BIN=/path/to/claude\n     claude-sm --help\n\n   Ensure PATH includes npm global bin (npm bin -g)."
        )
      );
      process.exit(1);
      return;
    }
    const fallbackMonitor = new FallbackMonitor({
      enabled: true,
      maxRestarts: 2,
      restartDelayMs: 1500,
      onFallback: (provider, reason) => {
        console.log(chalk.yellow(`
[auto-fallback] Switching to ${provider}`));
        console.log(chalk.gray(`   Reason: ${reason}`));
        console.log(chalk.gray(`   Session will continue on ${provider}...`));
        if (this.config.notifyOnDone || this.config.useWhatsApp) {
          sendNotification({
            type: "custom",
            title: "Model Fallback",
            message: `Claude unavailable (${reason}). Switched to ${provider}.`
          }).catch(() => {
          });
        }
      }
    });
    const fallbackAvailable = fallbackMonitor.isFallbackAvailable();
    if (fallbackAvailable) {
      console.log(
        chalk.gray(`   Auto-fallback: Qwen ready (on rate limit/error)`)
      );
    }
    const wrapper = fallbackMonitor.wrapProcess(claudeBin, claudeArgs, {
      env: process.env,
      cwd: process.cwd()
    });
    const claude = wrapper.start();
    claude.on("error", (err) => {
      console.error(chalk.red("\u274C Failed to launch Claude CLI."));
      if (err.code === "ENOENT") {
        console.error(
          chalk.gray("   Not found. Set CLAUDE_BIN or install claude on PATH.")
        );
      } else if (err.code === "EPERM" || err.code === "EACCES") {
        console.error(
          chalk.gray(
            "   Permission/sandbox issue. Try outside a sandbox or set CLAUDE_BIN."
          )
        );
      } else {
        console.error(chalk.gray(`   ${err.message}`));
      }
      process.exit(1);
    });
    claude.on("exit", async (code) => {
      this.stopGEPAWatcher();
      const status = fallbackMonitor.getStatus();
      if (status.inFallback) {
        console.log(
          chalk.yellow(
            `
Session completed on fallback provider: ${status.currentProvider}`
          )
        );
      }
      this.saveContext("Claude session ended", {
        action: "session_end",
        exitCode: code
      });
      if (this.config.tracingEnabled) {
        const summary = trace.getExecutionSummary();
        console.log();
        console.log(chalk.gray("\u2500".repeat(42)));
        console.log(chalk.blue("Debug Trace Summary:"));
        console.log(chalk.gray(summary));
      }
      if (this.config.notifyOnDone || this.config.useRemote) {
        await this.sendDoneNotification(code);
      }
      if (this.config.worktreePath) {
        console.log();
        console.log(chalk.gray("\u2500".repeat(42)));
        console.log(chalk.blue("Session ended in worktree:"));
        console.log(chalk.gray(`  ${this.config.worktreePath}`));
        console.log();
        console.log(chalk.gray("To remove worktree: gd_claude"));
        console.log(chalk.gray("To merge to main: cwm"));
      }
      process.exit(code || 0);
    });
    process.on("SIGINT", () => {
      this.saveContext("Claude session interrupted", {
        action: "session_interrupt"
      });
      claude.kill("SIGINT");
    });
    process.on("SIGTERM", () => {
      this.saveContext("Claude session terminated", {
        action: "session_terminate"
      });
      claude.kill("SIGTERM");
    });
  }
}
program.name("claude-sm").description("Claude with StackMemory context and worktree isolation").version("1.0.0");
const configCmd = program.command("config").description("Manage claude-sm defaults");
configCmd.command("show").description("Show current default settings").action(() => {
  const config = loadSMConfig();
  console.log(chalk.blue("claude-sm defaults:"));
  const on = chalk.green("ON ");
  const off = chalk.gray("OFF");
  console.log(chalk.cyan("\n  Feature           Status"));
  console.log(chalk.gray("  \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
  console.log(`  Predictive Edit   ${config.defaultSweep ? on : off}`);
  console.log(`  Code Review       ${config.defaultGreptile ? on : off}`);
  console.log(`  Prompt Forge      ${config.defaultGEPA ? on : off}`);
  console.log(`  Model Switcher    ${config.defaultModelRouting ? on : off}`);
  console.log(`  Safe Branch       ${config.defaultWorktree ? on : off}`);
  console.log(`  Mobile Sync       ${config.defaultWhatsApp ? on : off}`);
  console.log(`  Session Insights  ${config.defaultTracing ? on : off}`);
  console.log(`  Task Alert        ${config.defaultNotifyOnDone ? on : off}`);
  console.log(chalk.gray("  \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
  console.log(`  Sandbox           ${config.defaultSandbox ? on : off}`);
  console.log(`  Chrome            ${config.defaultChrome ? on : off}`);
  console.log(`  Remote            ${config.defaultRemote ? on : off}`);
  console.log(chalk.gray(`
  Config: ${getConfigPath()}`));
});
configCmd.command("set <key> <value>").description("Set a default (e.g., set worktree true)").action((key, value) => {
  const config = loadSMConfig();
  const boolValue = value === "true" || value === "1" || value === "on";
  const keyMap = {
    worktree: "defaultWorktree",
    sandbox: "defaultSandbox",
    chrome: "defaultChrome",
    tracing: "defaultTracing",
    remote: "defaultRemote",
    "notify-done": "defaultNotifyOnDone",
    notifyondone: "defaultNotifyOnDone",
    whatsapp: "defaultWhatsApp",
    "model-routing": "defaultModelRouting",
    modelrouting: "defaultModelRouting",
    sweep: "defaultSweep",
    greptile: "defaultGreptile",
    gepa: "defaultGEPA"
  };
  const configKey = keyMap[key];
  if (!configKey) {
    console.log(chalk.red(`Unknown key: ${key}`));
    console.log(
      chalk.gray(
        "Valid keys: worktree, sandbox, chrome, tracing, remote, notify-done, whatsapp, sweep, greptile, gepa"
      )
    );
    process.exit(1);
  }
  config[configKey] = boolValue;
  saveSMConfig(config);
  console.log(chalk.green(`Set ${key} = ${boolValue}`));
});
configCmd.command("worktree-on").description("Enable worktree mode by default").action(() => {
  const config = loadSMConfig();
  config.defaultWorktree = true;
  saveSMConfig(config);
  console.log(chalk.green("Worktree mode enabled by default"));
});
configCmd.command("worktree-off").description("Disable worktree mode by default").action(() => {
  const config = loadSMConfig();
  config.defaultWorktree = false;
  saveSMConfig(config);
  console.log(chalk.green("Worktree mode disabled by default"));
});
configCmd.command("remote-on").description("Enable remote mode by default (WhatsApp for all questions)").action(() => {
  const config = loadSMConfig();
  config.defaultRemote = true;
  saveSMConfig(config);
  console.log(chalk.green("Remote mode enabled by default"));
});
configCmd.command("remote-off").description("Disable remote mode by default").action(() => {
  const config = loadSMConfig();
  config.defaultRemote = false;
  saveSMConfig(config);
  console.log(chalk.green("Remote mode disabled by default"));
});
configCmd.command("notify-done-on").description("Enable WhatsApp notification when session ends (default)").action(() => {
  const config = loadSMConfig();
  config.defaultNotifyOnDone = true;
  saveSMConfig(config);
  console.log(chalk.green("Notify-on-done enabled by default"));
});
configCmd.command("notify-done-off").description("Disable notification when session ends").action(() => {
  const config = loadSMConfig();
  config.defaultNotifyOnDone = false;
  saveSMConfig(config);
  console.log(chalk.green("Notify-on-done disabled by default"));
});
configCmd.command("whatsapp-on").description("Enable WhatsApp mode by default (auto-starts webhook + ngrok)").action(() => {
  const config = loadSMConfig();
  config.defaultWhatsApp = true;
  config.defaultNotifyOnDone = true;
  saveSMConfig(config);
  console.log(chalk.green("WhatsApp mode enabled by default"));
  console.log(chalk.gray("Sessions will auto-start webhook and ngrok"));
});
configCmd.command("whatsapp-off").description("Disable WhatsApp mode by default").action(() => {
  const config = loadSMConfig();
  config.defaultWhatsApp = false;
  saveSMConfig(config);
  console.log(chalk.green("WhatsApp mode disabled by default"));
});
configCmd.command("model-routing-on").description(
  "Enable model routing by default (route tasks to Qwen/other models)"
).action(() => {
  const config = loadSMConfig();
  config.defaultModelRouting = true;
  saveSMConfig(config);
  console.log(chalk.green("Model routing enabled by default"));
  console.log(chalk.gray("Configure with: stackmemory model setup-qwen"));
});
configCmd.command("model-routing-off").description("Disable model routing by default (use Claude only)").action(() => {
  const config = loadSMConfig();
  config.defaultModelRouting = false;
  saveSMConfig(config);
  console.log(chalk.green("Model routing disabled by default"));
});
configCmd.command("greptile-on").description(
  "Enable Greptile AI code review by default (requires GREPTILE_API_KEY)"
).action(() => {
  const config = loadSMConfig();
  config.defaultGreptile = true;
  saveSMConfig(config);
  console.log(chalk.green("Greptile enabled by default"));
  if (!process.env["GREPTILE_API_KEY"]) {
    console.log(chalk.gray("Set GREPTILE_API_KEY in .env to activate"));
  }
});
configCmd.command("greptile-off").description("Disable Greptile AI code review by default").action(() => {
  const config = loadSMConfig();
  config.defaultGreptile = false;
  saveSMConfig(config);
  console.log(chalk.green("Greptile disabled by default"));
});
configCmd.command("gepa-on").description("Enable GEPA auto-optimization of CLAUDE.md on changes").action(() => {
  const config = loadSMConfig();
  config.defaultGEPA = true;
  saveSMConfig(config);
  console.log(chalk.green("GEPA auto-optimization enabled by default"));
  console.log(
    chalk.gray("CLAUDE.md changes will trigger evolutionary optimization")
  );
});
configCmd.command("gepa-off").description("Disable GEPA auto-optimization").action(() => {
  const config = loadSMConfig();
  config.defaultGEPA = false;
  saveSMConfig(config);
  console.log(chalk.green("GEPA auto-optimization disabled by default"));
});
configCmd.command("setup").description("Interactive feature setup wizard").action(async () => {
  const inquirer = await import("inquirer");
  const ora = (await import("ora")).default;
  const config = loadSMConfig();
  console.log(chalk.cyan("\nClaude-SM Feature Setup\n"));
  const features = [
    {
      key: "defaultSweep",
      name: "Predictive Edit",
      desc: "AI-powered next-edit suggestions in real-time"
    },
    {
      key: "defaultGreptile",
      name: "Code Review",
      desc: "Automated code review with deep codebase intelligence"
    },
    {
      key: "defaultGEPA",
      name: "Prompt Forge",
      desc: "Evolutionary optimization of system prompts"
    },
    {
      key: "defaultModelRouting",
      name: "Model Switcher",
      desc: "Smart routing across Claude, Qwen, and other models"
    },
    {
      key: "defaultWorktree",
      name: "Safe Branch",
      desc: "Isolated git worktrees for conflict-free parallel work"
    },
    {
      key: "defaultWhatsApp",
      name: "Mobile Sync",
      desc: "Remote control and notifications via WhatsApp"
    },
    {
      key: "defaultTracing",
      name: "Session Insights",
      desc: "Deep execution tracing and performance analytics"
    },
    {
      key: "defaultNotifyOnDone",
      name: "Task Alert",
      desc: "Instant notification when sessions complete"
    }
  ];
  const choices = features.map((f) => ({
    name: `${f.name} - ${f.desc}`,
    value: f.key,
    checked: config[f.key]
  }));
  const { selected } = await inquirer.default.prompt([
    {
      type: "checkbox",
      name: "selected",
      message: "Select features to enable:",
      choices
    }
  ]);
  const selectedKeys = selected;
  for (const f of features) {
    config[f.key] = selectedKeys.includes(f.key);
  }
  saveSMConfig(config);
  if (config.defaultSweep) {
    let hasPty = false;
    try {
      await import("node-pty");
      hasPty = true;
    } catch {
    }
    if (!hasPty) {
      const spinner = ora("Installing node-pty...").start();
      try {
        execSync("npm install node-pty", {
          stdio: "ignore",
          cwd: process.cwd()
        });
        spinner.succeed("node-pty installed");
      } catch {
        spinner.fail("Failed to install node-pty");
        console.log(chalk.gray("  Install manually: npm install node-pty"));
      }
    }
  }
  if (config.defaultGreptile) {
    const apiKey = process.env["GREPTILE_API_KEY"];
    if (!apiKey) {
      const { key } = await inquirer.default.prompt([
        {
          type: "password",
          name: "key",
          message: "Enter your Greptile API key (from app.greptile.com):",
          mask: "*"
        }
      ]);
      if (key && key.trim()) {
        const envPath = path.join(process.cwd(), ".env");
        const line = `
GREPTILE_API_KEY=${key.trim()}
`;
        fs.appendFileSync(envPath, line);
        process.env["GREPTILE_API_KEY"] = key.trim();
        console.log(chalk.green("  API key saved to .env"));
      }
    }
    const currentKey = process.env["GREPTILE_API_KEY"];
    if (currentKey) {
      try {
        const result = execSync("claude mcp list 2>/dev/null", {
          encoding: "utf-8"
        });
        if (!result.includes("greptile")) {
          execSync(
            `claude mcp add --transport http greptile https://api.greptile.com/mcp --header "Authorization: Bearer ${currentKey}"`,
            { stdio: "ignore" }
          );
          console.log(chalk.green("  Greptile MCP server registered"));
        }
      } catch {
      }
    }
  }
  console.log(chalk.cyan("\nFeature summary:"));
  for (const f of features) {
    const on = config[f.key];
    const mark = on ? chalk.green("ON") : chalk.gray("OFF");
    console.log(`  ${mark}  ${f.name}`);
  }
  console.log(chalk.gray(`
Saved to ${getConfigPath()}`));
});
program.command("spawn <count>").description("Spawn N parallel Claude workers in tmux panes").option("-t, --task <desc>", "Task description for each worker").option("--worktree", "Create isolated git worktrees per worker").option("--no-sweep", "Disable Sweep predictions").option("--no-attach", "Do not attach to tmux session after creation").action(async (countStr, opts) => {
  const count = parseInt(countStr, 10);
  if (isNaN(count) || count < 1 || count > 8) {
    console.error(chalk.red("Worker count must be between 1 and 8"));
    process.exit(1);
  }
  if (!isTmuxAvailable()) {
    console.error(chalk.red("tmux is required for parallel workers."));
    console.log(chalk.gray("Install with: brew install tmux"));
    process.exit(1);
  }
  const sessionId = uuidv4().substring(0, 8);
  const sessionName = `claude-sm-${sessionId}`;
  console.log(
    chalk.blue(`Spawning ${count} workers in tmux session: ${sessionName}`)
  );
  createTmuxSession(sessionName, count);
  const workers = [];
  const panes = listPanes(sessionName);
  for (let i = 0; i < count; i++) {
    const workerId = `w${i}-${uuidv4().substring(0, 6)}`;
    const stateDir = ensureWorkerStateDir(workerId);
    const pane = panes[i] || String(i);
    const parts = ["claude-sm"];
    if (opts["sweep"] === false) parts.push("--no-sweep");
    if (opts["worktree"]) parts.push("--worktree");
    if (opts["task"]) parts.push("--task", `"${opts["task"]}"`);
    const cmd = parts.join(" ");
    sendToPane(
      sessionName,
      pane,
      `export SWEEP_INSTANCE_ID=${workerId} SWEEP_STATE_DIR=${stateDir} && ${cmd}`
    );
    workers.push({
      id: workerId,
      pane,
      cwd: process.cwd(),
      startedAt: (/* @__PURE__ */ new Date()).toISOString(),
      stateDir,
      task: opts["task"]
    });
    console.log(
      chalk.gray(
        `  Worker ${i}: ${workerId} (pane ${pane}, state: ${stateDir})`
      )
    );
  }
  const session = {
    sessionName,
    workers,
    createdAt: (/* @__PURE__ */ new Date()).toISOString()
  };
  saveRegistry(session);
  console.log(chalk.green(`
Registry saved (${workers.length} workers)`));
  if (opts["attach"] !== false) {
    console.log(chalk.gray("Attaching to tmux session..."));
    attachToSession(sessionName);
  } else {
    console.log(
      chalk.gray(`Attach later with: tmux attach -t ${sessionName}`)
    );
  }
});
const workersCmd = program.command("workers").description("List active workers (default) or manage them");
workersCmd.command("list", { isDefault: true }).description("List active workers").action(() => {
  const session = loadRegistry();
  if (!session) {
    console.log(chalk.gray("No active worker session."));
    return;
  }
  const alive = sessionExists(session.sessionName);
  const status = alive ? chalk.green("ACTIVE") : chalk.red("DEAD");
  console.log(chalk.blue(`Session: ${session.sessionName} [${status}]`));
  console.log(chalk.gray(`Created: ${session.createdAt}`));
  console.log();
  for (const w of session.workers) {
    const taskLabel = w.task ? ` task="${w.task}"` : "";
    console.log(`  ${chalk.cyan(w.id)} pane=${w.pane}${taskLabel}`);
    console.log(chalk.gray(`    state: ${w.stateDir}`));
  }
});
workersCmd.command("kill [id]").description("Kill entire session or send Ctrl-C to a specific worker").action((id) => {
  const session = loadRegistry();
  if (!session) {
    console.log(chalk.gray("No active worker session."));
    return;
  }
  if (id) {
    const worker = session.workers.find((w) => w.id === id);
    if (!worker) {
      console.error(chalk.red(`Worker ${id} not found.`));
      process.exit(1);
    }
    sendCtrlC(session.sessionName, worker.pane);
    console.log(
      chalk.yellow(`Sent Ctrl-C to worker ${id} (pane ${worker.pane})`)
    );
  } else {
    if (sessionExists(session.sessionName)) {
      killTmuxSession(session.sessionName);
      console.log(
        chalk.yellow(`Killed tmux session: ${session.sessionName}`)
      );
    }
    clearRegistry();
    console.log(chalk.gray("Registry cleared."));
  }
});
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(
  "--whatsapp",
  "Enable WhatsApp mode (auto-start webhook + ngrok + notifications)"
).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").option("--sweep", "Enable Sweep next-edit predictions (PTY wrapper)").option("--no-sweep", "Disable Sweep predictions").option("--greptile", "Enable Greptile AI code review (MCP server)").option("--no-greptile", "Disable Greptile integration").option("--gepa", "Enable GEPA auto-optimization of CLAUDE.md").option("--no-gepa", "Disable GEPA auto-optimization").helpOption("-h, --help", "Display help").allowUnknownOption(true).action(async (_options) => {
  const claudeSM = new ClaudeSM();
  const args = process.argv.slice(2);
  await claudeSM.run(args);
});
program.parse(process.argv);
//# sourceMappingURL=claude-sm.js.map
