// src/lib/claudeMdTemplate.ts
import {
  readdirSync,
  readFileSync,
  statSync
} from "node:fs";
import { createRequire } from "node:module";
import PATH from "node:path";
var require2 = createRequire(import.meta.url);
var packageRoot = PATH.dirname(require2.resolve("@xylabs/toolchain/package.json"));
var templatesDir = PATH.resolve(packageRoot, "templates", "claude");
function applyPackageManager(content, pm) {
  const xyCommand = pm === "npm" ? "npm exec -- xy" : pm === "bun" ? "bun run xy" : `${pm} xy`;
  const addCommand = pm === "npm" ? "npm install" : pm === "bun" ? "bun add" : `${pm} add`;
  return content.replaceAll("yarn xy", xyCommand).replaceAll("pnpm xy", xyCommand).replaceAll("yarn add", addCommand).replaceAll("pnpm add", addCommand);
}
var XYLABS_SKILLS_PREFIX = "xylabs-";
var claudeSkillTemplates = () => {
  const skillsDir = PATH.resolve(templatesDir, "skills");
  const dirs = readdirSync(skillsDir).filter(
    (f) => f.startsWith(XYLABS_SKILLS_PREFIX) && statSync(PATH.resolve(skillsDir, f)).isDirectory()
  );
  const result = {};
  for (const dir of dirs) {
    const dirPath = PATH.resolve(skillsDir, dir);
    const files = readdirSync(dirPath, { recursive: true, encoding: "utf8" });
    result[dir] = {};
    for (const file of files) {
      if (statSync(PATH.resolve(dirPath, file)).isFile()) {
        result[dir][file] = readFileSync(PATH.resolve(dirPath, file), "utf8");
      }
    }
  }
  return result;
};

// src/pm/workspaces.ts
import { existsSync, readFileSync as readFileSync2 } from "node:fs";
import PATH2 from "node:path";
import { globSync } from "glob";
function readJsonFile(path) {
  if (!existsSync(path)) return void 0;
  try {
    return JSON.parse(readFileSync2(path, "utf8"));
  } catch {
    return void 0;
  }
}
function readRootPackageJson(cwd = process.cwd()) {
  return readJsonFile(PATH2.resolve(cwd, "package.json"));
}
function detectPackageManagerFromPackageJson(cwd = process.cwd()) {
  const packageManager = readRootPackageJson(cwd)?.packageManager;
  if (!packageManager) return void 0;
  return packageManager.split("@")[0];
}

// src/pm/detectPackageManager.ts
import { existsSync as existsSync2 } from "node:fs";
var knownPackageManagers = /* @__PURE__ */ new Set(["bun", "npm", "pnpm", "yarn"]);
function detectPackageManager() {
  const packageManager = detectPackageManagerFromPackageJson();
  if (packageManager && knownPackageManagers.has(packageManager)) {
    return packageManager;
  }
  if (existsSync2("pnpm-lock.yaml") || existsSync2("pnpm-workspace.yaml")) return "pnpm";
  if (existsSync2("bun.lock") || existsSync2("bun.lockb")) return "bun";
  if (existsSync2("yarn.lock") || existsSync2(".yarnrc.yml")) return "yarn";
  if (existsSync2("package-lock.json") || existsSync2("npm-shrinkwrap.json")) return "npm";
  return "yarn";
}

// src/lib/initCwd.ts
function INIT_CWD() {
  return process.env.INIT_CWD ?? process.cwd();
}

// src/lib/reporting/runWithEnvelope.ts
import { performance as performance2 } from "node:perf_hooks";

// src/lib/reporting/xyReporter.ts
import { performance } from "node:perf_hooks";
var jsonMode = false;
var originalStdoutWrite;
var envelopeEmitted = false;
var currentCommand = "unknown";
var startTime = 0;
function isJsonMode() {
  return jsonMode;
}
function setCurrentCommand(name) {
  currentCommand = name;
  startTime = performance.now();
  envelopeEmitted = false;
}
function emitJson(envelope) {
  if (envelopeEmitted) return;
  envelopeEmitted = true;
  const json = JSON.stringify(envelope) + "\n";
  if (originalStdoutWrite) {
    originalStdoutWrite(json);
  } else {
    process.stdout.write(json);
  }
}

