import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
import { Command } from "commander";
import chalk from "chalk";
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
import { join } from "path";
import { homedir } from "os";
import { execSync } from "child_process";
const CLAUDE_DIR = join(homedir(), ".claude");
const CLAUDE_CONFIG_FILE = join(CLAUDE_DIR, "config.json");
const MCP_CONFIG_FILE = join(CLAUDE_DIR, "stackmemory-mcp.json");
const HOOKS_JSON = join(CLAUDE_DIR, "hooks.json");
function createSetupMCPCommand() {
  return new Command("setup-mcp").description("Auto-configure Claude Code MCP integration").option("--dry-run", "Show what would be configured without making changes").option("--reset", "Reset MCP configuration to defaults").action(async (options) => {
    console.log(chalk.cyan("\nStackMemory MCP Setup\n"));
    if (options.dryRun) {
      console.log(chalk.yellow("[DRY RUN] No changes will be made.\n"));
    }
    if (!existsSync(CLAUDE_DIR)) {
      if (options.dryRun) {
        console.log(chalk.gray(`Would create: ${CLAUDE_DIR}`));
      } else {
        mkdirSync(CLAUDE_DIR, { recursive: true });
        console.log(chalk.green("[OK]") + " Created ~/.claude directory");
      }
    }
    const mcpConfig = {
      mcpServers: {
        stackmemory: {
          command: "stackmemory",
          args: ["mcp-server"],
          env: {
            NODE_ENV: "production"
          }
        }
      }
    };
    if (options.dryRun) {
      console.log(
        chalk.gray(`Would write MCP config to: ${MCP_CONFIG_FILE}`)
      );
      console.log(chalk.gray(JSON.stringify(mcpConfig, null, 2)));
    } else {
      writeFileSync(MCP_CONFIG_FILE, JSON.stringify(mcpConfig, null, 2));
      console.log(chalk.green("[OK]") + " Created MCP server configuration");
    }
    let claudeConfig = {};
    if (existsSync(CLAUDE_CONFIG_FILE)) {
      try {
        claudeConfig = JSON.parse(readFileSync(CLAUDE_CONFIG_FILE, "utf8"));
      } catch {
        console.log(
          chalk.yellow("[WARN]") + " Could not parse existing config.json, creating new"
        );
      }
    }
    if (!claudeConfig.mcp) {
      claudeConfig.mcp = {};
    }
    const mcp = claudeConfig.mcp;
    if (!mcp.configFiles) {
      mcp.configFiles = [];
    }
    const configFiles = mcp.configFiles;
    if (!configFiles.includes(MCP_CONFIG_FILE)) {
      configFiles.push(MCP_CONFIG_FILE);
    }
    if (options.dryRun) {
      console.log(chalk.gray(`Would update: ${CLAUDE_CONFIG_FILE}`));
    } else {
      writeFileSync(
        CLAUDE_CONFIG_FILE,
        JSON.stringify(claudeConfig, null, 2)
      );
      console.log(chalk.green("[OK]") + " Updated Claude config.json");
    }
    console.log(chalk.cyan("\nValidating configuration..."));
    try {
      execSync("stackmemory --version", { stdio: "pipe" });
      console.log(chalk.green("[OK]") + " stackmemory CLI is installed");
    } catch {
      console.log(chalk.yellow("[WARN]") + " stackmemory CLI not in PATH");
      console.log(chalk.gray("  You may need to restart your terminal"));
    }
    try {
      execSync("claude --version", { stdio: "pipe" });
      console.log(chalk.green("[OK]") + " Claude Code is installed");
    } catch {
      console.log(chalk.yellow("[WARN]") + " Claude Code not found");
      console.log(chalk.gray("  Install from: https://claude.ai/code"));
    }
    if (!options.dryRun) {
      console.log(chalk.green("\nMCP setup complete!"));
      console.log(chalk.cyan("\nNext steps:"));
      console.log(chalk.white("  1. Restart Claude Code"));
      console.log(
        chalk.white(
          "  2. The StackMemory MCP tools will be available automatically"
        )
      );
      console.log(
        chalk.gray(
          '\nTo verify: Run "stackmemory doctor" to check all integrations'
        )
      );
    }
  });
}
function createDoctorCommand() {
  return new Command("doctor").description("Diagnose StackMemory configuration and common issues").option("--fix", "Attempt to automatically fix issues").action(async (options) => {
    console.log(chalk.cyan("\nStackMemory Doctor\n"));
    console.log(chalk.gray("Checking configuration and dependencies...\n"));
    const results = [];
    const projectDir = join(process.cwd(), ".stackmemory");
    const dbPath = join(projectDir, "context.db");
    if (existsSync(dbPath)) {
      results.push({
        name: "Project Initialization",
        status: "ok",
        message: "StackMemory is initialized in this project"
      });
    } else if (existsSync(projectDir)) {
      results.push({
        name: "Project Initialization",
        status: "warn",
        message: ".stackmemory directory exists but database not found",
        fix: "Run: stackmemory init"
      });
    } else {
      results.push({
        name: "Project Initialization",
        status: "error",
        message: "StackMemory not initialized in this project",
        fix: "Run: stackmemory init"
      });
    }
    if (existsSync(dbPath)) {
      try {
        const Database = (await import("better-sqlite3")).default;
        const db = new Database(dbPath, { readonly: true });
        const tables = db.prepare("SELECT name FROM sqlite_master WHERE type='table'").all();
        db.close();
        const hasFrames = tables.some((t) => t.name === "frames");
        if (hasFrames) {
          results.push({
            name: "Database Integrity",
            status: "ok",
            message: `Database has ${tables.length} tables`
          });
        } else {
          results.push({
            name: "Database Integrity",
            status: "warn",
            message: "Database exists but missing expected tables",
            fix: "Run: stackmemory init --interactive"
          });
        }
      } catch (error) {
        results.push({
          name: "Database Integrity",
          status: "error",
          message: `Database error: ${error.message}`,
          fix: "Remove .stackmemory/context.db and run: stackmemory init"
        });
      }
    }
    if (existsSync(MCP_CONFIG_FILE)) {
      try {
        const config = JSON.parse(readFileSync(MCP_CONFIG_FILE, "utf8"));
        if (config.mcpServers?.stackmemory) {
          results.push({
            name: "MCP Configuration",
            status: "ok",
            message: "MCP server configured"
          });
        } else {
          results.push({
            name: "MCP Configuration",
            status: "warn",
            message: "MCP config file exists but stackmemory server not configured",
            fix: "Run: stackmemory setup-mcp"
          });
        }
      } catch {
        results.push({
          name: "MCP Configuration",
          status: "error",
          message: "Invalid MCP configuration file",
          fix: "Run: stackmemory setup-mcp --reset"
        });
      }
    } else {
      results.push({
        name: "MCP Configuration",
        status: "warn",
        message: "MCP not configured for Claude Code",
        fix: "Run: stackmemory setup-mcp"
      });
    }
    if (existsSync(HOOKS_JSON)) {
      try {
        const hooks = JSON.parse(readFileSync(HOOKS_JSON, "utf8"));
        const hasTraceHook = !!hooks["tool-use-approval"];
        if (hasTraceHook) {
          results.push({
            name: "Claude Hooks",
            status: "ok",
            message: "Tool tracing hook installed"
          });
        } else {
          results.push({
            name: "Claude Hooks",
            status: "warn",
            message: "Hooks file exists but tracing not configured",
            fix: "Run: stackmemory hooks install"
          });
        }
      } catch {
        results.push({
          name: "Claude Hooks",
          status: "warn",
          message: "Could not read hooks.json"
        });
      }
    } else {
      results.push({
        name: "Claude Hooks",
        status: "warn",
        message: "Claude hooks not installed (optional)",
        fix: "Run: stackmemory hooks install"
      });
    }
    const envChecks = [
      { key: "LINEAR_API_KEY", name: "Linear API Key", optional: true },
      { key: "TWILIO_ACCOUNT_SID", name: "Twilio Account", optional: true }
    ];
    for (const check of envChecks) {
      const value = process.env[check.key];
      if (value) {
        results.push({
          name: check.name,
          status: "ok",
          message: "Environment variable set"
        });
      } else if (!check.optional) {
        results.push({
          name: check.name,
          status: "error",
          message: "Required environment variable not set",
          fix: `Set ${check.key} in your .env file`
        });
      }
    }
    const homeStackmemory = join(homedir(), ".stackmemory");
    if (existsSync(homeStackmemory)) {
      try {
        const testFile = join(homeStackmemory, ".write-test");
        writeFileSync(testFile, "test");
        const { unlinkSync } = await import("fs");
        unlinkSync(testFile);
        results.push({
          name: "File Permissions",
          status: "ok",
          message: "~/.stackmemory is writable"
        });
      } catch {
        results.push({
          name: "File Permissions",
          status: "error",
          message: "~/.stackmemory is not writable",
          fix: "Run: chmod 700 ~/.stackmemory"
        });
      }
    }
    let hasErrors = false;
    let hasWarnings = false;
    for (const result of results) {
      const icon = result.status === "ok" ? chalk.green("[OK]") : result.status === "warn" ? chalk.yellow("[WARN]") : chalk.red("[ERROR]");
      console.log(`${icon} ${result.name}`);
      console.log(chalk.gray(`    ${result.message}`));
      if (result.fix) {
        console.log(chalk.cyan(`    Fix: ${result.fix}`));
        if (options.fix && result.status !== "ok") {
          if (result.fix.includes("stackmemory setup-mcp")) {
            console.log(chalk.gray("    Attempting auto-fix..."));
            try {
              execSync("stackmemory setup-mcp", { stdio: "inherit" });
            } catch {
              console.log(chalk.red("    Auto-fix failed"));
            }
          }
        }
      }
      if (result.status === "error") hasErrors = true;
      if (result.status === "warn") hasWarnings = true;
    }
    console.log("");
    if (hasErrors) {
      console.log(
        chalk.red("Some issues need attention. Run suggested fixes above.")
      );
      process.exit(1);
    } else if (hasWarnings) {
      console.log(
        chalk.yellow(
          "StackMemory is working but some optional features are not configured."
        )
      );
    } else {
      console.log(
        chalk.green("All checks passed! StackMemory is properly configured.")
      );
    }
  });
}
function createSetupPluginsCommand() {
  const cmd = new Command("setup-plugins");
  cmd.description("Install StackMemory plugins for Claude Code").option("--force", "Overwrite existing plugins").action(async (options) => {
    console.log(
      chalk.cyan("Installing StackMemory plugins for Claude Code...\n")
    );
    const pluginsDir = join(CLAUDE_DIR, "plugins");
    if (!existsSync(pluginsDir)) {
      mkdirSync(pluginsDir, { recursive: true });
      console.log(chalk.gray(`Created: ${pluginsDir}`));
    }
    const possiblePaths = [
      join(process.cwd(), "plugins"),
      join(__dirname, "..", "..", "..", "plugins"),
      join(homedir(), ".stackmemory", "plugins")
    ];
    try {
      const globalRoot = execSync("npm root -g", {
        encoding: "utf-8"
      }).trim();
      possiblePaths.push(
        join(globalRoot, "@stackmemoryai", "stackmemory", "plugins")
      );
    } catch {
    }
    let sourcePluginsDir;
    for (const p of possiblePaths) {
      if (existsSync(p) && existsSync(join(p, "stackmemory"))) {
        sourcePluginsDir = p;
        break;
      }
    }
    if (!sourcePluginsDir) {
      console.log(chalk.red("Could not find StackMemory plugins directory"));
      console.log(chalk.gray("Searched:"));
      possiblePaths.forEach((p) => console.log(chalk.gray(`  - ${p}`)));
      process.exit(1);
    }
    console.log(chalk.gray(`Source: ${sourcePluginsDir}
`));
    const plugins = ["stackmemory", "ralph-wiggum"];
    let installed = 0;
    for (const plugin of plugins) {
      const sourcePath = join(sourcePluginsDir, plugin);
      const targetPath = join(pluginsDir, plugin);
      if (!existsSync(sourcePath)) {
        console.log(chalk.yellow(`  [SKIP] ${plugin} - not found in source`));
        continue;
      }
      if (existsSync(targetPath)) {
        if (options.force) {
          try {
            execSync(`rm -rf "${targetPath}"`, { encoding: "utf-8" });
          } catch {
            console.log(
              chalk.red(`  [ERROR] ${plugin} - could not remove existing`)
            );
            continue;
          }
        } else {
          console.log(
            chalk.gray(`  [EXISTS] ${plugin} - use --force to overwrite`)
          );
          continue;
        }
      }
      try {
        execSync(`ln -s "${sourcePath}" "${targetPath}"`, {
          encoding: "utf-8"
        });
        console.log(chalk.green(`  [OK] ${plugin}`));
        installed++;
      } catch (err) {
        console.log(
          chalk.red(`  [ERROR] ${plugin} - ${err.message}`)
        );
      }
    }
    console.log("");
    if (installed > 0) {
      console.log(chalk.green(`Installed ${installed} plugin(s)`));
      console.log(chalk.gray("\nAvailable commands in Claude Code:"));
      console.log(
        chalk.white("  /sm-status    ") + chalk.gray("Show StackMemory status")
      );
      console.log(
        chalk.white("  /sm-capture   ") + chalk.gray("Capture work for handoff")
      );
      console.log(
        chalk.white("  /sm-restore   ") + chalk.gray("Restore from last handoff")
      );
      console.log(
        chalk.white("  /sm-decision  ") + chalk.gray("Record a decision")
      );
      console.log(
        chalk.white("  /sm-help      ") + chalk.gray("Show all commands")
      );
      console.log(
        chalk.white("  /ralph-loop   ") + chalk.gray("Start Ralph iteration loop")
      );
    } else {
      console.log(chalk.yellow("No plugins installed"));
    }
  });
  return cmd;
}
function createSetupRemoteCommand() {
  const cmd = new Command("setup-remote");
  cmd.description("Configure remote MCP server to auto-start on boot").option("--port <number>", "Port for remote server", "3847").option("--project <path>", "Project root directory").option("--uninstall", "Remove the auto-start service").option("--status", "Check service status").action(async (options) => {
    const home = homedir();
    const platform = process.platform;
    const serviceName = platform === "darwin" ? "com.stackmemory.remote-mcp" : "stackmemory-remote-mcp";
    const serviceDir = platform === "darwin" ? join(home, "Library", "LaunchAgents") : join(home, ".config", "systemd", "user");
    const serviceFile = platform === "darwin" ? join(serviceDir, `${serviceName}.plist`) : join(serviceDir, `${serviceName}.service`);
    const logDir = join(home, ".stackmemory", "logs");
    const pidFile = join(home, ".stackmemory", "remote-mcp.pid");
    if (options.status) {
      console.log(chalk.cyan("\nRemote MCP Server Status\n"));
      if (platform === "darwin") {
        try {
          const result = execSync(
            `launchctl list | grep ${serviceName} || true`,
            { encoding: "utf-8" }
          );
          if (result.includes(serviceName)) {
            console.log(chalk.green("[RUNNING]") + " Service is active");
            try {
              const health = execSync(
                `curl -s http://localhost:${options.port}/health 2>/dev/null`,
                { encoding: "utf-8" }
              );
              const data = JSON.parse(health);
              console.log(chalk.gray(`  Project: ${data.projectId}`));
              console.log(
                chalk.gray(`  URL: http://localhost:${options.port}/sse`)
              );
            } catch {
              console.log(
                chalk.yellow("  Server not responding to health check")
              );
            }
          } else {
            console.log(chalk.yellow("[STOPPED]") + " Service not running");
          }
        } catch {
          console.log(chalk.yellow("[UNKNOWN]") + " Could not check status");
        }
      } else if (platform === "linux") {
        try {
          execSync(`systemctl --user is-active ${serviceName}`, {
            stdio: "pipe"
          });
          console.log(chalk.green("[RUNNING]") + " Service is active");
        } catch {
          console.log(chalk.yellow("[STOPPED]") + " Service not running");
        }
      }
      console.log(chalk.gray(`
Service file: ${serviceFile}`));
      console.log(chalk.gray(`Logs: ${logDir}/remote-mcp.log`));
      return;
    }
    if (options.uninstall) {
      console.log(chalk.cyan("\nUninstalling Remote MCP Server Service\n"));
      if (platform === "darwin") {
        try {
          execSync(`launchctl unload "${serviceFile}"`, { stdio: "pipe" });
          console.log(chalk.green("[OK]") + " Service unloaded");
        } catch {
          console.log(chalk.gray("[SKIP]") + " Service was not loaded");
        }
        if (existsSync(serviceFile)) {
          const fs = await import("fs/promises");
          await fs.unlink(serviceFile);
          console.log(chalk.green("[OK]") + " Service file removed");
        }
      } else if (platform === "linux") {
        try {
          execSync(`systemctl --user stop ${serviceName}`, { stdio: "pipe" });
          execSync(`systemctl --user disable ${serviceName}`, {
            stdio: "pipe"
          });
          console.log(chalk.green("[OK]") + " Service stopped and disabled");
        } catch {
          console.log(chalk.gray("[SKIP]") + " Service was not running");
        }
        if (existsSync(serviceFile)) {
          const fs = await import("fs/promises");
          await fs.unlink(serviceFile);
          execSync("systemctl --user daemon-reload", { stdio: "pipe" });
          console.log(chalk.green("[OK]") + " Service file removed");
        }
      }
      console.log(chalk.green("\nRemote MCP service uninstalled"));
      return;
    }
    console.log(chalk.cyan("\nSetting up Remote MCP Server Auto-Start\n"));
    if (platform !== "darwin" && platform !== "linux") {
      console.log(
        chalk.red("Auto-start is only supported on macOS and Linux")
      );
      console.log(chalk.gray("\nManual start: stackmemory mcp-remote"));
      return;
    }
    if (!existsSync(serviceDir)) {
      mkdirSync(serviceDir, { recursive: true });
    }
    if (!existsSync(logDir)) {
      mkdirSync(logDir, { recursive: true });
    }
    let nodePath;
    try {
      nodePath = execSync("which node", { encoding: "utf-8" }).trim();
    } catch {
      nodePath = "/usr/local/bin/node";
    }
    let stackmemoryPath;
    try {
      stackmemoryPath = execSync("which stackmemory", {
        encoding: "utf-8"
      }).trim();
    } catch {
      try {
        const npmRoot = execSync("npm root -g", { encoding: "utf-8" }).trim();
        stackmemoryPath = join(
          npmRoot,
          "@stackmemoryai",
          "stackmemory",
          "dist",
          "cli",
          "index.js"
        );
      } catch {
        stackmemoryPath = "npx stackmemory";
      }
    }
    const projectPath = options.project || home;
    const port = options.port || "3847";
    if (platform === "darwin") {
      const plist = `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>${serviceName}</string>

    <key>ProgramArguments</key>
    <array>
        <string>${stackmemoryPath.includes("npx") ? "npx" : nodePath}</string>
        ${stackmemoryPath.includes("npx") ? "<string>stackmemory</string>" : `<string>${stackmemoryPath}</string>`}
        <string>mcp-remote</string>
        <string>--port</string>
        <string>${port}</string>
        <string>--project</string>
        <string>${projectPath}</string>
    </array>

    <key>RunAtLoad</key>
    <true/>

    <key>KeepAlive</key>
    <dict>
        <key>SuccessfulExit</key>
        <false/>
    </dict>

    <key>WorkingDirectory</key>
    <string>${projectPath}</string>

    <key>StandardOutPath</key>
    <string>${logDir}/remote-mcp.log</string>

    <key>StandardErrorPath</key>
    <string>${logDir}/remote-mcp.error.log</string>

    <key>EnvironmentVariables</key>
    <dict>
        <key>HOME</key>
        <string>${home}</string>
        <key>PATH</key>
        <string>/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin</string>
        <key>NODE_ENV</key>
        <string>production</string>
    </dict>

    <key>ThrottleInterval</key>
    <integer>10</integer>
</dict>
</plist>`;
      writeFileSync(serviceFile, plist);
      console.log(chalk.green("[OK]") + " Created launchd service file");
      try {
        execSync(`launchctl unload "${serviceFile}" 2>/dev/null`, {
          stdio: "pipe"
        });
      } catch {
      }
      try {
        execSync(`launchctl load -w "${serviceFile}"`, { stdio: "pipe" });
        console.log(chalk.green("[OK]") + " Service loaded and started");
      } catch (err) {
        console.log(chalk.red("[ERROR]") + ` Failed to load service: ${err}`);
        return;
      }
    } else if (platform === "linux") {
      const service = `[Unit]
Description=StackMemory Remote MCP Server
Documentation=https://github.com/stackmemoryai/stackmemory
After=network.target

[Service]
Type=simple
ExecStart=${stackmemoryPath.includes("npx") ? "npx stackmemory" : `${nodePath} ${stackmemoryPath}`} mcp-remote --port ${port} --project ${projectPath}
Restart=on-failure
RestartSec=10
WorkingDirectory=${projectPath}

Environment=HOME=${home}
Environment=PATH=/usr/local/bin:/usr/bin:/bin
Environment=NODE_ENV=production

StandardOutput=append:${logDir}/remote-mcp.log
StandardError=append:${logDir}/remote-mcp.error.log

[Install]
WantedBy=default.target`;
      writeFileSync(serviceFile, service);
      console.log(chalk.green("[OK]") + " Created systemd service file");
      try {
        execSync("systemctl --user daemon-reload", { stdio: "pipe" });
        execSync(`systemctl --user enable ${serviceName}`, { stdio: "pipe" });
        execSync(`systemctl --user start ${serviceName}`, { stdio: "pipe" });
        console.log(chalk.green("[OK]") + " Service enabled and started");
      } catch (err) {
        console.log(
          chalk.red("[ERROR]") + ` Failed to start service: ${err}`
        );
        return;
      }
    }
    console.log(chalk.cyan("\nVerifying server...\n"));
    await new Promise((resolve) => setTimeout(resolve, 2e3));
    try {
      const health = execSync(
        `curl -s http://localhost:${port}/health 2>/dev/null`,
        { encoding: "utf-8" }
      );
      const data = JSON.parse(health);
      console.log(chalk.green("[OK]") + " Server is running");
      console.log(chalk.gray(`  Project: ${data.projectId}`));
    } catch {
      console.log(
        chalk.yellow("[WARN]") + " Server not responding yet (may still be starting)"
      );
    }
    console.log(
      chalk.green("\nRemote MCP Server configured for auto-start!")
    );
    console.log(chalk.cyan("\nConnection info:"));
    console.log(chalk.white(`  URL: http://localhost:${port}/sse`));
    console.log(chalk.white(`  Health: http://localhost:${port}/health`));
    console.log(chalk.gray(`
Logs: ${logDir}/remote-mcp.log`));
    console.log(chalk.gray(`Service: ${serviceFile}`));
    console.log(chalk.cyan("\nFor external access (ngrok):"));
    console.log(chalk.white(`  ngrok http ${port}`));
    console.log(chalk.gray("  Then use the ngrok URL + /sse in Claude.ai"));
  });
  return cmd;
}
function registerSetupCommands(program) {
  program.addCommand(createSetupMCPCommand());
  program.addCommand(createDoctorCommand());
  program.addCommand(createSetupPluginsCommand());
  program.addCommand(createSetupRemoteCommand());
}
export {
  createDoctorCommand,
  createSetupMCPCommand,
  createSetupPluginsCommand,
  createSetupRemoteCommand,
  registerSetupCommands
};
//# sourceMappingURL=setup.js.map
