@sunasteriskrnd/takumi 1.0.0-dev.30 → 1.0.0-dev.32

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 (2) hide show
  1. package/dist/index.js +661 -321
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -19815,7 +19815,7 @@ var package_default;
19815
19815
  var init_package = __esm(() => {
19816
19816
  package_default = {
19817
19817
  name: "@sunasteriskrnd/takumi",
19818
- version: "1.0.0-dev.30",
19818
+ version: "1.0.0-dev.32",
19819
19819
  description: "CLI tool for bootstrapping and managing Takumi projects",
19820
19820
  type: "module",
19821
19821
  repository: {
@@ -22283,6 +22283,7 @@ var init_commands = __esm(() => {
22283
22283
  fresh: exports_external.boolean().default(false),
22284
22284
  force: exports_external.boolean().default(false),
22285
22285
  installSkills: exports_external.boolean().default(false),
22286
+ installHooks: exports_external.boolean().default(false),
22286
22287
  withSudo: exports_external.boolean().default(false),
22287
22288
  prefix: exports_external.boolean().default(false),
22288
22289
  beta: exports_external.boolean().default(false),
@@ -50740,7 +50741,7 @@ __export(exports_monorepo_resolver, {
50740
50741
  resolveMonorepoRoot: () => resolveMonorepoRoot
50741
50742
  });
50742
50743
  import { existsSync as existsSync54, readFileSync as readFileSync22 } from "node:fs";
50743
- import { dirname as dirname32, join as join114, resolve as resolve26 } from "node:path";
50744
+ import { dirname as dirname33, join as join116, resolve as resolve26 } from "node:path";
50744
50745
  import { fileURLToPath as fileURLToPath3 } from "node:url";
50745
50746
  function parseMetadataAt(metadataPath) {
50746
50747
  if (!existsSync54(metadataPath))
@@ -50757,7 +50758,7 @@ function parseMetadataAt(metadataPath) {
50757
50758
  }
50758
50759
  }
50759
50760
  function readSourceDirFromPackageJson(candidateRoot) {
50760
- const packageJsonPath = join114(candidateRoot, "package.json");
50761
+ const packageJsonPath = join116(candidateRoot, "package.json");
50761
50762
  if (!existsSync54(packageJsonPath))
50762
50763
  return null;
50763
50764
  try {
@@ -50780,7 +50781,7 @@ function tryReadAtCandidate(candidateRoot) {
50780
50781
  };
50781
50782
  }
50782
50783
  const sourceDir = readSourceDirFromPackageJson(candidateRoot) ?? "claude";
50783
- const sourceRoot = join114(candidateRoot, sourceDir);
50784
+ const sourceRoot = join116(candidateRoot, sourceDir);
50784
50785
  const nestedMetadata = parseMetadataAt(getManifestPath(sourceRoot)) ?? parseMetadataAt(getLegacyManifestPath(sourceRoot));
50785
50786
  if (nestedMetadata) {
50786
50787
  return {
@@ -50798,7 +50799,7 @@ function walkUpForMetadata(startDir, maxDepth = 5) {
50798
50799
  const result = tryReadAtCandidate(current);
50799
50800
  if (result)
50800
50801
  return result;
50801
- const parent = dirname32(current);
50802
+ const parent = dirname33(current);
50802
50803
  if (parent === current)
50803
50804
  break;
50804
50805
  current = parent;
@@ -50808,13 +50809,13 @@ function walkUpForMetadata(startDir, maxDepth = 5) {
50808
50809
  function resolveMonorepoRoot() {
50809
50810
  try {
50810
50811
  const thisFile = fileURLToPath3(import.meta.url);
50811
- const thisDir = dirname32(thisFile);
50812
+ const thisDir = dirname33(thisFile);
50812
50813
  const result2 = walkUpForMetadata(thisDir);
50813
50814
  if (result2)
50814
50815
  return result2;
50815
50816
  } catch {}
50816
50817
  if (process.argv[1]) {
50817
- const binDir = dirname32(resolve26(process.argv[1]));
50818
+ const binDir = dirname33(resolve26(process.argv[1]));
50818
50819
  const result2 = walkUpForMetadata(binDir);
50819
50820
  if (result2)
50820
50821
  return result2;
@@ -54914,6 +54915,143 @@ function tryOpenBrowser(target) {
54914
54915
  // src/domains/sessions/server.ts
54915
54916
  import * as http from "node:http";
54916
54917
 
54918
+ // src/domains/sessions/analytics-source.ts
54919
+ import { readdirSync as readdirSync6 } from "node:fs";
54920
+ import { join as join77 } from "node:path";
54921
+
54922
+ // src/domains/sessions/analytics.ts
54923
+ var DAY_MS = 24 * 60 * 60 * 1000;
54924
+ var PER_DAY_MAX = 371;
54925
+ var LAST_N_DAYS = 30;
54926
+ var TOP_PROJECTS = 12;
54927
+ var num = (v2) => typeof v2 === "number" && Number.isFinite(v2) ? v2 : 0;
54928
+ function dayKey(ms) {
54929
+ return new Date(ms).toISOString().slice(0, 10);
54930
+ }
54931
+ function startedMs(startedAt) {
54932
+ if (typeof startedAt !== "string")
54933
+ return null;
54934
+ const ms = Date.parse(startedAt);
54935
+ return Number.isNaN(ms) ? null : ms;
54936
+ }
54937
+ function normalizeTokens(t) {
54938
+ const o2 = t ?? {};
54939
+ return {
54940
+ input: num(o2.input),
54941
+ output: num(o2.output),
54942
+ cacheRead: num(o2.cacheRead),
54943
+ cacheWrite: num(o2.cacheWrite)
54944
+ };
54945
+ }
54946
+ function aggregateTokens(agg) {
54947
+ return normalizeTokens(agg?.tokens);
54948
+ }
54949
+ var sumTokens = (t) => t.input + t.output + t.cacheRead + t.cacheWrite;
54950
+ function accumulateTokens(a3, b3) {
54951
+ a3.input += b3.input;
54952
+ a3.output += b3.output;
54953
+ a3.cacheRead += b3.cacheRead;
54954
+ a3.cacheWrite += b3.cacheWrite;
54955
+ }
54956
+ function buildLast30(byDay, now) {
54957
+ const out = [];
54958
+ const todayMs = Date.parse(`${dayKey(now)}T00:00:00.000Z`);
54959
+ for (let i = LAST_N_DAYS - 1;i >= 0; i -= 1) {
54960
+ const date = dayKey(todayMs - i * DAY_MS);
54961
+ out.push({ date, count: byDay.get(date) ?? 0 });
54962
+ }
54963
+ return out;
54964
+ }
54965
+ function foldAnalytics(aggregates, now) {
54966
+ const totals = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
54967
+ const eventsByDay = new Map;
54968
+ const tokensByDow = new Map;
54969
+ const tokensByProject = new Map;
54970
+ const tokensByModel = new Map;
54971
+ const tokensByDay = new Map;
54972
+ for (let d3 = 0;d3 < 7; d3 += 1)
54973
+ tokensByDow.set(d3, 0);
54974
+ let agentCount = 0;
54975
+ let toolCallCount = 0;
54976
+ let eventTotal = 0;
54977
+ let earliestMs = null;
54978
+ let latestMs = null;
54979
+ const oldestAllowedMs = Date.parse(`${dayKey(now - PER_DAY_MAX * DAY_MS)}T00:00:00.000Z`);
54980
+ for (const agg of aggregates) {
54981
+ const t = aggregateTokens(agg);
54982
+ totals.input += t.input;
54983
+ totals.output += t.output;
54984
+ totals.cacheRead += t.cacheRead;
54985
+ totals.cacheWrite += t.cacheWrite;
54986
+ agentCount += num(agg?.agentCount);
54987
+ toolCallCount += num(agg?.toolCallCount);
54988
+ const events = num(agg?.eventCount);
54989
+ eventTotal += events;
54990
+ const sessionTokens = sumTokens(t);
54991
+ const label = agg?.projectLabel || "(unknown)";
54992
+ tokensByProject.set(label, (tokensByProject.get(label) ?? 0) + sessionTokens);
54993
+ const perModel = agg?.tokensByModel;
54994
+ if (perModel && typeof perModel === "object") {
54995
+ for (const [model, mtok] of Object.entries(perModel)) {
54996
+ let acc = tokensByModel.get(model);
54997
+ if (!acc) {
54998
+ acc = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
54999
+ tokensByModel.set(model, acc);
55000
+ }
55001
+ accumulateTokens(acc, normalizeTokens(mtok));
55002
+ }
55003
+ }
55004
+ const ms = startedMs(agg?.startedAt);
55005
+ if (ms === null)
55006
+ continue;
55007
+ if (earliestMs === null || ms < earliestMs)
55008
+ earliestMs = ms;
55009
+ if (latestMs === null || ms > latestMs)
55010
+ latestMs = ms;
55011
+ const key = dayKey(ms);
55012
+ eventsByDay.set(key, (eventsByDay.get(key) ?? 0) + events);
55013
+ tokensByDay.set(key, (tokensByDay.get(key) ?? 0) + sessionTokens);
55014
+ const dow = new Date(ms).getUTCDay();
55015
+ tokensByDow.set(dow, (tokensByDow.get(dow) ?? 0) + sessionTokens);
55016
+ }
55017
+ const perDay = [...eventsByDay.entries()].filter(([date]) => Date.parse(`${date}T00:00:00.000Z`) >= oldestAllowedMs).map(([date, count]) => ({ date, count })).sort((a3, b3) => a3.date.localeCompare(b3.date));
55018
+ const byProjectAll = [...tokensByProject.entries()].map(([label, tokens]) => ({ label, tokens })).sort((a3, b3) => b3.tokens - a3.tokens || a3.label.localeCompare(b3.label));
55019
+ const byProject = byProjectAll.slice(0, TOP_PROJECTS);
55020
+ const daily = buildLast30(tokensByDay, now);
55021
+ const rankedModels = [...tokensByModel.entries()].map(([label, tokens]) => ({ label, tokens, total: sumTokens(tokens) })).filter((m2) => m2.total > 0).sort((a3, b3) => b3.total - a3.total || a3.label.localeCompare(b3.label)).slice(0, TOP_PROJECTS);
55022
+ const byModel = rankedModels.map(({ label, total }) => ({ label, tokens: total }));
55023
+ const byModelDetailed = rankedModels.map(({ label, tokens }) => ({ label, tokens }));
55024
+ const cacheDenom = totals.cacheRead + totals.input;
55025
+ const cacheHitRate = cacheDenom > 0 ? totals.cacheRead / cacheDenom : 0;
55026
+ return {
55027
+ schemaVersion: 1,
55028
+ generatedAt: new Date(now).toISOString(),
55029
+ sessionCount: aggregates.length,
55030
+ agentCount,
55031
+ toolCallCount,
55032
+ totals,
55033
+ cacheHitRate,
55034
+ events: {
55035
+ total: eventTotal,
55036
+ perDay,
55037
+ last30: buildLast30(eventsByDay, now)
55038
+ },
55039
+ tokens: {
55040
+ byType: { ...totals },
55041
+ byWeekday: [...tokensByDow.entries()].map(([dow, tokens]) => ({ dow, tokens })).sort((a3, b3) => a3.dow - b3.dow),
55042
+ byProject,
55043
+ daily,
55044
+ byModel,
55045
+ byModelDetailed
55046
+ },
55047
+ window: {
55048
+ earliest: earliestMs === null ? null : new Date(earliestMs).toISOString(),
55049
+ latest: latestMs === null ? null : new Date(latestMs).toISOString(),
55050
+ retentionLimited: earliestMs !== null && earliestMs >= now - PER_DAY_MAX * DAY_MS
55051
+ }
55052
+ };
55053
+ }
55054
+
54917
55055
  // src/domains/sessions/adapters/claude.ts
54918
55056
  import * as fs15 from "node:fs";
54919
55057
  import * as os4 from "node:os";
@@ -54936,6 +55074,18 @@ function safeJSON(line) {
54936
55074
  return null;
54937
55075
  }
54938
55076
  }
55077
+ function peekText(content) {
55078
+ if (typeof content === "string")
55079
+ return content;
55080
+ if (Array.isArray(content)) {
55081
+ return content.filter((it) => it && it.type === "text").map((it) => it.text || "").join(`
55082
+ `);
55083
+ }
55084
+ return "";
55085
+ }
55086
+ function isInterruptText(s) {
55087
+ return /^\s*\[Request interrupted\b/.test(String(s || ""));
55088
+ }
54939
55089
  function readNew(transcriptPath, fromOffset) {
54940
55090
  if (!transcriptPath || !fs14.existsSync(transcriptPath)) {
54941
55091
  return { records: [], newOffset: fromOffset || 0 };
@@ -55086,18 +55236,6 @@ function decodeProjectDir(name) {
55086
55236
  p = `/${p}`;
55087
55237
  return p.replace(/\/+/g, "/");
55088
55238
  }
55089
- function peekText(c2) {
55090
- if (typeof c2 === "string")
55091
- return c2;
55092
- if (Array.isArray(c2)) {
55093
- return c2.filter((it) => it && it.type === "text").map((it) => it.text || "").join(`
55094
- `);
55095
- }
55096
- return "";
55097
- }
55098
- function isInterruptText(s) {
55099
- return /^\s*\[Request interrupted\b/.test(String(s || ""));
55100
- }
55101
55239
  function stripCommandTags(s) {
55102
55240
  let out = String(s || "");
55103
55241
  for (const tag of HARNESS_TAGS) {
@@ -56171,6 +56309,189 @@ function invalidate() {
56171
56309
  }
56172
56310
  }
56173
56311
 
56312
+ // src/domains/sessions/transcript-metrics.ts
56313
+ import { basename as basename15, dirname as dirname20, join as join76 } from "node:path";
56314
+ function addModelTokens(byModel, model, t) {
56315
+ if (!model)
56316
+ return;
56317
+ byModel[model] = byModel[model] ? addTokens(byModel[model], t) : { ...t };
56318
+ }
56319
+ function toAggregate(session, m2) {
56320
+ return {
56321
+ startedAt: session.startedAt ?? null,
56322
+ tokens: {
56323
+ input: m2.tokens.input,
56324
+ output: m2.tokens.output,
56325
+ cacheRead: m2.tokens.cacheRead,
56326
+ cacheWrite: m2.tokens.cacheCreate
56327
+ },
56328
+ agentCount: m2.agentCount,
56329
+ toolCallCount: m2.toolCallCount,
56330
+ eventCount: m2.eventCount,
56331
+ projectLabel: session.project ?? "(unknown)",
56332
+ tokensByModel: Object.fromEntries(Object.entries(m2.tokensByModel).map(([model, t]) => [
56333
+ model,
56334
+ { input: t.input, output: t.output, cacheRead: t.cacheRead, cacheWrite: t.cacheCreate }
56335
+ ]))
56336
+ };
56337
+ }
56338
+ function zeroMetrics() {
56339
+ return {
56340
+ tokens: emptyTokens(),
56341
+ tokensByModel: {},
56342
+ agentCount: 0,
56343
+ toolCallCount: 0,
56344
+ eventCount: 0
56345
+ };
56346
+ }
56347
+ function isPromptUser2(r2) {
56348
+ if (!r2 || r2.type !== "user" || r2.isSidechain || r2.isMeta)
56349
+ return false;
56350
+ const c2 = r2.message?.content;
56351
+ if (isInterruptText(peekText(c2)))
56352
+ return false;
56353
+ if (typeof c2 === "string")
56354
+ return c2.length > 0;
56355
+ if (Array.isArray(c2)) {
56356
+ const arr = c2;
56357
+ if (arr.some((it) => it?.type === "tool_result"))
56358
+ return false;
56359
+ return arr.some((it) => it?.type === "text");
56360
+ }
56361
+ return false;
56362
+ }
56363
+ function scanClaudeMetrics(filePath, includeSidechain = false) {
56364
+ const m2 = zeroMetrics();
56365
+ try {
56366
+ const { records } = readNew(filePath, 0);
56367
+ for (const rec of records) {
56368
+ const r2 = rec;
56369
+ if (!r2)
56370
+ continue;
56371
+ const isAssistant = r2.type === "assistant" || r2.message?.role === "assistant";
56372
+ if (isAssistant && (includeSidechain || !r2.isSidechain)) {
56373
+ const tok = tokensOfClaude(rec);
56374
+ if (tok) {
56375
+ m2.tokens = addTokens(m2.tokens, tok);
56376
+ addModelTokens(m2.tokensByModel, r2.message?.model, tok);
56377
+ }
56378
+ const content = r2.message?.content;
56379
+ if (Array.isArray(content)) {
56380
+ for (const it of content) {
56381
+ const block = it;
56382
+ if (block?.type !== "tool_use")
56383
+ continue;
56384
+ m2.toolCallCount += 1;
56385
+ m2.eventCount += 1;
56386
+ if (block.name === "Task")
56387
+ m2.agentCount += 1;
56388
+ }
56389
+ }
56390
+ } else if (isPromptUser2(r2)) {
56391
+ m2.eventCount += 1;
56392
+ }
56393
+ }
56394
+ } catch {
56395
+ return zeroMetrics();
56396
+ }
56397
+ return m2;
56398
+ }
56399
+ function scanCodexMetrics(filePath) {
56400
+ const m2 = zeroMetrics();
56401
+ let currentModel;
56402
+ try {
56403
+ const { records } = readNew(filePath, 0);
56404
+ for (const rec of records) {
56405
+ const r2 = rec;
56406
+ if (!r2)
56407
+ continue;
56408
+ if (r2.type === "turn_context") {
56409
+ if (r2.payload?.model)
56410
+ currentModel = r2.payload.model;
56411
+ } else if (r2.type === "event_msg") {
56412
+ if (r2.payload?.type === "token_count") {
56413
+ const tok = tokensOfCodex(rec);
56414
+ if (tok) {
56415
+ m2.tokens = addTokens(m2.tokens, tok);
56416
+ addModelTokens(m2.tokensByModel, currentModel, tok);
56417
+ }
56418
+ } else if (r2.payload?.type === "user_message") {
56419
+ m2.eventCount += 1;
56420
+ }
56421
+ } else if (r2.type === "response_item" && r2.payload?.type === "function_call") {
56422
+ m2.toolCallCount += 1;
56423
+ m2.eventCount += 1;
56424
+ if (r2.payload?.name === "spawn_agent")
56425
+ m2.agentCount += 1;
56426
+ }
56427
+ }
56428
+ } catch {
56429
+ return zeroMetrics();
56430
+ }
56431
+ return m2;
56432
+ }
56433
+ function scanMetrics(adapterName, filePath) {
56434
+ return adapterName === "codex" ? scanCodexMetrics(filePath) : scanClaudeMetrics(filePath);
56435
+ }
56436
+ function mergeMetrics(a3, b3) {
56437
+ const tokensByModel = { ...a3.tokensByModel };
56438
+ for (const [model, tok] of Object.entries(b3.tokensByModel)) {
56439
+ tokensByModel[model] = tokensByModel[model] ? addTokens(tokensByModel[model], tok) : { ...tok };
56440
+ }
56441
+ return {
56442
+ tokens: addTokens(a3.tokens, b3.tokens),
56443
+ tokensByModel,
56444
+ agentCount: a3.agentCount + b3.agentCount,
56445
+ toolCallCount: a3.toolCallCount + b3.toolCallCount,
56446
+ eventCount: a3.eventCount + b3.eventCount
56447
+ };
56448
+ }
56449
+ function subagentDirFor(mainPath) {
56450
+ const stem = basename15(mainPath).replace(/\.jsonl$/i, "");
56451
+ return join76(dirname20(mainPath), stem, "subagents");
56452
+ }
56453
+
56454
+ // src/domains/sessions/analytics-source.ts
56455
+ var cache2 = null;
56456
+ function scanSessionMetrics(adapterName, mainPath) {
56457
+ const main2 = scanMetrics(adapterName, mainPath);
56458
+ if (adapterName === "codex")
56459
+ return main2;
56460
+ const dir = subagentDirFor(mainPath);
56461
+ let files;
56462
+ try {
56463
+ files = readdirSync6(dir).filter((f3) => f3.endsWith(".jsonl"));
56464
+ } catch {
56465
+ return main2;
56466
+ }
56467
+ let merged = main2;
56468
+ for (const f3 of files) {
56469
+ merged = mergeMetrics(merged, scanClaudeMetrics(join77(dir, f3), true));
56470
+ }
56471
+ return { ...merged, agentCount: main2.agentCount + files.length };
56472
+ }
56473
+ async function readAllAggregates(refresh2 = false) {
56474
+ if (refresh2)
56475
+ invalidate();
56476
+ const sessions = await list({ refresh: refresh2 });
56477
+ const aggregates = [];
56478
+ for (const s of sessions) {
56479
+ try {
56480
+ aggregates.push(toAggregate(s, scanSessionMetrics(s.adapterName, s.path)));
56481
+ } catch {}
56482
+ }
56483
+ return aggregates;
56484
+ }
56485
+ function invalidate2() {
56486
+ cache2 = null;
56487
+ }
56488
+ async function getAnalytics(opts = {}) {
56489
+ if (cache2 && !opts.refresh)
56490
+ return cache2;
56491
+ cache2 = foldAnalytics(await readAllAggregates(opts.refresh), Date.now());
56492
+ return cache2;
56493
+ }
56494
+
56174
56495
  // src/domains/sessions/origin-allowlist.ts
56175
56496
  init_build_config();
56176
56497
  function originOf(url) {
@@ -56253,6 +56574,14 @@ async function route(req, res, version3) {
56253
56574
  sendJSON(res, 200, list2);
56254
56575
  return;
56255
56576
  }
56577
+ if (pathname === "/api/analytics") {
56578
+ const refresh2 = url.searchParams.get("refresh") === "1";
56579
+ if (refresh2)
56580
+ invalidate2();
56581
+ const payload = await getAnalytics({ refresh: refresh2 });
56582
+ sendJSON(res, 200, payload);
56583
+ return;
56584
+ }
56256
56585
  const m2 = pathname.match(/^\/api\/sessions\/([^/]+)\/state$/);
56257
56586
  if (m2?.[1]) {
56258
56587
  const id = decodeURIComponent(m2[1]);
@@ -57502,7 +57831,7 @@ init_takumi_constants();
57502
57831
  import { existsSync as existsSync35, realpathSync } from "node:fs";
57503
57832
  import { chmod as chmod2, mkdir as mkdir18, readFile as readFile32, writeFile as writeFile22 } from "node:fs/promises";
57504
57833
  import { platform as platform5 } from "node:os";
57505
- import { join as join76 } from "node:path";
57834
+ import { join as join78 } from "node:path";
57506
57835
  var CACHE_FILE = "install-info.json";
57507
57836
  var CACHE_TTL = 30 * 24 * 60 * 60 * 1000;
57508
57837
  function detectFromBinaryPath() {
@@ -57586,7 +57915,7 @@ function detectFromEnv() {
57586
57915
  }
57587
57916
  async function readCachedPm() {
57588
57917
  try {
57589
- const cacheFile = join76(PathResolver.getConfigDir(false), CACHE_FILE);
57918
+ const cacheFile = join78(PathResolver.getConfigDir(false), CACHE_FILE);
57590
57919
  if (!existsSync35(cacheFile)) {
57591
57920
  return null;
57592
57921
  }
@@ -57617,7 +57946,7 @@ async function saveCachedPm(pm, getVersion) {
57617
57946
  return;
57618
57947
  try {
57619
57948
  const configDir = PathResolver.getConfigDir(false);
57620
- const cacheFile = join76(configDir, CACHE_FILE);
57949
+ const cacheFile = join78(configDir, CACHE_FILE);
57621
57950
  if (!existsSync35(configDir)) {
57622
57951
  await mkdir18(configDir, { recursive: true });
57623
57952
  if (platform5() !== "win32") {
@@ -57680,7 +58009,7 @@ async function findOwningPm() {
57680
58009
  async function clearCache() {
57681
58010
  try {
57682
58011
  const { unlink: unlink7 } = await import("node:fs/promises");
57683
- const cacheFile = join76(PathResolver.getConfigDir(false), CACHE_FILE);
58012
+ const cacheFile = join78(PathResolver.getConfigDir(false), CACHE_FILE);
57684
58013
  if (existsSync35(cacheFile)) {
57685
58014
  await unlink7(cacheFile);
57686
58015
  logger.debug("Package manager cache cleared");
@@ -57942,17 +58271,17 @@ async function checkCliVersion() {
57942
58271
  init_paths();
57943
58272
  init_registry();
57944
58273
  import { existsSync as existsSync36, statSync as statSync5 } from "node:fs";
57945
- import { join as join77 } from "node:path";
58274
+ import { join as join79 } from "node:path";
57946
58275
  function checkClaudeMd(setup, projectDir) {
57947
58276
  const results = [];
57948
58277
  const claudeCodeInstaller2 = getInstaller("claude-code");
57949
58278
  if (claudeCodeInstaller2?.isInstalledGlobally()) {
57950
58279
  const claudeGlobal = setup.globals.find((g2) => g2.provider === "claude-code") ?? setup.globals[0];
57951
58280
  const globalPath = claudeGlobal?.path ?? claudeCodeInstaller2.globalRoot();
57952
- const globalClaudeMd = join77(globalPath, "CLAUDE.md");
58281
+ const globalClaudeMd = join79(globalPath, "CLAUDE.md");
57953
58282
  results.push(checkClaudeMdFile(globalClaudeMd, "Global CLAUDE.md", "sk-global-claude-md"));
57954
58283
  }
57955
- const projectClaudeMd = join77(getLocalClaudeDir(projectDir), "CLAUDE.md");
58284
+ const projectClaudeMd = join79(getLocalClaudeDir(projectDir), "CLAUDE.md");
57956
58285
  results.push(checkClaudeMdFile(projectClaudeMd, "Project CLAUDE.md", "sk-project-claude-md"));
57957
58286
  return results;
57958
58287
  }
@@ -58011,9 +58340,9 @@ function checkClaudeMdFile(path9, name, id) {
58011
58340
  }
58012
58341
  // src/domains/health-checks/checkers/active-plan-checker.ts
58013
58342
  import { existsSync as existsSync37, readFileSync as readFileSync10 } from "node:fs";
58014
- import { join as join78 } from "node:path";
58343
+ import { join as join80 } from "node:path";
58015
58344
  function checkActivePlan(projectDir) {
58016
- const activePlanPath = join78(projectDir, ".claude", "active-plan");
58345
+ const activePlanPath = join80(projectDir, ".claude", "active-plan");
58017
58346
  if (!existsSync37(activePlanPath)) {
58018
58347
  return {
58019
58348
  id: "sk-active-plan",
@@ -58027,7 +58356,7 @@ function checkActivePlan(projectDir) {
58027
58356
  }
58028
58357
  try {
58029
58358
  const targetPath = readFileSync10(activePlanPath, "utf-8").trim();
58030
- const fullPath = join78(projectDir, targetPath);
58359
+ const fullPath = join80(projectDir, targetPath);
58031
58360
  if (!existsSync37(fullPath)) {
58032
58361
  return {
58033
58362
  id: "sk-active-plan",
@@ -58093,7 +58422,7 @@ function checkComponentCounts(setup) {
58093
58422
  init_registry();
58094
58423
  init_logger();
58095
58424
  import { constants, access, unlink as unlink7, writeFile as writeFile23 } from "node:fs/promises";
58096
- import { join as join79 } from "node:path";
58425
+ import { join as join81 } from "node:path";
58097
58426
 
58098
58427
  // src/domains/health-checks/checkers/shared.ts
58099
58428
  init_registry();
@@ -58168,7 +58497,7 @@ async function checkGlobalDirWritable(provider) {
58168
58497
  }
58169
58498
  const timestamp = Date.now();
58170
58499
  const random = Math.random().toString(36).substring(2);
58171
- const testFile = join79(globalDir, `.sk-write-test-${timestamp}-${random}`);
58500
+ const testFile = join81(globalDir, `.sk-write-test-${timestamp}-${random}`);
58172
58501
  try {
58173
58502
  await writeFile23(testFile, "test", { encoding: "utf-8", flag: "wx" });
58174
58503
  } catch (_error) {
@@ -58205,7 +58534,7 @@ init_paths();
58205
58534
  init_registry();
58206
58535
  import { existsSync as existsSync38 } from "node:fs";
58207
58536
  import { readdir as readdir23 } from "node:fs/promises";
58208
- import { join as join80 } from "node:path";
58537
+ import { join as join82 } from "node:path";
58209
58538
 
58210
58539
  // src/domains/health-checks/utils/path-normalizer.ts
58211
58540
  import { normalize as normalize6 } from "node:path";
@@ -58217,8 +58546,8 @@ function normalizePath(filePath) {
58217
58546
 
58218
58547
  // src/domains/health-checks/checkers/hooks-checker.ts
58219
58548
  async function checkHooksExist(projectDir) {
58220
- const globalHooksDir = join80(getInstaller("claude-code")?.globalRoot() ?? "", "hooks");
58221
- const projectHooksDir = join80(getLocalClaudeDir(projectDir), "hooks");
58549
+ const globalHooksDir = join82(getInstaller("claude-code")?.globalRoot() ?? "", "hooks");
58550
+ const projectHooksDir = join82(getLocalClaudeDir(projectDir), "hooks");
58222
58551
  const globalExists = existsSync38(globalHooksDir);
58223
58552
  const projectExists = existsSync38(projectHooksDir);
58224
58553
  let hookCount = 0;
@@ -58227,7 +58556,7 @@ async function checkHooksExist(projectDir) {
58227
58556
  const files = await readdir23(globalHooksDir, { withFileTypes: false });
58228
58557
  const hooks = files.filter((f3) => HOOK_EXTENSIONS2.some((ext2) => f3.endsWith(ext2)));
58229
58558
  hooks.forEach((hook) => {
58230
- const fullPath = join80(globalHooksDir, hook);
58559
+ const fullPath = join82(globalHooksDir, hook);
58231
58560
  checkedFiles.add(normalizePath(fullPath));
58232
58561
  });
58233
58562
  }
@@ -58237,7 +58566,7 @@ async function checkHooksExist(projectDir) {
58237
58566
  const files = await readdir23(projectHooksDir, { withFileTypes: false });
58238
58567
  const hooks = files.filter((f3) => HOOK_EXTENSIONS2.some((ext2) => f3.endsWith(ext2)));
58239
58568
  hooks.forEach((hook) => {
58240
- const fullPath = join80(projectHooksDir, hook);
58569
+ const fullPath = join82(projectHooksDir, hook);
58241
58570
  checkedFiles.add(normalizePath(fullPath));
58242
58571
  });
58243
58572
  }
@@ -58268,14 +58597,14 @@ async function checkHooksExist(projectDir) {
58268
58597
  init_registry();
58269
58598
  import { existsSync as existsSync39 } from "node:fs";
58270
58599
  import { readFile as readFile33 } from "node:fs/promises";
58271
- import { join as join81 } from "node:path";
58600
+ import { join as join83 } from "node:path";
58272
58601
  async function checkCodexHooksHealth() {
58273
58602
  const codex = getInstaller("codex");
58274
58603
  if (!codex?.isInstalledGlobally())
58275
58604
  return [];
58276
58605
  const codexRoot = codex.globalRoot();
58277
- const configTomlPath = join81(codexRoot, "config.toml");
58278
- const hooksJsonPath = join81(codexRoot, "hooks.json");
58606
+ const configTomlPath = join83(codexRoot, "config.toml");
58607
+ const hooksJsonPath = join83(codexRoot, "hooks.json");
58279
58608
  if (!existsSync39(hooksJsonPath))
58280
58609
  return [];
58281
58610
  const results = [];
@@ -58355,10 +58684,10 @@ init_registry();
58355
58684
  init_logger();
58356
58685
  import { existsSync as existsSync40 } from "node:fs";
58357
58686
  import { readFile as readFile34 } from "node:fs/promises";
58358
- import { join as join82 } from "node:path";
58687
+ import { join as join84 } from "node:path";
58359
58688
  async function checkSettingsValid(projectDir) {
58360
- const globalSettings = join82(getInstaller("claude-code")?.globalRoot() ?? "", "settings.json");
58361
- const projectSettings = join82(getLocalClaudeDir(projectDir), "settings.json");
58689
+ const globalSettings = join84(getInstaller("claude-code")?.globalRoot() ?? "", "settings.json");
58690
+ const projectSettings = join84(getLocalClaudeDir(projectDir), "settings.json");
58362
58691
  const settingsPath = existsSync40(globalSettings) ? globalSettings : existsSync40(projectSettings) ? projectSettings : null;
58363
58692
  if (!settingsPath) {
58364
58693
  return {
@@ -58432,10 +58761,10 @@ init_logger();
58432
58761
  import { existsSync as existsSync41 } from "node:fs";
58433
58762
  import { readFile as readFile35 } from "node:fs/promises";
58434
58763
  import { homedir as homedir24 } from "node:os";
58435
- import { dirname as dirname20, join as join83, normalize as normalize7, resolve as resolve19 } from "node:path";
58764
+ import { dirname as dirname21, join as join85, normalize as normalize7, resolve as resolve19 } from "node:path";
58436
58765
  async function checkPathRefsValid(projectDir) {
58437
- const globalClaudeMd = join83(getInstaller("claude-code")?.globalRoot() ?? "", "CLAUDE.md");
58438
- const projectClaudeMd = join83(getLocalClaudeDir(projectDir), "CLAUDE.md");
58766
+ const globalClaudeMd = join85(getInstaller("claude-code")?.globalRoot() ?? "", "CLAUDE.md");
58767
+ const projectClaudeMd = join85(getLocalClaudeDir(projectDir), "CLAUDE.md");
58439
58768
  const claudeMdPath = existsSync41(globalClaudeMd) ? globalClaudeMd : existsSync41(projectClaudeMd) ? projectClaudeMd : null;
58440
58769
  if (!claudeMdPath) {
58441
58770
  return {
@@ -58463,7 +58792,7 @@ async function checkPathRefsValid(projectDir) {
58463
58792
  autoFixable: false
58464
58793
  };
58465
58794
  }
58466
- const baseDir = dirname20(claudeMdPath);
58795
+ const baseDir = dirname21(claudeMdPath);
58467
58796
  const home6 = homedir24();
58468
58797
  const broken = [];
58469
58798
  for (const ref of refs) {
@@ -58531,7 +58860,7 @@ async function checkPathRefsValid(projectDir) {
58531
58860
  init_paths();
58532
58861
  import { existsSync as existsSync42 } from "node:fs";
58533
58862
  import { readdir as readdir24 } from "node:fs/promises";
58534
- import { join as join84 } from "node:path";
58863
+ import { join as join86 } from "node:path";
58535
58864
  async function checkProjectConfigCompleteness(setup, projectDir) {
58536
58865
  if (setup.globals.some((g2) => g2.path === setup.project.path)) {
58537
58866
  return {
@@ -58548,12 +58877,12 @@ async function checkProjectConfigCompleteness(setup, projectDir) {
58548
58877
  const requiredDirs = ["agents", "commands", "skills"];
58549
58878
  const missingDirs = [];
58550
58879
  for (const dir of requiredDirs) {
58551
- const dirPath = join84(projectClaudeDir, dir);
58880
+ const dirPath = join86(projectClaudeDir, dir);
58552
58881
  if (!existsSync42(dirPath)) {
58553
58882
  missingDirs.push(dir);
58554
58883
  }
58555
58884
  }
58556
- const hasRulesOrWorkflows = existsSync42(join84(projectClaudeDir, "rules")) || existsSync42(join84(projectClaudeDir, "workflows"));
58885
+ const hasRulesOrWorkflows = existsSync42(join86(projectClaudeDir, "rules")) || existsSync42(join86(projectClaudeDir, "workflows"));
58557
58886
  if (!hasRulesOrWorkflows) {
58558
58887
  missingDirs.push("rules");
58559
58888
  }
@@ -58994,7 +59323,7 @@ init_registry();
58994
59323
  init_environment();
58995
59324
  import { constants as constants2, access as access2, mkdir as mkdir19, readFile as readFile36, unlink as unlink8, writeFile as writeFile24 } from "node:fs/promises";
58996
59325
  import { arch as arch2, homedir as homedir25, platform as platform6 } from "node:os";
58997
- import { join as join86, normalize as normalize8 } from "node:path";
59326
+ import { join as join88, normalize as normalize8 } from "node:path";
58998
59327
  function shouldSkipExpensiveOperations4() {
58999
59328
  return shouldSkipExpensiveOperations();
59000
59329
  }
@@ -59087,7 +59416,7 @@ async function checkGlobalDirAccess(provider) {
59087
59416
  autoFixable: false
59088
59417
  };
59089
59418
  }
59090
- const testFile = join86(globalDir, ".sk-doctor-access-test");
59419
+ const testFile = join88(globalDir, ".sk-doctor-access-test");
59091
59420
  try {
59092
59421
  await mkdir19(globalDir, { recursive: true });
59093
59422
  await writeFile24(testFile, "test", "utf-8");
@@ -59165,7 +59494,7 @@ async function checkWSLBoundary() {
59165
59494
  // src/domains/health-checks/platform/windows-checker.ts
59166
59495
  init_registry();
59167
59496
  import { mkdir as mkdir20, symlink as symlink2, unlink as unlink9, writeFile as writeFile25 } from "node:fs/promises";
59168
- import { join as join87 } from "node:path";
59497
+ import { join as join89 } from "node:path";
59169
59498
  async function checkLongPathSupport() {
59170
59499
  if (shouldSkipExpensiveOperations4()) {
59171
59500
  return {
@@ -59217,8 +59546,8 @@ async function checkSymlinkSupport() {
59217
59546
  };
59218
59547
  }
59219
59548
  const testDir = getInstaller("claude-code")?.globalRoot() ?? "";
59220
- const target = join87(testDir, ".sk-symlink-test-target");
59221
- const link = join87(testDir, ".sk-symlink-test-link");
59549
+ const target = join89(testDir, ".sk-symlink-test-target");
59550
+ const link = join89(testDir, ".sk-symlink-test-link");
59222
59551
  try {
59223
59552
  await mkdir20(testDir, { recursive: true });
59224
59553
  await writeFile25(target, "test", "utf-8");
@@ -59514,15 +59843,15 @@ class AutoHealer {
59514
59843
  import { execSync as execSync4, spawnSync as spawnSync4 } from "node:child_process";
59515
59844
  import { readFileSync as readFileSync11, unlinkSync as unlinkSync4, writeFileSync as writeFileSync6 } from "node:fs";
59516
59845
  import { tmpdir as tmpdir2 } from "node:os";
59517
- import { dirname as dirname21, join as join88 } from "node:path";
59846
+ import { dirname as dirname22, join as join90 } from "node:path";
59518
59847
  import { fileURLToPath as fileURLToPath2 } from "node:url";
59519
59848
  init_environment();
59520
59849
  init_logger();
59521
59850
  init_dist2();
59522
59851
  function getCliVersion3() {
59523
59852
  try {
59524
- const __dirname3 = dirname21(fileURLToPath2(import.meta.url));
59525
- const pkgPath = join88(__dirname3, "../../../package.json");
59853
+ const __dirname3 = dirname22(fileURLToPath2(import.meta.url));
59854
+ const pkgPath = join90(__dirname3, "../../../package.json");
59526
59855
  const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
59527
59856
  return pkg.version || "unknown";
59528
59857
  } catch (err) {
@@ -59661,7 +59990,7 @@ class ReportGenerator {
59661
59990
  return null;
59662
59991
  }
59663
59992
  }
59664
- const tmpFile = join88(tmpdir2(), `sk-report-${Date.now()}.txt`);
59993
+ const tmpFile = join90(tmpdir2(), `sk-report-${Date.now()}.txt`);
59665
59994
  writeFileSync6(tmpFile, report);
59666
59995
  try {
59667
59996
  const result = spawnSync4("gh", ["gist", "create", tmpFile, "--desc", "Takumi Diagnostic Report"], {
@@ -59986,7 +60315,7 @@ import { execSync as execSync5 } from "node:child_process";
59986
60315
  // src/domains/hooks/handlers/_shared/env-file.ts
59987
60316
  import { randomUUID as randomUUID2 } from "node:crypto";
59988
60317
  import { renameSync as renameSync2, unlinkSync as unlinkSync5, writeFileSync as writeFileSync7 } from "node:fs";
59989
- import { basename as basename15, dirname as dirname22, join as join89 } from "node:path";
60318
+ import { basename as basename16, dirname as dirname23, join as join91 } from "node:path";
59990
60319
  function hexEscape(code) {
59991
60320
  return `\\x${code.toString(16).padStart(2, "0")}`;
59992
60321
  }
@@ -60038,8 +60367,8 @@ function renderEnvFile(entries) {
60038
60367
  }
60039
60368
  function writeEnvFile(filePath, entries) {
60040
60369
  const content = renderEnvFile(entries);
60041
- const dir = dirname22(filePath);
60042
- const tmpPath = join89(dir, `.${basename15(filePath)}.${randomUUID2()}.tmp`);
60370
+ const dir = dirname23(filePath);
60371
+ const tmpPath = join91(dir, `.${basename16(filePath)}.${randomUUID2()}.tmp`);
60043
60372
  try {
60044
60373
  writeFileSync7(tmpPath, content, { encoding: "utf8", mode: 384 });
60045
60374
  } catch (err) {
@@ -60087,10 +60416,10 @@ var defaultCommandRunner = (command, opts) => {
60087
60416
  // src/domains/hooks/handlers/convention-quality-gate/debounce.ts
60088
60417
  import { readFileSync as readFileSync12, writeFileSync as writeFileSync8 } from "node:fs";
60089
60418
  import { tmpdir as tmpdir3 } from "node:os";
60090
- import { join as join90 } from "node:path";
60419
+ import { join as join92 } from "node:path";
60091
60420
  function stateFilePath(sessionId) {
60092
60421
  const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 128) || "default";
60093
- return join90(tmpdir3(), `takumi-guardrail-${safe}.json`);
60422
+ return join92(tmpdir3(), `takumi-guardrail-${safe}.json`);
60094
60423
  }
60095
60424
  function isWithinDebounce(sessionId, debounceMs, now) {
60096
60425
  try {
@@ -60515,7 +60844,7 @@ function detectBroadGlob(pattern, pathHint) {
60515
60844
  // src/domains/hooks/handlers/guard-breadth-scout/check-ignore.ts
60516
60845
  var import_ignore3 = __toESM(require_ignore(), 1);
60517
60846
  import { existsSync as existsSync44, readFileSync as readFileSync13 } from "node:fs";
60518
- import { dirname as dirname23, join as join91 } from "node:path";
60847
+ import { dirname as dirname24, join as join93 } from "node:path";
60519
60848
  var BUILTIN_HEAVY_DIR_LINES = [
60520
60849
  "node_modules",
60521
60850
  ".pnp",
@@ -60552,9 +60881,9 @@ var BUILTIN_HEAVY_DIR_LINES = [
60552
60881
  function findGitRoot(startDir) {
60553
60882
  let dir = startDir;
60554
60883
  while (true) {
60555
- if (existsSync44(join91(dir, ".git")))
60884
+ if (existsSync44(join93(dir, ".git")))
60556
60885
  return dir;
60557
- const parent = dirname23(dir);
60886
+ const parent = dirname24(dir);
60558
60887
  if (parent === dir)
60559
60888
  return null;
60560
60889
  dir = parent;
@@ -60582,11 +60911,11 @@ function loadIgnoreConfig(cwd2) {
60582
60911
  const gitRoot = findGitRoot(cwd2);
60583
60912
  const candidatePaths = [];
60584
60913
  if (gitRoot) {
60585
- candidatePaths.push(join91(gitRoot, ".claude", ".tkmignore"));
60586
- candidatePaths.push(join91(gitRoot, ".claude", ".skignore"));
60914
+ candidatePaths.push(join93(gitRoot, ".claude", ".tkmignore"));
60915
+ candidatePaths.push(join93(gitRoot, ".claude", ".skignore"));
60587
60916
  }
60588
- candidatePaths.push(join91(cwd2, ".claude", ".tkmignore"));
60589
- candidatePaths.push(join91(cwd2, ".claude", ".skignore"));
60917
+ candidatePaths.push(join93(cwd2, ".claude", ".tkmignore"));
60918
+ candidatePaths.push(join93(cwd2, ".claude", ".skignore"));
60590
60919
  for (const candidate of candidatePaths) {
60591
60920
  const lines = readIgnoreFile(candidate);
60592
60921
  if (lines !== null) {
@@ -61050,10 +61379,10 @@ function getBasename(normalized) {
61050
61379
  function isSensitivePath(normalized) {
61051
61380
  if (!normalized)
61052
61381
  return false;
61053
- const basename16 = getBasename(normalized);
61054
- if (SAFE_LIST_RE.test(basename16))
61382
+ const basename17 = getBasename(normalized);
61383
+ if (SAFE_LIST_RE.test(basename17))
61055
61384
  return false;
61056
- return SENSITIVE_CATEGORY_PATTERNS.some((re2) => re2.test(basename16) || re2.test(normalized));
61385
+ return SENSITIVE_CATEGORY_PATTERNS.some((re2) => re2.test(basename17) || re2.test(normalized));
61057
61386
  }
61058
61387
  function normalizeForMatch(raw) {
61059
61388
  let value = raw;
@@ -61134,20 +61463,20 @@ function findFirstRelevantPath(candidates) {
61134
61463
  }
61135
61464
  return null;
61136
61465
  }
61137
- function buildApprovalPayload(file, basename16) {
61466
+ function buildApprovalPayload(file, basename17) {
61138
61467
  return {
61139
61468
  type: "SECRET_READ_REQUEST",
61140
61469
  file,
61141
- basename: basename16,
61470
+ basename: basename17,
61142
61471
  question: {
61143
61472
  header: "Secret-bearing file",
61144
- text: `"${basename16}" looks like it stores credentials or secrets. Should the agent be allowed to read it?`,
61473
+ text: `"${basename17}" looks like it stores credentials or secrets. Should the agent be allowed to read it?`,
61145
61474
  options: [
61146
61475
  {
61147
61476
  label: "Approve",
61148
- description: `Allow reading "${basename16}" once, then retry with that approval.`
61477
+ description: `Allow reading "${basename17}" once, then retry with that approval.`
61149
61478
  },
61150
- { label: "Decline", description: `Keep "${basename16}" blocked and do not read it.` }
61479
+ { label: "Decline", description: `Keep "${basename17}" blocked and do not read it.` }
61151
61480
  ]
61152
61481
  }
61153
61482
  };
@@ -61283,7 +61612,7 @@ function resolveEndpoint() {
61283
61612
  init_manifest_path_resolver();
61284
61613
  import { existsSync as existsSync45, readFileSync as readFileSync14 } from "node:fs";
61285
61614
  import { homedir as homedir26 } from "node:os";
61286
- import { dirname as dirname24, join as join92, resolve as resolve20 } from "node:path";
61615
+ import { dirname as dirname25, join as join94, resolve as resolve20 } from "node:path";
61287
61616
  var PROVIDER_DIRS = [".claude", ".codex"];
61288
61617
  var MAX_WALK = 6;
61289
61618
  function readManifestRaw(path11) {
@@ -61302,25 +61631,25 @@ function findManifest(cwd2) {
61302
61631
  let dir = resolve20(cwd2);
61303
61632
  for (let i = 0;i < MAX_WALK; i++) {
61304
61633
  for (const provider of PROVIDER_DIRS) {
61305
- const providerRoot = join92(dir, provider);
61634
+ const providerRoot = join94(dir, provider);
61306
61635
  if (existsSync45(providerRoot)) {
61307
61636
  const path11 = findManifestInProviderDir(providerRoot);
61308
61637
  if (path11)
61309
61638
  return path11;
61310
61639
  }
61311
61640
  }
61312
- const parent = dirname24(dir);
61641
+ const parent = dirname25(dir);
61313
61642
  if (parent === dir)
61314
61643
  break;
61315
61644
  dir = parent;
61316
61645
  }
61317
61646
  const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT;
61318
61647
  if (pluginRoot) {
61319
- const pluginPath = findManifestInProviderDir(join92(pluginRoot, ".claude"));
61648
+ const pluginPath = findManifestInProviderDir(join94(pluginRoot, ".claude"));
61320
61649
  if (pluginPath)
61321
61650
  return pluginPath;
61322
61651
  }
61323
- const globalPath = findManifestInProviderDir(join92(homedir26(), ".claude"));
61652
+ const globalPath = findManifestInProviderDir(join94(homedir26(), ".claude"));
61324
61653
  if (globalPath)
61325
61654
  return globalPath;
61326
61655
  return null;
@@ -61412,7 +61741,7 @@ async function readStdinJson() {
61412
61741
  // src/domains/hooks/telemetry/lib/detached-put.ts
61413
61742
  import { spawn as spawn2 } from "node:child_process";
61414
61743
  import { openSync as openSync4 } from "node:fs";
61415
- import { dirname as dirname25, join as join93 } from "node:path";
61744
+ import { dirname as dirname26, join as join95 } from "node:path";
61416
61745
  var ALLOWED_ENV_PREFIXES = ["TKM_", "TAKUMI_"];
61417
61746
  var ALLOWED_ENV_KEYS = new Set(["HOME", "USERPROFILE", "PATH", "NODE_ENV"]);
61418
61747
  var DETACH_DEBUG_LOG_NAME = "detach-debug.log";
@@ -61420,7 +61749,7 @@ function effectiveDetachMode(flags) {
61420
61749
  return flags.noDetach ? "inline" : "detached";
61421
61750
  }
61422
61751
  function sessionDebugLogPath(sessionDir) {
61423
- return join93(sessionDir, DETACH_DEBUG_LOG_NAME);
61752
+ return join95(sessionDir, DETACH_DEBUG_LOG_NAME);
61424
61753
  }
61425
61754
  var BUNFS_PREFIX = "/$bunfs/";
61426
61755
  function resolveInvocationPrefix() {
@@ -61448,9 +61777,9 @@ function resolveInvocationPrefix() {
61448
61777
  }
61449
61778
  function resolvePreloadScript(entryPath) {
61450
61779
  try {
61451
- const srcDir = dirname25(entryPath);
61452
- const repoRoot = dirname25(srcDir);
61453
- return join93(repoRoot, "scripts", "preload-config-override.ts");
61780
+ const srcDir = dirname26(entryPath);
61781
+ const repoRoot = dirname26(srcDir);
61782
+ return join95(repoRoot, "scripts", "preload-config-override.ts");
61454
61783
  } catch {
61455
61784
  return null;
61456
61785
  }
@@ -61522,13 +61851,13 @@ import { promises as fs20 } from "node:fs";
61522
61851
 
61523
61852
  // src/domains/hooks/telemetry/lib/session-paths.ts
61524
61853
  init_paths2();
61525
- import { join as join95 } from "node:path";
61854
+ import { join as join97 } from "node:path";
61526
61855
 
61527
61856
  // src/shared/project-paths.ts
61528
61857
  init_paths2();
61529
61858
  import { createHash as createHash9 } from "node:crypto";
61530
61859
  import { realpathSync as realpathSync2 } from "node:fs";
61531
- import { basename as basename16, join as join94 } from "node:path";
61860
+ import { basename as basename17, join as join96 } from "node:path";
61532
61861
  function encodeCwd(cwd2) {
61533
61862
  const stripped = cwd2.replace(/^\/+/, "");
61534
61863
  const sanitized = stripped.replace(/[^a-zA-Z0-9-]/g, "-");
@@ -61544,13 +61873,13 @@ function computeProjectHash(cwd2) {
61544
61873
  return createHash9("sha256").update(canonical).digest("hex").slice(0, 16);
61545
61874
  }
61546
61875
  function getProjectLabel(cwd2) {
61547
- return basename16(cwd2) || "";
61876
+ return basename17(cwd2) || "";
61548
61877
  }
61549
61878
  function getProjectsRoot() {
61550
- return join94(getConfigDir(), "projects");
61879
+ return join96(getConfigDir(), "projects");
61551
61880
  }
61552
61881
  function getProjectDir(args) {
61553
- return join94(getProjectsRoot(), encodeCwd(args.cwd), args.agent);
61882
+ return join96(getProjectsRoot(), encodeCwd(args.cwd), args.agent);
61554
61883
  }
61555
61884
 
61556
61885
  // src/domains/hooks/telemetry/lib/session-paths.ts
@@ -61562,35 +61891,35 @@ function safeSessionSegment(sessionId) {
61562
61891
  return cleaned.length > 0 ? cleaned.slice(0, MAX_SESSION_ID_LEN) : null;
61563
61892
  }
61564
61893
  function getSessionsRoot() {
61565
- return join95(getConfigDir(), "sessions");
61894
+ return join97(getConfigDir(), "sessions");
61566
61895
  }
61567
61896
  function getSessionDirV2(args) {
61568
61897
  const segment = safeSessionSegment(args.sessionId);
61569
61898
  if (!segment)
61570
61899
  return null;
61571
- return join95(getProjectDir({ agent: args.agent, cwd: args.cwd }), "sessions", segment);
61900
+ return join97(getProjectDir({ agent: args.agent, cwd: args.cwd }), "sessions", segment);
61572
61901
  }
61573
61902
  function getEventsFile(sessionDir) {
61574
- return join95(sessionDir, "events.jsonl");
61903
+ return join97(sessionDir, "events.jsonl");
61575
61904
  }
61576
61905
  function getSummaryFile(sessionDir) {
61577
- return join95(sessionDir, "summary.json");
61906
+ return join97(sessionDir, "summary.json");
61578
61907
  }
61579
61908
  function getLastPushFile(sessionDir) {
61580
- return join95(sessionDir, "last_push.txt");
61909
+ return join97(sessionDir, "last_push.txt");
61581
61910
  }
61582
61911
  var OBSERVATIONS_FILENAME = "observations.jsonl";
61583
61912
  function getObservationsFile(sessionDir) {
61584
- return join95(sessionDir, OBSERVATIONS_FILENAME);
61913
+ return join97(sessionDir, OBSERVATIONS_FILENAME);
61585
61914
  }
61586
61915
  function getObservationsFlushingFile(sessionDir) {
61587
- return join95(sessionDir, `${OBSERVATIONS_FILENAME}.flushing`);
61916
+ return join97(sessionDir, `${OBSERVATIONS_FILENAME}.flushing`);
61588
61917
  }
61589
61918
  function getObservationsPushedFile(sessionDir) {
61590
- return join95(sessionDir, "obs_pushed.txt");
61919
+ return join97(sessionDir, "obs_pushed.txt");
61591
61920
  }
61592
61921
  function getMetaFile(sessionDir) {
61593
- return join95(sessionDir, "meta.json");
61922
+ return join97(sessionDir, "meta.json");
61594
61923
  }
61595
61924
 
61596
61925
  // src/domains/hooks/telemetry/lib/session-meta.ts
@@ -61762,7 +62091,7 @@ async function shouldFlush(args) {
61762
62091
  }
61763
62092
 
61764
62093
  // src/domains/hooks/telemetry/lib/transcript-reader.ts
61765
- function num(v2) {
62094
+ function num2(v2) {
61766
62095
  return typeof v2 === "number" && Number.isFinite(v2) ? v2 : 0;
61767
62096
  }
61768
62097
  function zeroTokens2() {
@@ -61781,10 +62110,10 @@ function extractTokens(record) {
61781
62110
  if (!usage)
61782
62111
  return null;
61783
62112
  return {
61784
- input: num(usage.input_tokens),
61785
- output: num(usage.output_tokens),
61786
- cache_read: num(usage.cache_read_input_tokens),
61787
- cache_write: num(usage.cache_creation_input_tokens)
62113
+ input: num2(usage.input_tokens),
62114
+ output: num2(usage.output_tokens),
62115
+ cache_read: num2(usage.cache_read_input_tokens),
62116
+ cache_write: num2(usage.cache_creation_input_tokens)
61788
62117
  };
61789
62118
  }
61790
62119
  async function tailRead(args) {
@@ -61919,8 +62248,8 @@ async function runSessionEndFlush(data, ctx) {
61919
62248
  session_end_raw: data
61920
62249
  };
61921
62250
  const { promises: fs23 } = await import("node:fs");
61922
- const { join: join96 } = await import("node:path");
61923
- const target = join96(sessionDir, "meta.json");
62251
+ const { join: join98 } = await import("node:path");
62252
+ const target = join98(sessionDir, "meta.json");
61924
62253
  const tmp = `${target}.tmp`;
61925
62254
  await fs23.writeFile(tmp, JSON.stringify(updated), "utf8");
61926
62255
  await fs23.rename(tmp, target);
@@ -61995,17 +62324,17 @@ init_takumi_constants();
61995
62324
 
61996
62325
  // src/domains/hooks/lib/jsonl-append.ts
61997
62326
  import { promises as fs23, appendFileSync as appendFileSync2, mkdirSync as mkdirSync4 } from "node:fs";
61998
- import { dirname as dirname26 } from "node:path";
62327
+ import { dirname as dirname27 } from "node:path";
61999
62328
  async function appendJsonl(filePath, record) {
62000
62329
  try {
62001
- await fs23.mkdir(dirname26(filePath), { recursive: true });
62330
+ await fs23.mkdir(dirname27(filePath), { recursive: true });
62002
62331
  await fs23.appendFile(filePath, `${JSON.stringify(record)}
62003
62332
  `, "utf8");
62004
62333
  } catch {}
62005
62334
  }
62006
62335
  function appendJsonlLineSync(filePath, line) {
62007
62336
  try {
62008
- mkdirSync4(dirname26(filePath), { recursive: true });
62337
+ mkdirSync4(dirname27(filePath), { recursive: true });
62009
62338
  appendFileSync2(filePath, `${line}
62010
62339
  `, "utf8");
62011
62340
  } catch {}
@@ -62088,15 +62417,15 @@ function diagnoseStopFailure(status2, error) {
62088
62417
  return "server_error_check_takumi_web_logs";
62089
62418
  return null;
62090
62419
  }
62091
- function num2(v2) {
62420
+ function num3(v2) {
62092
62421
  return typeof v2 === "number" && Number.isFinite(v2) ? v2 : 0;
62093
62422
  }
62094
62423
  function usageToTokens(usage) {
62095
62424
  return {
62096
- input: num2(usage.input_tokens),
62097
- output: num2(usage.output_tokens),
62098
- cache_read: num2(usage.cache_read_tokens),
62099
- cache_write: num2(usage.cache_write_tokens)
62425
+ input: num3(usage.input_tokens),
62426
+ output: num3(usage.output_tokens),
62427
+ cache_read: num3(usage.cache_read_tokens),
62428
+ cache_write: num3(usage.cache_write_tokens)
62100
62429
  };
62101
62430
  }
62102
62431
  function readCliVersion2() {
@@ -62271,11 +62600,11 @@ async function handleStop(agent, flags = {}) {
62271
62600
  // src/domains/hooks/telemetry/otlp/observations-export.ts
62272
62601
  init_paths2();
62273
62602
  import { promises as fs27, openSync as openSync6 } from "node:fs";
62274
- import { join as join97 } from "node:path";
62603
+ import { join as join99 } from "node:path";
62275
62604
 
62276
62605
  // src/domains/hooks/telemetry/lib/retention.ts
62277
62606
  import { promises as fs24 } from "node:fs";
62278
- import { join as join96 } from "node:path";
62607
+ import { join as join98 } from "node:path";
62279
62608
  async function pathExists24(path11) {
62280
62609
  try {
62281
62610
  await fs24.access(path11);
@@ -62310,7 +62639,7 @@ async function decideDelete(dir, args) {
62310
62639
  async function listChildren(dir) {
62311
62640
  try {
62312
62641
  const names = await fs24.readdir(dir);
62313
- return names.map((n) => join96(dir, n));
62642
+ return names.map((n) => join98(dir, n));
62314
62643
  } catch {
62315
62644
  return [];
62316
62645
  }
@@ -62321,7 +62650,7 @@ async function collectV2Sessions() {
62321
62650
  const sessions = [];
62322
62651
  for (const projectDir of projects) {
62323
62652
  for (const agentDir of await listChildren(projectDir)) {
62324
- for (const sessionDir of await listChildren(join96(agentDir, "sessions"))) {
62653
+ for (const sessionDir of await listChildren(join98(agentDir, "sessions"))) {
62325
62654
  sessions.push(sessionDir);
62326
62655
  }
62327
62656
  }
@@ -62750,7 +63079,7 @@ async function exportSessionObservations(sessionDir, opts = {}, deps = {}) {
62750
63079
  }
62751
63080
  }
62752
63081
  function lockPath() {
62753
- return join97(getConfigDir(), "obs-flush.lock");
63082
+ return join99(getConfigDir(), "obs-flush.lock");
62754
63083
  }
62755
63084
  async function acquireSweepLock(now) {
62756
63085
  const path11 = lockPath();
@@ -63289,11 +63618,11 @@ var metricsRecord = {
63289
63618
 
63290
63619
  // src/domains/hooks/handlers/session-init/handler.ts
63291
63620
  import { mkdirSync as mkdirSync5 } from "node:fs";
63292
- import { dirname as dirname27, join as join101 } from "node:path";
63621
+ import { dirname as dirname28, join as join103 } from "node:path";
63293
63622
 
63294
63623
  // src/domains/hooks/handlers/_shared/project-detector.ts
63295
63624
  import { existsSync as existsSync46, readFileSync as readFileSync15 } from "node:fs";
63296
- import { join as join98 } from "node:path";
63625
+ import { join as join100 } from "node:path";
63297
63626
  var LOCKFILE_PRIORITY = [
63298
63627
  { manager: "bun", files: ["bun.lockb", "bun.lock"] },
63299
63628
  { manager: "pnpm", files: ["pnpm-lock.yaml"] },
@@ -63328,14 +63657,14 @@ var APP_FRAMEWORKS = new Set([
63328
63657
  var WORKSPACE_MARKER_FILES = ["pnpm-workspace.yaml", "turbo.json", "lerna.json"];
63329
63658
  function fileExists(cwd2, name) {
63330
63659
  try {
63331
- return existsSync46(join98(cwd2, name));
63660
+ return existsSync46(join100(cwd2, name));
63332
63661
  } catch {
63333
63662
  return false;
63334
63663
  }
63335
63664
  }
63336
63665
  function readPackageJson(cwd2) {
63337
63666
  try {
63338
- const raw = readFileSync15(join98(cwd2, "package.json"), "utf8");
63667
+ const raw = readFileSync15(join100(cwd2, "package.json"), "utf8");
63339
63668
  const parsed = JSON.parse(raw);
63340
63669
  if (parsed && typeof parsed === "object")
63341
63670
  return parsed;
@@ -63419,25 +63748,25 @@ function detectProject(cwd2) {
63419
63748
  // src/domains/hooks/handlers/session-init/env-entries.ts
63420
63749
  import { createHash as createHash11 } from "node:crypto";
63421
63750
  import { platform as platform8, userInfo } from "node:os";
63422
- import { join as join100 } from "node:path";
63751
+ import { join as join102 } from "node:path";
63423
63752
 
63424
63753
  // src/domains/hooks/handlers/session-init/plan-resolver.ts
63425
- import { existsSync as existsSync47, readFileSync as readFileSync16, readdirSync as readdirSync6 } from "node:fs";
63426
- import { join as join99 } from "node:path";
63754
+ import { existsSync as existsSync47, readFileSync as readFileSync16, readdirSync as readdirSync7 } from "node:fs";
63755
+ import { join as join101 } from "node:path";
63427
63756
  var MAX_PLAN_DIRS = 100;
63428
63757
  var MAX_PLAN_FILE_BYTES = 64 * 1024;
63429
63758
  function listPlanDirs(plansPath) {
63430
63759
  try {
63431
63760
  if (!existsSync47(plansPath))
63432
63761
  return [];
63433
- return readdirSync6(plansPath, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort().slice(0, MAX_PLAN_DIRS);
63762
+ return readdirSync7(plansPath, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort().slice(0, MAX_PLAN_DIRS);
63434
63763
  } catch {
63435
63764
  return [];
63436
63765
  }
63437
63766
  }
63438
63767
  function planFileMentionsSession(planDir, sessionId) {
63439
63768
  try {
63440
- const planFile = join99(planDir, "plan.md");
63769
+ const planFile = join101(planDir, "plan.md");
63441
63770
  if (!existsSync47(planFile))
63442
63771
  return false;
63443
63772
  const body = readFileSync16(planFile, { encoding: "utf8" });
@@ -63452,7 +63781,7 @@ function resolveActivePlan(plansPath, sessionId) {
63452
63781
  if (!sessionId)
63453
63782
  return "";
63454
63783
  for (const name of listPlanDirs(plansPath)) {
63455
- const dir = join99(plansPath, name);
63784
+ const dir = join101(plansPath, name);
63456
63785
  if (name.includes(sessionId) || planFileMentionsSession(dir, sessionId)) {
63457
63786
  return dir;
63458
63787
  }
@@ -63473,7 +63802,7 @@ function resolveSuggestedPlan(plansPath, branch, branchPattern) {
63473
63802
  return "";
63474
63803
  for (const name of listPlanDirs(plansPath)) {
63475
63804
  if (name.includes(slug))
63476
- return join99(plansPath, name);
63805
+ return join101(plansPath, name);
63477
63806
  }
63478
63807
  return "";
63479
63808
  }
@@ -63527,11 +63856,11 @@ function buildEnvEntries(params) {
63527
63856
  const plan = config.plan ?? {};
63528
63857
  const locale = config.locale ?? {};
63529
63858
  const validation = plan.validation ?? {};
63530
- const settingsDir = join100(projectRoot, ".claude");
63531
- const docsPath = join100(projectRoot, paths.docs ?? "docs");
63532
- const plansPath = join100(projectRoot, paths.plans ?? "plans");
63859
+ const settingsDir = join102(projectRoot, ".claude");
63860
+ const docsPath = join102(projectRoot, paths.docs ?? "docs");
63861
+ const plansPath = join102(projectRoot, paths.plans ?? "plans");
63533
63862
  const reportsDir = plan.reportsDir ?? "reports";
63534
- const reportsPath = join100(plansPath, reportsDir);
63863
+ const reportsPath = join102(plansPath, reportsDir);
63535
63864
  const namingFormat = plan.namingFormat ?? "";
63536
63865
  const activePlan = resolveActivePlan(plansPath, ctx.sessionId);
63537
63866
  const suggestedPlan = resolveSuggestedPlan(plansPath, branch, plan.resolution?.branchPattern ?? "");
@@ -63612,11 +63941,11 @@ function resolveEnvFilePath(settingsDir) {
63612
63941
  const override = process.env.CLAUDE_ENV_FILE;
63613
63942
  if (override && override.trim().length > 0)
63614
63943
  return override;
63615
- return join101(settingsDir, DEFAULT_ENV_FILE);
63944
+ return join103(settingsDir, DEFAULT_ENV_FILE);
63616
63945
  }
63617
63946
  function persistEntries(envFilePath, entries) {
63618
63947
  try {
63619
- mkdirSync5(dirname27(envFilePath), { recursive: true });
63948
+ mkdirSync5(dirname28(envFilePath), { recursive: true });
63620
63949
  writeEnvFile(envFilePath, entries);
63621
63950
  return true;
63622
63951
  } catch {
@@ -63669,7 +63998,7 @@ import { execFileSync as execFileSync3 } from "node:child_process";
63669
63998
  import { createHash as createHash12 } from "node:crypto";
63670
63999
  import { existsSync as existsSync48, mkdirSync as mkdirSync6, readFileSync as readFileSync17, rmSync as rmSync3, statSync as statSync6, writeFileSync as writeFileSync9 } from "node:fs";
63671
64000
  import { homedir as homedir27, platform as platform9, tmpdir as tmpdir4 } from "node:os";
63672
- import { basename as basename17, join as join102, resolve as resolve21 } from "node:path";
64001
+ import { basename as basename18, join as join104, resolve as resolve21 } from "node:path";
63673
64002
  var INJECTED_TTL_MS = 12 * 60 * 60 * 1000;
63674
64003
  var RESERVATION_TTL_MS = 60 * 1000;
63675
64004
  function gitBranch(dir) {
@@ -63742,16 +64071,16 @@ function buildPromptContext(args) {
63742
64071
  function scopeKey(baseDir) {
63743
64072
  const abs = resolve21(baseDir || ".");
63744
64073
  const hash = createHash12("sha256").update(abs).digest("hex").slice(0, 16);
63745
- const slug = basename17(abs).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 24) || "root";
64074
+ const slug = basename18(abs).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 24) || "root";
63746
64075
  return `${slug}-${hash}`;
63747
64076
  }
63748
64077
  function stateDir() {
63749
- return join102(tmpdir4(), "takumi-context-throttle");
64078
+ return join104(tmpdir4(), "takumi-context-throttle");
63750
64079
  }
63751
64080
  function stateFile(sessionId, scope, transcriptPath) {
63752
64081
  const key = `${sessionId}\x00${scope}\x00${transcriptPath ?? ""}`;
63753
64082
  const hash = createHash12("sha256").update(key).digest("hex").slice(0, 32);
63754
- return join102(stateDir(), `${hash}.json`);
64083
+ return join104(stateDir(), `${hash}.json`);
63755
64084
  }
63756
64085
  function readState(file) {
63757
64086
  try {
@@ -63820,8 +64149,8 @@ function clearPending(sessionId, scope, transcriptPath) {
63820
64149
  } catch {}
63821
64150
  }
63822
64151
  function resolveSkillsVenv(_cwd) {
63823
- const base = join102(homedir27(), ".claude", "skills", ".venv");
63824
- const interpreter = platform9() === "win32" ? join102(base, "Scripts", "python.exe") : join102(base, "bin", "python3");
64152
+ const base = join104(homedir27(), ".claude", "skills", ".venv");
64153
+ const interpreter = platform9() === "win32" ? join104(base, "Scripts", "python.exe") : join104(base, "bin", "python3");
63825
64154
  return existsSync48(interpreter) ? interpreter : null;
63826
64155
  }
63827
64156
 
@@ -63860,12 +64189,12 @@ var sessionPromptContext = {
63860
64189
  };
63861
64190
 
63862
64191
  // src/domains/hooks/handlers/session-subagent-init/context-block.ts
63863
- import { join as join104 } from "node:path";
64192
+ import { join as join106 } from "node:path";
63864
64193
 
63865
64194
  // src/domains/hooks/handlers/session-subagent-init/context-sources.ts
63866
64195
  import { execFileSync as execFileSync4 } from "node:child_process";
63867
- import { readdirSync as readdirSync7, statSync as statSync7 } from "node:fs";
63868
- import { isAbsolute as isAbsolute4, join as join103, resolve as resolve22 } from "node:path";
64196
+ import { readdirSync as readdirSync8, statSync as statSync7 } from "node:fs";
64197
+ import { isAbsolute as isAbsolute4, join as join105, resolve as resolve22 } from "node:path";
63869
64198
  var MAX_DOCS_FILES = 15;
63870
64199
  var MAX_DOCS_SUBDIRS = 5;
63871
64200
  function gitFacts(dir) {
@@ -63897,16 +64226,16 @@ function planDirTemplate(format, dateStr) {
63897
64226
  }
63898
64227
  function detectPlan(plansAbs) {
63899
64228
  try {
63900
- const entries = readdirSync7(plansAbs, { withFileTypes: true });
64229
+ const entries = readdirSync8(plansAbs, { withFileTypes: true });
63901
64230
  let best = null;
63902
64231
  for (const e2 of entries) {
63903
64232
  if (!e2.isDirectory())
63904
64233
  continue;
63905
- const dir = join103(plansAbs, e2.name);
64234
+ const dir = join105(plansAbs, e2.name);
63906
64235
  try {
63907
- if (!readdirSync7(dir).includes("plan.md"))
64236
+ if (!readdirSync8(dir).includes("plan.md"))
63908
64237
  continue;
63909
- const mtime = statSync7(join103(dir, "plan.md")).mtimeMs;
64238
+ const mtime = statSync7(join105(dir, "plan.md")).mtimeMs;
63910
64239
  if (!best || mtime > best.mtime)
63911
64240
  best = { name: e2.name, mtime };
63912
64241
  } catch {}
@@ -63918,7 +64247,7 @@ function detectPlan(plansAbs) {
63918
64247
  }
63919
64248
  function docsCatalogue(docsAbs) {
63920
64249
  try {
63921
- const entries = readdirSync7(docsAbs, { withFileTypes: true });
64250
+ const entries = readdirSync8(docsAbs, { withFileTypes: true });
63922
64251
  const files = entries.filter((e2) => e2.isFile() && e2.name.toLowerCase().endsWith(".md")).map((e2) => e2.name).sort();
63923
64252
  const subdirs = entries.filter((e2) => e2.isDirectory()).map((e2) => e2.name).sort();
63924
64253
  const lines = [];
@@ -63929,7 +64258,7 @@ function docsCatalogue(docsAbs) {
63929
64258
  for (const d3 of subdirs.slice(0, MAX_DOCS_SUBDIRS)) {
63930
64259
  let count = 0;
63931
64260
  try {
63932
- count = readdirSync7(join103(docsAbs, d3)).length;
64261
+ count = readdirSync8(join105(docsAbs, d3)).length;
63933
64262
  } catch {}
63934
64263
  lines.push(`- ${d3}/ (${count} entries)`);
63935
64264
  }
@@ -63973,11 +64302,11 @@ function buildSubagentContext(input, ctx) {
63973
64302
  const agentId = strField(input, "agent_id") || "unknown";
63974
64303
  const plansAbs = abs(base, cfg.paths?.plans?.trim() || "plans");
63975
64304
  const docsAbs = abs(base, cfg.paths?.docs?.trim() || "docs");
63976
- const reportsAbs = join104(plansAbs, cfg.plan?.reportsDir?.trim() || "reports");
64305
+ const reportsAbs = join106(plansAbs, cfg.plan?.reportsDir?.trim() || "reports");
63977
64306
  const dateStr = stamp(cfg.plan?.dateFormat?.trim() || "YYMMDD-HHmm", new Date);
63978
64307
  const namingFormat = cfg.plan?.namingFormat?.trim() || "{date}-{slug}";
63979
- const planDir = join104(plansAbs, planDirTemplate(namingFormat, dateStr));
63980
- const reportFile = join104(reportsAbs, `${agentKey}-${dateStr}-{slug}-report.md`);
64308
+ const planDir = join106(plansAbs, planDirTemplate(namingFormat, dateStr));
64309
+ const reportFile = join106(reportsAbs, `${agentKey}-${dateStr}-{slug}-report.md`);
63981
64310
  const activePlan = detectPlan(plansAbs);
63982
64311
  const venv = resolveSkillsVenv(effectiveCwd);
63983
64312
  const respLang = cfg.locale?.responseLanguage?.trim() || null;
@@ -64580,7 +64909,7 @@ init_hooks_settings_merger();
64580
64909
  // src/commands/portable/settings-write-with-confirm.ts
64581
64910
  init_safe_prompts();
64582
64911
  import { existsSync as existsSync49, mkdirSync as mkdirSync7, readFileSync as readFileSync18, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as writeFileSync10 } from "node:fs";
64583
- import { dirname as dirname28 } from "node:path";
64912
+ import { dirname as dirname29 } from "node:path";
64584
64913
 
64585
64914
  // node_modules/diff/libesm/diff/base.js
64586
64915
  class Diff {
@@ -65783,7 +66112,7 @@ function diffStats(diff) {
65783
66112
  return { additions, deletions };
65784
66113
  }
65785
66114
  function atomicWrite2(path11, contents, backupPath) {
65786
- mkdirSync7(dirname28(path11), { recursive: true });
66115
+ mkdirSync7(dirname29(path11), { recursive: true });
65787
66116
  const tmp = `${path11}.tmp`;
65788
66117
  try {
65789
66118
  writeFileSync10(tmp, contents);
@@ -65874,13 +66203,13 @@ import { existsSync as existsSync50 } from "node:fs";
65874
66203
  // src/commands/hooks/lib/settings-path-resolver.ts
65875
66204
  import { lstatSync as lstatSync3, realpathSync as realpathSync3 } from "node:fs";
65876
66205
  import { homedir as homedir28 } from "node:os";
65877
- import { join as join105 } from "node:path";
66206
+ import { join as join107 } from "node:path";
65878
66207
  function rawPath(agent, global3) {
65879
66208
  const root = global3 ? homedir28() : process.cwd();
65880
66209
  if (agent === "claude") {
65881
- return join105(root, ".claude", "settings.json");
66210
+ return join107(root, ".claude", "settings.json");
65882
66211
  }
65883
- return join105(root, ".codex", "hooks.json");
66212
+ return join107(root, ".codex", "hooks.json");
65884
66213
  }
65885
66214
  function resolveSettingsPath(agent, options2 = {}) {
65886
66215
  const originalPath = rawPath(agent, Boolean(options2.global));
@@ -66030,7 +66359,7 @@ function buildHookSection(agent, bin, flags = {}, handlers3 = HOOK_HANDLERS) {
66030
66359
  // src/commands/hooks/uninstall-handler.ts
66031
66360
  init_logger();
66032
66361
  import { existsSync as existsSync51, mkdirSync as mkdirSync8, readFileSync as readFileSync19, renameSync as renameSync4, rmSync as rmSync5, writeFileSync as writeFileSync11 } from "node:fs";
66033
- import { dirname as dirname29 } from "node:path";
66362
+ import { dirname as dirname30 } from "node:path";
66034
66363
  var AGENT_DISPLAY2 = {
66035
66364
  claude: "Claude Code",
66036
66365
  codex: "Codex"
@@ -66071,7 +66400,7 @@ function pruneHooksSection(hooks, agent) {
66071
66400
  return { pruned, removed };
66072
66401
  }
66073
66402
  function writeAtomic(path11, contents) {
66074
- mkdirSync8(dirname29(path11), { recursive: true });
66403
+ mkdirSync8(dirname30(path11), { recursive: true });
66075
66404
  const tmp = `${path11}.tmp`;
66076
66405
  try {
66077
66406
  writeFileSync11(tmp, contents);
@@ -66139,6 +66468,12 @@ var AGENT_DISPLAY3 = {
66139
66468
  claude: "Claude Code",
66140
66469
  codex: "Codex"
66141
66470
  };
66471
+ function selectHandlersForInstall(categories) {
66472
+ if (!categories)
66473
+ return HOOK_HANDLERS;
66474
+ const wanted = new Set(categories);
66475
+ return HOOK_HANDLERS.filter((h2) => wanted.has(h2.category));
66476
+ }
66142
66477
  function countEntries(section) {
66143
66478
  let count = 0;
66144
66479
  for (const groups of Object.values(section)) {
@@ -66155,7 +66490,7 @@ async function installForAgent(agent, options2, interactive, useStepUI) {
66155
66490
  const section = buildHookSection(agent, options2.bin, {
66156
66491
  noDetach: options2.noDetach,
66157
66492
  debug: options2.debug
66158
- });
66493
+ }, selectHandlersForInstall(options2.categories));
66159
66494
  const entriesPlanned = countEntries(section);
66160
66495
  const result = await writeSettingsWithConfirm({
66161
66496
  path: location2.realPath,
@@ -67573,7 +67908,7 @@ init_logger();
67573
67908
  init_takumi_constants();
67574
67909
  var import_fs_extra31 = __toESM(require_lib(), 1);
67575
67910
  var import_semver5 = __toESM(require_semver2(), 1);
67576
- import { join as join106 } from "node:path";
67911
+ import { join as join108 } from "node:path";
67577
67912
  function evaluateCliVersionGate(input) {
67578
67913
  const min = typeof input.minCliVersion === "string" ? input.minCliVersion.trim() : undefined;
67579
67914
  if (!min)
@@ -67594,7 +67929,7 @@ function evaluateCliVersionGate(input) {
67594
67929
  }
67595
67930
  async function readKitMinCliVersion(extractDir) {
67596
67931
  try {
67597
- const resolved = await findManifestPath(join106(extractDir, ".claude"));
67932
+ const resolved = await findManifestPath(join108(extractDir, ".claude"));
67598
67933
  if (!resolved)
67599
67934
  return;
67600
67935
  const raw = await import_fs_extra31.readFile(resolved.path, "utf-8");
@@ -67624,6 +67959,7 @@ function createInitContext(rawOptions, prompts) {
67624
67959
  exclude: [],
67625
67960
  only: [],
67626
67961
  installSkills: false,
67962
+ installHooks: false,
67627
67963
  withSudo: false,
67628
67964
  forceOverwrite: false,
67629
67965
  forceOverwriteSettings: false,
@@ -67785,7 +68121,7 @@ init_logger();
67785
68121
  init_safe_spinner();
67786
68122
  import { mkdir as mkdir25, stat as stat10 } from "node:fs/promises";
67787
68123
  import { tmpdir as tmpdir5 } from "node:os";
67788
- import { join as join112 } from "node:path";
68124
+ import { join as join114 } from "node:path";
67789
68125
 
67790
68126
  // src/shared/temp-cleanup.ts
67791
68127
  init_logger();
@@ -67804,7 +68140,7 @@ init_logger();
67804
68140
  init_output_manager();
67805
68141
  import { createWriteStream as createWriteStream2, rmSync as rmSync6 } from "node:fs";
67806
68142
  import { mkdir as mkdir21 } from "node:fs/promises";
67807
- import { join as join107 } from "node:path";
68143
+ import { join as join109 } from "node:path";
67808
68144
 
67809
68145
  // src/shared/progress-bar.ts
67810
68146
  init_output_manager();
@@ -68014,7 +68350,7 @@ var MAX_DOWNLOAD_SIZE = 500 * 1024 * 1024;
68014
68350
  class FileDownloader {
68015
68351
  async downloadAsset(asset, destDir) {
68016
68352
  try {
68017
- const destPath = join107(destDir, asset.name);
68353
+ const destPath = join109(destDir, asset.name);
68018
68354
  await mkdir21(destDir, { recursive: true });
68019
68355
  output.info(`Downloading ${asset.name} (${formatBytes(asset.size)})...`);
68020
68356
  logger.verbose("Download details", {
@@ -68099,7 +68435,7 @@ class FileDownloader {
68099
68435
  }
68100
68436
  async downloadFile(params) {
68101
68437
  const { url, name, size, destDir, token } = params;
68102
- const destPath = join107(destDir, name);
68438
+ const destPath = join109(destDir, name);
68103
68439
  await mkdir21(destDir, { recursive: true });
68104
68440
  output.info(`Downloading ${name}${size ? ` (${formatBytes(size)})` : ""}...`);
68105
68441
  const headers = {};
@@ -68202,7 +68538,7 @@ init_logger();
68202
68538
  init_types2();
68203
68539
  import { constants as constants3 } from "node:fs";
68204
68540
  import { access as access3, readdir as readdir25 } from "node:fs/promises";
68205
- import { join as join108 } from "node:path";
68541
+ import { join as join110 } from "node:path";
68206
68542
  async function validateExtraction(extractDir) {
68207
68543
  try {
68208
68544
  const entries = await readdir25(extractDir, { encoding: "utf8" });
@@ -68214,7 +68550,7 @@ async function validateExtraction(extractDir) {
68214
68550
  const missingPaths = [];
68215
68551
  for (const path11 of criticalPaths) {
68216
68552
  try {
68217
- await access3(join108(extractDir, path11), constants3.F_OK);
68553
+ await access3(join110(extractDir, path11), constants3.F_OK);
68218
68554
  logger.debug(`Found: ${path11}`);
68219
68555
  } catch {
68220
68556
  logger.warning(`Expected path not found: ${path11}`);
@@ -68236,7 +68572,7 @@ async function validateExtraction(extractDir) {
68236
68572
  // src/domains/installation/extraction/tar-extractor.ts
68237
68573
  init_logger();
68238
68574
  import { copyFile as copyFile5, mkdir as mkdir23, readdir as readdir27, rm as rm7, stat as stat8 } from "node:fs/promises";
68239
- import { join as join110 } from "node:path";
68575
+ import { join as join112 } from "node:path";
68240
68576
 
68241
68577
  // node_modules/tar/dist/esm/index.min.js
68242
68578
  import Kr from "events";
@@ -71449,7 +71785,7 @@ function decodeFilePath(path11) {
71449
71785
  init_logger();
71450
71786
  init_types2();
71451
71787
  import { copyFile as copyFile4, lstat as lstat6, mkdir as mkdir22, readdir as readdir26 } from "node:fs/promises";
71452
- import { join as join109, relative as relative16 } from "node:path";
71788
+ import { join as join111, relative as relative16 } from "node:path";
71453
71789
  async function withRetry2(fn2, retries = 3) {
71454
71790
  for (let i = 0;i < retries; i++) {
71455
71791
  try {
@@ -71471,8 +71807,8 @@ async function moveDirectoryContents(sourceDir, destDir, shouldExclude, sizeTrac
71471
71807
  await mkdir22(destDir, { recursive: true });
71472
71808
  const entries = await readdir26(sourceDir, { encoding: "utf8" });
71473
71809
  for (const entry of entries) {
71474
- const sourcePath = join109(sourceDir, entry);
71475
- const destPath = join109(destDir, entry);
71810
+ const sourcePath = join111(sourceDir, entry);
71811
+ const destPath = join111(destDir, entry);
71476
71812
  const relativePath = relative16(sourceDir, sourcePath);
71477
71813
  if (!isPathSafe(destDir, destPath)) {
71478
71814
  logger.warning(`Skipping unsafe path: ${relativePath}`);
@@ -71499,8 +71835,8 @@ async function copyDirectory(sourceDir, destDir, shouldExclude, sizeTracker) {
71499
71835
  await mkdir22(destDir, { recursive: true });
71500
71836
  const entries = await readdir26(sourceDir, { encoding: "utf8" });
71501
71837
  for (const entry of entries) {
71502
- const sourcePath = join109(sourceDir, entry);
71503
- const destPath = join109(destDir, entry);
71838
+ const sourcePath = join111(sourceDir, entry);
71839
+ const destPath = join111(destDir, entry);
71504
71840
  const relativePath = relative16(sourceDir, sourcePath);
71505
71841
  if (!isPathSafe(destDir, destPath)) {
71506
71842
  logger.warning(`Skipping unsafe path: ${relativePath}`);
@@ -71555,7 +71891,7 @@ class TarExtractor {
71555
71891
  logger.debug(`Root entries: ${entries.join(", ")}`);
71556
71892
  if (entries.length === 1) {
71557
71893
  const rootEntry = entries[0];
71558
- const rootPath = join110(tempExtractDir, rootEntry);
71894
+ const rootPath = join112(tempExtractDir, rootEntry);
71559
71895
  const rootStat = await stat8(rootPath);
71560
71896
  if (rootStat.isDirectory()) {
71561
71897
  const rootContents = await readdir27(rootPath, { encoding: "utf8" });
@@ -71571,7 +71907,7 @@ class TarExtractor {
71571
71907
  }
71572
71908
  } else {
71573
71909
  await mkdir23(destDir, { recursive: true });
71574
- await copyFile5(rootPath, join110(destDir, rootEntry));
71910
+ await copyFile5(rootPath, join112(destDir, rootEntry));
71575
71911
  }
71576
71912
  } else {
71577
71913
  logger.debug("Multiple root entries - moving all");
@@ -71592,7 +71928,7 @@ class TarExtractor {
71592
71928
  init_logger();
71593
71929
  import { createWriteStream as createWriteStream3 } from "node:fs";
71594
71930
  import { chmod as chmod3, copyFile as copyFile6, mkdir as mkdir24, readdir as readdir28, rm as rm8, stat as stat9 } from "node:fs/promises";
71595
- import { dirname as dirname30, join as join111, resolve as resolve24 } from "node:path";
71931
+ import { dirname as dirname31, join as join113, resolve as resolve24 } from "node:path";
71596
71932
  import { pipeline } from "node:stream/promises";
71597
71933
  import yauzl from "yauzl-promise";
71598
71934
  class ZipExtractor {
@@ -71606,7 +71942,7 @@ class ZipExtractor {
71606
71942
  logger.debug(`Root entries: ${entries.join(", ")}`);
71607
71943
  if (entries.length === 1) {
71608
71944
  const rootEntry = entries[0];
71609
- const rootPath = join111(tempExtractDir, rootEntry);
71945
+ const rootPath = join113(tempExtractDir, rootEntry);
71610
71946
  const rootStat = await stat9(rootPath);
71611
71947
  if (rootStat.isDirectory()) {
71612
71948
  const rootContents = await readdir28(rootPath, { encoding: "utf8" });
@@ -71622,7 +71958,7 @@ class ZipExtractor {
71622
71958
  }
71623
71959
  } else {
71624
71960
  await mkdir24(destDir, { recursive: true });
71625
- await copyFile6(rootPath, join111(destDir, rootEntry));
71961
+ await copyFile6(rootPath, join113(destDir, rootEntry));
71626
71962
  }
71627
71963
  } else {
71628
71964
  logger.debug("Multiple root entries - moving all");
@@ -71653,7 +71989,7 @@ class ZipExtractor {
71653
71989
  await mkdir24(outPath, { recursive: true });
71654
71990
  continue;
71655
71991
  }
71656
- await mkdir24(dirname30(outPath), { recursive: true });
71992
+ await mkdir24(dirname31(outPath), { recursive: true });
71657
71993
  const readStream = await entry.openReadStream();
71658
71994
  await pipeline(readStream, createWriteStream3(outPath));
71659
71995
  const unixMode = entry.externalFileAttributes >>> 16 & 511;
@@ -71751,7 +72087,7 @@ class DownloadManager {
71751
72087
  async createTempDir() {
71752
72088
  const timestamp = Date.now();
71753
72089
  const counter = DownloadManager.tempDirCounter++;
71754
- const primaryTempDir = join112(tmpdir5(), `takumi-${timestamp}-${counter}`);
72090
+ const primaryTempDir = join114(tmpdir5(), `takumi-${timestamp}-${counter}`);
71755
72091
  try {
71756
72092
  await mkdir25(primaryTempDir, { recursive: true });
71757
72093
  logger.debug(`Created temp directory: ${primaryTempDir}`);
@@ -71768,7 +72104,7 @@ Solutions:
71768
72104
  2. Set HOME environment variable
71769
72105
  3. Try running from a different directory`);
71770
72106
  }
71771
- const fallbackTempDir = join112(homeDir, ".sunagentkit", "tmp", `takumi-${timestamp}-${counter}`);
72107
+ const fallbackTempDir = join114(homeDir, ".sunagentkit", "tmp", `takumi-${timestamp}-${counter}`);
71772
72108
  try {
71773
72109
  await mkdir25(fallbackTempDir, { recursive: true });
71774
72110
  logger.debug(`Created temp directory (fallback): ${fallbackTempDir}`);
@@ -72341,6 +72677,7 @@ async function resolveOptions(ctx) {
72341
72677
  docsDir: parsed.docsDir,
72342
72678
  plansDir: parsed.plansDir,
72343
72679
  installSkills: parsed.installSkills ?? false,
72680
+ installHooks: parsed.installHooks ?? false,
72344
72681
  withSudo: parsed.withSudo ?? false,
72345
72682
  forceOverwrite: parsed.forceOverwrite ?? false,
72346
72683
  forceOverwriteSettings: parsed.forceOverwriteSettings ?? false,
@@ -72474,7 +72811,7 @@ Re-run with explicit base kit, e.g. --kit ${BASE_KIT} --kit ${parsed2.join(" --k
72474
72811
  }
72475
72812
  // src/commands/init/phases/selection-handler.ts
72476
72813
  import { mkdir as mkdir26 } from "node:fs/promises";
72477
- import { join as join116, resolve as resolve28 } from "node:path";
72814
+ import { join as join118, resolve as resolve28 } from "node:path";
72478
72815
 
72479
72816
  // src/commands/shared/agent-selector.ts
72480
72817
  init_registry();
@@ -72627,8 +72964,8 @@ init_logger();
72627
72964
  init_safe_spinner();
72628
72965
  init_takumi_constants();
72629
72966
  var import_fs_extra32 = __toESM(require_lib(), 1);
72630
- import { existsSync as existsSync55, readdirSync as readdirSync8, rmSync as rmSync7, rmdirSync as rmdirSync2, unlinkSync as unlinkSync6 } from "node:fs";
72631
- import { dirname as dirname33, join as join115, resolve as resolve27 } from "node:path";
72967
+ import { existsSync as existsSync55, readdirSync as readdirSync9, rmSync as rmSync7, rmdirSync as rmdirSync2, unlinkSync as unlinkSync6 } from "node:fs";
72968
+ import { dirname as dirname34, join as join117, resolve as resolve27 } from "node:path";
72632
72969
  var TAKUMI_SUBDIRECTORIES = ["commands", "agents", "skills", "rules", "hooks"];
72633
72970
  async function analyzeFreshInstallation(claudeDir) {
72634
72971
  const metadata = await readManifest(claudeDir);
@@ -72674,14 +73011,14 @@ async function analyzeFreshInstallation(claudeDir) {
72674
73011
  }
72675
73012
  function cleanupEmptyDirectories2(filePath, claudeDir) {
72676
73013
  const normalizedClaudeDir = resolve27(claudeDir);
72677
- let currentDir = resolve27(dirname33(filePath));
73014
+ let currentDir = resolve27(dirname34(filePath));
72678
73015
  while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir)) {
72679
73016
  try {
72680
- const entries = readdirSync8(currentDir);
73017
+ const entries = readdirSync9(currentDir);
72681
73018
  if (entries.length === 0) {
72682
73019
  rmdirSync2(currentDir);
72683
73020
  logger.debug(`Removed empty directory: ${currentDir}`);
72684
- currentDir = resolve27(dirname33(currentDir));
73021
+ currentDir = resolve27(dirname34(currentDir));
72685
73022
  } else {
72686
73023
  break;
72687
73024
  }
@@ -72698,7 +73035,7 @@ async function removeFilesByOwnership(claudeDir, analysis, includeModified) {
72698
73035
  const filesToRemove = includeModified ? [...analysis.ckFiles, ...analysis.ckModifiedFiles] : analysis.ckFiles;
72699
73036
  const filesToPreserve = includeModified ? analysis.userFiles : [...analysis.ckModifiedFiles, ...analysis.userFiles];
72700
73037
  for (const file of filesToRemove) {
72701
- const fullPath = join115(claudeDir, file.path);
73038
+ const fullPath = join117(claudeDir, file.path);
72702
73039
  try {
72703
73040
  if (existsSync55(fullPath)) {
72704
73041
  unlinkSync6(fullPath);
@@ -72772,7 +73109,7 @@ async function removeSubdirectoriesFallback(claudeDir) {
72772
73109
  const removedFiles = [];
72773
73110
  let removedDirCount = 0;
72774
73111
  for (const subdir of TAKUMI_SUBDIRECTORIES) {
72775
- const subdirPath = join115(claudeDir, subdir);
73112
+ const subdirPath = join117(claudeDir, subdir);
72776
73113
  if (await import_fs_extra32.pathExists(subdirPath)) {
72777
73114
  rmSync7(subdirPath, { recursive: true, force: true });
72778
73115
  removedDirCount++;
@@ -72997,7 +73334,7 @@ async function handleSelection(ctx) {
72997
73334
  }
72998
73335
  if (!ctx.options.fresh) {
72999
73336
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
73000
- const claudeDir = prefix ? join116(resolvedDir, prefix) : resolvedDir;
73337
+ const claudeDir = prefix ? join118(resolvedDir, prefix) : resolvedDir;
73001
73338
  try {
73002
73339
  const existingMetadata = await readManifest(claudeDir);
73003
73340
  if (existingMetadata?.kits) {
@@ -73030,7 +73367,7 @@ async function handleSelection(ctx) {
73030
73367
  }
73031
73368
  if (ctx.options.fresh) {
73032
73369
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
73033
- const claudeDir = prefix ? join116(resolvedDir, prefix) : resolvedDir;
73370
+ const claudeDir = prefix ? join118(resolvedDir, prefix) : resolvedDir;
73034
73371
  const canProceed = await handleFreshInstallation(claudeDir, ctx.prompts);
73035
73372
  if (!canProceed) {
73036
73373
  return { ...ctx, cancelled: true };
@@ -73050,7 +73387,7 @@ async function handleSelection(ctx) {
73050
73387
  let currentVersion = null;
73051
73388
  try {
73052
73389
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
73053
- const claudeDir = prefix ? join116(resolvedDir, prefix) : resolvedDir;
73390
+ const claudeDir = prefix ? join118(resolvedDir, prefix) : resolvedDir;
73054
73391
  const existingMetadata = await readManifest(claudeDir);
73055
73392
  currentVersion = existingMetadata?.kits?.[kitType]?.version || null;
73056
73393
  if (currentVersion) {
@@ -73138,7 +73475,7 @@ async function handleSelection(ctx) {
73138
73475
  if (ctx.options.yes && !ctx.options.fresh && !ctx.options.force && releaseTag && !isOfflineMode) {
73139
73476
  try {
73140
73477
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
73141
- const claudeDir = prefix ? join116(resolvedDir, prefix) : resolvedDir;
73478
+ const claudeDir = prefix ? join118(resolvedDir, prefix) : resolvedDir;
73142
73479
  const existingMetadata = await readManifest(claudeDir);
73143
73480
  const installedKitVersion = existingMetadata?.kits?.[kitType]?.version;
73144
73481
  if (installedKitVersion && versionsMatch(installedKitVersion, releaseTag)) {
@@ -73161,7 +73498,7 @@ async function handleSelection(ctx) {
73161
73498
  let currentSecondaryVersion = null;
73162
73499
  try {
73163
73500
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
73164
- const claudeDir = prefix ? join116(resolvedDir, prefix) : resolvedDir;
73501
+ const claudeDir = prefix ? join118(resolvedDir, prefix) : resolvedDir;
73165
73502
  const existingMetadata = await readManifest(claudeDir);
73166
73503
  currentSecondaryVersion = existingMetadata?.kits?.[secondaryKit]?.version || null;
73167
73504
  } catch {}
@@ -73245,12 +73582,12 @@ function resolveGlobalTargetDir(targetAgents2) {
73245
73582
  // src/commands/init/phases/sync-handler.ts
73246
73583
  init_paths();
73247
73584
  import { copyFile as copyFile7, mkdir as mkdir28, open as open2, readFile as readFile41, rename as rename7, stat as stat12, unlink as unlink11, writeFile as writeFile28 } from "node:fs/promises";
73248
- import { dirname as dirname34, join as join119, resolve as resolve29 } from "node:path";
73585
+ import { dirname as dirname35, join as join121, resolve as resolve29 } from "node:path";
73249
73586
 
73250
73587
  // src/domains/sync/config-version-checker.ts
73251
73588
  init_auth_client();
73252
73589
  import { mkdir as mkdir27, readFile as readFile39, unlink as unlink10, writeFile as writeFile27 } from "node:fs/promises";
73253
- import { join as join117 } from "node:path";
73590
+ import { join as join119 } from "node:path";
73254
73591
  init_version_utils();
73255
73592
  init_logger();
73256
73593
  init_path_resolver();
@@ -73286,7 +73623,7 @@ var CACHE_FILENAME = "config-update-cache.json";
73286
73623
  class ConfigVersionChecker {
73287
73624
  static getCacheFilePath(kitType, global3) {
73288
73625
  const cacheDir = PathResolver.getCacheDir(global3);
73289
- return join117(cacheDir, `${kitType}-${CACHE_FILENAME}`);
73626
+ return join119(cacheDir, `${kitType}-${CACHE_FILENAME}`);
73290
73627
  }
73291
73628
  static async loadCache(kitType, global3) {
73292
73629
  try {
@@ -73302,12 +73639,12 @@ class ConfigVersionChecker {
73302
73639
  return null;
73303
73640
  }
73304
73641
  }
73305
- static async saveCache(kitType, global3, cache2) {
73642
+ static async saveCache(kitType, global3, cache3) {
73306
73643
  try {
73307
73644
  const cachePath = ConfigVersionChecker.getCacheFilePath(kitType, global3);
73308
73645
  const cacheDir = PathResolver.getCacheDir(global3);
73309
73646
  await mkdir27(cacheDir, { recursive: true });
73310
- await writeFile27(cachePath, JSON.stringify(cache2, null, 2));
73647
+ await writeFile27(cachePath, JSON.stringify(cache3, null, 2));
73311
73648
  } catch (error) {
73312
73649
  logger.debug(`Cache write failed: ${error instanceof Error ? error.message : "Unknown error"}`);
73313
73650
  }
@@ -73349,14 +73686,14 @@ class ConfigVersionChecker {
73349
73686
  }
73350
73687
  static async checkForUpdates(kitType, currentVersion, global3 = false) {
73351
73688
  const normalizedCurrent = currentVersion.replace(/^v/, "");
73352
- const cache2 = await ConfigVersionChecker.loadCache(kitType, global3);
73689
+ const cache3 = await ConfigVersionChecker.loadCache(kitType, global3);
73353
73690
  const now = Date.now();
73354
- if (cache2 && now - cache2.lastCheck < CACHE_TTL_MS) {
73355
- const hasUpdates = isNewerVersion(normalizedCurrent, cache2.latestVersion);
73691
+ if (cache3 && now - cache3.lastCheck < CACHE_TTL_MS) {
73692
+ const hasUpdates = isNewerVersion(normalizedCurrent, cache3.latestVersion);
73356
73693
  return {
73357
73694
  hasUpdates,
73358
73695
  currentVersion: normalizedCurrent,
73359
- latestVersion: cache2.latestVersion,
73696
+ latestVersion: cache3.latestVersion,
73360
73697
  fromCache: true
73361
73698
  };
73362
73699
  }
@@ -73374,12 +73711,12 @@ class ConfigVersionChecker {
73374
73711
  fromCache: false
73375
73712
  };
73376
73713
  }
73377
- if (cache2) {
73378
- const hasUpdates = isNewerVersion(normalizedCurrent, cache2.latestVersion);
73714
+ if (cache3) {
73715
+ const hasUpdates = isNewerVersion(normalizedCurrent, cache3.latestVersion);
73379
73716
  return {
73380
73717
  hasUpdates,
73381
73718
  currentVersion: normalizedCurrent,
73382
- latestVersion: cache2.latestVersion,
73719
+ latestVersion: cache3.latestVersion,
73383
73720
  fromCache: true
73384
73721
  };
73385
73722
  }
@@ -73406,7 +73743,7 @@ class ConfigVersionChecker {
73406
73743
  init_ownership_checker();
73407
73744
  init_logger();
73408
73745
  import { lstat as lstat7, readFile as readFile40, readlink, realpath as realpath3, stat as stat11 } from "node:fs/promises";
73409
- import { isAbsolute as isAbsolute5, join as join118, normalize as normalize9, relative as relative17 } from "node:path";
73746
+ import { isAbsolute as isAbsolute5, join as join120, normalize as normalize9, relative as relative17 } from "node:path";
73410
73747
  var MAX_SYNC_FILE_SIZE = 10 * 1024 * 1024;
73411
73748
  var MAX_SYMLINK_DEPTH = 20;
73412
73749
  async function validateSymlinkChain(path12, basePath, maxDepth = MAX_SYMLINK_DEPTH) {
@@ -73418,7 +73755,7 @@ async function validateSymlinkChain(path12, basePath, maxDepth = MAX_SYMLINK_DEP
73418
73755
  if (!stats.isSymbolicLink())
73419
73756
  break;
73420
73757
  const target = await readlink(current);
73421
- const resolvedTarget = isAbsolute5(target) ? target : join118(current, "..", target);
73758
+ const resolvedTarget = isAbsolute5(target) ? target : join120(current, "..", target);
73422
73759
  const normalizedTarget = normalize9(resolvedTarget);
73423
73760
  const rel = relative17(basePath, normalizedTarget);
73424
73761
  if (rel.startsWith("..") || isAbsolute5(rel)) {
@@ -73454,7 +73791,7 @@ async function validateSyncPath(basePath, filePath) {
73454
73791
  if (normalized.startsWith("..") || normalized.includes("/../")) {
73455
73792
  throw new Error(`Path traversal not allowed: ${filePath}`);
73456
73793
  }
73457
- const fullPath = join118(basePath, normalized);
73794
+ const fullPath = join120(basePath, normalized);
73458
73795
  const rel = relative17(basePath, fullPath);
73459
73796
  if (rel.startsWith("..") || isAbsolute5(rel)) {
73460
73797
  throw new Error(`Path escapes base directory: ${filePath}`);
@@ -73469,7 +73806,7 @@ async function validateSyncPath(basePath, filePath) {
73469
73806
  }
73470
73807
  } catch (error) {
73471
73808
  if (error.code === "ENOENT") {
73472
- const parentPath = join118(fullPath, "..");
73809
+ const parentPath = join120(fullPath, "..");
73473
73810
  try {
73474
73811
  const resolvedBase = await realpath3(basePath);
73475
73812
  const resolvedParent = await realpath3(parentPath);
@@ -73960,10 +74297,10 @@ function getLockTimeout() {
73960
74297
  var STALE_LOCK_THRESHOLD_MS = 5 * 60 * 1000;
73961
74298
  async function acquireSyncLock(global3) {
73962
74299
  const cacheDir = PathResolver.getCacheDir(global3);
73963
- const lockPath2 = join119(cacheDir, ".sync-lock");
74300
+ const lockPath2 = join121(cacheDir, ".sync-lock");
73964
74301
  const startTime = Date.now();
73965
74302
  const lockTimeout = getLockTimeout();
73966
- await mkdir28(dirname34(lockPath2), { recursive: true });
74303
+ await mkdir28(dirname35(lockPath2), { recursive: true });
73967
74304
  while (Date.now() - startTime < lockTimeout) {
73968
74305
  try {
73969
74306
  const handle = await open2(lockPath2, "wx");
@@ -74041,7 +74378,7 @@ async function executeSyncMerge(ctx) {
74041
74378
  try {
74042
74379
  const sourcePath = await validateSyncPath(upstreamDir, file.path);
74043
74380
  const targetPath = await validateSyncPath(ctx.claudeDir, file.path);
74044
- const targetDir = join119(targetPath, "..");
74381
+ const targetDir = join121(targetPath, "..");
74045
74382
  try {
74046
74383
  await mkdir28(targetDir, { recursive: true });
74047
74384
  } catch (mkdirError) {
@@ -74212,7 +74549,7 @@ async function createBackup(claudeDir, files, backupDir) {
74212
74549
  const sourcePath = await validateSyncPath(claudeDir, file.path);
74213
74550
  if (await import_fs_extra34.pathExists(sourcePath)) {
74214
74551
  const targetPath = await validateSyncPath(backupDir, file.path);
74215
- const targetDir = join119(targetPath, "..");
74552
+ const targetDir = join121(targetPath, "..");
74216
74553
  await mkdir28(targetDir, { recursive: true });
74217
74554
  await copyFile7(sourcePath, targetPath);
74218
74555
  }
@@ -74238,38 +74575,38 @@ init_logger();
74238
74575
  init_types2();
74239
74576
  var import_fs_extra35 = __toESM(require_lib(), 1);
74240
74577
  import { rename as rename8, rm as rm9 } from "node:fs/promises";
74241
- import { join as join120, relative as relative18 } from "node:path";
74578
+ import { join as join122, relative as relative18 } from "node:path";
74242
74579
  async function collectDirsToRename(extractDir, folders) {
74243
74580
  const dirsToRename = [];
74244
74581
  if (folders.docs !== DEFAULT_FOLDERS.docs) {
74245
- const docsPath = join120(extractDir, DEFAULT_FOLDERS.docs);
74582
+ const docsPath = join122(extractDir, DEFAULT_FOLDERS.docs);
74246
74583
  if (await import_fs_extra35.pathExists(docsPath)) {
74247
74584
  dirsToRename.push({
74248
74585
  from: docsPath,
74249
- to: join120(extractDir, folders.docs)
74586
+ to: join122(extractDir, folders.docs)
74250
74587
  });
74251
74588
  }
74252
- const claudeDocsPath = join120(extractDir, ".claude", DEFAULT_FOLDERS.docs);
74589
+ const claudeDocsPath = join122(extractDir, ".claude", DEFAULT_FOLDERS.docs);
74253
74590
  if (await import_fs_extra35.pathExists(claudeDocsPath)) {
74254
74591
  dirsToRename.push({
74255
74592
  from: claudeDocsPath,
74256
- to: join120(extractDir, ".claude", folders.docs)
74593
+ to: join122(extractDir, ".claude", folders.docs)
74257
74594
  });
74258
74595
  }
74259
74596
  }
74260
74597
  if (folders.plans !== DEFAULT_FOLDERS.plans) {
74261
- const plansPath = join120(extractDir, DEFAULT_FOLDERS.plans);
74598
+ const plansPath = join122(extractDir, DEFAULT_FOLDERS.plans);
74262
74599
  if (await import_fs_extra35.pathExists(plansPath)) {
74263
74600
  dirsToRename.push({
74264
74601
  from: plansPath,
74265
- to: join120(extractDir, folders.plans)
74602
+ to: join122(extractDir, folders.plans)
74266
74603
  });
74267
74604
  }
74268
- const claudePlansPath = join120(extractDir, ".claude", DEFAULT_FOLDERS.plans);
74605
+ const claudePlansPath = join122(extractDir, ".claude", DEFAULT_FOLDERS.plans);
74269
74606
  if (await import_fs_extra35.pathExists(claudePlansPath)) {
74270
74607
  dirsToRename.push({
74271
74608
  from: claudePlansPath,
74272
- to: join120(extractDir, ".claude", folders.plans)
74609
+ to: join122(extractDir, ".claude", folders.plans)
74273
74610
  });
74274
74611
  }
74275
74612
  }
@@ -74310,7 +74647,7 @@ async function renameFolders(dirsToRename, extractDir, options2) {
74310
74647
  init_logger();
74311
74648
  init_types2();
74312
74649
  import { readFile as readFile42, readdir as readdir29, writeFile as writeFile29 } from "node:fs/promises";
74313
- import { join as join121, relative as relative19 } from "node:path";
74650
+ import { join as join123, relative as relative19 } from "node:path";
74314
74651
  var TRANSFORMABLE_FILE_PATTERNS = [
74315
74652
  ".md",
74316
74653
  ".txt",
@@ -74363,7 +74700,7 @@ async function transformFileContents(dir, compiledReplacements, options2) {
74363
74700
  let replacementsCount = 0;
74364
74701
  const entries = await readdir29(dir, { withFileTypes: true });
74365
74702
  for (const entry of entries) {
74366
- const fullPath = join121(dir, entry.name);
74703
+ const fullPath = join123(dir, entry.name);
74367
74704
  if (entry.isDirectory()) {
74368
74705
  if (entry.name === "node_modules" || entry.name === ".git") {
74369
74706
  continue;
@@ -74500,7 +74837,7 @@ async function transformFolderPaths(extractDir, folders, options2 = {}) {
74500
74837
  init_logger();
74501
74838
  import { readFile as readFile43, readdir as readdir30, writeFile as writeFile30 } from "node:fs/promises";
74502
74839
  import { platform as platform11 } from "node:os";
74503
- import { extname as extname7, join as join122 } from "node:path";
74840
+ import { extname as extname7, join as join124 } from "node:path";
74504
74841
  var IS_WINDOWS3 = platform11() === "win32";
74505
74842
  var HOME_PREFIX = "$HOME";
74506
74843
  function getHomeDirPrefix() {
@@ -74589,8 +74926,8 @@ function transformContent(content) {
74589
74926
  }
74590
74927
  function shouldTransformFile3(filename) {
74591
74928
  const ext2 = extname7(filename).toLowerCase();
74592
- const basename18 = filename.split("/").pop() || filename;
74593
- return TRANSFORMABLE_EXTENSIONS3.has(ext2) || ALWAYS_TRANSFORM_FILES.has(basename18);
74929
+ const basename19 = filename.split("/").pop() || filename;
74930
+ return TRANSFORMABLE_EXTENSIONS3.has(ext2) || ALWAYS_TRANSFORM_FILES.has(basename19);
74594
74931
  }
74595
74932
  async function transformPathsForGlobalInstall(directory, options2 = {}) {
74596
74933
  let filesTransformed = 0;
@@ -74600,7 +74937,7 @@ async function transformPathsForGlobalInstall(directory, options2 = {}) {
74600
74937
  async function processDirectory2(dir) {
74601
74938
  const entries = await readdir30(dir, { withFileTypes: true });
74602
74939
  for (const entry of entries) {
74603
- const fullPath = join122(dir, entry.name);
74940
+ const fullPath = join124(dir, entry.name);
74604
74941
  if (entry.isDirectory()) {
74605
74942
  if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
74606
74943
  continue;
@@ -74692,6 +75029,7 @@ function mapAgentToHookAgent(agent) {
74692
75029
  return null;
74693
75030
  }
74694
75031
  async function installTkmHooksForAgents(targetAgents2, options2) {
75032
+ const categories = options2.installHooks ? undefined : ["metrics"];
74695
75033
  for (const agent of targetAgents2) {
74696
75034
  const hookAgent = mapAgentToHookAgent(agent);
74697
75035
  if (!hookAgent)
@@ -74701,6 +75039,7 @@ async function installTkmHooksForAgents(targetAgents2, options2) {
74701
75039
  agent: hookAgent,
74702
75040
  global: options2.global,
74703
75041
  dryRun: options2.dryRun,
75042
+ categories,
74704
75043
  yes: true
74705
75044
  });
74706
75045
  } catch (err) {
@@ -74820,7 +75159,8 @@ async function executeInit(options2, prompts) {
74820
75159
  if (!isSyncMode) {
74821
75160
  await installTkmHooksForAgents(targetAgents2, {
74822
75161
  global: Boolean(ctx.options.global),
74823
- dryRun: Boolean(ctx.options.dryRun)
75162
+ dryRun: Boolean(ctx.options.dryRun),
75163
+ installHooks: Boolean(ctx.options.installHooks)
74824
75164
  });
74825
75165
  }
74826
75166
  if (targetAgents2.length > 1) {
@@ -74883,19 +75223,19 @@ async function initCommand(options2) {
74883
75223
  // src/commands/plan/plan-command.ts
74884
75224
  init_output_manager();
74885
75225
  import { existsSync as existsSync60, statSync as statSync9 } from "node:fs";
74886
- import { dirname as dirname40, join as join126, parse as parse4, resolve as resolve33 } from "node:path";
75226
+ import { dirname as dirname41, join as join128, parse as parse4, resolve as resolve33 } from "node:path";
74887
75227
 
74888
75228
  // src/commands/plan/plan-read-handlers.ts
74889
75229
  import { existsSync as existsSync59, statSync as statSync8 } from "node:fs";
74890
- import { basename as basename20, dirname as dirname39, join as join125, relative as relative20, resolve as resolve31 } from "node:path";
75230
+ import { basename as basename21, dirname as dirname40, join as join127, relative as relative20, resolve as resolve31 } from "node:path";
74891
75231
 
74892
75232
  // src/domains/plan-parser/index.ts
74893
- import { dirname as dirname38 } from "node:path";
75233
+ import { dirname as dirname39 } from "node:path";
74894
75234
 
74895
75235
  // src/domains/plan-parser/plan-table-parser.ts
74896
75236
  var import_gray_matter5 = __toESM(require_gray_matter(), 1);
74897
75237
  import { readFileSync as readFileSync23 } from "node:fs";
74898
- import { dirname as dirname35, resolve as resolve30 } from "node:path";
75238
+ import { dirname as dirname36, resolve as resolve30 } from "node:path";
74899
75239
  function normalizeStatus(raw) {
74900
75240
  const s3 = raw.toLowerCase().trim();
74901
75241
  if (s3.includes("complete") || s3.includes("done") || s3.includes("✓") || s3.includes("✅")) {
@@ -74916,9 +75256,9 @@ function filenameToTitle(name) {
74916
75256
  }
74917
75257
  function buildAnchor(phaseId, name) {
74918
75258
  const suffix = phaseId.replace(/^\d+/, "");
74919
- const num3 = phaseId.replace(/[a-z]+$/i, "");
75259
+ const num4 = phaseId.replace(/[a-z]+$/i, "");
74920
75260
  const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
74921
- return `phase-${String(num3).padStart(2, "0")}${suffix}-${slug}`;
75261
+ return `phase-${String(num4).padStart(2, "0")}${suffix}-${slug}`;
74922
75262
  }
74923
75263
  function parseHeaderAwareTable(content, dir, options2) {
74924
75264
  const lines = content.split(`
@@ -75011,11 +75351,11 @@ function parseFormat1(content, dir, options2) {
75011
75351
  const regex2 = /\|\s*(\d+)([a-z]?)\s*\|\s*([^|]+)\s*\|\s*([^|]+)\s*\|\s*\[([^\]]+)\]\(([^)]+)\)/gi;
75012
75352
  const phases = [];
75013
75353
  for (const match2 of content.matchAll(regex2)) {
75014
- const [, num3, suffix, name, status2, linkText, linkPath] = match2;
75015
- const phaseId = `${num3}${suffix}`;
75354
+ const [, num4, suffix, name, status2, linkText, linkPath] = match2;
75355
+ const phaseId = `${num4}${suffix}`;
75016
75356
  const anchor = options2?.generateAnchors ? buildAnchor(phaseId, name.trim()) : null;
75017
75357
  phases.push({
75018
- phase: Number.parseInt(num3, 10),
75358
+ phase: Number.parseInt(num4, 10),
75019
75359
  phaseId,
75020
75360
  name: name.trim(),
75021
75361
  status: normalizeStatus(status2),
@@ -75030,12 +75370,12 @@ function parseFormat2(content, dir, options2) {
75030
75370
  const regex2 = /\|\s*\[(?:Phase\s*)?(\d+)([a-z]?)\]\(([^)]+)\)\s*\|\s*([^|]+)\s*\|\s*([^|]+)/gi;
75031
75371
  const phases = [];
75032
75372
  for (const match2 of content.matchAll(regex2)) {
75033
- const [, num3, suffix, linkPath, name, status2] = match2;
75034
- const phaseId = `${num3}${suffix}`;
75373
+ const [, num4, suffix, linkPath, name, status2] = match2;
75374
+ const phaseId = `${num4}${suffix}`;
75035
75375
  const linkText = `Phase ${phaseId}`;
75036
75376
  const anchor = options2?.generateAnchors ? buildAnchor(phaseId, name.trim()) : null;
75037
75377
  phases.push({
75038
- phase: Number.parseInt(num3, 10),
75378
+ phase: Number.parseInt(num4, 10),
75039
75379
  phaseId,
75040
75380
  name: name.trim(),
75041
75381
  status: normalizeStatus(status2),
@@ -75050,11 +75390,11 @@ function parseFormat2b(content, dir, options2) {
75050
75390
  const regex2 = /\|\s*(\d+)([a-z]?)\s*\|\s*\[([^\]]+)\]\(([^)]+)\)\s*\|\s*([^|]+)/gi;
75051
75391
  const phases = [];
75052
75392
  for (const match2 of content.matchAll(regex2)) {
75053
- const [, num3, suffix, name, linkPath, status2] = match2;
75054
- const phaseId = `${num3}${suffix}`;
75393
+ const [, num4, suffix, name, linkPath, status2] = match2;
75394
+ const phaseId = `${num4}${suffix}`;
75055
75395
  const anchor = options2?.generateAnchors ? buildAnchor(phaseId, name.trim()) : null;
75056
75396
  phases.push({
75057
- phase: Number.parseInt(num3, 10),
75397
+ phase: Number.parseInt(num4, 10),
75058
75398
  phaseId,
75059
75399
  name: name.trim(),
75060
75400
  status: normalizeStatus(status2),
@@ -75101,11 +75441,11 @@ function parseFormat3(content, _dir, options2) {
75101
75441
  if (headingMatch) {
75102
75442
  if (current)
75103
75443
  phases.push(current);
75104
- const [, num3, suffix, name] = headingMatch;
75105
- const phaseId = `${num3}${suffix}`;
75444
+ const [, num4, suffix, name] = headingMatch;
75445
+ const phaseId = `${num4}${suffix}`;
75106
75446
  const anchor = options2?.generateAnchors ? buildAnchor(phaseId, name.trim()) : null;
75107
75447
  current = {
75108
- phase: Number.parseInt(num3, 10),
75448
+ phase: Number.parseInt(num4, 10),
75109
75449
  phaseId,
75110
75450
  name: name.trim(),
75111
75451
  status: "pending",
@@ -75156,7 +75496,7 @@ function parseFormat4(content, planFilePath, options2) {
75156
75496
  const hasCheck = /[✅✓]/.test(line);
75157
75497
  current = { name, status: hasCheck ? "completed" : "pending" };
75158
75498
  } else if (fileMatch && current) {
75159
- const planDir = dirname35(planFilePath);
75499
+ const planDir = dirname36(planFilePath);
75160
75500
  current.file = resolve30(planDir, fileMatch[1].trim());
75161
75501
  } else if (statusMatch && current) {
75162
75502
  current.status = normalizeStatus(statusMatch[2]);
@@ -75181,11 +75521,11 @@ function parseFormat5(content, _dir, options2) {
75181
75521
  const phases = [];
75182
75522
  const phaseMap = new Map;
75183
75523
  for (const match2 of content.matchAll(/^(\d+)([a-z]?)[).]\s*\*\*([^*]+)\*\*/gim)) {
75184
- const [, num3, suffix, name] = match2;
75185
- const phaseId = `${num3}${suffix}`;
75524
+ const [, num4, suffix, name] = match2;
75525
+ const phaseId = `${num4}${suffix}`;
75186
75526
  const anchor = options2?.generateAnchors ? buildAnchor(phaseId, name.trim()) : null;
75187
75527
  phaseMap.set(name.trim().toLowerCase(), {
75188
- phase: Number.parseInt(num3, 10),
75528
+ phase: Number.parseInt(num4, 10),
75189
75529
  phaseId,
75190
75530
  name: name.trim(),
75191
75531
  status: "pending",
@@ -75214,12 +75554,12 @@ function parseFormat6(content, dir, options2) {
75214
75554
  const regex2 = /^-\s*\[(x| )\]\s*\*\*\[(?:Phase\s*)?(\d+)([a-z]?)[:\s]*([^\]]*)\]\(([^)]+)\)\*\*/gim;
75215
75555
  const phases = [];
75216
75556
  for (const match2 of content.matchAll(regex2)) {
75217
- const [, checked, num3, suffix, name, linkPath] = match2;
75218
- const phaseId = `${num3}${suffix}`;
75557
+ const [, checked, num4, suffix, name, linkPath] = match2;
75558
+ const phaseId = `${num4}${suffix}`;
75219
75559
  const phaseName = name.trim() || `Phase ${phaseId}`;
75220
75560
  const anchor = options2?.generateAnchors ? buildAnchor(phaseId, phaseName) : null;
75221
75561
  phases.push({
75222
- phase: Number.parseInt(num3, 10),
75562
+ phase: Number.parseInt(num4, 10),
75223
75563
  phaseId,
75224
75564
  name: phaseName,
75225
75565
  status: checked.toLowerCase() === "x" ? "completed" : "pending",
@@ -75261,19 +75601,19 @@ function parsePhasesFromBody(body, dir, options2) {
75261
75601
  }
75262
75602
  function parsePlanFile(planFilePath, options2) {
75263
75603
  const content = readFileSync23(planFilePath, "utf8");
75264
- const dir = dirname35(planFilePath);
75604
+ const dir = dirname36(planFilePath);
75265
75605
  const { data: frontmatter, content: body } = import_gray_matter5.default(content);
75266
75606
  const phases = parsePhasesFromBody(body, dir, options2);
75267
75607
  return { frontmatter, phases };
75268
75608
  }
75269
75609
  // src/domains/plan-parser/plan-scanner.ts
75270
- import { existsSync as existsSync56, readdirSync as readdirSync9 } from "node:fs";
75271
- import { join as join123 } from "node:path";
75610
+ import { existsSync as existsSync56, readdirSync as readdirSync10 } from "node:fs";
75611
+ import { join as join125 } from "node:path";
75272
75612
  function scanPlanDir(dir) {
75273
75613
  if (!existsSync56(dir))
75274
75614
  return [];
75275
75615
  try {
75276
- return readdirSync9(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join123(dir, entry.name, "plan.md")).filter(existsSync56);
75616
+ return readdirSync10(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join125(dir, entry.name, "plan.md")).filter(existsSync56);
75277
75617
  } catch {
75278
75618
  return [];
75279
75619
  }
@@ -75281,10 +75621,10 @@ function scanPlanDir(dir) {
75281
75621
  // src/domains/plan-parser/plan-validator.ts
75282
75622
  var import_gray_matter6 = __toESM(require_gray_matter(), 1);
75283
75623
  import { existsSync as existsSync57, readFileSync as readFileSync24 } from "node:fs";
75284
- import { basename as basename18, dirname as dirname36 } from "node:path";
75624
+ import { basename as basename19, dirname as dirname37 } from "node:path";
75285
75625
  function validatePlanFile(filePath, strict = false) {
75286
75626
  const content = readFileSync24(filePath, "utf8");
75287
- const dir = dirname36(filePath);
75627
+ const dir = dirname37(filePath);
75288
75628
  const issues = [];
75289
75629
  const lines = content.split(`
75290
75630
  `);
@@ -75321,13 +75661,13 @@ function validatePlanFile(filePath, strict = false) {
75321
75661
  }
75322
75662
  for (const phase of phases) {
75323
75663
  if (phase.file && !existsSync57(phase.file)) {
75324
- const fileBasename = basename18(phase.file);
75664
+ const fileBasename = basename19(phase.file);
75325
75665
  const refLine = lines.findIndex((l2) => l2.includes(fileBasename));
75326
75666
  issues.push({
75327
75667
  line: refLine >= 0 ? refLine + 1 : 1,
75328
75668
  severity: "warning",
75329
75669
  code: "missing-phase-file",
75330
- message: `Phase ${phase.phaseId} references '${basename18(phase.file)}' which doesn't exist`
75670
+ message: `Phase ${phase.phaseId} references '${basename19(phase.file)}' which doesn't exist`
75331
75671
  });
75332
75672
  }
75333
75673
  }
@@ -75342,12 +75682,12 @@ function validatePlanFile(filePath, strict = false) {
75342
75682
  var import_gray_matter7 = __toESM(require_gray_matter(), 1);
75343
75683
  import { mkdirSync as mkdirSync9, readFileSync as readFileSync25, writeFileSync as writeFileSync12 } from "node:fs";
75344
75684
  import { existsSync as existsSync58 } from "node:fs";
75345
- import { basename as basename19, dirname as dirname37, join as join124 } from "node:path";
75685
+ import { basename as basename20, dirname as dirname38, join as join126 } from "node:path";
75346
75686
  function phaseNameToFilename(id, name) {
75347
75687
  const numMatch = /^(\d+)([a-z]*)$/i.exec(id);
75348
- const num3 = numMatch ? numMatch[1] : id;
75688
+ const num4 = numMatch ? numMatch[1] : id;
75349
75689
  const suffix = numMatch ? numMatch[2].toLowerCase() : "";
75350
- const paddedNum = num3.padStart(2, "0");
75690
+ const paddedNum = num4.padStart(2, "0");
75351
75691
  const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
75352
75692
  return `phase-${paddedNum}${suffix}-${slug}.md`;
75353
75693
  }
@@ -75450,12 +75790,12 @@ function scaffoldPlan(options2) {
75450
75790
  mkdirSync9(dir, { recursive: true });
75451
75791
  const resolvedPhases = resolvePhaseIds(options2.phases);
75452
75792
  const optionsWithResolved = { ...options2, phases: resolvedPhases };
75453
- const planFile = join124(dir, "plan.md");
75793
+ const planFile = join126(dir, "plan.md");
75454
75794
  writeFileSync12(planFile, generatePlanMd(optionsWithResolved), "utf8");
75455
75795
  const phaseFiles = [];
75456
75796
  for (const phase of resolvedPhases) {
75457
75797
  const filename = phaseNameToFilename(phase.id, phase.name);
75458
- const phaseFile = join124(dir, filename);
75798
+ const phaseFile = join126(dir, filename);
75459
75799
  writeFileSync12(phaseFile, generatePhaseTemplate(phase), "utf8");
75460
75800
  phaseFiles.push(phaseFile);
75461
75801
  }
@@ -75465,14 +75805,14 @@ function nextSubPhaseId(afterId, existingIds) {
75465
75805
  const numMatch = /^(\d+)([a-z]*)$/i.exec(afterId);
75466
75806
  if (!numMatch)
75467
75807
  throw new Error(`Invalid phase ID: ${afterId}`);
75468
- const num3 = numMatch[1];
75808
+ const num4 = numMatch[1];
75469
75809
  const currentSuffix = numMatch[2].toLowerCase();
75470
75810
  const nextSuffixChar = currentSuffix === "" ? "b" : String.fromCharCode(currentSuffix.charCodeAt(0) + 1);
75471
75811
  if (nextSuffixChar > "z")
75472
- throw new Error(`Too many sub-phases for phase ${num3}`);
75473
- const candidate = `${num3}${nextSuffixChar}`;
75812
+ throw new Error(`Too many sub-phases for phase ${num4}`);
75813
+ const candidate = `${num4}${nextSuffixChar}`;
75474
75814
  if (existingIds.includes(candidate)) {
75475
- return nextSubPhaseId(`${num3}${nextSuffixChar}`, existingIds);
75815
+ return nextSubPhaseId(`${num4}${nextSuffixChar}`, existingIds);
75476
75816
  }
75477
75817
  return candidate;
75478
75818
  }
@@ -75521,7 +75861,7 @@ function updatePhaseStatus(planFile, phaseId, newStatus) {
75521
75861
  const updatedFrontmatter = { ...frontmatter, status: planStatus };
75522
75862
  const updatedContent = import_gray_matter7.default.stringify(updatedBody, updatedFrontmatter);
75523
75863
  writeFileSync12(planFile, updatedContent, "utf8");
75524
- const planDir = dirname37(planFile);
75864
+ const planDir = dirname38(planFile);
75525
75865
  const phaseFilename = phaseNameFilenameFromTableRow(updatedBody, phaseId, planDir);
75526
75866
  if (phaseFilename && existsSync58(phaseFilename)) {
75527
75867
  updatePhaseFileFrontmatter(phaseFilename, newStatus);
@@ -75535,7 +75875,7 @@ function phaseNameFilenameFromTableRow(body, phaseId, planDir) {
75535
75875
  continue;
75536
75876
  const linkMatch = /\[([^\]]+)\]\(\.\/([^)]+)\)/.exec(row);
75537
75877
  if (linkMatch)
75538
- return join124(planDir, linkMatch[2]);
75878
+ return join126(planDir, linkMatch[2]);
75539
75879
  }
75540
75880
  return null;
75541
75881
  }
@@ -75553,7 +75893,7 @@ function addPhase(planFile, name, afterId) {
75553
75893
  throw new Error("Non-canonical plan.md — cannot add phase");
75554
75894
  }
75555
75895
  const { data: frontmatter, content: body } = import_gray_matter7.default(raw);
75556
- const planDir = dirname37(planFile);
75896
+ const planDir = dirname38(planFile);
75557
75897
  const existingIds = [];
75558
75898
  for (const match2 of body.matchAll(/^\|\s*(\d+[a-z]?)\s*\|/gim)) {
75559
75899
  existingIds.push(match2[1].toLowerCase());
@@ -75582,7 +75922,7 @@ function addPhase(planFile, name, afterId) {
75582
75922
  insertIdx = i;
75583
75923
  }
75584
75924
  if (insertIdx === -1) {
75585
- throw new Error(`Phase ID "${afterId}" not found in ${basename19(planFile)}`);
75925
+ throw new Error(`Phase ID "${afterId}" not found in ${basename20(planFile)}`);
75586
75926
  }
75587
75927
  lines.splice(insertIdx + 1, 0, newRow);
75588
75928
  updatedBody = lines.join(`
@@ -75616,7 +75956,7 @@ function addPhase(planFile, name, afterId) {
75616
75956
  `);
75617
75957
  }
75618
75958
  writeFileSync12(planFile, import_gray_matter7.default.stringify(updatedBody, frontmatter), "utf8");
75619
- const phaseFilePath = join124(planDir, filename);
75959
+ const phaseFilePath = join126(planDir, filename);
75620
75960
  writeFileSync12(phaseFilePath, generatePhaseTemplate({ id: phaseId, name }), "utf8");
75621
75961
  return { phaseId, phaseFile: phaseFilePath };
75622
75962
  }
@@ -75628,7 +75968,7 @@ function buildPlanSummary(planFile) {
75628
75968
  const inProgress = phases.filter((p2) => p2.status === "in-progress").length;
75629
75969
  const pending = phases.filter((p2) => p2.status === "pending").length;
75630
75970
  return {
75631
- planDir: dirname38(planFile),
75971
+ planDir: dirname39(planFile),
75632
75972
  planFile,
75633
75973
  title: typeof frontmatter.title === "string" ? frontmatter.title : undefined,
75634
75974
  description: typeof frontmatter.description === "string" ? frontmatter.description : undefined,
@@ -75665,7 +76005,7 @@ async function handleParse(target, options2) {
75665
76005
  console.log(JSON.stringify({ file: relative20(process.cwd(), planFile), frontmatter, phases }, null, 2));
75666
76006
  return;
75667
76007
  }
75668
- const title = typeof frontmatter.title === "string" ? frontmatter.title : basename20(dirname39(planFile));
76008
+ const title = typeof frontmatter.title === "string" ? frontmatter.title : basename21(dirname40(planFile));
75669
76009
  console.log();
75670
76010
  console.log(import_picocolors25.default.bold(` Plan: ${title}`));
75671
76011
  console.log(` File: ${planFile}`);
@@ -75720,7 +76060,7 @@ async function handleValidate(target, options2) {
75720
76060
  }
75721
76061
  async function handleStatus(target, options2) {
75722
76062
  const t = target ? resolve31(target) : null;
75723
- const plansDir = t && existsSync59(t) && statSync8(t).isDirectory() && !existsSync59(join125(t, "plan.md")) ? t : null;
76063
+ const plansDir = t && existsSync59(t) && statSync8(t).isDirectory() && !existsSync59(join127(t, "plan.md")) ? t : null;
75724
76064
  if (plansDir) {
75725
76065
  const planFiles = scanPlanDir(plansDir);
75726
76066
  if (planFiles.length === 0) {
@@ -75745,14 +76085,14 @@ async function handleStatus(target, options2) {
75745
76085
  try {
75746
76086
  const s3 = buildPlanSummary(pf);
75747
76087
  const bar = progressBar(s3.completed, s3.totalPhases);
75748
- const title2 = s3.title ?? basename20(dirname39(pf));
76088
+ const title2 = s3.title ?? basename21(dirname40(pf));
75749
76089
  console.log(` ${import_picocolors25.default.bold(title2)}`);
75750
76090
  console.log(` ${bar}`);
75751
76091
  if (s3.inProgress > 0)
75752
76092
  console.log(` [~] ${s3.inProgress} in progress`);
75753
76093
  console.log();
75754
76094
  } catch {
75755
- console.log(` [X] Failed to read: ${basename20(dirname39(pf))}`);
76095
+ console.log(` [X] Failed to read: ${basename21(dirname40(pf))}`);
75756
76096
  console.log();
75757
76097
  }
75758
76098
  }
@@ -75776,7 +76116,7 @@ async function handleStatus(target, options2) {
75776
76116
  console.log(JSON.stringify(summary, null, 2));
75777
76117
  return;
75778
76118
  }
75779
- const title = summary.title ?? basename20(dirname39(planFile));
76119
+ const title = summary.title ?? basename21(dirname40(planFile));
75780
76120
  console.log();
75781
76121
  console.log(import_picocolors25.default.bold(` ${title}`));
75782
76122
  if (summary.status)
@@ -75802,7 +76142,7 @@ async function handleKanban(target, _options) {
75802
76142
  }
75803
76143
 
75804
76144
  // src/commands/plan/plan-write-handlers.ts
75805
- import { basename as basename21, relative as relative21, resolve as resolve32 } from "node:path";
76145
+ import { basename as basename22, relative as relative21, resolve as resolve32 } from "node:path";
75806
76146
  init_output_manager();
75807
76147
  var import_picocolors26 = __toESM(require_picocolors(), 1);
75808
76148
  async function handleCreate(target, options2) {
@@ -75855,7 +76195,7 @@ async function handleCreate(target, options2) {
75855
76195
  console.log(` Directory: ${resolve32(dir)}`);
75856
76196
  console.log(` Phases: ${result.phaseFiles.length}`);
75857
76197
  for (const f4 of result.phaseFiles) {
75858
- console.log(` [ ] ${basename21(f4)}`);
76198
+ console.log(` [ ] ${basename22(f4)}`);
75859
76199
  }
75860
76200
  console.log();
75861
76201
  }
@@ -75955,7 +76295,7 @@ function resolvePlanFile(target) {
75955
76295
  const stat13 = statSync9(t);
75956
76296
  if (stat13.isFile())
75957
76297
  return t;
75958
- const candidate = join126(t, "plan.md");
76298
+ const candidate = join128(t, "plan.md");
75959
76299
  if (existsSync60(candidate))
75960
76300
  return candidate;
75961
76301
  }
@@ -75963,10 +76303,10 @@ function resolvePlanFile(target) {
75963
76303
  let dir = process.cwd();
75964
76304
  const root = parse4(dir).root;
75965
76305
  while (dir !== root) {
75966
- const candidate = join126(dir, "plan.md");
76306
+ const candidate = join128(dir, "plan.md");
75967
76307
  if (existsSync60(candidate))
75968
76308
  return candidate;
75969
- dir = dirname40(dir);
76309
+ dir = dirname41(dir);
75970
76310
  }
75971
76311
  }
75972
76312
  return null;
@@ -76058,17 +76398,17 @@ init_logger();
76058
76398
  init_logger();
76059
76399
 
76060
76400
  // src/commands/telemetry/shared.ts
76061
- import { existsSync as existsSync61, readFileSync as readFileSync26, readdirSync as readdirSync10 } from "node:fs";
76401
+ import { existsSync as existsSync61, readFileSync as readFileSync26, readdirSync as readdirSync11 } from "node:fs";
76062
76402
  import { homedir as homedir29 } from "node:os";
76063
- import { join as join127 } from "node:path";
76403
+ import { join as join129 } from "node:path";
76064
76404
  init_token_store();
76065
76405
  init_manifest_path_resolver();
76066
76406
  init_takumi_constants();
76067
- var USER_CACHE_PATH = join127(homedir29(), ".claude", "sk-user.json");
76068
- var EVENT_BUFFER_DIR = join127(homedir29(), ".claude", "sk-events");
76069
- var RATE_STATE_PATH = join127(homedir29(), ".claude", "sk-rate-state.json");
76070
- var TAKUMI_MANIFEST_PATH = join127(homedir29(), ".claude", MANIFEST_FILENAME);
76071
- var LEGACY_METADATA_PATH = join127(homedir29(), ".claude", LEGACY_MANIFEST_FILENAME);
76407
+ var USER_CACHE_PATH = join129(homedir29(), ".claude", "sk-user.json");
76408
+ var EVENT_BUFFER_DIR = join129(homedir29(), ".claude", "sk-events");
76409
+ var RATE_STATE_PATH = join129(homedir29(), ".claude", "sk-rate-state.json");
76410
+ var TAKUMI_MANIFEST_PATH = join129(homedir29(), ".claude", MANIFEST_FILENAME);
76411
+ var LEGACY_METADATA_PATH = join129(homedir29(), ".claude", LEGACY_MANIFEST_FILENAME);
76072
76412
  var TELEMETRY_HOOK_FIELD = "hooks.telemetry";
76073
76413
  var TOKEN_PLACEHOLDER = "__INJECT_AT_RELEASE__";
76074
76414
  function readUserCache() {
@@ -76087,7 +76427,7 @@ function countBufferFiles() {
76087
76427
  try {
76088
76428
  if (!existsSync61(EVENT_BUFFER_DIR))
76089
76429
  return 0;
76090
- return readdirSync10(EVENT_BUFFER_DIR).filter((f4) => f4.endsWith(".jsonl")).length;
76430
+ return readdirSync11(EVENT_BUFFER_DIR).filter((f4) => f4.endsWith(".jsonl")).length;
76091
76431
  } catch {
76092
76432
  return 0;
76093
76433
  }
@@ -76097,7 +76437,7 @@ function readTelemetryConfig() {
76097
76437
  const envToken = process.env.TAKUMI_TELEMETRY_TOKEN;
76098
76438
  let metadata = null;
76099
76439
  try {
76100
- const resolved = findManifestPathSync(join127(homedir29(), ".claude"));
76440
+ const resolved = findManifestPathSync(join129(homedir29(), ".claude"));
76101
76441
  if (resolved) {
76102
76442
  metadata = JSON.parse(readFileSync26(resolved.path, "utf8"));
76103
76443
  }
@@ -76115,12 +76455,12 @@ function readTelemetryConfig() {
76115
76455
  return { endpoint, token };
76116
76456
  }
76117
76457
  function collectRuntimeContext() {
76118
- const cache2 = readUserCache();
76458
+ const cache3 = readUserCache();
76119
76459
  const { endpoint, token } = readTelemetryConfig();
76120
76460
  return {
76121
- githubLogin: typeof cache2?.githubLogin === "string" ? cache2.githubLogin : null,
76122
- cacheResolvedAt: typeof cache2?.resolvedAt === "number" ? cache2.resolvedAt : null,
76123
- cacheSource: cache2?.source === "gh" || cache2?.source === "manual" ? cache2.source : null,
76461
+ githubLogin: typeof cache3?.githubLogin === "string" ? cache3.githubLogin : null,
76462
+ cacheResolvedAt: typeof cache3?.resolvedAt === "number" ? cache3.resolvedAt : null,
76463
+ cacheSource: cache3?.source === "gh" || cache3?.source === "manual" ? cache3.source : null,
76124
76464
  bufferFileCount: countBufferFiles(),
76125
76465
  bufferDir: EVENT_BUFFER_DIR,
76126
76466
  rateStateExists: existsSync61(RATE_STATE_PATH),
@@ -76274,8 +76614,8 @@ init_logger();
76274
76614
  init_safe_prompts();
76275
76615
  init_safe_spinner();
76276
76616
  var import_fs_extra37 = __toESM(require_lib(), 1);
76277
- import { readdirSync as readdirSync12, rmSync as rmSync9 } from "node:fs";
76278
- import { join as join129, resolve as resolve34, sep as sep10 } from "node:path";
76617
+ import { readdirSync as readdirSync13, rmSync as rmSync9 } from "node:fs";
76618
+ import { join as join131, resolve as resolve34, sep as sep10 } from "node:path";
76279
76619
 
76280
76620
  // src/commands/uninstall/analysis-handler.ts
76281
76621
  init_metadata_migration();
@@ -76285,8 +76625,8 @@ init_logger();
76285
76625
  init_safe_prompts();
76286
76626
  init_takumi_constants();
76287
76627
  var import_picocolors27 = __toESM(require_picocolors(), 1);
76288
- import { existsSync as existsSync62, readdirSync as readdirSync11, rmSync as rmSync8 } from "node:fs";
76289
- import { dirname as dirname41, join as join128 } from "node:path";
76628
+ import { existsSync as existsSync62, readdirSync as readdirSync12, rmSync as rmSync8 } from "node:fs";
76629
+ import { dirname as dirname42, join as join130 } from "node:path";
76290
76630
  function listPresentManifestNames(installPath) {
76291
76631
  const present = [];
76292
76632
  if (existsSync62(getManifestPath(installPath)))
@@ -76309,15 +76649,15 @@ function classifyFileByOwnership(ownership, forceOverwrite, deleteReason) {
76309
76649
  }
76310
76650
  async function cleanupEmptyDirectories3(filePath, installationRoot) {
76311
76651
  let cleaned = 0;
76312
- let currentDir = dirname41(filePath);
76652
+ let currentDir = dirname42(filePath);
76313
76653
  while (currentDir !== installationRoot && currentDir.startsWith(installationRoot)) {
76314
76654
  try {
76315
- const entries = readdirSync11(currentDir);
76655
+ const entries = readdirSync12(currentDir);
76316
76656
  if (entries.length === 0) {
76317
76657
  rmSync8(currentDir, { recursive: true });
76318
76658
  cleaned++;
76319
76659
  logger.debug(`Removed empty directory: ${currentDir}`);
76320
- currentDir = dirname41(currentDir);
76660
+ currentDir = dirname42(currentDir);
76321
76661
  } else {
76322
76662
  break;
76323
76663
  }
@@ -76339,7 +76679,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
76339
76679
  if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
76340
76680
  const kitFiles = metadata.kits[kit].files || [];
76341
76681
  for (const trackedFile of kitFiles) {
76342
- const filePath = join128(installation.path, trackedFile.path);
76682
+ const filePath = join130(installation.path, trackedFile.path);
76343
76683
  if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
76344
76684
  result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
76345
76685
  continue;
@@ -76371,7 +76711,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
76371
76711
  return result;
76372
76712
  }
76373
76713
  for (const trackedFile of allTrackedFiles) {
76374
- const filePath = join128(installation.path, trackedFile.path);
76714
+ const filePath = join130(installation.path, trackedFile.path);
76375
76715
  const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
76376
76716
  if (!ownershipResult.exists)
76377
76717
  continue;
@@ -76470,7 +76810,7 @@ async function removeInstallations(installations, options2) {
76470
76810
  let removedCount = 0;
76471
76811
  let cleanedDirs = 0;
76472
76812
  for (const item of analysis.toDelete) {
76473
- const filePath = join129(installation.path, item.path);
76813
+ const filePath = join131(installation.path, item.path);
76474
76814
  if (!await import_fs_extra37.pathExists(filePath))
76475
76815
  continue;
76476
76816
  if (!await isPathSafeToRemove(filePath, installation.path)) {
@@ -76489,7 +76829,7 @@ async function removeInstallations(installations, options2) {
76489
76829
  await ManifestWriter.removeKitFromManifest(installation.path, options2.kit);
76490
76830
  }
76491
76831
  try {
76492
- const remaining = readdirSync12(installation.path);
76832
+ const remaining = readdirSync13(installation.path);
76493
76833
  if (remaining.length === 0) {
76494
76834
  rmSync9(installation.path, { recursive: true });
76495
76835
  logger.debug(`Removed empty installation directory: ${installation.path}`);
@@ -77197,7 +77537,7 @@ ${import_picocolors29.default.bold(import_picocolors29.default.cyan(result.kitCo
77197
77537
  // src/cli/command-registry.ts
77198
77538
  init_logger();
77199
77539
  function registerCommands(cli) {
77200
- cli.command("init", "Initialize or update Takumi project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit(s) to install (core, extras). Repeat the flag to install multiple kits, e.g. --kit core --kit extras.").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--only <pattern>", "Include only files matching glob pattern (can be used multiple times)").option("-g, --global", "Use platform-specific user configuration directory").option("--fresh", "Full reset: remove SK files, replace settings.json and CLAUDE.md, reinstall from scratch").option("--force", "Force reinstall even if already at latest version (use with --yes; re-onboards missing files without full reset)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /sk: prefix to all slash commands by moving them to commands/sk/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--dry-run", "Preview changes without applying them (requires --prefix)").option("--force-overwrite", "Override ownership protections and delete user-modified files (requires --prefix)").option("--force-overwrite-settings", "Fully replace settings.json instead of selective merge (destroys user customizations)").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("--sync", "Sync config files from upstream with interactive hunk-by-hunk merge").option("--use-git", "Use git clone instead of GitHub API (uses SSH/HTTPS credentials)").option("--archive <path>", "Use local archive file instead of downloading (zip/tar.gz)").option("--kit-path <path>", "Use local kit directory instead of downloading").option("--local", "Use local monorepo as kit source (auto-detects from CLI location)").option("--use-gh", "Force GitHub release source (bypass Worker R2 proxy; default uses Worker)").option("-a, --agent <agents...>", "Target agents (claude-code, codex). Default: claude-code").action(async (options2) => {
77540
+ cli.command("init", "Initialize or update Takumi project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit(s) to install (core, extras). Repeat the flag to install multiple kits, e.g. --kit core --kit extras.").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--only <pattern>", "Include only files matching glob pattern (can be used multiple times)").option("-g, --global", "Use platform-specific user configuration directory").option("--fresh", "Full reset: remove SK files, replace settings.json and CLAUDE.md, reinstall from scratch").option("--force", "Force reinstall even if already at latest version (use with --yes; re-onboards missing files without full reset)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--install-hooks", "Install all agent hooks (guard, session, convention, extension). Default installs only telemetry hooks.").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /sk: prefix to all slash commands by moving them to commands/sk/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--dry-run", "Preview changes without applying them (requires --prefix)").option("--force-overwrite", "Override ownership protections and delete user-modified files (requires --prefix)").option("--force-overwrite-settings", "Fully replace settings.json instead of selective merge (destroys user customizations)").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("--sync", "Sync config files from upstream with interactive hunk-by-hunk merge").option("--use-git", "Use git clone instead of GitHub API (uses SSH/HTTPS credentials)").option("--archive <path>", "Use local archive file instead of downloading (zip/tar.gz)").option("--kit-path <path>", "Use local kit directory instead of downloading").option("--local", "Use local monorepo as kit source (auto-detects from CLI location)").option("--use-gh", "Force GitHub release source (bypass Worker R2 proxy; default uses Worker)").option("-a, --agent <agents...>", "Target agents (claude-code, codex). Default: claude-code").action(async (options2) => {
77201
77541
  if (options2.exclude && !Array.isArray(options2.exclude)) {
77202
77542
  options2.exclude = [options2.exclude];
77203
77543
  }
@@ -77334,7 +77674,7 @@ init_manifest_path_resolver();
77334
77674
  init_logger();
77335
77675
  init_types2();
77336
77676
  import { readFileSync as readFileSync27 } from "node:fs";
77337
- import { join as join130 } from "node:path";
77677
+ import { join as join132 } from "node:path";
77338
77678
  var PROVIDER_LOCAL_SUBDIRS = {
77339
77679
  "claude-code": ".claude",
77340
77680
  codex: ".codex"
@@ -77389,7 +77729,7 @@ async function displayVersion() {
77389
77729
  const localSubdir = PROVIDER_LOCAL_SUBDIRS[provider];
77390
77730
  if (!localSubdir)
77391
77731
  continue;
77392
- const localRoot = join130(process.cwd(), localSubdir);
77732
+ const localRoot = join132(process.cwd(), localSubdir);
77393
77733
  if (localRoot === inst.globalRoot())
77394
77734
  continue;
77395
77735
  const resolved = findManifestPathSync(localRoot);