// src/lib/reporting/runWithEnvelope.ts
async function runWithEnvelope(command, action) {
  setCurrentCommand(command);
  const start = performance2.now();
  let exitCode;
  let envelope;
  try {
    const ret = await action();
    if (typeof ret === "number") {
      exitCode = ret;
    } else {
      exitCode = ret.exitCode;
      envelope = ret.envelope;
    }
  } catch (ex) {
    exitCode = 1;
    const message = ex instanceof Error ? ex.message : String(ex);
    envelope = {
      errorCount: 1,
      errors: [{ message }]
    };
    if (!isJsonMode()) {
      console.error(message);
    }
  }
  if (isJsonMode()) {
    emitJson({
      command,
      data: envelope?.data,
      durationMs: Math.round(performance2.now() - start),
      errorCount: envelope?.errorCount ?? (exitCode === 0 ? 0 : 1),
      errors: envelope?.errors,
      exitCode,
      schemaVersion: 1,
      success: exitCode === 0,
      warningCount: envelope?.warningCount ?? 0,
      warnings: envelope?.warnings
    });
  }
  return exitCode;
}
async function withEnvelope(command, action) {
  process.exitCode = await runWithEnvelope(command, action);
}

// src/actions/claude-skills.ts
import {
  existsSync as existsSync3,
  mkdirSync,
  readdirSync as readdirSync2,
  readFileSync as readFileSync3,
  rmSync,
  statSync as statSync2,
  writeFileSync
} from "node:fs";
import PATH3 from "node:path";
import chalk from "chalk";
var syncSkillFiles = (skillsDir) => {
  const pm = detectPackageManager();
  const rawTemplates = claudeSkillTemplates();
  const templateNames = new Set(Object.keys(rawTemplates));
  let updated = 0;
  let created = 0;
  for (const [skillName, files] of Object.entries(rawTemplates)) {
    const skillDir = PATH3.resolve(skillsDir, skillName);
    mkdirSync(skillDir, { recursive: true });
    for (const [filename, rawContent] of Object.entries(files)) {
      const content = applyPackageManager(rawContent, pm);
      const targetPath = PATH3.resolve(skillDir, filename);
      mkdirSync(PATH3.dirname(targetPath), { recursive: true });
      const existing = existsSync3(targetPath) ? readFileSync3(targetPath, "utf8") : void 0;
      if (existing === content) continue;
      writeFileSync(targetPath, content, "utf8");
      if (existing) {
        updated++;
      } else {
        created++;
      }
    }
  }
  return {
    created,
    templateNames,
    updated
  };
};
var removeStaleSkills = (skillsDir, templateNames) => {
  const existingSkills = readdirSync2(skillsDir).filter(
    (f) => f.startsWith(XYLABS_SKILLS_PREFIX) && statSync2(PATH3.resolve(skillsDir, f)).isDirectory()
  );
  let removed = 0;
  for (const dir of existingSkills) {
    if (!templateNames.has(dir)) {
      rmSync(PATH3.resolve(skillsDir, dir), { recursive: true });
      removed++;
    }
  }
  return removed;
};
var logSkillsResult = (created, updated, removed) => {
  if (created || updated || removed) {
    const parts = [
      created ? `${created} created` : "",
      updated ? `${updated} updated` : "",
      removed ? `${removed} removed` : ""
    ].filter(Boolean);
    console.log(chalk.green(`.claude/skills/${XYLABS_SKILLS_PREFIX}*/: ${parts.join(", ")}`));
  } else {
    console.log(chalk.gray(`.claude/skills/${XYLABS_SKILLS_PREFIX}*/: already up to date`));
  }
};
var claudeSkills = () => {
  const cwd = INIT_CWD();
  const skillsDir = PATH3.resolve(cwd, ".claude", "skills");
  mkdirSync(skillsDir, { recursive: true });
  const {
    created,
    templateNames,
    updated
  } = syncSkillFiles(skillsDir);
  const removed = removeStaleSkills(skillsDir, templateNames);
  logSkillsResult(created, updated, removed);
  return 0;
};

// src/xy/common/claude/skillsCommand.ts
var skillsCommand = {
  builder: (yargs) => yargs,
  command: "skills",
  describe: "Sync XY Labs standard Claude skills to .claude/skills/",
  handler: async (argv) => {
    if (argv.verbose) console.log("Claude Skills");
    await withEnvelope("claude skills", () => claudeSkills());
  }
};
export {
  skillsCommand
};
//# sourceMappingURL=skillsCommand.mjs.map
