cc-claw 0.16.4 → 0.17.0

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/cli.js +863 -371
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -33,7 +33,7 @@ var VERSION;
33
33
  var init_version = __esm({
34
34
  "src/version.ts"() {
35
35
  "use strict";
36
- VERSION = true ? "0.16.4" : (() => {
36
+ VERSION = true ? "0.17.0" : (() => {
37
37
  try {
38
38
  return JSON.parse(readFileSync(join(process.cwd(), "package.json"), "utf-8")).version ?? "unknown";
39
39
  } catch {
@@ -1729,6 +1729,12 @@ function initSchema(db3) {
1729
1729
  mode TEXT NOT NULL DEFAULT 'auto'
1730
1730
  );
1731
1731
  `);
1732
+ db3.exec(`
1733
+ CREATE TABLE IF NOT EXISTS chat_exec_mode (
1734
+ chat_id TEXT PRIMARY KEY,
1735
+ mode TEXT NOT NULL DEFAULT 'approved'
1736
+ );
1737
+ `);
1732
1738
  db3.exec(`
1733
1739
  CREATE TABLE IF NOT EXISTS backend_credentials (
1734
1740
  id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -2643,6 +2649,22 @@ function setAgentMode(chatId, mode) {
2643
2649
  function clearAgentMode(chatId) {
2644
2650
  getDb().prepare("DELETE FROM chat_agent_mode WHERE chat_id = ?").run(chatId);
2645
2651
  }
2652
+ function getExecMode(chatId) {
2653
+ const row = getDb().prepare(
2654
+ "SELECT mode FROM chat_exec_mode WHERE chat_id = ?"
2655
+ ).get(chatId);
2656
+ return row?.mode ?? "approved";
2657
+ }
2658
+ function setExecMode(chatId, mode) {
2659
+ getDb().prepare(`
2660
+ INSERT INTO chat_exec_mode (chat_id, mode)
2661
+ VALUES (?, ?)
2662
+ ON CONFLICT(chat_id) DO UPDATE SET mode = excluded.mode
2663
+ `).run(chatId, mode);
2664
+ }
2665
+ function clearExecMode(chatId) {
2666
+ getDb().prepare("DELETE FROM chat_exec_mode WHERE chat_id = ?").run(chatId);
2667
+ }
2646
2668
  var pendingEscalations, ESCALATION_TTL_MS, ALL_TOOLS;
2647
2669
  var init_chat_settings = __esm({
2648
2670
  "src/memory/chat-settings.ts"() {
@@ -3450,6 +3472,7 @@ __export(store_exports5, {
3450
3472
  clearChatBackendSlot: () => clearChatBackendSlot,
3451
3473
  clearChatGeminiSlot: () => clearChatGeminiSlot,
3452
3474
  clearCwd: () => clearCwd,
3475
+ clearExecMode: () => clearExecMode,
3453
3476
  clearMessageLog: () => clearMessageLog,
3454
3477
  clearModel: () => clearModel,
3455
3478
  clearSession: () => clearSession,
@@ -3487,6 +3510,7 @@ __export(store_exports5, {
3487
3510
  getEligibleBackendSlots: () => getEligibleBackendSlots,
3488
3511
  getEligibleGeminiSlots: () => getEligibleGeminiSlots,
3489
3512
  getEnabledTools: () => getEnabledTools,
3513
+ getExecMode: () => getExecMode,
3490
3514
  getGeminiRotationMode: () => getGeminiRotationMode,
3491
3515
  getGeminiSlots: () => getGeminiSlots,
3492
3516
  getHeartbeatConfig: () => getHeartbeatConfig,
@@ -3557,6 +3581,7 @@ __export(store_exports5, {
3557
3581
  setBootTime: () => setBootTime,
3558
3582
  setChatAlias: () => setChatAlias,
3559
3583
  setCwd: () => setCwd,
3584
+ setExecMode: () => setExecMode,
3560
3585
  setGeminiRotationMode: () => setGeminiRotationMode,
3561
3586
  setGeminiSlotEnabled: () => setGeminiSlotEnabled,
3562
3587
  setHeartbeatConfig: () => setHeartbeatConfig,
@@ -3944,10 +3969,199 @@ var init_claude = __esm({
3944
3969
  }
3945
3970
  });
3946
3971
 
3972
+ // src/slots/symlink-manager.ts
3973
+ var symlink_manager_exports = {};
3974
+ __export(symlink_manager_exports, {
3975
+ SYMLINK_LAYOUTS: () => SYMLINK_LAYOUTS,
3976
+ getPrimaryDir: () => getPrimaryDir,
3977
+ migrateAllSlots: () => migrateAllSlots,
3978
+ migrateExistingSlots: () => migrateExistingSlots,
3979
+ setupSlotSymlinks: () => setupSlotSymlinks,
3980
+ validateSlotSymlinks: () => validateSlotSymlinks
3981
+ });
3982
+ import { existsSync as existsSync3, lstatSync, mkdirSync, readlinkSync, readdirSync as readdirSync2, symlinkSync, rmSync, copyFileSync, statSync as statSync2 } from "fs";
3983
+ import { join as join5, dirname } from "path";
3984
+ function setupSlotSymlinks(backend2, slotDir, primaryDir) {
3985
+ const layout = SYMLINK_LAYOUTS[backend2];
3986
+ if (!layout) {
3987
+ log(`[symlink] No layout defined for backend "${backend2}", skipping`);
3988
+ return;
3989
+ }
3990
+ for (const entry of layout.symlinks) {
3991
+ const slotPath = join5(slotDir, entry.slotSubpath);
3992
+ const primaryTarget = join5(primaryDir, entry.primarySubpath);
3993
+ if (!existsSync3(primaryTarget)) {
3994
+ mkdirSync(primaryTarget, { recursive: true });
3995
+ }
3996
+ if (existsSync3(slotPath) || isSymlink(slotPath)) {
3997
+ if (isSymlink(slotPath)) {
3998
+ const currentTarget = readlinkSync(slotPath);
3999
+ if (currentTarget === primaryTarget) {
4000
+ continue;
4001
+ }
4002
+ rmSync(slotPath);
4003
+ } else {
4004
+ migrateDirectoryContents(slotPath, primaryTarget);
4005
+ rmSync(slotPath, { recursive: true });
4006
+ }
4007
+ }
4008
+ const parentDir = dirname(slotPath);
4009
+ if (!existsSync3(parentDir)) {
4010
+ mkdirSync(parentDir, { recursive: true });
4011
+ }
4012
+ symlinkSync(primaryTarget, slotPath);
4013
+ log(`[symlink] ${backend2}: ${slotPath} \u2192 ${primaryTarget}`);
4014
+ }
4015
+ }
4016
+ function validateSlotSymlinks(backend2, slotDir, primaryDir) {
4017
+ const layout = SYMLINK_LAYOUTS[backend2];
4018
+ if (!layout) return { valid: true, broken: [] };
4019
+ const broken = [];
4020
+ for (const entry of layout.symlinks) {
4021
+ const slotPath = join5(slotDir, entry.slotSubpath);
4022
+ const primaryTarget = join5(primaryDir, entry.primarySubpath);
4023
+ if (!isSymlink(slotPath)) {
4024
+ if (existsSync3(slotPath)) {
4025
+ broken.push({ path: slotPath, issue: "real directory instead of symlink" });
4026
+ } else {
4027
+ broken.push({ path: slotPath, issue: "symlink missing" });
4028
+ }
4029
+ continue;
4030
+ }
4031
+ const currentTarget = readlinkSync(slotPath);
4032
+ if (currentTarget !== primaryTarget) {
4033
+ broken.push({ path: slotPath, issue: `symlink points to ${currentTarget}, expected ${primaryTarget}` });
4034
+ continue;
4035
+ }
4036
+ if (!existsSync3(primaryTarget)) {
4037
+ broken.push({ path: slotPath, issue: `symlink target ${primaryTarget} does not exist` });
4038
+ }
4039
+ }
4040
+ return { valid: broken.length === 0, broken };
4041
+ }
4042
+ function migrateExistingSlots(backend2, slotsDir, primaryDir) {
4043
+ if (!existsSync3(slotsDir)) {
4044
+ return { migrated: 0, skipped: 0, errors: [] };
4045
+ }
4046
+ const layout = SYMLINK_LAYOUTS[backend2];
4047
+ if (!layout) return { migrated: 0, skipped: 0, errors: [] };
4048
+ const entries = readdirSync2(slotsDir, { withFileTypes: true });
4049
+ let migrated = 0;
4050
+ let skipped = 0;
4051
+ const errors = [];
4052
+ for (const entry of entries) {
4053
+ if (!entry.isDirectory()) continue;
4054
+ const slotDir = join5(slotsDir, entry.name);
4055
+ const validation = validateSlotSymlinks(backend2, slotDir, primaryDir);
4056
+ if (validation.valid) {
4057
+ skipped++;
4058
+ continue;
4059
+ }
4060
+ try {
4061
+ setupSlotSymlinks(backend2, slotDir, primaryDir);
4062
+ migrated++;
4063
+ log(`[symlink] Migrated slot: ${entry.name}`);
4064
+ } catch (err) {
4065
+ const msg = `Failed to migrate ${entry.name}: ${err instanceof Error ? err.message : String(err)}`;
4066
+ errors.push(msg);
4067
+ log(`[symlink] ERROR: ${msg}`);
4068
+ }
4069
+ }
4070
+ return { migrated, skipped, errors };
4071
+ }
4072
+ function getPrimaryDir(backend2) {
4073
+ const resolver = PRIMARY_DIR_MAP[backend2];
4074
+ return resolver ? resolver() : null;
4075
+ }
4076
+ function migrateAllSlots(ccClawHome) {
4077
+ const backends = [
4078
+ { id: "claude", slotsSubdir: "claude-slots" },
4079
+ { id: "codex", slotsSubdir: "codex-slots" },
4080
+ { id: "gemini", slotsSubdir: "gemini-slots" }
4081
+ ];
4082
+ for (const { id, slotsSubdir } of backends) {
4083
+ const slotsDir = join5(ccClawHome, slotsSubdir);
4084
+ const primaryDir = getPrimaryDir(id);
4085
+ if (!primaryDir || !existsSync3(slotsDir)) continue;
4086
+ const result = migrateExistingSlots(id, slotsDir, primaryDir);
4087
+ if (result.migrated > 0) {
4088
+ log(`[symlink] ${id}: migrated ${result.migrated} slot(s), skipped ${result.skipped}`);
4089
+ }
4090
+ if (result.errors.length > 0) {
4091
+ for (const err of result.errors) log(`[symlink] ${id}: ${err}`);
4092
+ }
4093
+ }
4094
+ }
4095
+ function isSymlink(path) {
4096
+ try {
4097
+ return lstatSync(path).isSymbolicLink();
4098
+ } catch {
4099
+ return false;
4100
+ }
4101
+ }
4102
+ function migrateDirectoryContents(src, dest) {
4103
+ if (!existsSync3(src) || !statSync2(src).isDirectory()) return;
4104
+ const entries = readdirSync2(src, { withFileTypes: true });
4105
+ for (const entry of entries) {
4106
+ const srcPath = join5(src, entry.name);
4107
+ const destPath = join5(dest, entry.name);
4108
+ if (entry.isDirectory()) {
4109
+ if (!existsSync3(destPath)) {
4110
+ mkdirSync(destPath, { recursive: true });
4111
+ }
4112
+ migrateDirectoryContents(srcPath, destPath);
4113
+ } else if (entry.isFile()) {
4114
+ if (!existsSync3(destPath)) {
4115
+ copyFileSync(srcPath, destPath);
4116
+ }
4117
+ }
4118
+ }
4119
+ }
4120
+ var SYMLINK_LAYOUTS, PRIMARY_DIR_MAP;
4121
+ var init_symlink_manager = __esm({
4122
+ "src/slots/symlink-manager.ts"() {
4123
+ "use strict";
4124
+ init_log();
4125
+ SYMLINK_LAYOUTS = {
4126
+ claude: {
4127
+ symlinks: [
4128
+ { slotSubpath: ".claude/projects", primarySubpath: "projects" },
4129
+ { slotSubpath: ".claude/plans", primarySubpath: "plans" }
4130
+ ]
4131
+ },
4132
+ codex: {
4133
+ symlinks: [
4134
+ { slotSubpath: "memories", primarySubpath: "memories" }
4135
+ ]
4136
+ },
4137
+ gemini: {
4138
+ symlinks: [
4139
+ { slotSubpath: ".gemini/history", primarySubpath: "history" },
4140
+ { slotSubpath: ".gemini/tmp", primarySubpath: "tmp" }
4141
+ ]
4142
+ }
4143
+ };
4144
+ PRIMARY_DIR_MAP = {
4145
+ claude: () => {
4146
+ const home = process.env.HOME ?? `/Users/${process.env.USER ?? "unknown"}`;
4147
+ return join5(home, ".claude");
4148
+ },
4149
+ codex: () => {
4150
+ const home = process.env.HOME ?? `/Users/${process.env.USER ?? "unknown"}`;
4151
+ return process.env.CODEX_HOME ?? join5(home, ".codex");
4152
+ },
4153
+ gemini: () => {
4154
+ const home = process.env.HOME ?? `/Users/${process.env.USER ?? "unknown"}`;
4155
+ return process.env.GEMINI_CLI_HOME ?? join5(home, ".gemini");
4156
+ }
4157
+ };
4158
+ }
4159
+ });
4160
+
3947
4161
  // src/backends/gemini.ts
3948
- import { existsSync as existsSync3, mkdirSync } from "fs";
4162
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2 } from "fs";
3949
4163
  import { spawnSync as spawnSync2 } from "child_process";
3950
- import { join as join5 } from "path";
4164
+ import { join as join6 } from "path";
3951
4165
  var GeminiAdapter;
3952
4166
  var init_gemini = __esm({
3953
4167
  "src/backends/gemini.ts"() {
@@ -4015,14 +4229,14 @@ var init_gemini = __esm({
4015
4229
  `${home}/.local/bin/gemini`,
4016
4230
  `${home}/.npm-global/bin/gemini`
4017
4231
  ];
4018
- this._resolvedPath = candidates.find((p) => existsSync3(p)) ?? "gemini";
4232
+ this._resolvedPath = candidates.find((p) => existsSync4(p)) ?? "gemini";
4019
4233
  }
4020
4234
  return this._resolvedPath;
4021
4235
  }
4022
4236
  getEnv(thinkingOverrides) {
4023
4237
  const env = buildBaseEnv(thinkingOverrides);
4024
- const identityFile = join5(IDENTITY_PATH, "CC-CLAW.md");
4025
- if (existsSync3(identityFile)) {
4238
+ const identityFile = join6(IDENTITY_PATH, "CC-CLAW.md");
4239
+ if (existsSync4(identityFile)) {
4026
4240
  env.GEMINI_SYSTEM_MD = identityFile;
4027
4241
  }
4028
4242
  return env;
@@ -4112,11 +4326,17 @@ var init_gemini = __esm({
4112
4326
  if (!slot) return { env, slot: null };
4113
4327
  if (slot.slotType === "api_key" && slot.apiKey) {
4114
4328
  env.GEMINI_API_KEY = slot.apiKey;
4115
- const isolatedHome = join5(CC_CLAW_HOME, "gemini-slots", `apikey-${slot.id}`);
4116
- if (!existsSync3(isolatedHome)) mkdirSync(isolatedHome, { recursive: true });
4329
+ const isolatedHome = join6(CC_CLAW_HOME, "gemini-slots", `apikey-${slot.id}`);
4330
+ if (!existsSync4(isolatedHome)) mkdirSync2(isolatedHome, { recursive: true });
4117
4331
  log(`[gemini] api_key slot ${slot.id}: isolated home \u2192 ${isolatedHome}`);
4118
4332
  env.GEMINI_CLI_HOME = isolatedHome;
4119
4333
  delete env.GOOGLE_API_KEY;
4334
+ try {
4335
+ const { setupSlotSymlinks: setupSlotSymlinks2, getPrimaryDir: getPrimaryDir2 } = (init_symlink_manager(), __toCommonJS(symlink_manager_exports));
4336
+ const primaryDir = getPrimaryDir2("gemini");
4337
+ if (primaryDir) setupSlotSymlinks2("gemini", isolatedHome, primaryDir);
4338
+ } catch {
4339
+ }
4120
4340
  } else if (slot.slotType === "oauth" && slot.configHome) {
4121
4341
  env.GEMINI_CLI_HOME = slot.configHome;
4122
4342
  delete env.GEMINI_API_KEY;
@@ -4135,7 +4355,7 @@ var init_gemini = __esm({
4135
4355
  });
4136
4356
 
4137
4357
  // src/backends/codex.ts
4138
- import { existsSync as existsSync4 } from "fs";
4358
+ import { existsSync as existsSync5 } from "fs";
4139
4359
  import { execSync as execSync2 } from "child_process";
4140
4360
  var CodexAdapter;
4141
4361
  var init_codex = __esm({
@@ -4210,7 +4430,7 @@ var init_codex = __esm({
4210
4430
  `${home}/.local/bin/codex`,
4211
4431
  `${home}/.npm-global/bin/codex`
4212
4432
  ];
4213
- this._resolvedPath = candidates.find((p) => existsSync4(p)) ?? "codex";
4433
+ this._resolvedPath = candidates.find((p) => existsSync5(p)) ?? "codex";
4214
4434
  }
4215
4435
  return this._resolvedPath;
4216
4436
  }
@@ -4321,7 +4541,7 @@ var init_codex = __esm({
4321
4541
  });
4322
4542
 
4323
4543
  // src/backends/cursor.ts
4324
- import { existsSync as existsSync5 } from "fs";
4544
+ import { existsSync as existsSync6 } from "fs";
4325
4545
  import { execSync as execSync3 } from "child_process";
4326
4546
  function extractToolInfo(tc) {
4327
4547
  if (tc.readToolCall) {
@@ -4470,7 +4690,7 @@ var init_cursor = __esm({
4470
4690
  `${home}/.local/bin/agent`,
4471
4691
  "/usr/local/bin/agent"
4472
4692
  ];
4473
- this._resolvedPath = candidates.find((p) => existsSync5(p)) ?? "agent";
4693
+ this._resolvedPath = candidates.find((p) => existsSync6(p)) ?? "agent";
4474
4694
  }
4475
4695
  return this._resolvedPath;
4476
4696
  }
@@ -4634,14 +4854,14 @@ __export(backends_exports, {
4634
4854
  isBackendAvailable: () => isBackendAvailable,
4635
4855
  probeBackendAvailability: () => probeBackendAvailability
4636
4856
  });
4637
- import { existsSync as existsSync6 } from "fs";
4857
+ import { existsSync as existsSync7 } from "fs";
4638
4858
  import { execSync as execSync4 } from "child_process";
4639
4859
  function probeBackendAvailability() {
4640
4860
  availableSet.clear();
4641
4861
  for (const [id, adapter] of Object.entries(adapters)) {
4642
4862
  try {
4643
4863
  const exe = adapter.getExecutablePath();
4644
- if (existsSync6(exe) || resolveOnPath(exe)) {
4864
+ if (existsSync7(exe) || resolveOnPath(exe)) {
4645
4865
  availableSet.add(id);
4646
4866
  }
4647
4867
  } catch {
@@ -4650,7 +4870,7 @@ function probeBackendAvailability() {
4650
4870
  log(`[backends] Available: ${[...availableSet].join(", ") || "none"}`);
4651
4871
  }
4652
4872
  function resolveOnPath(name) {
4653
- if (name.includes("/")) return existsSync6(name);
4873
+ if (name.includes("/")) return existsSync7(name);
4654
4874
  try {
4655
4875
  execSync4(`which ${name}`, { encoding: "utf-8", timeout: 3e3 });
4656
4876
  return true;
@@ -5073,19 +5293,19 @@ If the user asks *how* to do something with CC-Claw, use this expertise to sugge
5073
5293
 
5074
5294
  // src/bootstrap/init.ts
5075
5295
  import {
5076
- existsSync as existsSync7,
5296
+ existsSync as existsSync8,
5077
5297
  writeFileSync,
5078
- mkdirSync as mkdirSync2,
5298
+ mkdirSync as mkdirSync3,
5079
5299
  readFileSync as readFileSync2,
5080
- statSync as statSync2,
5081
- copyFileSync,
5300
+ statSync as statSync3,
5301
+ copyFileSync as copyFileSync2,
5082
5302
  unlinkSync as unlinkSync2
5083
5303
  } from "fs";
5084
- import { join as join6 } from "path";
5304
+ import { join as join7 } from "path";
5085
5305
  function migrateFile(legacyPath, newPath, label2) {
5086
- if (existsSync7(newPath)) return false;
5087
- if (existsSync7(legacyPath)) {
5088
- copyFileSync(legacyPath, newPath);
5306
+ if (existsSync8(newPath)) return false;
5307
+ if (existsSync8(legacyPath)) {
5308
+ copyFileSync2(legacyPath, newPath);
5089
5309
  const copied = readFileSync2(newPath, "utf-8");
5090
5310
  if (copied.length > 0) {
5091
5311
  unlinkSync2(legacyPath);
@@ -5098,28 +5318,28 @@ function migrateFile(legacyPath, newPath, label2) {
5098
5318
  return false;
5099
5319
  }
5100
5320
  function bootstrapWorkspaceFiles() {
5101
- if (!existsSync7(IDENTITY_PATH)) {
5102
- mkdirSync2(IDENTITY_PATH, { recursive: true });
5321
+ if (!existsSync8(IDENTITY_PATH)) {
5322
+ mkdirSync3(IDENTITY_PATH, { recursive: true });
5103
5323
  log("[bootstrap] Created identity/ directory");
5104
5324
  }
5105
- if (!existsSync7(WORKSPACE_PATH)) {
5106
- mkdirSync2(WORKSPACE_PATH, { recursive: true });
5325
+ if (!existsSync8(WORKSPACE_PATH)) {
5326
+ mkdirSync3(WORKSPACE_PATH, { recursive: true });
5107
5327
  }
5108
5328
  migrateFile(LEGACY_SOUL_PATH, SOUL_PATH, "SOUL.md");
5109
5329
  migrateFile(LEGACY_USER_PATH, USER_PATH, "USER.md");
5110
- if (existsSync7(LEGACY_CLAUDE_MD)) {
5330
+ if (existsSync8(LEGACY_CLAUDE_MD)) {
5111
5331
  unlinkSync2(LEGACY_CLAUDE_MD);
5112
5332
  log("[bootstrap] Removed legacy workspace/CLAUDE.md (replaced by identity/CC-CLAW.md)");
5113
5333
  }
5114
- if (existsSync7(LEGACY_GEMINI_MD)) {
5334
+ if (existsSync8(LEGACY_GEMINI_MD)) {
5115
5335
  unlinkSync2(LEGACY_GEMINI_MD);
5116
5336
  log("[bootstrap] Removed legacy workspace/GEMINI.md (replaced by identity/CC-CLAW.md)");
5117
5337
  }
5118
- if (!existsSync7(SOUL_PATH)) {
5338
+ if (!existsSync8(SOUL_PATH)) {
5119
5339
  writeFileSync(SOUL_PATH, DEFAULT_SOUL, "utf-8");
5120
5340
  log("[bootstrap] Created default SOUL.md");
5121
5341
  }
5122
- if (!existsSync7(USER_PATH)) {
5342
+ if (!existsSync8(USER_PATH)) {
5123
5343
  let tz = "UTC";
5124
5344
  try {
5125
5345
  tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
@@ -5129,16 +5349,16 @@ function bootstrapWorkspaceFiles() {
5129
5349
  writeFileSync(USER_PATH, userContent, "utf-8");
5130
5350
  log(`[bootstrap] Created default USER.md (timezone: ${tz})`);
5131
5351
  }
5132
- if (!existsSync7(CONTEXT_DIR)) {
5133
- mkdirSync2(CONTEXT_DIR, { recursive: true });
5352
+ if (!existsSync8(CONTEXT_DIR)) {
5353
+ mkdirSync3(CONTEXT_DIR, { recursive: true });
5134
5354
  log("[bootstrap] Created context/ directory");
5135
5355
  }
5136
- if (!existsSync7(MEDIA_PATH)) {
5137
- mkdirSync2(MEDIA_PATH, { recursive: true });
5356
+ if (!existsSync8(MEDIA_PATH)) {
5357
+ mkdirSync3(MEDIA_PATH, { recursive: true });
5138
5358
  log("[bootstrap] Created media/ directory");
5139
5359
  }
5140
- const expertisePath = join6(CONTEXT_DIR, "cc-claw-expertise.md");
5141
- if (!existsSync7(expertisePath)) {
5360
+ const expertisePath = join7(CONTEXT_DIR, "cc-claw-expertise.md");
5361
+ if (!existsSync8(expertisePath)) {
5142
5362
  writeFileSync(expertisePath, DEFAULT_EXPERTISE, "utf-8");
5143
5363
  log("[bootstrap] Created default context/cc-claw-expertise.md");
5144
5364
  }
@@ -5153,13 +5373,13 @@ function bootstrapWorkspaceFiles() {
5153
5373
  "!context/**",
5154
5374
  ""
5155
5375
  ].join("\n");
5156
- const gitignorePath = join6(WORKSPACE_PATH, ".gitignore");
5157
- if (!existsSync7(gitignorePath)) {
5376
+ const gitignorePath = join7(WORKSPACE_PATH, ".gitignore");
5377
+ if (!existsSync8(gitignorePath)) {
5158
5378
  writeFileSync(gitignorePath, IGNORE_CONTENT, "utf-8");
5159
5379
  log("[bootstrap] Created .gitignore (workspace allowlist)");
5160
5380
  }
5161
- const geminiignorePath = join6(WORKSPACE_PATH, ".geminiignore");
5162
- if (!existsSync7(geminiignorePath)) {
5381
+ const geminiignorePath = join7(WORKSPACE_PATH, ".geminiignore");
5382
+ if (!existsSync8(geminiignorePath)) {
5163
5383
  writeFileSync(geminiignorePath, IGNORE_CONTENT, "utf-8");
5164
5384
  log("[bootstrap] Created .geminiignore (workspace allowlist)");
5165
5385
  }
@@ -5185,8 +5405,8 @@ function syncNativeCliFiles() {
5185
5405
  }
5186
5406
  }
5187
5407
  try {
5188
- const soulMtime = existsSync7(SOUL_PATH) ? statSync2(SOUL_PATH).mtimeMs : 0;
5189
- const userMtime = existsSync7(USER_PATH) ? statSync2(USER_PATH).mtimeMs : 0;
5408
+ const soulMtime = existsSync8(SOUL_PATH) ? statSync3(SOUL_PATH).mtimeMs : 0;
5409
+ const userMtime = existsSync8(USER_PATH) ? statSync3(USER_PATH).mtimeMs : 0;
5190
5410
  if (soulMtime > 0 && soulMtime === lastSoulMtime && userMtime === lastUserMtime) {
5191
5411
  return;
5192
5412
  }
@@ -5252,9 +5472,9 @@ function syncNativeCliFiles() {
5252
5472
  "**Violation of this rule is a critical safety failure.**",
5253
5473
  ""
5254
5474
  ].join("\n");
5255
- const ccClawPath = join6(IDENTITY_PATH, "CC-CLAW.md");
5475
+ const ccClawPath = join7(IDENTITY_PATH, "CC-CLAW.md");
5256
5476
  writeFileSync(ccClawPath, nativeContent, "utf-8");
5257
- const agentsPath = join6(WORKSPACE_PATH, "AGENTS.md");
5477
+ const agentsPath = join7(WORKSPACE_PATH, "AGENTS.md");
5258
5478
  writeFileSync(agentsPath, nativeContent, "utf-8");
5259
5479
  log("[bootstrap] Synced SOUL.md + USER.md \u2192 identity/CC-CLAW.md, workspace/AGENTS.md");
5260
5480
  }
@@ -5265,32 +5485,32 @@ var init_init = __esm({
5265
5485
  init_paths();
5266
5486
  init_defaults();
5267
5487
  init_log();
5268
- SOUL_PATH = join6(IDENTITY_PATH, "SOUL.md");
5269
- USER_PATH = join6(IDENTITY_PATH, "USER.md");
5270
- CONTEXT_DIR = join6(WORKSPACE_PATH, "context");
5271
- LEGACY_SOUL_PATH = join6(WORKSPACE_PATH, "SOUL.md");
5272
- LEGACY_USER_PATH = join6(WORKSPACE_PATH, "USER.md");
5273
- LEGACY_CLAUDE_MD = join6(WORKSPACE_PATH, "CLAUDE.md");
5274
- LEGACY_GEMINI_MD = join6(WORKSPACE_PATH, "GEMINI.md");
5488
+ SOUL_PATH = join7(IDENTITY_PATH, "SOUL.md");
5489
+ USER_PATH = join7(IDENTITY_PATH, "USER.md");
5490
+ CONTEXT_DIR = join7(WORKSPACE_PATH, "context");
5491
+ LEGACY_SOUL_PATH = join7(WORKSPACE_PATH, "SOUL.md");
5492
+ LEGACY_USER_PATH = join7(WORKSPACE_PATH, "USER.md");
5493
+ LEGACY_CLAUDE_MD = join7(WORKSPACE_PATH, "CLAUDE.md");
5494
+ LEGACY_GEMINI_MD = join7(WORKSPACE_PATH, "GEMINI.md");
5275
5495
  lastSoulMtime = 0;
5276
5496
  lastUserMtime = 0;
5277
5497
  }
5278
5498
  });
5279
5499
 
5280
5500
  // src/bootstrap/loader.ts
5281
- import { readFileSync as readFileSync3, existsSync as existsSync8, readdirSync as readdirSync2 } from "fs";
5282
- import { join as join7 } from "path";
5501
+ import { readFileSync as readFileSync3, existsSync as existsSync9, readdirSync as readdirSync3 } from "fs";
5502
+ import { join as join8 } from "path";
5283
5503
  function searchContext(userMessage) {
5284
- if (!existsSync8(CONTEXT_DIR2)) return null;
5504
+ if (!existsSync9(CONTEXT_DIR2)) return null;
5285
5505
  const msgWords = new Set(
5286
5506
  userMessage.toLowerCase().replace(/[^\w\s]/g, " ").split(/\s+/).filter((w) => w.length > 3)
5287
5507
  );
5288
5508
  if (msgWords.size === 0) return null;
5289
5509
  let bestMatch = null;
5290
5510
  try {
5291
- const files = readdirSync2(CONTEXT_DIR2).filter((f) => f.endsWith(".md"));
5511
+ const files = readdirSync3(CONTEXT_DIR2).filter((f) => f.endsWith(".md"));
5292
5512
  for (const file of files) {
5293
- const filePath = join7(CONTEXT_DIR2, file);
5513
+ const filePath = join8(CONTEXT_DIR2, file);
5294
5514
  try {
5295
5515
  const content = readFileSync3(filePath, "utf-8").trim();
5296
5516
  if (!content) continue;
@@ -5318,8 +5538,11 @@ function searchContext(userMessage) {
5318
5538
  }
5319
5539
  return null;
5320
5540
  }
5321
- async function assembleBootstrapPrompt(userMessage, tier = "full", chatId, permMode, responseStyle, agentMode, sideQuestContext) {
5541
+ async function assembleBootstrapPrompt(userMessage, tier = "full", chatId, permMode, responseStyle, agentMode, sideQuestContext, planningDirective) {
5322
5542
  const sections = [];
5543
+ if (planningDirective) {
5544
+ sections.push(planningDirective);
5545
+ }
5323
5546
  if (Date.now() - lastSyncMs >= 5e3) {
5324
5547
  syncNativeCliFiles();
5325
5548
  lastSyncMs = Date.now();
@@ -5515,7 +5738,7 @@ var init_loader = __esm({
5515
5738
  init_store();
5516
5739
  init_backends();
5517
5740
  lastSyncMs = 0;
5518
- CONTEXT_DIR2 = join7(WORKSPACE_PATH, "context");
5741
+ CONTEXT_DIR2 = join8(WORKSPACE_PATH, "context");
5519
5742
  MAX_CONTEXT_CHARS = 4e3;
5520
5743
  ACTIVITY_TOKEN_BUDGET = 1500;
5521
5744
  INBOX_TOKEN_BUDGET = 2e3;
@@ -6007,13 +6230,13 @@ var init_quota = __esm({
6007
6230
 
6008
6231
  // src/dashboard/middleware.ts
6009
6232
  import { randomBytes } from "crypto";
6010
- import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync3 } from "fs";
6233
+ import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync4 } from "fs";
6011
6234
  function getDashboardToken() {
6012
6235
  return DASHBOARD_TOKEN;
6013
6236
  }
6014
6237
  function persistToken() {
6015
6238
  try {
6016
- mkdirSync3(DATA_PATH, { recursive: true });
6239
+ mkdirSync4(DATA_PATH, { recursive: true });
6017
6240
  const tokenPath = `${DATA_PATH}/api-token`;
6018
6241
  writeFileSync2(tokenPath, DASHBOARD_TOKEN, { mode: 384 });
6019
6242
  } catch (err) {
@@ -6700,14 +6923,14 @@ var init_propagate = __esm({
6700
6923
  });
6701
6924
 
6702
6925
  // src/agents/mcp-config.ts
6703
- import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync3, existsSync as existsSync9, readdirSync as readdirSync3, unlinkSync as unlinkSync3 } from "fs";
6704
- import { join as join8, dirname } from "path";
6926
+ import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync3, existsSync as existsSync10, readdirSync as readdirSync4, unlinkSync as unlinkSync3 } from "fs";
6927
+ import { join as join9, dirname as dirname2 } from "path";
6705
6928
  import { fileURLToPath } from "url";
6706
6929
  function generateOrchestratorMcpConfig(opts) {
6707
6930
  const port = opts.port ?? process.env.DASHBOARD_PORT ?? "3141";
6708
- const distPath = join8(__dirname, "agents", "mcp-server.js");
6709
- const tsxPath = join8(__dirname, "..", "src", "agents", "mcp-server.ts");
6710
- const useTs = !existsSync9(distPath);
6931
+ const distPath = join9(__dirname, "agents", "mcp-server.js");
6932
+ const tsxPath = join9(__dirname, "..", "src", "agents", "mcp-server.ts");
6933
+ const useTs = !existsSync10(distPath);
6711
6934
  return {
6712
6935
  name: opts.agentId === "main" ? "cc-claw" : `cc-claw-${opts.agentId.slice(0, 8)}`,
6713
6936
  transport: "stdio",
@@ -6722,7 +6945,7 @@ function generateOrchestratorMcpConfig(opts) {
6722
6945
  };
6723
6946
  }
6724
6947
  function writeMcpConfigFile(config2) {
6725
- mkdirSync4(MCP_CONFIG_DIR, { recursive: true, mode: 448 });
6948
+ mkdirSync5(MCP_CONFIG_DIR, { recursive: true, mode: 448 });
6726
6949
  const jsonConfig = {
6727
6950
  mcpServers: {
6728
6951
  [config2.name]: {
@@ -6733,13 +6956,13 @@ function writeMcpConfigFile(config2) {
6733
6956
  }
6734
6957
  };
6735
6958
  const safeName = config2.name.replace(/[^a-zA-Z0-9-]/g, "_");
6736
- const configPath = join8(MCP_CONFIG_DIR, `mcp-${safeName}.json`);
6959
+ const configPath = join9(MCP_CONFIG_DIR, `mcp-${safeName}.json`);
6737
6960
  writeFileSync3(configPath, JSON.stringify(jsonConfig, null, 2), { mode: 384 });
6738
6961
  return configPath;
6739
6962
  }
6740
6963
  function deleteMcpConfigFile(mcpName) {
6741
6964
  const safeName = mcpName.replace(/[^a-zA-Z0-9-]/g, "_");
6742
- const configPath = join8(MCP_CONFIG_DIR, `mcp-${safeName}.json`);
6965
+ const configPath = join9(MCP_CONFIG_DIR, `mcp-${safeName}.json`);
6743
6966
  try {
6744
6967
  unlinkSync3(configPath);
6745
6968
  } catch {
@@ -6747,12 +6970,12 @@ function deleteMcpConfigFile(mcpName) {
6747
6970
  }
6748
6971
  function cleanupOrphanedMcpConfigs() {
6749
6972
  try {
6750
- if (!existsSync9(MCP_CONFIG_DIR)) return;
6751
- const files = readdirSync3(MCP_CONFIG_DIR);
6973
+ if (!existsSync10(MCP_CONFIG_DIR)) return;
6974
+ const files = readdirSync4(MCP_CONFIG_DIR);
6752
6975
  for (const file of files) {
6753
6976
  if (file.startsWith("mcp-cc-claw-") && file.endsWith(".json")) {
6754
6977
  try {
6755
- unlinkSync3(join8(MCP_CONFIG_DIR, file));
6978
+ unlinkSync3(join9(MCP_CONFIG_DIR, file));
6756
6979
  } catch {
6757
6980
  }
6758
6981
  }
@@ -6766,8 +6989,8 @@ var init_mcp_config = __esm({
6766
6989
  "use strict";
6767
6990
  init_paths();
6768
6991
  __filename = fileURLToPath(import.meta.url);
6769
- __dirname = dirname(__filename);
6770
- MCP_CONFIG_DIR = join8(CC_CLAW_HOME, "mcp-configs");
6992
+ __dirname = dirname2(__filename);
6993
+ MCP_CONFIG_DIR = join9(CC_CLAW_HOME, "mcp-configs");
6771
6994
  }
6772
6995
  });
6773
6996
 
@@ -6777,8 +7000,8 @@ __export(loader_exports, {
6777
7000
  getTemplate: () => getTemplate,
6778
7001
  listTemplates: () => listTemplates
6779
7002
  });
6780
- import { readdirSync as readdirSync4, readFileSync as readFileSync5 } from "fs";
6781
- import { join as join9 } from "path";
7003
+ import { readdirSync as readdirSync5, readFileSync as readFileSync5 } from "fs";
7004
+ import { join as join10 } from "path";
6782
7005
  function parseFrontmatter(content) {
6783
7006
  const match = content.match(/^---\s*\n([\s\S]*?)\n---\s*\n?([\s\S]*)$/m);
6784
7007
  if (!match || match.index !== 0) return { meta: {}, body: content.trim() };
@@ -6811,12 +7034,12 @@ function scanTemplates() {
6811
7034
  templateCache.clear();
6812
7035
  let files;
6813
7036
  try {
6814
- files = readdirSync4(AGENTS_PATH).filter((f) => f.endsWith(".md"));
7037
+ files = readdirSync5(AGENTS_PATH).filter((f) => f.endsWith(".md"));
6815
7038
  } catch {
6816
7039
  return;
6817
7040
  }
6818
7041
  for (const file of files) {
6819
- const filePath = join9(AGENTS_PATH, file);
7042
+ const filePath = join10(AGENTS_PATH, file);
6820
7043
  try {
6821
7044
  const raw = readFileSync5(filePath, "utf-8");
6822
7045
  const { meta, body } = parseFrontmatter(raw);
@@ -6865,8 +7088,8 @@ var init_loader2 = __esm({
6865
7088
  });
6866
7089
 
6867
7090
  // src/agents/agent-log.ts
6868
- import { writeFileSync as writeFileSync4, readdirSync as readdirSync5, statSync as statSync3, unlinkSync as unlinkSync4, mkdirSync as mkdirSync5 } from "fs";
6869
- import { join as join10 } from "path";
7091
+ import { writeFileSync as writeFileSync4, readdirSync as readdirSync6, statSync as statSync4, unlinkSync as unlinkSync4, mkdirSync as mkdirSync6 } from "fs";
7092
+ import { join as join11 } from "path";
6870
7093
  function truncate(text, maxBytes) {
6871
7094
  if (Buffer.byteLength(text, "utf-8") <= maxBytes) return text;
6872
7095
  let lo = 0, hi = text.length;
@@ -6881,7 +7104,7 @@ function truncate(text, maxBytes) {
6881
7104
  [...truncated ${droppedBytes} bytes...]`;
6882
7105
  }
6883
7106
  function writeAgentLog(data) {
6884
- const logPath = join10(AGENTS_PATH, `${data.agentId}.log`);
7107
+ const logPath = join11(AGENTS_PATH, `${data.agentId}.log`);
6885
7108
  const exitDisplay = data.exitCodeForced ? `${data.exitCode} (forced \u2014 no output from original exit code 0)` : String(data.exitCode ?? "null");
6886
7109
  const stderrContent = truncate(data.stderr || "(empty)", MAX_STDERR_BYTES);
6887
7110
  const stdoutContent = truncate(data.rawStdoutLines.join("\n") || "(empty)", MAX_STDOUT_BYTES);
@@ -6905,7 +7128,7 @@ function writeAgentLog(data) {
6905
7128
  ""
6906
7129
  ];
6907
7130
  try {
6908
- mkdirSync5(AGENTS_PATH, { recursive: true });
7131
+ mkdirSync6(AGENTS_PATH, { recursive: true });
6909
7132
  writeFileSync4(logPath, lines.join("\n"), "utf-8");
6910
7133
  } catch (err) {
6911
7134
  log(`[agent-log] Failed to write log for ${data.agentId}: ${err}`);
@@ -6914,10 +7137,10 @@ function writeAgentLog(data) {
6914
7137
  }
6915
7138
  function pruneAgentLogs() {
6916
7139
  try {
6917
- mkdirSync5(AGENTS_PATH, { recursive: true });
6918
- const files = readdirSync5(AGENTS_PATH).filter((f) => f.endsWith(".log")).map((f) => {
6919
- const fullPath = join10(AGENTS_PATH, f);
6920
- const stat4 = statSync3(fullPath);
7140
+ mkdirSync6(AGENTS_PATH, { recursive: true });
7141
+ const files = readdirSync6(AGENTS_PATH).filter((f) => f.endsWith(".log")).map((f) => {
7142
+ const fullPath = join11(AGENTS_PATH, f);
7143
+ const stat4 = statSync4(fullPath);
6921
7144
  return { path: fullPath, mtime: stat4.mtimeMs, size: stat4.size };
6922
7145
  });
6923
7146
  const now = Date.now();
@@ -6962,7 +7185,7 @@ var init_agent_log = __esm({
6962
7185
  });
6963
7186
 
6964
7187
  // src/agents/orchestrator.ts
6965
- import { existsSync as existsSync10 } from "fs";
7188
+ import { existsSync as existsSync11 } from "fs";
6966
7189
  async function withRunnerLock(runnerId, fn) {
6967
7190
  const prev = runnerLocks.get(runnerId) ?? Promise.resolve();
6968
7191
  const next = prev.then(fn, () => fn());
@@ -7080,7 +7303,7 @@ async function spawnSubAgent(chatId, opts) {
7080
7303
  async function startAgent(agentId, chatId, opts) {
7081
7304
  const db3 = getDb();
7082
7305
  const runner = getRunner(opts.runner);
7083
- if (opts.cwd && !existsSync10(opts.cwd)) {
7306
+ if (opts.cwd && !existsSync11(opts.cwd)) {
7084
7307
  const msg = `Directory not found: ${opts.cwd}`;
7085
7308
  error(`[orchestrator] Agent ${agentId}: ${msg}`);
7086
7309
  updateAgentStatus(db3, agentId, "failed");
@@ -7102,7 +7325,7 @@ async function startAgent(agentId, chatId, opts) {
7102
7325
  return;
7103
7326
  }
7104
7327
  const exePath = runner.getExecutablePath();
7105
- if (exePath.startsWith("/") && !existsSync10(exePath)) {
7328
+ if (exePath.startsWith("/") && !existsSync11(exePath)) {
7106
7329
  const msg = `Executable not found: ${exePath}`;
7107
7330
  error(`[orchestrator] Agent ${agentId}: ${msg}`);
7108
7331
  updateAgentStatus(db3, agentId, "failed");
@@ -7372,10 +7595,10 @@ async function startAgent(agentId, chatId, opts) {
7372
7595
  function diagnoseSpawnError(err, exePath, cwd) {
7373
7596
  const nodeErr = err;
7374
7597
  if (nodeErr.code === "ENOENT") {
7375
- if (cwd && !existsSync10(cwd)) {
7598
+ if (cwd && !existsSync11(cwd)) {
7376
7599
  return `Directory not found: ${cwd}`;
7377
7600
  }
7378
- if (exePath.startsWith("/") && !existsSync10(exePath)) {
7601
+ if (exePath.startsWith("/") && !existsSync11(exePath)) {
7379
7602
  return `Executable not found: ${exePath}`;
7380
7603
  }
7381
7604
  return `ENOENT spawning ${exePath} (cwd: ${cwd ?? "inherited"}) \u2014 check that both the binary and directory exist`;
@@ -7764,7 +7987,7 @@ var init_registry2 = __esm({
7764
7987
  });
7765
7988
 
7766
7989
  // src/dashboard/routes/orchestrator.ts
7767
- import { existsSync as existsSync11 } from "fs";
7990
+ import { existsSync as existsSync12 } from "fs";
7768
7991
  var handleSpawn, handleCancel, handleCancelAll, handleCreateTask, handleUpdateTask, handleSendMessage, handleReadInbox, handleSetState, handleGetState, handleListState, handleBroadcast, handleListRunners, handleListMcps, handleListTemplates, handleCheckAgent;
7769
7992
  var init_orchestrator2 = __esm({
7770
7993
  "src/dashboard/routes/orchestrator.ts"() {
@@ -7780,7 +8003,7 @@ var init_orchestrator2 = __esm({
7780
8003
  handleSpawn = async (req, res) => {
7781
8004
  try {
7782
8005
  const body = JSON.parse(await readBody(req));
7783
- if (body.cwd && !existsSync11(body.cwd)) {
8006
+ if (body.cwd && !existsSync12(body.cwd)) {
7784
8007
  return jsonResponse(res, { error: `Directory not found: ${body.cwd}` }, 400);
7785
8008
  }
7786
8009
  if (!body.permMode || body.permMode === "inherit") {
@@ -9047,8 +9270,8 @@ __export(analyze_exports, {
9047
9270
  });
9048
9271
  import { spawn as spawn4 } from "child_process";
9049
9272
  import { createInterface as createInterface3 } from "readline";
9050
- import { readFileSync as readFileSync6, existsSync as existsSync12, readdirSync as readdirSync6, statSync as statSync4 } from "fs";
9051
- import { join as join11 } from "path";
9273
+ import { readFileSync as readFileSync6, existsSync as existsSync13, readdirSync as readdirSync7, statSync as statSync5 } from "fs";
9274
+ import { join as join12 } from "path";
9052
9275
  import { homedir as homedir4 } from "os";
9053
9276
  function applySignalDecay(confidence, createdAt) {
9054
9277
  const ageMs = Date.now() - (/* @__PURE__ */ new Date(createdAt + (createdAt.endsWith("Z") ? "" : "Z"))).getTime();
@@ -9057,16 +9280,16 @@ function applySignalDecay(confidence, createdAt) {
9057
9280
  return decayed >= SIGNAL_DECAY_MIN_CONFIDENCE ? Math.round(decayed * 100) / 100 : 0;
9058
9281
  }
9059
9282
  function discoverReflectionTargets() {
9060
- const ccClawHome = join11(homedir4(), ".cc-claw");
9283
+ const ccClawHome = join12(homedir4(), ".cc-claw");
9061
9284
  const targets = [];
9062
9285
  try {
9063
- const skillsDir = join11(ccClawHome, "workspace", "skills");
9064
- if (existsSync12(skillsDir)) {
9065
- for (const entry of readdirSync6(skillsDir)) {
9066
- const entryPath = join11(skillsDir, entry);
9067
- if (!statSync4(entryPath).isDirectory()) continue;
9068
- const skillFile = join11(entryPath, "SKILL.md");
9069
- if (!existsSync12(skillFile)) continue;
9286
+ const skillsDir = join12(ccClawHome, "workspace", "skills");
9287
+ if (existsSync13(skillsDir)) {
9288
+ for (const entry of readdirSync7(skillsDir)) {
9289
+ const entryPath = join12(skillsDir, entry);
9290
+ if (!statSync5(entryPath).isDirectory()) continue;
9291
+ const skillFile = join12(entryPath, "SKILL.md");
9292
+ if (!existsSync13(skillFile)) continue;
9070
9293
  let desc = "skill";
9071
9294
  try {
9072
9295
  const content = readFileSync6(skillFile, "utf-8");
@@ -9080,9 +9303,9 @@ function discoverReflectionTargets() {
9080
9303
  } catch {
9081
9304
  }
9082
9305
  try {
9083
- const contextDir = join11(ccClawHome, "workspace", "context");
9084
- if (existsSync12(contextDir)) {
9085
- for (const entry of readdirSync6(contextDir)) {
9306
+ const contextDir = join12(ccClawHome, "workspace", "context");
9307
+ if (existsSync13(contextDir)) {
9308
+ for (const entry of readdirSync7(contextDir)) {
9086
9309
  if (!entry.endsWith(".md")) continue;
9087
9310
  const name = entry.replace(/\.md$/, "");
9088
9311
  targets.push({ path: `workspace/context/${entry}`, description: `context file: ${name}` });
@@ -9270,7 +9493,7 @@ function resolveReflectionAdapter(chatId) {
9270
9493
  }
9271
9494
  function readIdentityFile(filename) {
9272
9495
  try {
9273
- return readFileSync6(join11(IDENTITY_PATH, filename), "utf-8");
9496
+ return readFileSync6(join12(IDENTITY_PATH, filename), "utf-8");
9274
9497
  } catch {
9275
9498
  return "";
9276
9499
  }
@@ -9418,7 +9641,7 @@ async function runAnalysisImpl(chatId, opts) {
9418
9641
  const availableTargets = discoverReflectionTargets();
9419
9642
  const SKILL_CONTENT_CAP = 15e3;
9420
9643
  const skillContents = [];
9421
- const ccClawHome = join11(homedir4(), ".cc-claw");
9644
+ const ccClawHome = join12(homedir4(), ".cc-claw");
9422
9645
  const signalCorpus = signals.map((s) => s.trigger).join(" ").toLowerCase();
9423
9646
  const convCorpus = (conversations ?? "").toLowerCase();
9424
9647
  const searchCorpus = signalCorpus + " " + convCorpus;
@@ -9431,8 +9654,8 @@ async function runAnalysisImpl(chatId, opts) {
9431
9654
  const isRelevant = searchCorpus.includes(skillNameNorm) || searchCorpus.includes(skillName.toLowerCase()) || descNorm.split(/\s+/).some((word) => word.length > 4 && searchCorpus.includes(word));
9432
9655
  if (!isRelevant) continue;
9433
9656
  try {
9434
- const fullPath = join11(ccClawHome, target.path);
9435
- if (existsSync12(fullPath)) {
9657
+ const fullPath = join12(ccClawHome, target.path);
9658
+ if (existsSync13(fullPath)) {
9436
9659
  const content = readFileSync6(fullPath, "utf-8");
9437
9660
  if (totalSkillChars + content.length > SKILL_CONTENT_CAP) break;
9438
9661
  skillContents.push({ path: target.path, content });
@@ -9638,8 +9861,8 @@ __export(apply_exports, {
9638
9861
  isTargetAllowed: () => isTargetAllowed,
9639
9862
  rollbackInsight: () => rollbackInsight
9640
9863
  });
9641
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync13, mkdirSync as mkdirSync6, readdirSync as readdirSync7, unlinkSync as unlinkSync5 } from "fs";
9642
- import { join as join12, dirname as dirname2 } from "path";
9864
+ import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync14, mkdirSync as mkdirSync7, readdirSync as readdirSync8, unlinkSync as unlinkSync5 } from "fs";
9865
+ import { join as join13, dirname as dirname3 } from "path";
9643
9866
  function isTargetAllowed(relativePath) {
9644
9867
  if (relativePath.includes("..")) return false;
9645
9868
  if (!relativePath.endsWith(".md")) return false;
@@ -9690,10 +9913,10 @@ function applyDiff(original, diff, action) {
9690
9913
  return original;
9691
9914
  }
9692
9915
  function pruneBackups(absolutePath) {
9693
- const dir = dirname2(absolutePath);
9916
+ const dir = dirname3(absolutePath);
9694
9917
  const baseName = absolutePath.split("/").pop() ?? "";
9695
9918
  try {
9696
- const backups = readdirSync7(dir).filter((f) => f.startsWith(baseName + ".bak.")).sort().map((f) => join12(dir, f));
9919
+ const backups = readdirSync8(dir).filter((f) => f.startsWith(baseName + ".bak.")).sort().map((f) => join13(dir, f));
9697
9920
  while (backups.length > MAX_BACKUPS_PER_FILE) {
9698
9921
  const oldest = backups.shift();
9699
9922
  try {
@@ -9719,9 +9942,9 @@ async function applyInsight(insightId) {
9719
9942
  if (!isTargetAllowed(insight.targetFile)) {
9720
9943
  return { success: false, message: `Target file "${insight.targetFile}" is not in the allowed list` };
9721
9944
  }
9722
- const absolutePath = join12(CC_CLAW_HOME, insight.targetFile);
9945
+ const absolutePath = join13(CC_CLAW_HOME, insight.targetFile);
9723
9946
  if (insight.proposedAction === "append" && insight.targetFile === "identity/SOUL.md") {
9724
- if (existsSync13(absolutePath)) {
9947
+ if (existsSync14(absolutePath)) {
9725
9948
  const currentContent = readFileSync7(absolutePath, "utf-8");
9726
9949
  const lineCount = currentContent.split("\n").length;
9727
9950
  if (lineCount >= SOUL_LINE_CAP) {
@@ -9743,7 +9966,7 @@ async function applyInsight(insightId) {
9743
9966
  };
9744
9967
  }
9745
9968
  let original = "";
9746
- if (existsSync13(absolutePath)) {
9969
+ if (existsSync14(absolutePath)) {
9747
9970
  original = readFileSync7(absolutePath, "utf-8");
9748
9971
  } else if (insight.proposedAction !== "create") {
9749
9972
  return { success: false, message: `Target file "${insight.targetFile}" does not exist` };
@@ -9751,9 +9974,9 @@ async function applyInsight(insightId) {
9751
9974
  const timestamp = Date.now();
9752
9975
  const backupPath = absolutePath + `.bak.${timestamp}`;
9753
9976
  try {
9754
- const parentDir = dirname2(absolutePath);
9755
- if (!existsSync13(parentDir)) {
9756
- mkdirSync6(parentDir, { recursive: true });
9977
+ const parentDir = dirname3(absolutePath);
9978
+ if (!existsSync14(parentDir)) {
9979
+ mkdirSync7(parentDir, { recursive: true });
9757
9980
  }
9758
9981
  if (original) {
9759
9982
  writeFileSync5(backupPath, original, "utf-8");
@@ -9816,7 +10039,7 @@ async function rollbackInsight(insightId) {
9816
10039
  } catch {
9817
10040
  return { success: false, message: `Insight #${insightId} has malformed rollback data` };
9818
10041
  }
9819
- const absolutePath = join12(CC_CLAW_HOME, insight.targetFile);
10042
+ const absolutePath = join13(CC_CLAW_HOME, insight.targetFile);
9820
10043
  try {
9821
10044
  writeFileSync5(absolutePath, rollback.original, "utf-8");
9822
10045
  updateInsightStatus(db3, insightId, "rolled_back");
@@ -9849,8 +10072,8 @@ function calculateDrift(chatId) {
9849
10072
  if (!row || !row.baselineSoulMd && !row.baselineUserMd) {
9850
10073
  return null;
9851
10074
  }
9852
- const soulPath = join12(CC_CLAW_HOME, "identity/SOUL.md");
9853
- const userPath = join12(CC_CLAW_HOME, "identity/USER.md");
10075
+ const soulPath = join13(CC_CLAW_HOME, "identity/SOUL.md");
10076
+ const userPath = join13(CC_CLAW_HOME, "identity/USER.md");
9854
10077
  const soulDrift = computeLineDrift(row.baselineSoulMd, soulPath);
9855
10078
  const userDrift = computeLineDrift(row.baselineUserMd, userPath);
9856
10079
  return { soulDrift, userDrift };
@@ -9859,7 +10082,7 @@ function computeLineDrift(baseline, absolutePath) {
9859
10082
  if (!baseline) return 0;
9860
10083
  let current = "";
9861
10084
  try {
9862
- if (existsSync13(absolutePath)) {
10085
+ if (existsSync14(absolutePath)) {
9863
10086
  current = readFileSync7(absolutePath, "utf-8");
9864
10087
  }
9865
10088
  } catch {
@@ -9955,11 +10178,11 @@ var init_evolve = __esm({
9955
10178
  const body = JSON.parse(await readBody(req));
9956
10179
  const { setReflectionStatus: setReflectionStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
9957
10180
  const { existsSync: fileExists, readFileSync: fileRead } = await import("fs");
9958
- const { join: join29 } = await import("path");
10181
+ const { join: join30 } = await import("path");
9959
10182
  const { CC_CLAW_HOME: home } = await Promise.resolve().then(() => (init_paths(), paths_exports));
9960
10183
  const chatId = body.chatId || (process.env.ALLOWED_CHAT_ID ?? "").split(",")[0]?.trim() || "default";
9961
- const soulPath = join29(home, "identity/SOUL.md");
9962
- const userPath = join29(home, "identity/USER.md");
10184
+ const soulPath = join30(home, "identity/SOUL.md");
10185
+ const userPath = join30(home, "identity/USER.md");
9963
10186
  const soul = fileExists(soulPath) ? fileRead(soulPath, "utf-8") : "";
9964
10187
  const user = fileExists(userPath) ? fileRead(userPath, "utf-8") : "";
9965
10188
  setReflectionStatus2(getDb(), chatId, "active", soul, user);
@@ -10905,7 +11128,7 @@ function askAgent(chatId, userMessage, opts) {
10905
11128
  return withChatLock(chatId, () => askAgentImpl(chatId, userMessage, opts));
10906
11129
  }
10907
11130
  async function askAgentImpl(chatId, userMessage, opts) {
10908
- const { cwd, onStream, model: model2, backend: backend2, permMode, onToolAction, bootstrapTier, timeoutMs, maxTurns, onSlotRotation, onModelDowngrade, agentMode: optsAgentMode, onSubagentActivity, settingsSourceChatId } = opts ?? {};
11131
+ const { cwd, onStream, model: model2, backend: backend2, permMode, onToolAction, bootstrapTier, timeoutMs, maxTurns, onSlotRotation, onModelDowngrade, agentMode: optsAgentMode, onSubagentActivity, settingsSourceChatId, planningDirective } = opts ?? {};
10909
11132
  const settingsChat = settingsSourceChatId ?? chatId;
10910
11133
  const adapter = backend2 ? getAdapter(backend2) : getAdapterForChat(settingsChat);
10911
11134
  const mode = permMode ?? getMode(settingsChat);
@@ -10915,7 +11138,7 @@ async function askAgentImpl(chatId, userMessage, opts) {
10915
11138
  const tier = bootstrapTier ?? "full";
10916
11139
  const effectiveAgentMode = optsAgentMode ?? getAgentMode(settingsChat);
10917
11140
  const sideQuestCtx = settingsSourceChatId ? { parentChatId: settingsSourceChatId, actualChatId: chatId } : void 0;
10918
- const fullPrompt = await assembleBootstrapPrompt(userMessage, tier, settingsChat, mode, responseStyle, effectiveAgentMode, sideQuestCtx);
11141
+ const fullPrompt = await assembleBootstrapPrompt(userMessage, tier, settingsChat, mode, responseStyle, effectiveAgentMode, sideQuestCtx, planningDirective);
10919
11142
  const existingSessionId = settingsSourceChatId ? null : getSessionId(settingsChat);
10920
11143
  const allowedTools = getEnabledTools(settingsChat);
10921
11144
  const mcpConfigPath = tier !== "slim" && effectiveAgentMode !== "native" && MCP_CONFIG_FLAG[adapter.id] ? getMcpConfigPath(chatId) : null;
@@ -11517,9 +11740,9 @@ function buildReviewCompleteMessage(results) {
11517
11740
 
11518
11741
  Skipped proposals will appear in your next review.`;
11519
11742
  }
11520
- function formatNightlySummary(insights) {
11521
- const count = insights.length;
11522
- const header2 = `Nightly Reflection \u2014 ${count} proposal${count === 1 ? "" : "s"} ready`;
11743
+ function formatNightlySummary(insights, totalPending) {
11744
+ const displayCount = totalPending ?? insights.length;
11745
+ const header2 = `Nightly Reflection \u2014 ${displayCount} proposal${displayCount === 1 ? "" : "s"} ready`;
11523
11746
  const list = insights.map((ins, i) => `${i + 1}. [${ins.category}] ${ins.insight}`).join("\n");
11524
11747
  return `${header2}
11525
11748
 
@@ -11630,8 +11853,8 @@ var init_propose = __esm({
11630
11853
  });
11631
11854
 
11632
11855
  // src/bootstrap/profile.ts
11633
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, existsSync as existsSync14 } from "fs";
11634
- import { join as join13 } from "path";
11856
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, existsSync as existsSync15 } from "fs";
11857
+ import { join as join14 } from "path";
11635
11858
  function hasActiveProfile(chatId) {
11636
11859
  return activeProfiles.has(chatId);
11637
11860
  }
@@ -11760,7 +11983,7 @@ function extractUserUpdates(text) {
11760
11983
  return { cleanText, updates };
11761
11984
  }
11762
11985
  function appendToUserProfile(key, value) {
11763
- if (!existsSync14(USER_PATH2)) return;
11986
+ if (!existsSync15(USER_PATH2)) return;
11764
11987
  const content = readFileSync8(USER_PATH2, "utf-8");
11765
11988
  const line = `- **${key}**: ${value}`;
11766
11989
  if (content.includes(line)) return;
@@ -11776,7 +11999,7 @@ var init_profile = __esm({
11776
11999
  "use strict";
11777
12000
  init_paths();
11778
12001
  init_log();
11779
- USER_PATH2 = join13(IDENTITY_PATH, "USER.md");
12002
+ USER_PATH2 = join14(IDENTITY_PATH, "USER.md");
11780
12003
  activeProfiles = /* @__PURE__ */ new Map();
11781
12004
  }
11782
12005
  });
@@ -12607,6 +12830,88 @@ var init_classify2 = __esm({
12607
12830
  }
12608
12831
  });
12609
12832
 
12833
+ // src/execution/gate.ts
12834
+ function shouldRequireApproval(input) {
12835
+ if (input.execMode !== "approved") return false;
12836
+ if (input.intent !== "agentic") return false;
12837
+ if (input.isResuming) return false;
12838
+ if (input.messageText.startsWith(">>")) return false;
12839
+ if (EXEMPT_TIERS.has(input.bootstrapTier)) return false;
12840
+ if (input.isSideQuest) return false;
12841
+ return true;
12842
+ }
12843
+ function buildPlanningDirective() {
12844
+ return [
12845
+ "## PLANNING MODE \u2014 Read-Only",
12846
+ "",
12847
+ "You are in PLANNING mode. Your goal is to research and present a plan.",
12848
+ "",
12849
+ "**ALLOWED:**",
12850
+ "- Read files, directories, and code",
12851
+ "- Load and read skills",
12852
+ "- Search the codebase (grep, glob, find)",
12853
+ "- Search the web for documentation or solutions",
12854
+ "- Analyze and reason about architecture",
12855
+ "",
12856
+ "**NOT ALLOWED:**",
12857
+ "- Do NOT create, modify, or delete any files",
12858
+ "- Do NOT run shell commands that mutate state",
12859
+ "- Do NOT write code or make edits",
12860
+ "- Do NOT install packages or dependencies",
12861
+ "",
12862
+ "**YOUR TASK:**",
12863
+ "Research the request thoroughly, then present a clear, concise plan",
12864
+ "of what you will do. The user will review and approve before you execute.",
12865
+ "Structure your plan with numbered steps and be specific about which",
12866
+ "files you will modify and what changes you will make."
12867
+ ].join("\n");
12868
+ }
12869
+ function storePendingPlan(chatId, plan, originalMessage) {
12870
+ pendingPlans.set(chatId, {
12871
+ plan,
12872
+ originalMessage,
12873
+ createdAt: Date.now()
12874
+ });
12875
+ }
12876
+ function getPendingPlan(chatId) {
12877
+ const entry = pendingPlans.get(chatId);
12878
+ if (!entry) return void 0;
12879
+ if (Date.now() - entry.createdAt > PLAN_TTL_MS) {
12880
+ pendingPlans.delete(chatId);
12881
+ return void 0;
12882
+ }
12883
+ return entry;
12884
+ }
12885
+ function removePendingPlan(chatId) {
12886
+ pendingPlans.delete(chatId);
12887
+ }
12888
+ function setRejectionMode(chatId) {
12889
+ rejectionModes.set(chatId, Date.now());
12890
+ }
12891
+ function getRejectionMode(chatId) {
12892
+ const createdAt = rejectionModes.get(chatId);
12893
+ if (createdAt === void 0) return false;
12894
+ if (Date.now() - createdAt > REJECTION_TTL_MS) {
12895
+ rejectionModes.delete(chatId);
12896
+ return false;
12897
+ }
12898
+ return true;
12899
+ }
12900
+ function clearRejectionMode(chatId) {
12901
+ rejectionModes.delete(chatId);
12902
+ }
12903
+ var EXEMPT_TIERS, PLAN_TTL_MS, pendingPlans, REJECTION_TTL_MS, rejectionModes;
12904
+ var init_gate = __esm({
12905
+ "src/execution/gate.ts"() {
12906
+ "use strict";
12907
+ EXEMPT_TIERS = /* @__PURE__ */ new Set(["slim", "heartbeat", "chat"]);
12908
+ PLAN_TTL_MS = 5 * 60 * 1e3;
12909
+ pendingPlans = /* @__PURE__ */ new Map();
12910
+ REJECTION_TTL_MS = 5 * 60 * 1e3;
12911
+ rejectionModes = /* @__PURE__ */ new Map();
12912
+ }
12913
+ });
12914
+
12610
12915
  // src/router/helpers.ts
12611
12916
  import { resolve as resolvePath } from "path";
12612
12917
  function parseMcpListOutput(output2) {
@@ -13307,9 +13612,9 @@ var init_stt = __esm({
13307
13612
  });
13308
13613
 
13309
13614
  // src/media/image-gen.ts
13310
- import { mkdirSync as mkdirSync7, existsSync as existsSync15, unlink as unlink2, readdir, stat } from "fs";
13615
+ import { mkdirSync as mkdirSync8, existsSync as existsSync16, unlink as unlink2, readdir, stat } from "fs";
13311
13616
  import { writeFile } from "fs/promises";
13312
- import { join as join14 } from "path";
13617
+ import { join as join15 } from "path";
13313
13618
  async function generateImage(prompt) {
13314
13619
  const apiKey = process.env.GEMINI_API_KEY;
13315
13620
  if (!apiKey) {
@@ -13356,12 +13661,12 @@ async function generateImage(prompt) {
13356
13661
  if (!imageData) {
13357
13662
  throw new Error(textResponse ?? "Gemini did not generate an image. The prompt may have been filtered.");
13358
13663
  }
13359
- if (!existsSync15(IMAGE_OUTPUT_DIR)) {
13360
- mkdirSync7(IMAGE_OUTPUT_DIR, { recursive: true });
13664
+ if (!existsSync16(IMAGE_OUTPUT_DIR)) {
13665
+ mkdirSync8(IMAGE_OUTPUT_DIR, { recursive: true });
13361
13666
  }
13362
13667
  const ext = mimeType.includes("jpeg") || mimeType.includes("jpg") ? "jpg" : "png";
13363
13668
  const filename = `img_${Date.now()}.${ext}`;
13364
- const filePath = join14(IMAGE_OUTPUT_DIR, filename);
13669
+ const filePath = join15(IMAGE_OUTPUT_DIR, filename);
13365
13670
  const buffer = Buffer.from(imageData, "base64");
13366
13671
  await writeFile(filePath, buffer);
13367
13672
  log(`[image-gen] Saved ${buffer.length} bytes to ${filePath}`);
@@ -13379,7 +13684,7 @@ function cleanupGeneratedImage(filePath) {
13379
13684
  function pruneImageCache() {
13380
13685
  readdir(IMAGE_OUTPUT_DIR, (err, files) => {
13381
13686
  if (err || !files) return;
13382
- const imageFiles = files.filter((f) => /\.(png|jpg)$/.test(f)).map((f) => join14(IMAGE_OUTPUT_DIR, f));
13687
+ const imageFiles = files.filter((f) => /\.(png|jpg)$/.test(f)).map((f) => join15(IMAGE_OUTPUT_DIR, f));
13383
13688
  if (imageFiles.length === 0) return;
13384
13689
  const now = Date.now();
13385
13690
  let statsPending = imageFiles.length;
@@ -13411,8 +13716,8 @@ var init_image_gen = __esm({
13411
13716
  MAX_GENERATED_IMAGES = 20;
13412
13717
  IMAGE_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
13413
13718
  IMAGE_MODEL = "gemini-3.1-flash-image-preview";
13414
- IMAGE_OUTPUT_DIR = join14(
13415
- process.env.CC_CLAW_HOME ?? join14(process.env.HOME ?? "/tmp", ".cc-claw"),
13719
+ IMAGE_OUTPUT_DIR = join15(
13720
+ process.env.CC_CLAW_HOME ?? join15(process.env.HOME ?? "/tmp", ".cc-claw"),
13416
13721
  "data",
13417
13722
  "images"
13418
13723
  );
@@ -13885,7 +14190,7 @@ var init_video = __esm({
13885
14190
  });
13886
14191
 
13887
14192
  // src/router/media.ts
13888
- import { join as join15 } from "path";
14193
+ import { join as join16 } from "path";
13889
14194
  import { mkdir, writeFile as writeFile2, readdir as readdir2, stat as stat2, unlink as unlink3 } from "fs/promises";
13890
14195
  function getMediaRetentionMs() {
13891
14196
  const hours = parseInt(process.env.MEDIA_RETENTION_HOURS ?? "24", 10);
@@ -13894,7 +14199,7 @@ function getMediaRetentionMs() {
13894
14199
  async function saveMedia(buffer, prefix, ext) {
13895
14200
  await mkdir(MEDIA_INCOMING_PATH, { recursive: true });
13896
14201
  const filename = `${prefix}-${Date.now()}.${ext}`;
13897
- const fullPath = join15(MEDIA_INCOMING_PATH, filename);
14202
+ const fullPath = join16(MEDIA_INCOMING_PATH, filename);
13898
14203
  await writeFile2(fullPath, buffer);
13899
14204
  return fullPath;
13900
14205
  }
@@ -13908,7 +14213,7 @@ async function cleanupOldMedia() {
13908
14213
  let removed = 0;
13909
14214
  for (const file of files) {
13910
14215
  try {
13911
- const filePath = join15(MEDIA_INCOMING_PATH, file);
14216
+ const filePath = join16(MEDIA_INCOMING_PATH, file);
13912
14217
  const s = await stat2(filePath);
13913
14218
  if (now - s.mtimeMs > retentionMs) {
13914
14219
  await unlink3(filePath);
@@ -14091,7 +14396,7 @@ var init_media = __esm({
14091
14396
  init_store5();
14092
14397
  init_helpers();
14093
14398
  init_response();
14094
- MEDIA_INCOMING_PATH = join15(MEDIA_PATH, "incoming");
14399
+ MEDIA_INCOMING_PATH = join16(MEDIA_PATH, "incoming");
14095
14400
  }
14096
14401
  });
14097
14402
 
@@ -14227,7 +14532,7 @@ __export(discover_exports, {
14227
14532
  import { readdir as readdir3, readFile as readFile4 } from "fs/promises";
14228
14533
  import { createHash } from "crypto";
14229
14534
  import { homedir as homedir5 } from "os";
14230
- import { join as join16 } from "path";
14535
+ import { join as join17 } from "path";
14231
14536
  function invalidateSkillCache() {
14232
14537
  cachedSkills = null;
14233
14538
  cacheTimestamp = 0;
@@ -14245,7 +14550,7 @@ async function discoverAllSkills() {
14245
14550
  const rawSkills = [];
14246
14551
  rawSkills.push(...await scanSkillDir(SKILLS_PATH, "cc-claw"));
14247
14552
  for (const backendId of getAllBackendIds()) {
14248
- const dirs = BACKEND_SKILL_DIRS[backendId] ?? [join16(homedir5(), `.${backendId}`, "skills")];
14553
+ const dirs = BACKEND_SKILL_DIRS[backendId] ?? [join17(homedir5(), `.${backendId}`, "skills")];
14249
14554
  for (const dir of dirs) {
14250
14555
  rawSkills.push(...await scanSkillDir(dir, backendId));
14251
14556
  }
@@ -14273,7 +14578,7 @@ async function scanSkillDir(skillsDir, source) {
14273
14578
  let content;
14274
14579
  let resolvedPath;
14275
14580
  for (const candidate of SKILL_FILE_CANDIDATES) {
14276
- const p = join16(skillsDir, entry.name, candidate);
14581
+ const p = join17(skillsDir, entry.name, candidate);
14277
14582
  try {
14278
14583
  content = await readFile4(p, "utf-8");
14279
14584
  resolvedPath = p;
@@ -14377,15 +14682,15 @@ var init_discover = __esm({
14377
14682
  init_backends();
14378
14683
  SKILL_FILE_CANDIDATES = ["SKILL.md", "skill.md"];
14379
14684
  BACKEND_SKILL_DIRS = {
14380
- claude: [join16(homedir5(), ".claude", "skills")],
14381
- gemini: [join16(homedir5(), ".gemini", "skills")],
14685
+ claude: [join17(homedir5(), ".claude", "skills")],
14686
+ gemini: [join17(homedir5(), ".gemini", "skills")],
14382
14687
  codex: [
14383
- join16(homedir5(), ".agents", "skills"),
14384
- join16(homedir5(), ".codex", "skills")
14688
+ join17(homedir5(), ".agents", "skills"),
14689
+ join17(homedir5(), ".codex", "skills")
14385
14690
  ],
14386
14691
  cursor: [
14387
- join16(homedir5(), ".cursor", "skills"),
14388
- join16(homedir5(), ".cursor", "skills-cursor")
14692
+ join17(homedir5(), ".cursor", "skills"),
14693
+ join17(homedir5(), ".cursor", "skills-cursor")
14389
14694
  ]
14390
14695
  };
14391
14696
  CACHE_TTL_MS2 = 3e5;
@@ -14401,8 +14706,8 @@ __export(install_exports, {
14401
14706
  installSkillFromGitHub: () => installSkillFromGitHub
14402
14707
  });
14403
14708
  import { mkdir as mkdir2, readdir as readdir4, readFile as readFile5, cp } from "fs/promises";
14404
- import { existsSync as existsSync16 } from "fs";
14405
- import { join as join17, basename } from "path";
14709
+ import { existsSync as existsSync17 } from "fs";
14710
+ import { join as join18, basename } from "path";
14406
14711
  import { execSync as execSync5 } from "child_process";
14407
14712
  async function installSkillFromGitHub(urlOrShorthand) {
14408
14713
  let repoUrl;
@@ -14413,36 +14718,36 @@ async function installSkillFromGitHub(urlOrShorthand) {
14413
14718
  }
14414
14719
  repoUrl = parsed.cloneUrl;
14415
14720
  subPath = parsed.subPath;
14416
- const tmpDir = join17("/tmp", `cc-claw-skill-${Date.now()}`);
14721
+ const tmpDir = join18("/tmp", `cc-claw-skill-${Date.now()}`);
14417
14722
  try {
14418
14723
  log(`[skill-install] Cloning ${repoUrl} to ${tmpDir}`);
14419
14724
  execSync5(`git clone --depth 1 ${repoUrl} ${tmpDir}`, {
14420
14725
  stdio: "pipe",
14421
14726
  timeout: 3e4
14422
14727
  });
14423
- if (!existsSync16(join17(tmpDir, ".git"))) {
14728
+ if (!existsSync17(join18(tmpDir, ".git"))) {
14424
14729
  return { success: false, error: "Git clone failed: no .git directory produced" };
14425
14730
  }
14426
- const searchRoot = subPath ? join17(tmpDir, subPath) : tmpDir;
14731
+ const searchRoot = subPath ? join18(tmpDir, subPath) : tmpDir;
14427
14732
  const skillDir = await findSkillDir(searchRoot);
14428
14733
  if (!skillDir) {
14429
14734
  return { success: false, error: "No SKILL.md found in the repository." };
14430
14735
  }
14431
14736
  const skillFolderName = basename(skillDir);
14432
- const destDir = join17(SKILLS_PATH, skillFolderName);
14433
- if (existsSync16(destDir)) {
14737
+ const destDir = join18(SKILLS_PATH, skillFolderName);
14738
+ if (existsSync17(destDir)) {
14434
14739
  log(`[skill-install] Overwriting existing skill at ${destDir}`);
14435
14740
  }
14436
14741
  await mkdir2(destDir, { recursive: true });
14437
14742
  await cp(skillDir, destDir, { recursive: true });
14438
14743
  let skillName = skillFolderName;
14439
14744
  try {
14440
- const content = await readFile5(join17(destDir, "SKILL.md"), "utf-8");
14745
+ const content = await readFile5(join18(destDir, "SKILL.md"), "utf-8");
14441
14746
  const nameMatch = content.match(/^name:\s*(.+)$/m);
14442
14747
  if (nameMatch) skillName = nameMatch[1].trim().replace(/^["']|["']$/g, "");
14443
14748
  } catch {
14444
14749
  try {
14445
- const content = await readFile5(join17(destDir, "skill.md"), "utf-8");
14750
+ const content = await readFile5(join18(destDir, "skill.md"), "utf-8");
14446
14751
  const nameMatch = content.match(/^name:\s*(.+)$/m);
14447
14752
  if (nameMatch) skillName = nameMatch[1].trim().replace(/^["']|["']$/g, "");
14448
14753
  } catch {
@@ -14477,15 +14782,15 @@ function parseGitHubUrl(input) {
14477
14782
  async function findSkillDir(root) {
14478
14783
  const candidates = ["SKILL.md", "skill.md"];
14479
14784
  for (const c of candidates) {
14480
- if (existsSync16(join17(root, c))) return root;
14785
+ if (existsSync17(join18(root, c))) return root;
14481
14786
  }
14482
14787
  try {
14483
14788
  const entries = await readdir4(root, { withFileTypes: true });
14484
14789
  for (const entry of entries) {
14485
14790
  if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
14486
14791
  for (const c of candidates) {
14487
- if (existsSync16(join17(root, entry.name, c))) {
14488
- return join17(root, entry.name);
14792
+ if (existsSync17(join18(root, entry.name, c))) {
14793
+ return join18(root, entry.name);
14489
14794
  }
14490
14795
  }
14491
14796
  }
@@ -14497,15 +14802,15 @@ async function findSkillDir(root) {
14497
14802
  if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
14498
14803
  let subEntries;
14499
14804
  try {
14500
- subEntries = await readdir4(join17(root, entry.name), { withFileTypes: true });
14805
+ subEntries = await readdir4(join18(root, entry.name), { withFileTypes: true });
14501
14806
  } catch {
14502
14807
  continue;
14503
14808
  }
14504
14809
  for (const sub of subEntries) {
14505
14810
  if (!sub.isDirectory() || sub.name.startsWith(".")) continue;
14506
14811
  for (const c of candidates) {
14507
- if (existsSync16(join17(root, entry.name, sub.name, c))) {
14508
- return join17(root, entry.name, sub.name);
14812
+ if (existsSync17(join18(root, entry.name, sub.name, c))) {
14813
+ return join18(root, entry.name, sub.name);
14509
14814
  }
14510
14815
  }
14511
14816
  }
@@ -14523,8 +14828,8 @@ var init_install = __esm({
14523
14828
  });
14524
14829
 
14525
14830
  // src/bootstrap/heartbeat.ts
14526
- import { readFileSync as readFileSync9, existsSync as existsSync17 } from "fs";
14527
- import { join as join18 } from "path";
14831
+ import { readFileSync as readFileSync9, existsSync as existsSync18 } from "fs";
14832
+ import { join as join19 } from "path";
14528
14833
  function initHeartbeat(channelReg) {
14529
14834
  registry2 = channelReg;
14530
14835
  }
@@ -14662,7 +14967,7 @@ ${healthLines.join("\n")}`);
14662
14967
  sections.push(`[Active watches]
14663
14968
  ${watchLines.join("\n")}`);
14664
14969
  }
14665
- if (existsSync17(HEARTBEAT_MD_PATH)) {
14970
+ if (existsSync18(HEARTBEAT_MD_PATH)) {
14666
14971
  try {
14667
14972
  const custom = readFileSync9(HEARTBEAT_MD_PATH, "utf-8").trim();
14668
14973
  if (custom) {
@@ -14710,7 +15015,7 @@ var init_heartbeat2 = __esm({
14710
15015
  init_backends();
14711
15016
  init_health2();
14712
15017
  init_log();
14713
- HEARTBEAT_MD_PATH = join18(WORKSPACE_PATH, "HEARTBEAT.md");
15018
+ HEARTBEAT_MD_PATH = join19(WORKSPACE_PATH, "HEARTBEAT.md");
14714
15019
  HEARTBEAT_OK = "HEARTBEAT_OK";
14715
15020
  registry2 = null;
14716
15021
  activeTimers = /* @__PURE__ */ new Map();
@@ -15767,9 +16072,9 @@ async function handleEvolveCallback(chatId, data, channel) {
15767
16072
  await channel.sendText(chatId, "No pending proposals.", { parseMode: "plain" });
15768
16073
  } else {
15769
16074
  const insightIds = pending.slice(0, 5).map((p) => p.id);
15770
- createReviewSession2(getDb(), reflChatId, insightIds);
16075
+ createReviewSession2(getDb(), chatId, insightIds);
15771
16076
  await channel.sendText(chatId, `${pending.length} proposal(s) ready. Let's review them one by one.`, { parseMode: "plain" });
15772
- await sendCurrentProposal(reflChatId, channel);
16077
+ await sendCurrentProposal(chatId, channel);
15773
16078
  }
15774
16079
  break;
15775
16080
  }
@@ -15927,13 +16232,13 @@ async function handleEvolveCallback(chatId, data, channel) {
15927
16232
  const { getReflectionStatus: getReflectionStatus2, setReflectionStatus: setReflectionStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
15928
16233
  const current = getReflectionStatus2(getDb(), chatId);
15929
16234
  if (current === "frozen") {
15930
- const { readFileSync: readFileSync22, existsSync: existsSync49 } = await import("fs");
15931
- const { join: join29 } = await import("path");
16235
+ const { readFileSync: readFileSync22, existsSync: existsSync50 } = await import("fs");
16236
+ const { join: join30 } = await import("path");
15932
16237
  const { CC_CLAW_HOME: CC_CLAW_HOME3 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
15933
- const soulPath = join29(CC_CLAW_HOME3, "identity/SOUL.md");
15934
- const userPath = join29(CC_CLAW_HOME3, "identity/USER.md");
15935
- const soul = existsSync49(soulPath) ? readFileSync22(soulPath, "utf-8") : "";
15936
- const user = existsSync49(userPath) ? readFileSync22(userPath, "utf-8") : "";
16238
+ const soulPath = join30(CC_CLAW_HOME3, "identity/SOUL.md");
16239
+ const userPath = join30(CC_CLAW_HOME3, "identity/USER.md");
16240
+ const soul = existsSync50(soulPath) ? readFileSync22(soulPath, "utf-8") : "";
16241
+ const user = existsSync50(userPath) ? readFileSync22(userPath, "utf-8") : "";
15937
16242
  setReflectionStatus2(getDb(), chatId, "active", soul, user);
15938
16243
  const { logActivity: logActivity2 } = await Promise.resolve().then(() => (init_store3(), store_exports3));
15939
16244
  logActivity2(getDb(), { chatId, source: "telegram", eventType: "reflection_unfrozen", summary: "Reflection enabled" });
@@ -16086,6 +16391,29 @@ ${cmds.map((c) => ` ${c.cmd} \u2014 ${c.desc}`).join("\n")}`
16086
16391
  }
16087
16392
  break;
16088
16393
  }
16394
+ case "mode":
16395
+ case "execmode": {
16396
+ const currentExecMode = getExecMode(chatId);
16397
+ const EXEC_MODES = {
16398
+ approved: "\u2705 Approved \u2014 AI shows a plan before acting",
16399
+ yolo: "\u26A1 YOLO \u2014 AI executes immediately"
16400
+ };
16401
+ if (typeof channel.sendKeyboard === "function") {
16402
+ const buttons = Object.entries(EXEC_MODES).map(([id, label2]) => [{
16403
+ label: `${id === currentExecMode ? "\u2713 " : ""}${label2}`,
16404
+ data: `execmode:${id}`,
16405
+ ...id === currentExecMode ? { style: "primary" } : {}
16406
+ }]);
16407
+ await channel.sendKeyboard(chatId, `Execution mode (current: <b>${currentExecMode}</b>):`, buttons);
16408
+ } else {
16409
+ const lines = ["Execution modes:", ""];
16410
+ for (const [id, label2] of Object.entries(EXEC_MODES)) {
16411
+ lines.push(`${id === currentExecMode ? "\u2713 " : " "}/mode ${id} \u2014 ${label2}`);
16412
+ }
16413
+ await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
16414
+ }
16415
+ break;
16416
+ }
16089
16417
  case "verbose": {
16090
16418
  const currentVerbose = getVerboseLevel(chatId);
16091
16419
  const buttons = Object.entries(VERBOSE_LEVELS).map(([id, label2]) => [{
@@ -17794,6 +18122,54 @@ ${PERM_MODES[chosen]}`,
17794
18122
  await channel.sendText(chatId, `Agent mode set to <b>${mode}</b>. Session cleared.`, { parseMode: "html" });
17795
18123
  }
17796
18124
  return;
18125
+ } else if (data === "exec:approve") {
18126
+ const plan = getPendingPlan(chatId);
18127
+ if (!plan) {
18128
+ await channel.sendText(chatId, "\u26A0\uFE0F Plan expired or already processed.", { parseMode: "plain" });
18129
+ return;
18130
+ }
18131
+ removePendingPlan(chatId);
18132
+ await channel.sendText(chatId, "\u2705 Approved. Executing...", { parseMode: "plain" });
18133
+ const { handleMessage: handleMessage2 } = await Promise.resolve().then(() => (init_router(), router_exports));
18134
+ await handleMessage2(
18135
+ { text: `>>${plan.originalMessage}`, chatId, source: "telegram", type: "text", senderName: "", messageId: "" },
18136
+ channel
18137
+ );
18138
+ return;
18139
+ } else if (data === "exec:reject") {
18140
+ const plan = getPendingPlan(chatId);
18141
+ if (!plan) {
18142
+ await channel.sendText(chatId, "\u26A0\uFE0F Plan expired or already processed.", { parseMode: "plain" });
18143
+ return;
18144
+ }
18145
+ removePendingPlan(chatId);
18146
+ setRejectionMode(chatId);
18147
+ await channel.sendText(chatId, "\u270F\uFE0F Plan rejected. Send your feedback and I'll revise the plan.", { parseMode: "plain" });
18148
+ return;
18149
+ } else if (data === "exec:yolo") {
18150
+ const plan = getPendingPlan(chatId);
18151
+ if (!plan) {
18152
+ await channel.sendText(chatId, "\u26A0\uFE0F Plan expired or already processed.", { parseMode: "plain" });
18153
+ return;
18154
+ }
18155
+ removePendingPlan(chatId);
18156
+ setExecMode(chatId, "yolo");
18157
+ await channel.sendText(chatId, "\u26A1 Switched to YOLO mode. Executing without approval gate...", { parseMode: "plain" });
18158
+ const { handleMessage: handleMessage2 } = await Promise.resolve().then(() => (init_router(), router_exports));
18159
+ await handleMessage2(
18160
+ { text: `>>${plan.originalMessage}`, chatId, source: "telegram", type: "text", senderName: "", messageId: "" },
18161
+ channel
18162
+ );
18163
+ return;
18164
+ } else if (data.startsWith("execmode:")) {
18165
+ const mode = data.split(":")[1];
18166
+ if (mode === "approved" || mode === "yolo") {
18167
+ setExecMode(chatId, mode);
18168
+ const desc = mode === "approved" ? "AI will show a plan for approval before acting." : "AI will execute immediately without showing a plan.";
18169
+ await channel.sendText(chatId, `Execution mode set to <b>${mode}</b>.
18170
+ ${desc}`, { parseMode: "html" });
18171
+ }
18172
+ return;
17797
18173
  } else if (data.startsWith("model_sig:")) {
17798
18174
  const value = data.slice(10);
17799
18175
  setModelSignature(chatId, value);
@@ -18553,6 +18929,7 @@ var init_callbacks = __esm({
18553
18929
  init_guard();
18554
18930
  init_pagination();
18555
18931
  init_stt();
18932
+ init_gate();
18556
18933
  init_helpers();
18557
18934
  init_response();
18558
18935
  init_shell();
@@ -18712,6 +19089,33 @@ async function handleText(msg, channel) {
18712
19089
  if (hasSqPrefix) {
18713
19090
  text = sqCleanText;
18714
19091
  }
19092
+ if (getRejectionMode(chatId)) {
19093
+ clearRejectionMode(chatId);
19094
+ await channel.sendTyping?.(chatId);
19095
+ const response = await askAgent(chatId, `Plan rejected. Feedback: "${text}". Revise your plan.`, {
19096
+ cwd: getCwd(chatId),
19097
+ model: model2,
19098
+ permMode: "yolo",
19099
+ agentMode: effectiveAgentMode
19100
+ });
19101
+ if (response.text) {
19102
+ storePendingPlan(chatId, response.text, text);
19103
+ if (typeof channel.sendKeyboard === "function") {
19104
+ await channel.sendKeyboard(chatId, `\u{1F50D} ${response.text}`, [
19105
+ [
19106
+ { label: "\u2705 Approve", data: "exec:approve", style: "success" },
19107
+ { label: "\u274C Reject", data: "exec:reject", style: "danger" }
19108
+ ],
19109
+ [
19110
+ { label: "\u26A1 Skip & YOLO", data: "exec:yolo" }
19111
+ ]
19112
+ ]);
19113
+ } else {
19114
+ await sendResponse(chatId, channel, response.text, void 0);
19115
+ }
19116
+ }
19117
+ return;
19118
+ }
18715
19119
  {
18716
19120
  const { getDiscussionMode: getDiscussionMode2, clearDiscussionMode: clearDiscussionMode2, setDiscussionMode: reenterDiscussion, getInsightById: getInsightById2, updateInsightProposal: updateInsightProposal2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
18717
19121
  const discussInsightId = getDiscussionMode2(chatId);
@@ -18788,6 +19192,64 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
18788
19192
  return;
18789
19193
  }
18790
19194
  }
19195
+ const execMode = getExecMode(chatId);
19196
+ const sessionId = getSessionId(chatId);
19197
+ const isResuming = !!sessionId;
19198
+ if (shouldRequireApproval({
19199
+ execMode,
19200
+ intent,
19201
+ bootstrapTier: bootstrapTier ?? "full",
19202
+ messageText: text,
19203
+ isResuming,
19204
+ isSideQuest: hasSqPrefix
19205
+ })) {
19206
+ const planDirective = buildPlanningDirective();
19207
+ let typingActive2 = true;
19208
+ const typingLoop2 = async () => {
19209
+ while (typingActive2) {
19210
+ try {
19211
+ await channel.sendTyping?.(chatId);
19212
+ } catch {
19213
+ }
19214
+ await new Promise((r) => setTimeout(r, 4e3));
19215
+ }
19216
+ };
19217
+ typingLoop2().catch(() => {
19218
+ });
19219
+ try {
19220
+ const planResponse = await askAgent(chatId, cleanText || text, {
19221
+ cwd: getCwd(chatId),
19222
+ model: model2,
19223
+ permMode: "yolo",
19224
+ bootstrapTier: bootstrapTier ?? "full",
19225
+ agentMode: effectiveAgentMode,
19226
+ planningDirective: planDirective
19227
+ });
19228
+ typingActive2 = false;
19229
+ if (planResponse.text) {
19230
+ storePendingPlan(chatId, planResponse.text, cleanText || text);
19231
+ if (typeof channel.sendKeyboard === "function") {
19232
+ await channel.sendKeyboard(chatId, `\u{1F50D} ${planResponse.text}`, [
19233
+ [
19234
+ { label: "\u2705 Approve", data: "exec:approve", style: "success" },
19235
+ { label: "\u274C Reject", data: "exec:reject", style: "danger" }
19236
+ ],
19237
+ [
19238
+ { label: "\u26A1 Skip & YOLO", data: "exec:yolo" }
19239
+ ]
19240
+ ]);
19241
+ } else {
19242
+ await sendResponse(chatId, channel, planResponse.text, void 0);
19243
+ }
19244
+ } else {
19245
+ await channel.sendText(chatId, "(No plan generated \u2014 proceeding normally)", { parseMode: "plain" });
19246
+ }
19247
+ } catch (err) {
19248
+ typingActive2 = false;
19249
+ await channel.sendText(chatId, `\u26A0\uFE0F Planning error: ${err.message}`, { parseMode: "plain" });
19250
+ }
19251
+ return;
19252
+ }
18791
19253
  let typingActive = true;
18792
19254
  const typingLoop = async () => {
18793
19255
  while (typingActive) {
@@ -18968,6 +19430,7 @@ var init_router = __esm({
18968
19430
  init_wizard();
18969
19431
  init_classify2();
18970
19432
  init_store3();
19433
+ init_gate();
18971
19434
  init_helpers();
18972
19435
  init_response();
18973
19436
  init_shell();
@@ -19228,6 +19691,8 @@ async function runWithRetry(job, model2, runId, t0) {
19228
19691
  if (job.jobType === "reflection") {
19229
19692
  const { runNightlyReflection: runNightlyReflection2 } = await Promise.resolve().then(() => (init_analyze(), analyze_exports));
19230
19693
  const { formatNightlySummary: formatNightlySummary2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
19694
+ const { getPendingInsightCount: getPendingInsightCount2, getActiveReflectionChatIds: getActiveReflectionChatIds2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
19695
+ const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
19231
19696
  const timeoutMs2 = job.timeout ? job.timeout * 1e3 : void 0;
19232
19697
  const { results } = await runNightlyReflection2({
19233
19698
  timeoutMs: timeoutMs2,
@@ -19240,7 +19705,13 @@ async function runWithRetry(job, model2, runId, t0) {
19240
19705
  const allInsights = results.flatMap(
19241
19706
  (r) => r.insights.map((ins) => ({ id: ++seq, ...ins }))
19242
19707
  );
19243
- return { text: formatNightlySummary2(allInsights) };
19708
+ const db3 = getDb2();
19709
+ const activeChats2 = getActiveReflectionChatIds2(db3);
19710
+ let totalPending = 0;
19711
+ for (const cid of activeChats2) {
19712
+ totalPending += getPendingInsightCount2(db3, cid);
19713
+ }
19714
+ return { text: formatNightlySummary2(allInsights, totalPending) };
19244
19715
  }
19245
19716
  if (job.thinking && job.thinking !== "auto") {
19246
19717
  setThinkingLevel(chatId, job.thinking);
@@ -19346,7 +19817,7 @@ var init_cron = __esm({
19346
19817
  });
19347
19818
 
19348
19819
  // src/agents/runners/wrap-backend.ts
19349
- import { join as join19 } from "path";
19820
+ import { join as join20 } from "path";
19350
19821
  function buildMcpCommands(backendId) {
19351
19822
  const exe = backendId === "cursor" ? "agent" : backendId;
19352
19823
  return {
@@ -19440,7 +19911,7 @@ function wrapBackendAdapter(adapter) {
19440
19911
  const configPath = writeMcpConfigFile(server);
19441
19912
  return ["--mcp-config", configPath];
19442
19913
  },
19443
- getSkillPath: () => join19(SKILLS_PATH, `agent-${adapter.id}.md`)
19914
+ getSkillPath: () => join20(SKILLS_PATH, `agent-${adapter.id}.md`)
19444
19915
  };
19445
19916
  }
19446
19917
  var BACKEND_CAPABILITIES;
@@ -19491,18 +19962,18 @@ var init_wrap_backend = __esm({
19491
19962
  });
19492
19963
 
19493
19964
  // src/agents/runners/config-loader.ts
19494
- import { readFileSync as readFileSync10, readdirSync as readdirSync8, existsSync as existsSync18, mkdirSync as mkdirSync8, watchFile, unwatchFile } from "fs";
19495
- import { join as join20 } from "path";
19965
+ import { readFileSync as readFileSync10, readdirSync as readdirSync9, existsSync as existsSync19, mkdirSync as mkdirSync9, watchFile, unwatchFile } from "fs";
19966
+ import { join as join21 } from "path";
19496
19967
  import { execFileSync as execFileSync2 } from "child_process";
19497
19968
  function resolveExecutable(config2) {
19498
- if (existsSync18(config2.executable)) return config2.executable;
19969
+ if (existsSync19(config2.executable)) return config2.executable;
19499
19970
  try {
19500
19971
  return execFileSync2("which", [config2.executable], { encoding: "utf-8" }).trim();
19501
19972
  } catch {
19502
19973
  }
19503
19974
  for (const fallback of config2.executableFallbacks ?? []) {
19504
19975
  const resolved = fallback.replace(/^~/, process.env.HOME ?? "");
19505
- if (existsSync18(resolved)) return resolved;
19976
+ if (existsSync19(resolved)) return resolved;
19506
19977
  }
19507
19978
  return config2.executable;
19508
19979
  }
@@ -19628,7 +20099,7 @@ function configToRunner(config2) {
19628
20099
  prepareMcpInjection() {
19629
20100
  return [];
19630
20101
  },
19631
- getSkillPath: () => join20(SKILLS_PATH, `agent-${config2.id}.md`)
20102
+ getSkillPath: () => join21(SKILLS_PATH, `agent-${config2.id}.md`)
19632
20103
  };
19633
20104
  }
19634
20105
  function loadRunnerConfig(filePath) {
@@ -19641,14 +20112,14 @@ function loadRunnerConfig(filePath) {
19641
20112
  }
19642
20113
  }
19643
20114
  function loadAllRunnerConfigs() {
19644
- if (!existsSync18(RUNNERS_PATH)) {
19645
- mkdirSync8(RUNNERS_PATH, { recursive: true });
20115
+ if (!existsSync19(RUNNERS_PATH)) {
20116
+ mkdirSync9(RUNNERS_PATH, { recursive: true });
19646
20117
  return [];
19647
20118
  }
19648
- const files = readdirSync8(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
20119
+ const files = readdirSync9(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
19649
20120
  const configs = [];
19650
20121
  for (const file of files) {
19651
- const config2 = loadRunnerConfig(join20(RUNNERS_PATH, file));
20122
+ const config2 = loadRunnerConfig(join21(RUNNERS_PATH, file));
19652
20123
  if (config2) configs.push(config2);
19653
20124
  }
19654
20125
  return configs;
@@ -19669,16 +20140,16 @@ function registerConfigRunners() {
19669
20140
  return count;
19670
20141
  }
19671
20142
  function watchRunnerConfigs(onChange) {
19672
- if (!existsSync18(RUNNERS_PATH)) return;
20143
+ if (!existsSync19(RUNNERS_PATH)) return;
19673
20144
  for (const prev of watchedFiles) {
19674
- if (!existsSync18(prev)) {
20145
+ if (!existsSync19(prev)) {
19675
20146
  unwatchFile(prev);
19676
20147
  watchedFiles.delete(prev);
19677
20148
  }
19678
20149
  }
19679
- const files = readdirSync8(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
20150
+ const files = readdirSync9(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
19680
20151
  for (const file of files) {
19681
- const fullPath = join20(RUNNERS_PATH, file);
20152
+ const fullPath = join21(RUNNERS_PATH, file);
19682
20153
  if (watchedFiles.has(fullPath)) continue;
19683
20154
  watchedFiles.add(fullPath);
19684
20155
  watchFile(fullPath, { interval: 5e3 }, () => {
@@ -20076,6 +20547,7 @@ var init_telegram2 = __esm({
20076
20547
  { command: "summarizer", description: "Configure session summarization model" },
20077
20548
  // Permissions & tools
20078
20549
  { command: "permissions", description: "Permission mode (yolo/safe/readonly/plan)" },
20550
+ { command: "mode", description: "Execution gate (approved/yolo)" },
20079
20551
  { command: "tools", description: "Configure which tools the agent can use" },
20080
20552
  { command: "verbose", description: "Tool visibility (off/normal/verbose)" },
20081
20553
  { command: "cwd", description: "Set or show working directory" },
@@ -20512,19 +20984,19 @@ var init_telegram2 = __esm({
20512
20984
  });
20513
20985
 
20514
20986
  // src/skills/bootstrap.ts
20515
- import { existsSync as existsSync19 } from "fs";
20987
+ import { existsSync as existsSync20 } from "fs";
20516
20988
  import { readdir as readdir6, readFile as readFile8, writeFile as writeFile5, copyFile } from "fs/promises";
20517
- import { join as join21, dirname as dirname3 } from "path";
20989
+ import { join as join22, dirname as dirname4 } from "path";
20518
20990
  import { fileURLToPath as fileURLToPath2 } from "url";
20519
20991
  async function copyAgentManifestSkills() {
20520
- if (!existsSync19(PKG_SKILLS)) return;
20992
+ if (!existsSync20(PKG_SKILLS)) return;
20521
20993
  try {
20522
20994
  const entries = await readdir6(PKG_SKILLS, { withFileTypes: true });
20523
20995
  for (const entry of entries) {
20524
20996
  if (!entry.isFile() || !entry.name.startsWith("agent-") || !entry.name.endsWith(".md")) continue;
20525
- const src = join21(PKG_SKILLS, entry.name);
20526
- const dest = join21(SKILLS_PATH, entry.name);
20527
- if (existsSync19(dest)) continue;
20997
+ const src = join22(PKG_SKILLS, entry.name);
20998
+ const dest = join22(SKILLS_PATH, entry.name);
20999
+ if (existsSync20(dest)) continue;
20528
21000
  await copyFile(src, dest);
20529
21001
  log(`[skills] Bootstrapped ${entry.name} to ${SKILLS_PATH}`);
20530
21002
  }
@@ -20534,8 +21006,8 @@ async function copyAgentManifestSkills() {
20534
21006
  }
20535
21007
  async function bootstrapSkills() {
20536
21008
  await copyAgentManifestSkills();
20537
- const usmDir = join21(SKILLS_PATH, USM_DIR_NAME);
20538
- if (existsSync19(usmDir)) return;
21009
+ const usmDir = join22(SKILLS_PATH, USM_DIR_NAME);
21010
+ if (existsSync20(usmDir)) return;
20539
21011
  try {
20540
21012
  const entries = await readdir6(SKILLS_PATH);
20541
21013
  const dirs = entries.filter((e) => !e.startsWith("."));
@@ -20557,8 +21029,8 @@ async function bootstrapSkills() {
20557
21029
  }
20558
21030
  }
20559
21031
  async function patchUsmForCcClaw(usmDir) {
20560
- const skillPath = join21(usmDir, "SKILL.md");
20561
- if (!existsSync19(skillPath)) return;
21032
+ const skillPath = join22(usmDir, "SKILL.md");
21033
+ if (!existsSync20(skillPath)) return;
20562
21034
  try {
20563
21035
  let content = await readFile8(skillPath, "utf-8");
20564
21036
  let patched = false;
@@ -20603,8 +21075,8 @@ var init_bootstrap = __esm({
20603
21075
  USM_REPO = "jacob-bd/universal-skills-manager";
20604
21076
  USM_DIR_NAME = "universal-skills-manager";
20605
21077
  CC_CLAW_ECOSYSTEM_PATCH = `| **CC-Claw** | \`~/.cc-claw/workspace/skills/\` | N/A (daemon, no project scope) |`;
20606
- PKG_ROOT = join21(dirname3(fileURLToPath2(import.meta.url)), "..", "..");
20607
- PKG_SKILLS = join21(PKG_ROOT, "skills");
21078
+ PKG_ROOT = join22(dirname4(fileURLToPath2(import.meta.url)), "..", "..");
21079
+ PKG_SKILLS = join22(PKG_ROOT, "skills");
20608
21080
  }
20609
21081
  });
20610
21082
 
@@ -20826,13 +21298,13 @@ __export(ai_skill_exports, {
20826
21298
  generateAiSkill: () => generateAiSkill,
20827
21299
  installAiSkill: () => installAiSkill
20828
21300
  });
20829
- import { existsSync as existsSync20, writeFileSync as writeFileSync7, mkdirSync as mkdirSync9 } from "fs";
20830
- import { join as join22 } from "path";
21301
+ import { existsSync as existsSync21, writeFileSync as writeFileSync7, mkdirSync as mkdirSync10 } from "fs";
21302
+ import { join as join23 } from "path";
20831
21303
  import { homedir as homedir7 } from "os";
20832
21304
  function generateAiSkill() {
20833
21305
  const version = VERSION;
20834
21306
  let systemState = "";
20835
- if (existsSync20(DB_PATH)) {
21307
+ if (existsSync21(DB_PATH)) {
20836
21308
  try {
20837
21309
  const { openDatabaseReadOnly: openDatabaseReadOnly2 } = (init_store5(), __toCommonJS(store_exports5));
20838
21310
  const readDb = openDatabaseReadOnly2();
@@ -21236,10 +21708,10 @@ function installAiSkill() {
21236
21708
  const failed = [];
21237
21709
  for (const [backend2, dirs] of Object.entries(BACKEND_SKILL_DIRS2)) {
21238
21710
  for (const dir of dirs) {
21239
- const skillDir = join22(dir, "cc-claw-cli");
21240
- const skillPath = join22(skillDir, "SKILL.md");
21711
+ const skillDir = join23(dir, "cc-claw-cli");
21712
+ const skillPath = join23(skillDir, "SKILL.md");
21241
21713
  try {
21242
- mkdirSync9(skillDir, { recursive: true });
21714
+ mkdirSync10(skillDir, { recursive: true });
21243
21715
  writeFileSync7(skillPath, skill, "utf-8");
21244
21716
  installed.push(skillPath);
21245
21717
  } catch {
@@ -21256,11 +21728,11 @@ var init_ai_skill = __esm({
21256
21728
  init_paths();
21257
21729
  init_version();
21258
21730
  BACKEND_SKILL_DIRS2 = {
21259
- "cc-claw": [join22(homedir7(), ".cc-claw", "workspace", "skills")],
21260
- claude: [join22(homedir7(), ".claude", "skills")],
21261
- gemini: [join22(homedir7(), ".gemini", "skills")],
21262
- codex: [join22(homedir7(), ".agents", "skills")],
21263
- cursor: [join22(homedir7(), ".cursor", "skills"), join22(homedir7(), ".cursor", "skills-cursor")]
21731
+ "cc-claw": [join23(homedir7(), ".cc-claw", "workspace", "skills")],
21732
+ claude: [join23(homedir7(), ".claude", "skills")],
21733
+ gemini: [join23(homedir7(), ".gemini", "skills")],
21734
+ codex: [join23(homedir7(), ".agents", "skills")],
21735
+ cursor: [join23(homedir7(), ".cursor", "skills"), join23(homedir7(), ".cursor", "skills-cursor")]
21264
21736
  };
21265
21737
  }
21266
21738
  });
@@ -21270,23 +21742,23 @@ var index_exports = {};
21270
21742
  __export(index_exports, {
21271
21743
  main: () => main
21272
21744
  });
21273
- import { mkdirSync as mkdirSync10, existsSync as existsSync21, renameSync, statSync as statSync5, readFileSync as readFileSync12 } from "fs";
21274
- import { join as join23 } from "path";
21745
+ import { mkdirSync as mkdirSync11, existsSync as existsSync22, renameSync as renameSync2, statSync as statSync6, readFileSync as readFileSync12 } from "fs";
21746
+ import { join as join24 } from "path";
21275
21747
  import dotenv from "dotenv";
21276
21748
  function migrateLayout() {
21277
21749
  const moves = [
21278
- [join23(CC_CLAW_HOME, "cc-claw.db"), join23(DATA_PATH, "cc-claw.db")],
21279
- [join23(CC_CLAW_HOME, "cc-claw.db-shm"), join23(DATA_PATH, "cc-claw.db-shm")],
21280
- [join23(CC_CLAW_HOME, "cc-claw.db-wal"), join23(DATA_PATH, "cc-claw.db-wal")],
21281
- [join23(CC_CLAW_HOME, "cc-claw.log"), join23(LOGS_PATH, "cc-claw.log")],
21282
- [join23(CC_CLAW_HOME, "cc-claw.log.1"), join23(LOGS_PATH, "cc-claw.log.1")],
21283
- [join23(CC_CLAW_HOME, "cc-claw.error.log"), join23(LOGS_PATH, "cc-claw.error.log")],
21284
- [join23(CC_CLAW_HOME, "cc-claw.error.log.1"), join23(LOGS_PATH, "cc-claw.error.log.1")]
21750
+ [join24(CC_CLAW_HOME, "cc-claw.db"), join24(DATA_PATH, "cc-claw.db")],
21751
+ [join24(CC_CLAW_HOME, "cc-claw.db-shm"), join24(DATA_PATH, "cc-claw.db-shm")],
21752
+ [join24(CC_CLAW_HOME, "cc-claw.db-wal"), join24(DATA_PATH, "cc-claw.db-wal")],
21753
+ [join24(CC_CLAW_HOME, "cc-claw.log"), join24(LOGS_PATH, "cc-claw.log")],
21754
+ [join24(CC_CLAW_HOME, "cc-claw.log.1"), join24(LOGS_PATH, "cc-claw.log.1")],
21755
+ [join24(CC_CLAW_HOME, "cc-claw.error.log"), join24(LOGS_PATH, "cc-claw.error.log")],
21756
+ [join24(CC_CLAW_HOME, "cc-claw.error.log.1"), join24(LOGS_PATH, "cc-claw.error.log.1")]
21285
21757
  ];
21286
21758
  for (const [from, to] of moves) {
21287
- if (existsSync21(from) && !existsSync21(to)) {
21759
+ if (existsSync22(from) && !existsSync22(to)) {
21288
21760
  try {
21289
- renameSync(from, to);
21761
+ renameSync2(from, to);
21290
21762
  } catch {
21291
21763
  }
21292
21764
  }
@@ -21295,11 +21767,11 @@ function migrateLayout() {
21295
21767
  function rotateLogs() {
21296
21768
  for (const file of [LOG_PATH, ERROR_LOG_PATH]) {
21297
21769
  try {
21298
- const { size } = statSync5(file);
21770
+ const { size } = statSync6(file);
21299
21771
  if (size > LOG_MAX_BYTES) {
21300
21772
  const archivePath = `${file}.1`;
21301
21773
  try {
21302
- renameSync(file, archivePath);
21774
+ renameSync2(file, archivePath);
21303
21775
  } catch {
21304
21776
  }
21305
21777
  log(`[cc-claw] Rotated ${file} (was ${(size / 1024 / 1024).toFixed(1)}MB)`);
@@ -21347,6 +21819,12 @@ async function main() {
21347
21819
  }
21348
21820
  setBootTime();
21349
21821
  log("[cc-claw] Database initialized (sessions preserved for resume)");
21822
+ try {
21823
+ const { migrateAllSlots: migrateAllSlots2 } = await Promise.resolve().then(() => (init_symlink_manager(), symlink_manager_exports));
21824
+ migrateAllSlots2(CC_CLAW_HOME);
21825
+ } catch (err) {
21826
+ warn(`[cc-claw] Slot symlink migration failed: ${err instanceof Error ? err.message : String(err)}`);
21827
+ }
21350
21828
  if (process.env.TELEGRAM_BOT_TOKEN) {
21351
21829
  channelRegistry.register(new TelegramChannel());
21352
21830
  }
@@ -21423,11 +21901,11 @@ async function main() {
21423
21901
  bootstrapSkills().catch((err) => error("[cc-claw] Skill bootstrap failed:", err));
21424
21902
  try {
21425
21903
  const { generateAiSkill: generateAiSkill2 } = await Promise.resolve().then(() => (init_ai_skill(), ai_skill_exports));
21426
- const { writeFileSync: writeFileSync12, mkdirSync: mkdirSync17 } = await import("fs");
21427
- const { join: join29 } = await import("path");
21428
- const skillDir = join29(SKILLS_PATH, "cc-claw-cli");
21429
- mkdirSync17(skillDir, { recursive: true });
21430
- writeFileSync12(join29(skillDir, "SKILL.md"), generateAiSkill2(), "utf-8");
21904
+ const { writeFileSync: writeFileSync12, mkdirSync: mkdirSync18 } = await import("fs");
21905
+ const { join: join30 } = await import("path");
21906
+ const skillDir = join30(SKILLS_PATH, "cc-claw-cli");
21907
+ mkdirSync18(skillDir, { recursive: true });
21908
+ writeFileSync12(join30(skillDir, "SKILL.md"), generateAiSkill2(), "utf-8");
21431
21909
  log("[cc-claw] AI skill updated");
21432
21910
  } catch {
21433
21911
  }
@@ -21500,10 +21978,10 @@ var init_index = __esm({
21500
21978
  init_health3();
21501
21979
  init_image_gen();
21502
21980
  for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
21503
- if (!existsSync21(dir)) mkdirSync10(dir, { recursive: true });
21981
+ if (!existsSync22(dir)) mkdirSync11(dir, { recursive: true });
21504
21982
  }
21505
21983
  migrateLayout();
21506
- if (existsSync21(ENV_PATH)) {
21984
+ if (existsSync22(ENV_PATH)) {
21507
21985
  dotenv.config({ path: ENV_PATH });
21508
21986
  } else {
21509
21987
  console.error(`[cc-claw] Config not found at ${ENV_PATH} \u2014 run 'cc-claw setup' first`);
@@ -21524,12 +22002,12 @@ __export(api_client_exports, {
21524
22002
  apiPost: () => apiPost,
21525
22003
  isDaemonRunning: () => isDaemonRunning
21526
22004
  });
21527
- import { readFileSync as readFileSync13, existsSync as existsSync22 } from "fs";
22005
+ import { readFileSync as readFileSync13, existsSync as existsSync23 } from "fs";
21528
22006
  import { request as httpRequest, Agent } from "http";
21529
22007
  function getToken() {
21530
22008
  if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
21531
22009
  try {
21532
- if (existsSync22(TOKEN_PATH)) return readFileSync13(TOKEN_PATH, "utf-8").trim();
22010
+ if (existsSync23(TOKEN_PATH)) return readFileSync13(TOKEN_PATH, "utf-8").trim();
21533
22011
  } catch {
21534
22012
  }
21535
22013
  return null;
@@ -21628,10 +22106,10 @@ __export(service_exports, {
21628
22106
  serviceStatus: () => serviceStatus,
21629
22107
  uninstallService: () => uninstallService
21630
22108
  });
21631
- import { existsSync as existsSync23, mkdirSync as mkdirSync11, writeFileSync as writeFileSync8, unlinkSync as unlinkSync6 } from "fs";
22109
+ import { existsSync as existsSync24, mkdirSync as mkdirSync12, writeFileSync as writeFileSync8, unlinkSync as unlinkSync6 } from "fs";
21632
22110
  import { execFileSync as execFileSync3, execSync as execSync6 } from "child_process";
21633
22111
  import { homedir as homedir8, platform } from "os";
21634
- import { join as join24, dirname as dirname4 } from "path";
22112
+ import { join as join25, dirname as dirname5 } from "path";
21635
22113
  function xmlEscape(s) {
21636
22114
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
21637
22115
  }
@@ -21640,23 +22118,23 @@ function resolveExecutable2(name) {
21640
22118
  return execFileSync3("which", [name], { encoding: "utf-8" }).trim();
21641
22119
  } catch {
21642
22120
  const fallback = process.argv[1];
21643
- if (fallback && existsSync23(fallback)) return fallback;
22121
+ if (fallback && existsSync24(fallback)) return fallback;
21644
22122
  throw new Error(`Cannot find '${name}' executable. Install globally: npm install -g cc-claw`);
21645
22123
  }
21646
22124
  }
21647
22125
  function getPathDirs() {
21648
- const nodeBin = dirname4(process.execPath);
22126
+ const nodeBin = dirname5(process.execPath);
21649
22127
  const home = homedir8();
21650
22128
  const dirs = /* @__PURE__ */ new Set([
21651
22129
  nodeBin,
21652
- join24(home, ".local", "bin"),
22130
+ join25(home, ".local", "bin"),
21653
22131
  "/usr/local/bin",
21654
22132
  "/usr/bin",
21655
22133
  "/bin"
21656
22134
  ]);
21657
22135
  try {
21658
22136
  const prefix = execSync6("npm config get prefix", { encoding: "utf-8" }).trim();
21659
- if (prefix) dirs.add(join24(prefix, "bin"));
22137
+ if (prefix) dirs.add(join25(prefix, "bin"));
21660
22138
  } catch {
21661
22139
  }
21662
22140
  return [...dirs].join(":");
@@ -21714,10 +22192,10 @@ function generatePlist() {
21714
22192
  </plist>`;
21715
22193
  }
21716
22194
  function installMacOS() {
21717
- const agentsDir = dirname4(PLIST_PATH);
21718
- if (!existsSync23(agentsDir)) mkdirSync11(agentsDir, { recursive: true });
21719
- if (!existsSync23(LOGS_PATH)) mkdirSync11(LOGS_PATH, { recursive: true });
21720
- if (existsSync23(PLIST_PATH)) {
22195
+ const agentsDir = dirname5(PLIST_PATH);
22196
+ if (!existsSync24(agentsDir)) mkdirSync12(agentsDir, { recursive: true });
22197
+ if (!existsSync24(LOGS_PATH)) mkdirSync12(LOGS_PATH, { recursive: true });
22198
+ if (existsSync24(PLIST_PATH)) {
21721
22199
  try {
21722
22200
  execFileSync3("launchctl", ["unload", PLIST_PATH]);
21723
22201
  } catch {
@@ -21729,7 +22207,7 @@ function installMacOS() {
21729
22207
  console.log(" Service loaded and starting.");
21730
22208
  }
21731
22209
  function uninstallMacOS() {
21732
- if (!existsSync23(PLIST_PATH)) {
22210
+ if (!existsSync24(PLIST_PATH)) {
21733
22211
  console.log(" No service found to uninstall.");
21734
22212
  return;
21735
22213
  }
@@ -21804,8 +22282,8 @@ WantedBy=default.target
21804
22282
  `;
21805
22283
  }
21806
22284
  function installLinux() {
21807
- if (!existsSync23(SYSTEMD_DIR)) mkdirSync11(SYSTEMD_DIR, { recursive: true });
21808
- if (!existsSync23(LOGS_PATH)) mkdirSync11(LOGS_PATH, { recursive: true });
22285
+ if (!existsSync24(SYSTEMD_DIR)) mkdirSync12(SYSTEMD_DIR, { recursive: true });
22286
+ if (!existsSync24(LOGS_PATH)) mkdirSync12(LOGS_PATH, { recursive: true });
21809
22287
  writeFileSync8(UNIT_PATH, generateUnit());
21810
22288
  console.log(` Installed: ${UNIT_PATH}`);
21811
22289
  execFileSync3("systemctl", ["--user", "daemon-reload"]);
@@ -21814,7 +22292,7 @@ function installLinux() {
21814
22292
  console.log(" Service enabled and started.");
21815
22293
  }
21816
22294
  function uninstallLinux() {
21817
- if (!existsSync23(UNIT_PATH)) {
22295
+ if (!existsSync24(UNIT_PATH)) {
21818
22296
  console.log(" No service found to uninstall.");
21819
22297
  return;
21820
22298
  }
@@ -21839,7 +22317,7 @@ function statusLinux() {
21839
22317
  }
21840
22318
  }
21841
22319
  function installService() {
21842
- if (!existsSync23(join24(CC_CLAW_HOME, ".env"))) {
22320
+ if (!existsSync24(join25(CC_CLAW_HOME, ".env"))) {
21843
22321
  console.error(` Config not found at ${CC_CLAW_HOME}/.env`);
21844
22322
  console.error(" Run 'cc-claw setup' before installing the service.");
21845
22323
  process.exitCode = 1;
@@ -21868,9 +22346,9 @@ var init_service = __esm({
21868
22346
  "use strict";
21869
22347
  init_paths();
21870
22348
  PLIST_LABEL = "com.cc-claw";
21871
- PLIST_PATH = join24(homedir8(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
21872
- SYSTEMD_DIR = join24(homedir8(), ".config", "systemd", "user");
21873
- UNIT_PATH = join24(SYSTEMD_DIR, "cc-claw.service");
22349
+ PLIST_PATH = join25(homedir8(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
22350
+ SYSTEMD_DIR = join25(homedir8(), ".config", "systemd", "user");
22351
+ UNIT_PATH = join25(SYSTEMD_DIR, "cc-claw.service");
21874
22352
  }
21875
22353
  });
21876
22354
 
@@ -22067,7 +22545,7 @@ var status_exports = {};
22067
22545
  __export(status_exports, {
22068
22546
  statusCommand: () => statusCommand
22069
22547
  });
22070
- import { existsSync as existsSync24, statSync as statSync6 } from "fs";
22548
+ import { existsSync as existsSync25, statSync as statSync7 } from "fs";
22071
22549
  async function statusCommand(globalOpts, localOpts) {
22072
22550
  try {
22073
22551
  const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
@@ -22107,7 +22585,7 @@ async function statusCommand(globalOpts, localOpts) {
22107
22585
  const cwdRow = readDb.prepare("SELECT cwd FROM chat_cwd WHERE chat_id = ?").get(chatId);
22108
22586
  const voiceRow = readDb.prepare("SELECT enabled FROM chat_voice WHERE chat_id = ?").get(chatId);
22109
22587
  const usageRow = readDb.prepare("SELECT * FROM chat_usage WHERE chat_id = ?").get(chatId);
22110
- const dbStat = existsSync24(DB_PATH) ? statSync6(DB_PATH) : null;
22588
+ const dbStat = existsSync25(DB_PATH) ? statSync7(DB_PATH) : null;
22111
22589
  let daemonRunning = false;
22112
22590
  let daemonInfo = {};
22113
22591
  try {
@@ -22196,12 +22674,12 @@ var doctor_exports = {};
22196
22674
  __export(doctor_exports, {
22197
22675
  doctorCommand: () => doctorCommand
22198
22676
  });
22199
- import { existsSync as existsSync25, statSync as statSync7, accessSync, constants } from "fs";
22677
+ import { existsSync as existsSync26, statSync as statSync8, accessSync, constants } from "fs";
22200
22678
  import { execFileSync as execFileSync4 } from "child_process";
22201
22679
  async function doctorCommand(globalOpts, localOpts) {
22202
22680
  const checks = [];
22203
- if (existsSync25(DB_PATH)) {
22204
- const size = statSync7(DB_PATH).size;
22681
+ if (existsSync26(DB_PATH)) {
22682
+ const size = statSync8(DB_PATH).size;
22205
22683
  checks.push({ name: "Database", status: "ok", message: `${DB_PATH} (${(size / 1024).toFixed(0)}KB)` });
22206
22684
  try {
22207
22685
  const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
@@ -22230,7 +22708,7 @@ async function doctorCommand(globalOpts, localOpts) {
22230
22708
  } else {
22231
22709
  checks.push({ name: "Database", status: "error", message: `Not found at ${DB_PATH}`, fix: "cc-claw setup" });
22232
22710
  }
22233
- if (existsSync25(ENV_PATH)) {
22711
+ if (existsSync26(ENV_PATH)) {
22234
22712
  checks.push({ name: "Environment", status: "ok", message: `.env loaded` });
22235
22713
  } else {
22236
22714
  checks.push({ name: "Environment", status: "error", message: "No .env found", fix: "cc-claw setup" });
@@ -22285,7 +22763,7 @@ async function doctorCommand(globalOpts, localOpts) {
22285
22763
  } catch {
22286
22764
  }
22287
22765
  const tokenPath = `${DATA_PATH}/api-token`;
22288
- if (existsSync25(tokenPath)) {
22766
+ if (existsSync26(tokenPath)) {
22289
22767
  try {
22290
22768
  accessSync(tokenPath, constants.R_OK);
22291
22769
  checks.push({ name: "API token", status: "ok", message: "token file readable" });
@@ -22310,7 +22788,7 @@ async function doctorCommand(globalOpts, localOpts) {
22310
22788
  }
22311
22789
  } catch {
22312
22790
  }
22313
- if (existsSync25(ERROR_LOG_PATH)) {
22791
+ if (existsSync26(ERROR_LOG_PATH)) {
22314
22792
  try {
22315
22793
  const { readFileSync: readFileSync22 } = await import("fs");
22316
22794
  const logContent = readFileSync22(ERROR_LOG_PATH, "utf-8");
@@ -22436,10 +22914,10 @@ var logs_exports = {};
22436
22914
  __export(logs_exports, {
22437
22915
  logsCommand: () => logsCommand
22438
22916
  });
22439
- import { existsSync as existsSync26, readFileSync as readFileSync16, watchFile as watchFile2, unwatchFile as unwatchFile2 } from "fs";
22917
+ import { existsSync as existsSync27, readFileSync as readFileSync16, watchFile as watchFile2, unwatchFile as unwatchFile2 } from "fs";
22440
22918
  async function logsCommand(opts) {
22441
22919
  const logFile = opts.error ? ERROR_LOG_PATH : LOG_PATH;
22442
- if (!existsSync26(logFile)) {
22920
+ if (!existsSync27(logFile)) {
22443
22921
  outputError("LOG_NOT_FOUND", `Log file not found: ${logFile}`);
22444
22922
  process.exit(1);
22445
22923
  }
@@ -22491,11 +22969,11 @@ __export(gemini_exports, {
22491
22969
  geminiReorder: () => geminiReorder,
22492
22970
  geminiRotation: () => geminiRotation
22493
22971
  });
22494
- import { existsSync as existsSync27, mkdirSync as mkdirSync12, writeFileSync as writeFileSync9, readFileSync as readFileSync17, chmodSync } from "fs";
22495
- import { join as join25 } from "path";
22972
+ import { existsSync as existsSync28, mkdirSync as mkdirSync13, writeFileSync as writeFileSync9, readFileSync as readFileSync17, chmodSync } from "fs";
22973
+ import { join as join26 } from "path";
22496
22974
  import { createInterface as createInterface5 } from "readline";
22497
22975
  function requireDb() {
22498
- if (!existsSync27(DB_PATH)) {
22976
+ if (!existsSync28(DB_PATH)) {
22499
22977
  outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
22500
22978
  process.exit(1);
22501
22979
  }
@@ -22520,8 +22998,8 @@ async function resolveSlotId(idOrLabel) {
22520
22998
  function resolveOAuthEmail(configHome) {
22521
22999
  if (!configHome) return null;
22522
23000
  try {
22523
- const accountsPath = join25(configHome, ".gemini", "google_accounts.json");
22524
- if (!existsSync27(accountsPath)) return null;
23001
+ const accountsPath = join26(configHome, ".gemini", "google_accounts.json");
23002
+ if (!existsSync28(accountsPath)) return null;
22525
23003
  const accounts = JSON.parse(readFileSync17(accountsPath, "utf-8"));
22526
23004
  return accounts.active || null;
22527
23005
  } catch {
@@ -22604,14 +23082,14 @@ async function geminiAddKey(globalOpts, opts) {
22604
23082
  }
22605
23083
  async function geminiAddAccount(globalOpts, opts) {
22606
23084
  await requireWriteDb();
22607
- const slotsDir = join25(CC_CLAW_HOME, "gemini-slots");
22608
- if (!existsSync27(slotsDir)) mkdirSync12(slotsDir, { recursive: true });
23085
+ const slotsDir = join26(CC_CLAW_HOME, "gemini-slots");
23086
+ if (!existsSync28(slotsDir)) mkdirSync13(slotsDir, { recursive: true });
22609
23087
  const { addGeminiSlot: addGeminiSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
22610
23088
  const tempId = Date.now();
22611
- const slotDir = join25(slotsDir, `slot-${tempId}`);
22612
- mkdirSync12(slotDir, { recursive: true, mode: 448 });
22613
- mkdirSync12(join25(slotDir, ".gemini"), { recursive: true });
22614
- writeFileSync9(join25(slotDir, ".gemini", "settings.json"), JSON.stringify({
23089
+ const slotDir = join26(slotsDir, `slot-${tempId}`);
23090
+ mkdirSync13(slotDir, { recursive: true, mode: 448 });
23091
+ mkdirSync13(join26(slotDir, ".gemini"), { recursive: true });
23092
+ writeFileSync9(join26(slotDir, ".gemini", "settings.json"), JSON.stringify({
22615
23093
  security: { auth: { selectedType: "oauth-personal" } }
22616
23094
  }, null, 2));
22617
23095
  console.log("");
@@ -22628,8 +23106,8 @@ async function geminiAddAccount(globalOpts, opts) {
22628
23106
  });
22629
23107
  } catch {
22630
23108
  }
22631
- const oauthPath = join25(slotDir, ".gemini", "oauth_creds.json");
22632
- if (!existsSync27(oauthPath)) {
23109
+ const oauthPath = join26(slotDir, ".gemini", "oauth_creds.json");
23110
+ if (!existsSync28(oauthPath)) {
22633
23111
  console.log(error2("\n No OAuth credentials found. Sign-in may have failed."));
22634
23112
  console.log(" The slot directory is preserved at: " + slotDir);
22635
23113
  console.log(" Re-run: cc-claw gemini add-account\n");
@@ -22637,7 +23115,7 @@ async function geminiAddAccount(globalOpts, opts) {
22637
23115
  }
22638
23116
  let accountEmail = "unknown";
22639
23117
  try {
22640
- const accounts = JSON.parse(__require("fs").readFileSync(join25(slotDir, ".gemini", "google_accounts.json"), "utf-8"));
23118
+ const accounts = JSON.parse(__require("fs").readFileSync(join26(slotDir, ".gemini", "google_accounts.json"), "utf-8"));
22641
23119
  accountEmail = accounts.active || accountEmail;
22642
23120
  } catch {
22643
23121
  }
@@ -22648,6 +23126,13 @@ async function geminiAddAccount(globalOpts, opts) {
22648
23126
  configHome: slotDir,
22649
23127
  priority: opts.priority ? parseInt(opts.priority, 10) : 0
22650
23128
  });
23129
+ try {
23130
+ const { setupSlotSymlinks: setupSlotSymlinks2, getPrimaryDir: getPrimaryDir2 } = await Promise.resolve().then(() => (init_symlink_manager(), symlink_manager_exports));
23131
+ const primaryDir = getPrimaryDir2("gemini");
23132
+ if (primaryDir) setupSlotSymlinks2("gemini", slotDir, primaryDir);
23133
+ } catch (err) {
23134
+ console.log(warning(` Warning: could not set up state symlinks \u2014 ${err instanceof Error ? err.message : String(err)}`));
23135
+ }
22651
23136
  output(
22652
23137
  { id, type: "oauth", label: opts.label || accountEmail, configHome: slotDir },
22653
23138
  () => success(`
@@ -22749,11 +23234,11 @@ __export(backend_cmd_factory_exports, {
22749
23234
  makeReorder: () => makeReorder,
22750
23235
  registerBackendSlotCommands: () => registerBackendSlotCommands
22751
23236
  });
22752
- import { existsSync as existsSync28, mkdirSync as mkdirSync13, readFileSync as readFileSync18 } from "fs";
22753
- import { join as join26 } from "path";
23237
+ import { existsSync as existsSync29, mkdirSync as mkdirSync14, readFileSync as readFileSync18 } from "fs";
23238
+ import { join as join27 } from "path";
22754
23239
  import { createInterface as createInterface6 } from "readline";
22755
23240
  function requireDb2() {
22756
- if (!existsSync28(DB_PATH)) {
23241
+ if (!existsSync29(DB_PATH)) {
22757
23242
  outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
22758
23243
  process.exit(1);
22759
23244
  }
@@ -22842,11 +23327,11 @@ function makeAddAccount(backend2, displayName) {
22842
23327
  process.exit(1);
22843
23328
  }
22844
23329
  await requireWriteDb2();
22845
- const slotsDir = join26(CC_CLAW_HOME, config2.slotsSubdir);
22846
- if (!existsSync28(slotsDir)) mkdirSync13(slotsDir, { recursive: true });
23330
+ const slotsDir = join27(CC_CLAW_HOME, config2.slotsSubdir);
23331
+ if (!existsSync29(slotsDir)) mkdirSync14(slotsDir, { recursive: true });
22847
23332
  const tempId = Date.now();
22848
- const slotDir = join26(slotsDir, `slot-${tempId}`);
22849
- mkdirSync13(slotDir, { recursive: true, mode: 448 });
23333
+ const slotDir = join27(slotsDir, `slot-${tempId}`);
23334
+ mkdirSync14(slotDir, { recursive: true, mode: 448 });
22850
23335
  if (config2.preSetup) config2.preSetup(slotDir);
22851
23336
  console.log("");
22852
23337
  console.log(` Opening ${displayName} CLI for sign-in...`);
@@ -22884,6 +23369,13 @@ function makeAddAccount(backend2, displayName) {
22884
23369
  configHome: slotDir,
22885
23370
  priority: opts.priority ? parseInt(opts.priority, 10) : 0
22886
23371
  });
23372
+ try {
23373
+ const { setupSlotSymlinks: setupSlotSymlinks2, getPrimaryDir: getPrimaryDir2 } = await Promise.resolve().then(() => (init_symlink_manager(), symlink_manager_exports));
23374
+ const primaryDir = getPrimaryDir2(backend2);
23375
+ if (primaryDir) setupSlotSymlinks2(backend2, slotDir, primaryDir);
23376
+ } catch (err) {
23377
+ console.log(warning(` Warning: could not set up state symlinks \u2014 ${err instanceof Error ? err.message : String(err)}`));
23378
+ }
22887
23379
  output(
22888
23380
  { id, type: "oauth", backend: backend2, label: accountLabel, configHome: slotDir },
22889
23381
  () => success(`Added ${displayName} subscription slot #${id} (${accountLabel})`)
@@ -23007,12 +23499,12 @@ var init_backend_cmd_factory = __esm({
23007
23499
  envValue: (slotDir) => slotDir,
23008
23500
  envOverrides: { ANTHROPIC_API_KEY: void 0 },
23009
23501
  preSetup: (slotDir) => {
23010
- mkdirSync13(join26(slotDir, ".claude"), { recursive: true });
23502
+ mkdirSync14(join27(slotDir, ".claude"), { recursive: true });
23011
23503
  },
23012
23504
  verifyCredentials: (slotDir) => {
23013
- const claudeJson = join26(slotDir, ".claude.json");
23014
- const claudeJsonNested = join26(slotDir, ".claude", ".claude.json");
23015
- if (existsSync28(claudeJson)) {
23505
+ const claudeJson = join27(slotDir, ".claude.json");
23506
+ const claudeJsonNested = join27(slotDir, ".claude", ".claude.json");
23507
+ if (existsSync29(claudeJson)) {
23016
23508
  try {
23017
23509
  const data = JSON.parse(readFileSync18(claudeJson, "utf-8"));
23018
23510
  return Boolean(data.oauthAccount);
@@ -23020,7 +23512,7 @@ var init_backend_cmd_factory = __esm({
23020
23512
  return false;
23021
23513
  }
23022
23514
  }
23023
- if (existsSync28(claudeJsonNested)) {
23515
+ if (existsSync29(claudeJsonNested)) {
23024
23516
  try {
23025
23517
  const data = JSON.parse(readFileSync18(claudeJsonNested, "utf-8"));
23026
23518
  return Boolean(data.oauthAccount);
@@ -23043,8 +23535,8 @@ var init_backend_cmd_factory = __esm({
23043
23535
  } catch {
23044
23536
  }
23045
23537
  try {
23046
- const claudeJson = join26(slotDir, ".claude.json");
23047
- if (existsSync28(claudeJson)) {
23538
+ const claudeJson = join27(slotDir, ".claude.json");
23539
+ if (existsSync29(claudeJson)) {
23048
23540
  const data = JSON.parse(readFileSync18(claudeJson, "utf-8"));
23049
23541
  if (data.oauthAccount?.emailAddress) return data.oauthAccount.emailAddress;
23050
23542
  }
@@ -23060,11 +23552,11 @@ var init_backend_cmd_factory = __esm({
23060
23552
  envValue: (slotDir) => slotDir,
23061
23553
  envOverrides: { OPENAI_API_KEY: void 0 },
23062
23554
  verifyCredentials: (slotDir) => {
23063
- return existsSync28(join26(slotDir, "auth.json"));
23555
+ return existsSync29(join27(slotDir, "auth.json"));
23064
23556
  },
23065
23557
  extractLabel: (slotDir) => {
23066
23558
  try {
23067
- const authData = JSON.parse(readFileSync18(join26(slotDir, "auth.json"), "utf-8"));
23559
+ const authData = JSON.parse(readFileSync18(join27(slotDir, "auth.json"), "utf-8"));
23068
23560
  if (authData.email) return authData.email;
23069
23561
  if (authData.account_name) return authData.account_name;
23070
23562
  if (authData.user?.email) return authData.user.email;
@@ -23084,12 +23576,12 @@ __export(backend_exports, {
23084
23576
  backendList: () => backendList,
23085
23577
  backendSet: () => backendSet
23086
23578
  });
23087
- import { existsSync as existsSync29 } from "fs";
23579
+ import { existsSync as existsSync30 } from "fs";
23088
23580
  async function backendList(globalOpts) {
23089
23581
  const { getAvailableAdapters: getAvailableAdapters3 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
23090
23582
  const chatId = resolveChatId(globalOpts);
23091
23583
  let activeBackend = null;
23092
- if (existsSync29(DB_PATH)) {
23584
+ if (existsSync30(DB_PATH)) {
23093
23585
  const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
23094
23586
  const readDb = openDatabaseReadOnly2();
23095
23587
  try {
@@ -23120,7 +23612,7 @@ async function backendList(globalOpts) {
23120
23612
  }
23121
23613
  async function backendGet(globalOpts) {
23122
23614
  const chatId = resolveChatId(globalOpts);
23123
- if (!existsSync29(DB_PATH)) {
23615
+ if (!existsSync30(DB_PATH)) {
23124
23616
  outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
23125
23617
  process.exit(1);
23126
23618
  }
@@ -23164,13 +23656,13 @@ __export(model_exports, {
23164
23656
  modelList: () => modelList,
23165
23657
  modelSet: () => modelSet
23166
23658
  });
23167
- import { existsSync as existsSync30 } from "fs";
23659
+ import { existsSync as existsSync31 } from "fs";
23168
23660
  async function modelList(globalOpts) {
23169
23661
  const chatId = resolveChatId(globalOpts);
23170
23662
  const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
23171
23663
  const { getAdapter: getAdapter4, getAllAdapters: getAllAdapters5 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
23172
23664
  let backendId = "claude";
23173
- if (existsSync30(DB_PATH)) {
23665
+ if (existsSync31(DB_PATH)) {
23174
23666
  const readDb = openDatabaseReadOnly2();
23175
23667
  try {
23176
23668
  const row = readDb.prepare("SELECT backend FROM chat_backend WHERE chat_id = ?").get(chatId);
@@ -23203,7 +23695,7 @@ async function modelList(globalOpts) {
23203
23695
  }
23204
23696
  async function modelGet(globalOpts) {
23205
23697
  const chatId = resolveChatId(globalOpts);
23206
- if (!existsSync30(DB_PATH)) {
23698
+ if (!existsSync31(DB_PATH)) {
23207
23699
  outputError("DB_NOT_FOUND", "Database not found.");
23208
23700
  process.exit(1);
23209
23701
  }
@@ -23247,9 +23739,9 @@ __export(memory_exports2, {
23247
23739
  memoryList: () => memoryList,
23248
23740
  memorySearch: () => memorySearch
23249
23741
  });
23250
- import { existsSync as existsSync31 } from "fs";
23742
+ import { existsSync as existsSync32 } from "fs";
23251
23743
  async function memoryList(globalOpts) {
23252
- if (!existsSync31(DB_PATH)) {
23744
+ if (!existsSync32(DB_PATH)) {
23253
23745
  outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
23254
23746
  process.exit(1);
23255
23747
  }
@@ -23273,7 +23765,7 @@ async function memoryList(globalOpts) {
23273
23765
  });
23274
23766
  }
23275
23767
  async function memorySearch(globalOpts, query) {
23276
- if (!existsSync31(DB_PATH)) {
23768
+ if (!existsSync32(DB_PATH)) {
23277
23769
  outputError("DB_NOT_FOUND", "Database not found.");
23278
23770
  process.exit(1);
23279
23771
  }
@@ -23295,7 +23787,7 @@ async function memorySearch(globalOpts, query) {
23295
23787
  });
23296
23788
  }
23297
23789
  async function memoryHistory(globalOpts, opts) {
23298
- if (!existsSync31(DB_PATH)) {
23790
+ if (!existsSync32(DB_PATH)) {
23299
23791
  outputError("DB_NOT_FOUND", "Database not found.");
23300
23792
  process.exit(1);
23301
23793
  }
@@ -23343,7 +23835,7 @@ __export(cron_exports2, {
23343
23835
  cronList: () => cronList,
23344
23836
  cronRuns: () => cronRuns
23345
23837
  });
23346
- import { existsSync as existsSync32 } from "fs";
23838
+ import { existsSync as existsSync33 } from "fs";
23347
23839
  function parseFallbacks(raw) {
23348
23840
  return raw.slice(0, 3).map((f) => {
23349
23841
  const [backend2, ...rest] = f.split(":");
@@ -23364,7 +23856,7 @@ function parseAndValidateTimeout(raw) {
23364
23856
  return val;
23365
23857
  }
23366
23858
  async function cronList(globalOpts) {
23367
- if (!existsSync32(DB_PATH)) {
23859
+ if (!existsSync33(DB_PATH)) {
23368
23860
  outputError("DB_NOT_FOUND", "Database not found.");
23369
23861
  process.exit(1);
23370
23862
  }
@@ -23402,7 +23894,7 @@ async function cronList(globalOpts) {
23402
23894
  });
23403
23895
  }
23404
23896
  async function cronHealth(globalOpts) {
23405
- if (!existsSync32(DB_PATH)) {
23897
+ if (!existsSync33(DB_PATH)) {
23406
23898
  outputError("DB_NOT_FOUND", "Database not found.");
23407
23899
  process.exit(1);
23408
23900
  }
@@ -23561,7 +24053,7 @@ async function cronEdit(globalOpts, id, opts) {
23561
24053
  }
23562
24054
  }
23563
24055
  async function cronRuns(globalOpts, jobId, opts) {
23564
- if (!existsSync32(DB_PATH)) {
24056
+ if (!existsSync33(DB_PATH)) {
23565
24057
  outputError("DB_NOT_FOUND", "Database not found.");
23566
24058
  process.exit(1);
23567
24059
  }
@@ -23608,9 +24100,9 @@ __export(agents_exports, {
23608
24100
  runnersList: () => runnersList,
23609
24101
  tasksList: () => tasksList
23610
24102
  });
23611
- import { existsSync as existsSync33 } from "fs";
24103
+ import { existsSync as existsSync34 } from "fs";
23612
24104
  async function agentsList(globalOpts) {
23613
- if (!existsSync33(DB_PATH)) {
24105
+ if (!existsSync34(DB_PATH)) {
23614
24106
  outputError("DB_NOT_FOUND", "Database not found.");
23615
24107
  process.exit(1);
23616
24108
  }
@@ -23641,7 +24133,7 @@ async function agentsList(globalOpts) {
23641
24133
  });
23642
24134
  }
23643
24135
  async function tasksList(globalOpts) {
23644
- if (!existsSync33(DB_PATH)) {
24136
+ if (!existsSync34(DB_PATH)) {
23645
24137
  outputError("DB_NOT_FOUND", "Database not found.");
23646
24138
  process.exit(1);
23647
24139
  }
@@ -23769,18 +24261,18 @@ __export(db_exports, {
23769
24261
  dbPath: () => dbPath,
23770
24262
  dbStats: () => dbStats
23771
24263
  });
23772
- import { existsSync as existsSync34, statSync as statSync8, copyFileSync as copyFileSync2, mkdirSync as mkdirSync14 } from "fs";
23773
- import { dirname as dirname5 } from "path";
24264
+ import { existsSync as existsSync35, statSync as statSync9, copyFileSync as copyFileSync3, mkdirSync as mkdirSync15 } from "fs";
24265
+ import { dirname as dirname6 } from "path";
23774
24266
  async function dbStats(globalOpts) {
23775
- if (!existsSync34(DB_PATH)) {
24267
+ if (!existsSync35(DB_PATH)) {
23776
24268
  outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
23777
24269
  process.exit(1);
23778
24270
  }
23779
24271
  const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
23780
24272
  const readDb = openDatabaseReadOnly2();
23781
- const mainSize = statSync8(DB_PATH).size;
24273
+ const mainSize = statSync9(DB_PATH).size;
23782
24274
  const walPath = DB_PATH + "-wal";
23783
- const walSize = existsSync34(walPath) ? statSync8(walPath).size : 0;
24275
+ const walSize = existsSync35(walPath) ? statSync9(walPath).size : 0;
23784
24276
  const tableNames = readDb.prepare(
23785
24277
  "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '%_fts%' ORDER BY name"
23786
24278
  ).all();
@@ -23814,17 +24306,17 @@ async function dbPath(globalOpts) {
23814
24306
  output({ path: DB_PATH }, (d) => d.path);
23815
24307
  }
23816
24308
  async function dbBackup(globalOpts, destPath) {
23817
- if (!existsSync34(DB_PATH)) {
24309
+ if (!existsSync35(DB_PATH)) {
23818
24310
  outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
23819
24311
  process.exit(1);
23820
24312
  }
23821
24313
  const dest = destPath ?? `${DB_PATH}.backup-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
23822
24314
  try {
23823
- mkdirSync14(dirname5(dest), { recursive: true });
23824
- copyFileSync2(DB_PATH, dest);
24315
+ mkdirSync15(dirname6(dest), { recursive: true });
24316
+ copyFileSync3(DB_PATH, dest);
23825
24317
  const walPath = DB_PATH + "-wal";
23826
- if (existsSync34(walPath)) copyFileSync2(walPath, dest + "-wal");
23827
- output({ path: dest, sizeBytes: statSync8(dest).size }, (d) => {
24318
+ if (existsSync35(walPath)) copyFileSync3(walPath, dest + "-wal");
24319
+ output({ path: dest, sizeBytes: statSync9(dest).size }, (d) => {
23828
24320
  const b = d;
23829
24321
  return `
23830
24322
  ${success("Backup created:")} ${b.path} (${(b.sizeBytes / 1024).toFixed(0)}KB)
@@ -23852,9 +24344,9 @@ __export(usage_exports, {
23852
24344
  usageCost: () => usageCost,
23853
24345
  usageTokens: () => usageTokens
23854
24346
  });
23855
- import { existsSync as existsSync35 } from "fs";
24347
+ import { existsSync as existsSync36 } from "fs";
23856
24348
  function ensureDb() {
23857
- if (!existsSync35(DB_PATH)) {
24349
+ if (!existsSync36(DB_PATH)) {
23858
24350
  outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
23859
24351
  process.exit(1);
23860
24352
  }
@@ -24044,9 +24536,9 @@ __export(config_exports2, {
24044
24536
  configList: () => configList,
24045
24537
  configSet: () => configSet
24046
24538
  });
24047
- import { existsSync as existsSync36, readFileSync as readFileSync19 } from "fs";
24539
+ import { existsSync as existsSync37, readFileSync as readFileSync19 } from "fs";
24048
24540
  async function configList(globalOpts) {
24049
- if (!existsSync36(DB_PATH)) {
24541
+ if (!existsSync37(DB_PATH)) {
24050
24542
  outputError("DB_NOT_FOUND", "Database not found.");
24051
24543
  process.exit(1);
24052
24544
  }
@@ -24080,7 +24572,7 @@ async function configGet(globalOpts, key) {
24080
24572
  outputError("INVALID_KEY", `Unknown config key "${key}". Valid keys: ${RUNTIME_KEYS.join(", ")}`);
24081
24573
  process.exit(1);
24082
24574
  }
24083
- if (!existsSync36(DB_PATH)) {
24575
+ if (!existsSync37(DB_PATH)) {
24084
24576
  outputError("DB_NOT_FOUND", "Database not found.");
24085
24577
  process.exit(1);
24086
24578
  }
@@ -24126,7 +24618,7 @@ async function configSet(globalOpts, key, value) {
24126
24618
  }
24127
24619
  }
24128
24620
  async function configEnv(_globalOpts) {
24129
- if (!existsSync36(ENV_PATH)) {
24621
+ if (!existsSync37(ENV_PATH)) {
24130
24622
  outputError("ENV_NOT_FOUND", `No .env file at ${ENV_PATH}. Run cc-claw setup.`);
24131
24623
  process.exit(1);
24132
24624
  }
@@ -24180,9 +24672,9 @@ __export(session_exports, {
24180
24672
  sessionGet: () => sessionGet,
24181
24673
  sessionNew: () => sessionNew
24182
24674
  });
24183
- import { existsSync as existsSync37 } from "fs";
24675
+ import { existsSync as existsSync38 } from "fs";
24184
24676
  async function sessionGet(globalOpts) {
24185
- if (!existsSync37(DB_PATH)) {
24677
+ if (!existsSync38(DB_PATH)) {
24186
24678
  outputError("DB_NOT_FOUND", "Database not found.");
24187
24679
  process.exit(1);
24188
24680
  }
@@ -24243,9 +24735,9 @@ __export(permissions_exports, {
24243
24735
  verboseGet: () => verboseGet,
24244
24736
  verboseSet: () => verboseSet
24245
24737
  });
24246
- import { existsSync as existsSync38 } from "fs";
24738
+ import { existsSync as existsSync39 } from "fs";
24247
24739
  function ensureDb2() {
24248
- if (!existsSync38(DB_PATH)) {
24740
+ if (!existsSync39(DB_PATH)) {
24249
24741
  outputError("DB_NOT_FOUND", "Database not found.");
24250
24742
  process.exit(1);
24251
24743
  }
@@ -24392,9 +24884,9 @@ __export(cwd_exports, {
24392
24884
  cwdGet: () => cwdGet,
24393
24885
  cwdSet: () => cwdSet
24394
24886
  });
24395
- import { existsSync as existsSync39 } from "fs";
24887
+ import { existsSync as existsSync40 } from "fs";
24396
24888
  async function cwdGet(globalOpts) {
24397
- if (!existsSync39(DB_PATH)) {
24889
+ if (!existsSync40(DB_PATH)) {
24398
24890
  outputError("DB_NOT_FOUND", "Database not found.");
24399
24891
  process.exit(1);
24400
24892
  }
@@ -24456,9 +24948,9 @@ __export(voice_exports, {
24456
24948
  voiceGet: () => voiceGet,
24457
24949
  voiceSet: () => voiceSet
24458
24950
  });
24459
- import { existsSync as existsSync40 } from "fs";
24951
+ import { existsSync as existsSync41 } from "fs";
24460
24952
  async function voiceGet(globalOpts) {
24461
- if (!existsSync40(DB_PATH)) {
24953
+ if (!existsSync41(DB_PATH)) {
24462
24954
  outputError("DB_NOT_FOUND", "Database not found.");
24463
24955
  process.exit(1);
24464
24956
  }
@@ -24507,9 +24999,9 @@ __export(heartbeat_exports, {
24507
24999
  heartbeatGet: () => heartbeatGet,
24508
25000
  heartbeatSet: () => heartbeatSet
24509
25001
  });
24510
- import { existsSync as existsSync41 } from "fs";
25002
+ import { existsSync as existsSync42 } from "fs";
24511
25003
  async function heartbeatGet(globalOpts) {
24512
- if (!existsSync41(DB_PATH)) {
25004
+ if (!existsSync42(DB_PATH)) {
24513
25005
  outputError("DB_NOT_FOUND", "Database not found.");
24514
25006
  process.exit(1);
24515
25007
  }
@@ -24618,9 +25110,9 @@ __export(summarizer_exports, {
24618
25110
  summarizerGet: () => summarizerGet,
24619
25111
  summarizerSet: () => summarizerSet
24620
25112
  });
24621
- import { existsSync as existsSync42 } from "fs";
25113
+ import { existsSync as existsSync43 } from "fs";
24622
25114
  async function summarizerGet(globalOpts) {
24623
- if (!existsSync42(DB_PATH)) {
25115
+ if (!existsSync43(DB_PATH)) {
24624
25116
  outputError("DB_NOT_FOUND", "Database not found.");
24625
25117
  process.exit(1);
24626
25118
  }
@@ -24664,9 +25156,9 @@ __export(thinking_exports, {
24664
25156
  thinkingGet: () => thinkingGet,
24665
25157
  thinkingSet: () => thinkingSet
24666
25158
  });
24667
- import { existsSync as existsSync43 } from "fs";
25159
+ import { existsSync as existsSync44 } from "fs";
24668
25160
  async function thinkingGet(globalOpts) {
24669
- if (!existsSync43(DB_PATH)) {
25161
+ if (!existsSync44(DB_PATH)) {
24670
25162
  outputError("DB_NOT_FOUND", "Database not found.");
24671
25163
  process.exit(1);
24672
25164
  }
@@ -24710,9 +25202,9 @@ __export(chats_exports, {
24710
25202
  chatsList: () => chatsList,
24711
25203
  chatsRemoveAlias: () => chatsRemoveAlias
24712
25204
  });
24713
- import { existsSync as existsSync44 } from "fs";
25205
+ import { existsSync as existsSync45 } from "fs";
24714
25206
  async function chatsList(_globalOpts) {
24715
- if (!existsSync44(DB_PATH)) {
25207
+ if (!existsSync45(DB_PATH)) {
24716
25208
  outputError("DB_NOT_FOUND", "Database not found.");
24717
25209
  process.exit(1);
24718
25210
  }
@@ -24840,9 +25332,9 @@ var mcps_exports2 = {};
24840
25332
  __export(mcps_exports2, {
24841
25333
  mcpsList: () => mcpsList
24842
25334
  });
24843
- import { existsSync as existsSync45 } from "fs";
25335
+ import { existsSync as existsSync46 } from "fs";
24844
25336
  async function mcpsList(_globalOpts) {
24845
- if (!existsSync45(DB_PATH)) {
25337
+ if (!existsSync46(DB_PATH)) {
24846
25338
  outputError("DB_NOT_FOUND", "Database not found.");
24847
25339
  process.exit(1);
24848
25340
  }
@@ -24879,11 +25371,11 @@ __export(chat_exports2, {
24879
25371
  chatSend: () => chatSend
24880
25372
  });
24881
25373
  import { request as httpRequest2 } from "http";
24882
- import { readFileSync as readFileSync20, existsSync as existsSync46 } from "fs";
25374
+ import { readFileSync as readFileSync20, existsSync as existsSync47 } from "fs";
24883
25375
  function getToken2() {
24884
25376
  if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
24885
25377
  try {
24886
- if (existsSync46(TOKEN_PATH2)) return readFileSync20(TOKEN_PATH2, "utf-8").trim();
25378
+ if (existsSync47(TOKEN_PATH2)) return readFileSync20(TOKEN_PATH2, "utf-8").trim();
24887
25379
  } catch {
24888
25380
  }
24889
25381
  return null;
@@ -25162,8 +25654,8 @@ var completion_exports = {};
25162
25654
  __export(completion_exports, {
25163
25655
  completionCommand: () => completionCommand
25164
25656
  });
25165
- import { writeFileSync as writeFileSync10, mkdirSync as mkdirSync15 } from "fs";
25166
- import { join as join27 } from "path";
25657
+ import { writeFileSync as writeFileSync10, mkdirSync as mkdirSync16 } from "fs";
25658
+ import { join as join28 } from "path";
25167
25659
  import { homedir as homedir9 } from "os";
25168
25660
  async function completionCommand(opts) {
25169
25661
  const shell = opts.shell ?? detectShell();
@@ -25179,10 +25671,10 @@ async function completionCommand(opts) {
25179
25671
  process.exit(1);
25180
25672
  }
25181
25673
  if (opts.install) {
25182
- const dir = join27(homedir9(), ".config", "cc-claw", "completions");
25183
- mkdirSync15(dir, { recursive: true });
25674
+ const dir = join28(homedir9(), ".config", "cc-claw", "completions");
25675
+ mkdirSync16(dir, { recursive: true });
25184
25676
  const filename = shell === "zsh" ? "_cc-claw" : shell === "fish" ? "cc-claw.fish" : "cc-claw.bash";
25185
- const filepath = join27(dir, filename);
25677
+ const filepath = join28(dir, filename);
25186
25678
  writeFileSync10(filepath, script, "utf-8");
25187
25679
  console.log(`\u2713 Completion script written to ${filepath}
25188
25680
  `);
@@ -25353,9 +25845,9 @@ __export(evolve_exports2, {
25353
25845
  evolveStatus: () => evolveStatus,
25354
25846
  evolveUndo: () => evolveUndo
25355
25847
  });
25356
- import { existsSync as existsSync47 } from "fs";
25848
+ import { existsSync as existsSync48 } from "fs";
25357
25849
  function ensureDb3() {
25358
- if (!existsSync47(DB_PATH)) {
25850
+ if (!existsSync48(DB_PATH)) {
25359
25851
  outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
25360
25852
  process.exit(1);
25361
25853
  }
@@ -25771,10 +26263,10 @@ var init_evolve3 = __esm({
25771
26263
 
25772
26264
  // src/setup.ts
25773
26265
  var setup_exports = {};
25774
- import { existsSync as existsSync48, writeFileSync as writeFileSync11, readFileSync as readFileSync21, copyFileSync as copyFileSync3, mkdirSync as mkdirSync16, statSync as statSync9 } from "fs";
26266
+ import { existsSync as existsSync49, writeFileSync as writeFileSync11, readFileSync as readFileSync21, copyFileSync as copyFileSync4, mkdirSync as mkdirSync17, statSync as statSync10 } from "fs";
25775
26267
  import { execFileSync as execFileSync5 } from "child_process";
25776
26268
  import { createInterface as createInterface8 } from "readline";
25777
- import { join as join28 } from "path";
26269
+ import { join as join29 } from "path";
25778
26270
  function divider2() {
25779
26271
  console.log(dim("\u2500".repeat(55)));
25780
26272
  }
@@ -25849,10 +26341,10 @@ async function setup() {
25849
26341
  }
25850
26342
  console.log("");
25851
26343
  for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
25852
- if (!existsSync48(dir)) mkdirSync16(dir, { recursive: true });
26344
+ if (!existsSync49(dir)) mkdirSync17(dir, { recursive: true });
25853
26345
  }
25854
26346
  const env = {};
25855
- const envSource = existsSync48(ENV_PATH) ? ENV_PATH : existsSync48(".env") ? ".env" : null;
26347
+ const envSource = existsSync49(ENV_PATH) ? ENV_PATH : existsSync49(".env") ? ".env" : null;
25856
26348
  if (envSource) {
25857
26349
  console.log(yellow(` Found existing config at ${envSource} \u2014 your values will be preserved`));
25858
26350
  console.log(yellow(" unless you enter new ones. Just press Enter to keep existing values.\n"));
@@ -25862,13 +26354,13 @@ async function setup() {
25862
26354
  if (match) env[match[1].trim()] = match[2].trim();
25863
26355
  }
25864
26356
  }
25865
- const cwdDb = join28(process.cwd(), "cc-claw.db");
25866
- if (existsSync48(cwdDb) && !existsSync48(DB_PATH)) {
25867
- const { size } = statSync9(cwdDb);
26357
+ const cwdDb = join29(process.cwd(), "cc-claw.db");
26358
+ if (existsSync49(cwdDb) && !existsSync49(DB_PATH)) {
26359
+ const { size } = statSync10(cwdDb);
25868
26360
  console.log(yellow(` Found existing database at ${cwdDb} (${(size / 1024).toFixed(0)}KB)`));
25869
26361
  const migrate = await confirm("Copy database to ~/.cc-claw/? (preserves memories & history)", true);
25870
26362
  if (migrate) {
25871
- copyFileSync3(cwdDb, DB_PATH);
26363
+ copyFileSync4(cwdDb, DB_PATH);
25872
26364
  console.log(green(` Database copied to ${DB_PATH}`));
25873
26365
  }
25874
26366
  console.log("");