cc-claw 0.16.4 → 0.17.1

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 +875 -372
  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.1" : (() => {
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,87 @@ 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.messageText.startsWith(">>")) return false;
12838
+ if (EXEMPT_TIERS.has(input.bootstrapTier)) return false;
12839
+ if (input.isSideQuest) return false;
12840
+ return true;
12841
+ }
12842
+ function buildPlanningDirective() {
12843
+ return [
12844
+ "## PLANNING MODE \u2014 Read-Only",
12845
+ "",
12846
+ "You are in PLANNING mode. Your goal is to research and present a plan.",
12847
+ "",
12848
+ "**ALLOWED:**",
12849
+ "- Read files, directories, and code",
12850
+ "- Load and read skills",
12851
+ "- Search the codebase (grep, glob, find)",
12852
+ "- Search the web for documentation or solutions",
12853
+ "- Analyze and reason about architecture",
12854
+ "",
12855
+ "**NOT ALLOWED:**",
12856
+ "- Do NOT create, modify, or delete any files",
12857
+ "- Do NOT run shell commands that mutate state",
12858
+ "- Do NOT write code or make edits",
12859
+ "- Do NOT install packages or dependencies",
12860
+ "",
12861
+ "**YOUR TASK:**",
12862
+ "Research the request thoroughly, then present a clear, concise plan",
12863
+ "of what you will do. The user will review and approve before you execute.",
12864
+ "Structure your plan with numbered steps and be specific about which",
12865
+ "files you will modify and what changes you will make."
12866
+ ].join("\n");
12867
+ }
12868
+ function storePendingPlan(chatId, plan, originalMessage) {
12869
+ pendingPlans.set(chatId, {
12870
+ plan,
12871
+ originalMessage,
12872
+ createdAt: Date.now()
12873
+ });
12874
+ }
12875
+ function getPendingPlan(chatId) {
12876
+ const entry = pendingPlans.get(chatId);
12877
+ if (!entry) return void 0;
12878
+ if (Date.now() - entry.createdAt > PLAN_TTL_MS) {
12879
+ pendingPlans.delete(chatId);
12880
+ return void 0;
12881
+ }
12882
+ return entry;
12883
+ }
12884
+ function removePendingPlan(chatId) {
12885
+ pendingPlans.delete(chatId);
12886
+ }
12887
+ function setRejectionMode(chatId) {
12888
+ rejectionModes.set(chatId, Date.now());
12889
+ }
12890
+ function getRejectionMode(chatId) {
12891
+ const createdAt = rejectionModes.get(chatId);
12892
+ if (createdAt === void 0) return false;
12893
+ if (Date.now() - createdAt > REJECTION_TTL_MS) {
12894
+ rejectionModes.delete(chatId);
12895
+ return false;
12896
+ }
12897
+ return true;
12898
+ }
12899
+ function clearRejectionMode(chatId) {
12900
+ rejectionModes.delete(chatId);
12901
+ }
12902
+ var EXEMPT_TIERS, PLAN_TTL_MS, pendingPlans, REJECTION_TTL_MS, rejectionModes;
12903
+ var init_gate = __esm({
12904
+ "src/execution/gate.ts"() {
12905
+ "use strict";
12906
+ EXEMPT_TIERS = /* @__PURE__ */ new Set(["slim", "heartbeat", "chat"]);
12907
+ PLAN_TTL_MS = 5 * 60 * 1e3;
12908
+ pendingPlans = /* @__PURE__ */ new Map();
12909
+ REJECTION_TTL_MS = 5 * 60 * 1e3;
12910
+ rejectionModes = /* @__PURE__ */ new Map();
12911
+ }
12912
+ });
12913
+
12610
12914
  // src/router/helpers.ts
12611
12915
  import { resolve as resolvePath } from "path";
12612
12916
  function parseMcpListOutput(output2) {
@@ -13307,9 +13611,9 @@ var init_stt = __esm({
13307
13611
  });
13308
13612
 
13309
13613
  // src/media/image-gen.ts
13310
- import { mkdirSync as mkdirSync7, existsSync as existsSync15, unlink as unlink2, readdir, stat } from "fs";
13614
+ import { mkdirSync as mkdirSync8, existsSync as existsSync16, unlink as unlink2, readdir, stat } from "fs";
13311
13615
  import { writeFile } from "fs/promises";
13312
- import { join as join14 } from "path";
13616
+ import { join as join15 } from "path";
13313
13617
  async function generateImage(prompt) {
13314
13618
  const apiKey = process.env.GEMINI_API_KEY;
13315
13619
  if (!apiKey) {
@@ -13356,12 +13660,12 @@ async function generateImage(prompt) {
13356
13660
  if (!imageData) {
13357
13661
  throw new Error(textResponse ?? "Gemini did not generate an image. The prompt may have been filtered.");
13358
13662
  }
13359
- if (!existsSync15(IMAGE_OUTPUT_DIR)) {
13360
- mkdirSync7(IMAGE_OUTPUT_DIR, { recursive: true });
13663
+ if (!existsSync16(IMAGE_OUTPUT_DIR)) {
13664
+ mkdirSync8(IMAGE_OUTPUT_DIR, { recursive: true });
13361
13665
  }
13362
13666
  const ext = mimeType.includes("jpeg") || mimeType.includes("jpg") ? "jpg" : "png";
13363
13667
  const filename = `img_${Date.now()}.${ext}`;
13364
- const filePath = join14(IMAGE_OUTPUT_DIR, filename);
13668
+ const filePath = join15(IMAGE_OUTPUT_DIR, filename);
13365
13669
  const buffer = Buffer.from(imageData, "base64");
13366
13670
  await writeFile(filePath, buffer);
13367
13671
  log(`[image-gen] Saved ${buffer.length} bytes to ${filePath}`);
@@ -13379,7 +13683,7 @@ function cleanupGeneratedImage(filePath) {
13379
13683
  function pruneImageCache() {
13380
13684
  readdir(IMAGE_OUTPUT_DIR, (err, files) => {
13381
13685
  if (err || !files) return;
13382
- const imageFiles = files.filter((f) => /\.(png|jpg)$/.test(f)).map((f) => join14(IMAGE_OUTPUT_DIR, f));
13686
+ const imageFiles = files.filter((f) => /\.(png|jpg)$/.test(f)).map((f) => join15(IMAGE_OUTPUT_DIR, f));
13383
13687
  if (imageFiles.length === 0) return;
13384
13688
  const now = Date.now();
13385
13689
  let statsPending = imageFiles.length;
@@ -13411,8 +13715,8 @@ var init_image_gen = __esm({
13411
13715
  MAX_GENERATED_IMAGES = 20;
13412
13716
  IMAGE_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
13413
13717
  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"),
13718
+ IMAGE_OUTPUT_DIR = join15(
13719
+ process.env.CC_CLAW_HOME ?? join15(process.env.HOME ?? "/tmp", ".cc-claw"),
13416
13720
  "data",
13417
13721
  "images"
13418
13722
  );
@@ -13885,7 +14189,7 @@ var init_video = __esm({
13885
14189
  });
13886
14190
 
13887
14191
  // src/router/media.ts
13888
- import { join as join15 } from "path";
14192
+ import { join as join16 } from "path";
13889
14193
  import { mkdir, writeFile as writeFile2, readdir as readdir2, stat as stat2, unlink as unlink3 } from "fs/promises";
13890
14194
  function getMediaRetentionMs() {
13891
14195
  const hours = parseInt(process.env.MEDIA_RETENTION_HOURS ?? "24", 10);
@@ -13894,7 +14198,7 @@ function getMediaRetentionMs() {
13894
14198
  async function saveMedia(buffer, prefix, ext) {
13895
14199
  await mkdir(MEDIA_INCOMING_PATH, { recursive: true });
13896
14200
  const filename = `${prefix}-${Date.now()}.${ext}`;
13897
- const fullPath = join15(MEDIA_INCOMING_PATH, filename);
14201
+ const fullPath = join16(MEDIA_INCOMING_PATH, filename);
13898
14202
  await writeFile2(fullPath, buffer);
13899
14203
  return fullPath;
13900
14204
  }
@@ -13908,7 +14212,7 @@ async function cleanupOldMedia() {
13908
14212
  let removed = 0;
13909
14213
  for (const file of files) {
13910
14214
  try {
13911
- const filePath = join15(MEDIA_INCOMING_PATH, file);
14215
+ const filePath = join16(MEDIA_INCOMING_PATH, file);
13912
14216
  const s = await stat2(filePath);
13913
14217
  if (now - s.mtimeMs > retentionMs) {
13914
14218
  await unlink3(filePath);
@@ -14091,7 +14395,7 @@ var init_media = __esm({
14091
14395
  init_store5();
14092
14396
  init_helpers();
14093
14397
  init_response();
14094
- MEDIA_INCOMING_PATH = join15(MEDIA_PATH, "incoming");
14398
+ MEDIA_INCOMING_PATH = join16(MEDIA_PATH, "incoming");
14095
14399
  }
14096
14400
  });
14097
14401
 
@@ -14227,7 +14531,7 @@ __export(discover_exports, {
14227
14531
  import { readdir as readdir3, readFile as readFile4 } from "fs/promises";
14228
14532
  import { createHash } from "crypto";
14229
14533
  import { homedir as homedir5 } from "os";
14230
- import { join as join16 } from "path";
14534
+ import { join as join17 } from "path";
14231
14535
  function invalidateSkillCache() {
14232
14536
  cachedSkills = null;
14233
14537
  cacheTimestamp = 0;
@@ -14245,7 +14549,7 @@ async function discoverAllSkills() {
14245
14549
  const rawSkills = [];
14246
14550
  rawSkills.push(...await scanSkillDir(SKILLS_PATH, "cc-claw"));
14247
14551
  for (const backendId of getAllBackendIds()) {
14248
- const dirs = BACKEND_SKILL_DIRS[backendId] ?? [join16(homedir5(), `.${backendId}`, "skills")];
14552
+ const dirs = BACKEND_SKILL_DIRS[backendId] ?? [join17(homedir5(), `.${backendId}`, "skills")];
14249
14553
  for (const dir of dirs) {
14250
14554
  rawSkills.push(...await scanSkillDir(dir, backendId));
14251
14555
  }
@@ -14273,7 +14577,7 @@ async function scanSkillDir(skillsDir, source) {
14273
14577
  let content;
14274
14578
  let resolvedPath;
14275
14579
  for (const candidate of SKILL_FILE_CANDIDATES) {
14276
- const p = join16(skillsDir, entry.name, candidate);
14580
+ const p = join17(skillsDir, entry.name, candidate);
14277
14581
  try {
14278
14582
  content = await readFile4(p, "utf-8");
14279
14583
  resolvedPath = p;
@@ -14377,15 +14681,15 @@ var init_discover = __esm({
14377
14681
  init_backends();
14378
14682
  SKILL_FILE_CANDIDATES = ["SKILL.md", "skill.md"];
14379
14683
  BACKEND_SKILL_DIRS = {
14380
- claude: [join16(homedir5(), ".claude", "skills")],
14381
- gemini: [join16(homedir5(), ".gemini", "skills")],
14684
+ claude: [join17(homedir5(), ".claude", "skills")],
14685
+ gemini: [join17(homedir5(), ".gemini", "skills")],
14382
14686
  codex: [
14383
- join16(homedir5(), ".agents", "skills"),
14384
- join16(homedir5(), ".codex", "skills")
14687
+ join17(homedir5(), ".agents", "skills"),
14688
+ join17(homedir5(), ".codex", "skills")
14385
14689
  ],
14386
14690
  cursor: [
14387
- join16(homedir5(), ".cursor", "skills"),
14388
- join16(homedir5(), ".cursor", "skills-cursor")
14691
+ join17(homedir5(), ".cursor", "skills"),
14692
+ join17(homedir5(), ".cursor", "skills-cursor")
14389
14693
  ]
14390
14694
  };
14391
14695
  CACHE_TTL_MS2 = 3e5;
@@ -14401,8 +14705,8 @@ __export(install_exports, {
14401
14705
  installSkillFromGitHub: () => installSkillFromGitHub
14402
14706
  });
14403
14707
  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";
14708
+ import { existsSync as existsSync17 } from "fs";
14709
+ import { join as join18, basename } from "path";
14406
14710
  import { execSync as execSync5 } from "child_process";
14407
14711
  async function installSkillFromGitHub(urlOrShorthand) {
14408
14712
  let repoUrl;
@@ -14413,36 +14717,36 @@ async function installSkillFromGitHub(urlOrShorthand) {
14413
14717
  }
14414
14718
  repoUrl = parsed.cloneUrl;
14415
14719
  subPath = parsed.subPath;
14416
- const tmpDir = join17("/tmp", `cc-claw-skill-${Date.now()}`);
14720
+ const tmpDir = join18("/tmp", `cc-claw-skill-${Date.now()}`);
14417
14721
  try {
14418
14722
  log(`[skill-install] Cloning ${repoUrl} to ${tmpDir}`);
14419
14723
  execSync5(`git clone --depth 1 ${repoUrl} ${tmpDir}`, {
14420
14724
  stdio: "pipe",
14421
14725
  timeout: 3e4
14422
14726
  });
14423
- if (!existsSync16(join17(tmpDir, ".git"))) {
14727
+ if (!existsSync17(join18(tmpDir, ".git"))) {
14424
14728
  return { success: false, error: "Git clone failed: no .git directory produced" };
14425
14729
  }
14426
- const searchRoot = subPath ? join17(tmpDir, subPath) : tmpDir;
14730
+ const searchRoot = subPath ? join18(tmpDir, subPath) : tmpDir;
14427
14731
  const skillDir = await findSkillDir(searchRoot);
14428
14732
  if (!skillDir) {
14429
14733
  return { success: false, error: "No SKILL.md found in the repository." };
14430
14734
  }
14431
14735
  const skillFolderName = basename(skillDir);
14432
- const destDir = join17(SKILLS_PATH, skillFolderName);
14433
- if (existsSync16(destDir)) {
14736
+ const destDir = join18(SKILLS_PATH, skillFolderName);
14737
+ if (existsSync17(destDir)) {
14434
14738
  log(`[skill-install] Overwriting existing skill at ${destDir}`);
14435
14739
  }
14436
14740
  await mkdir2(destDir, { recursive: true });
14437
14741
  await cp(skillDir, destDir, { recursive: true });
14438
14742
  let skillName = skillFolderName;
14439
14743
  try {
14440
- const content = await readFile5(join17(destDir, "SKILL.md"), "utf-8");
14744
+ const content = await readFile5(join18(destDir, "SKILL.md"), "utf-8");
14441
14745
  const nameMatch = content.match(/^name:\s*(.+)$/m);
14442
14746
  if (nameMatch) skillName = nameMatch[1].trim().replace(/^["']|["']$/g, "");
14443
14747
  } catch {
14444
14748
  try {
14445
- const content = await readFile5(join17(destDir, "skill.md"), "utf-8");
14749
+ const content = await readFile5(join18(destDir, "skill.md"), "utf-8");
14446
14750
  const nameMatch = content.match(/^name:\s*(.+)$/m);
14447
14751
  if (nameMatch) skillName = nameMatch[1].trim().replace(/^["']|["']$/g, "");
14448
14752
  } catch {
@@ -14477,15 +14781,15 @@ function parseGitHubUrl(input) {
14477
14781
  async function findSkillDir(root) {
14478
14782
  const candidates = ["SKILL.md", "skill.md"];
14479
14783
  for (const c of candidates) {
14480
- if (existsSync16(join17(root, c))) return root;
14784
+ if (existsSync17(join18(root, c))) return root;
14481
14785
  }
14482
14786
  try {
14483
14787
  const entries = await readdir4(root, { withFileTypes: true });
14484
14788
  for (const entry of entries) {
14485
14789
  if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
14486
14790
  for (const c of candidates) {
14487
- if (existsSync16(join17(root, entry.name, c))) {
14488
- return join17(root, entry.name);
14791
+ if (existsSync17(join18(root, entry.name, c))) {
14792
+ return join18(root, entry.name);
14489
14793
  }
14490
14794
  }
14491
14795
  }
@@ -14497,15 +14801,15 @@ async function findSkillDir(root) {
14497
14801
  if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
14498
14802
  let subEntries;
14499
14803
  try {
14500
- subEntries = await readdir4(join17(root, entry.name), { withFileTypes: true });
14804
+ subEntries = await readdir4(join18(root, entry.name), { withFileTypes: true });
14501
14805
  } catch {
14502
14806
  continue;
14503
14807
  }
14504
14808
  for (const sub of subEntries) {
14505
14809
  if (!sub.isDirectory() || sub.name.startsWith(".")) continue;
14506
14810
  for (const c of candidates) {
14507
- if (existsSync16(join17(root, entry.name, sub.name, c))) {
14508
- return join17(root, entry.name, sub.name);
14811
+ if (existsSync17(join18(root, entry.name, sub.name, c))) {
14812
+ return join18(root, entry.name, sub.name);
14509
14813
  }
14510
14814
  }
14511
14815
  }
@@ -14523,8 +14827,8 @@ var init_install = __esm({
14523
14827
  });
14524
14828
 
14525
14829
  // src/bootstrap/heartbeat.ts
14526
- import { readFileSync as readFileSync9, existsSync as existsSync17 } from "fs";
14527
- import { join as join18 } from "path";
14830
+ import { readFileSync as readFileSync9, existsSync as existsSync18 } from "fs";
14831
+ import { join as join19 } from "path";
14528
14832
  function initHeartbeat(channelReg) {
14529
14833
  registry2 = channelReg;
14530
14834
  }
@@ -14662,7 +14966,7 @@ ${healthLines.join("\n")}`);
14662
14966
  sections.push(`[Active watches]
14663
14967
  ${watchLines.join("\n")}`);
14664
14968
  }
14665
- if (existsSync17(HEARTBEAT_MD_PATH)) {
14969
+ if (existsSync18(HEARTBEAT_MD_PATH)) {
14666
14970
  try {
14667
14971
  const custom = readFileSync9(HEARTBEAT_MD_PATH, "utf-8").trim();
14668
14972
  if (custom) {
@@ -14710,7 +15014,7 @@ var init_heartbeat2 = __esm({
14710
15014
  init_backends();
14711
15015
  init_health2();
14712
15016
  init_log();
14713
- HEARTBEAT_MD_PATH = join18(WORKSPACE_PATH, "HEARTBEAT.md");
15017
+ HEARTBEAT_MD_PATH = join19(WORKSPACE_PATH, "HEARTBEAT.md");
14714
15018
  HEARTBEAT_OK = "HEARTBEAT_OK";
14715
15019
  registry2 = null;
14716
15020
  activeTimers = /* @__PURE__ */ new Map();
@@ -15767,9 +16071,9 @@ async function handleEvolveCallback(chatId, data, channel) {
15767
16071
  await channel.sendText(chatId, "No pending proposals.", { parseMode: "plain" });
15768
16072
  } else {
15769
16073
  const insightIds = pending.slice(0, 5).map((p) => p.id);
15770
- createReviewSession2(getDb(), reflChatId, insightIds);
16074
+ createReviewSession2(getDb(), chatId, insightIds);
15771
16075
  await channel.sendText(chatId, `${pending.length} proposal(s) ready. Let's review them one by one.`, { parseMode: "plain" });
15772
- await sendCurrentProposal(reflChatId, channel);
16076
+ await sendCurrentProposal(chatId, channel);
15773
16077
  }
15774
16078
  break;
15775
16079
  }
@@ -15927,13 +16231,13 @@ async function handleEvolveCallback(chatId, data, channel) {
15927
16231
  const { getReflectionStatus: getReflectionStatus2, setReflectionStatus: setReflectionStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
15928
16232
  const current = getReflectionStatus2(getDb(), chatId);
15929
16233
  if (current === "frozen") {
15930
- const { readFileSync: readFileSync22, existsSync: existsSync49 } = await import("fs");
15931
- const { join: join29 } = await import("path");
16234
+ const { readFileSync: readFileSync22, existsSync: existsSync50 } = await import("fs");
16235
+ const { join: join30 } = await import("path");
15932
16236
  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") : "";
16237
+ const soulPath = join30(CC_CLAW_HOME3, "identity/SOUL.md");
16238
+ const userPath = join30(CC_CLAW_HOME3, "identity/USER.md");
16239
+ const soul = existsSync50(soulPath) ? readFileSync22(soulPath, "utf-8") : "";
16240
+ const user = existsSync50(userPath) ? readFileSync22(userPath, "utf-8") : "";
15937
16241
  setReflectionStatus2(getDb(), chatId, "active", soul, user);
15938
16242
  const { logActivity: logActivity2 } = await Promise.resolve().then(() => (init_store3(), store_exports3));
15939
16243
  logActivity2(getDb(), { chatId, source: "telegram", eventType: "reflection_unfrozen", summary: "Reflection enabled" });
@@ -16086,6 +16390,29 @@ ${cmds.map((c) => ` ${c.cmd} \u2014 ${c.desc}`).join("\n")}`
16086
16390
  }
16087
16391
  break;
16088
16392
  }
16393
+ case "mode":
16394
+ case "execmode": {
16395
+ const currentExecMode = getExecMode(chatId);
16396
+ const EXEC_MODES = {
16397
+ approved: "\u2705 Approved \u2014 AI shows a plan before acting",
16398
+ yolo: "\u26A1 YOLO \u2014 AI executes immediately"
16399
+ };
16400
+ if (typeof channel.sendKeyboard === "function") {
16401
+ const buttons = Object.entries(EXEC_MODES).map(([id, label2]) => [{
16402
+ label: `${id === currentExecMode ? "\u2713 " : ""}${label2}`,
16403
+ data: `execmode:${id}`,
16404
+ ...id === currentExecMode ? { style: "primary" } : {}
16405
+ }]);
16406
+ await channel.sendKeyboard(chatId, `Execution mode (current: <b>${currentExecMode}</b>):`, buttons);
16407
+ } else {
16408
+ const lines = ["Execution modes:", ""];
16409
+ for (const [id, label2] of Object.entries(EXEC_MODES)) {
16410
+ lines.push(`${id === currentExecMode ? "\u2713 " : " "}/mode ${id} \u2014 ${label2}`);
16411
+ }
16412
+ await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
16413
+ }
16414
+ break;
16415
+ }
16089
16416
  case "verbose": {
16090
16417
  const currentVerbose = getVerboseLevel(chatId);
16091
16418
  const buttons = Object.entries(VERBOSE_LEVELS).map(([id, label2]) => [{
@@ -16140,8 +16467,23 @@ Tap to toggle:`,
16140
16467
  setSessionStartedAt(chatId);
16141
16468
  logActivity(getDb(), { chatId, source: "telegram", eventType: "config_changed", summary: "New session started", detail: { field: "session", action: "reset", summarized } });
16142
16469
  if (typeof channel.sendKeyboard === "function" && oldSessionId) {
16143
- const msg2 = `\u2705 New session started. Previous session archived${exchangeCount > 0 ? ` (${exchangeCount} exchanges)` : ""}.`;
16470
+ let adapter;
16471
+ try {
16472
+ adapter = getAdapterForChat(chatId);
16473
+ } catch {
16474
+ adapter = null;
16475
+ }
16476
+ const currentModel = getModel(chatId) ?? adapter?.defaultModel ?? "default";
16477
+ const modelLabel = adapter ? formatModelShort(currentModel) : currentModel;
16478
+ const backendLabel = adapter?.displayName ?? getBackend(chatId) ?? "not set";
16479
+ const msg2 = `\u2705 New session started. Previous session archived${exchangeCount > 0 ? ` (${exchangeCount} exchanges)` : ""}.
16480
+
16481
+ \u{1F9E0} ${backendLabel} \xB7 ${modelLabel}`;
16144
16482
  const kbMsgId = await channel.sendKeyboard(chatId, msg2, [
16483
+ [
16484
+ { label: "Switch Backend", data: "menu:backend", style: "primary" },
16485
+ { label: "Switch Model", data: "menu:model", style: "primary" }
16486
+ ],
16145
16487
  [{ label: "Undo", data: "newchat:undo" }]
16146
16488
  ]);
16147
16489
  if (kbMsgId) {
@@ -17794,6 +18136,54 @@ ${PERM_MODES[chosen]}`,
17794
18136
  await channel.sendText(chatId, `Agent mode set to <b>${mode}</b>. Session cleared.`, { parseMode: "html" });
17795
18137
  }
17796
18138
  return;
18139
+ } else if (data === "exec:approve") {
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
+ await channel.sendText(chatId, "\u2705 Approved. Executing...", { parseMode: "plain" });
18147
+ const { handleMessage: handleMessage2 } = await Promise.resolve().then(() => (init_router(), router_exports));
18148
+ await handleMessage2(
18149
+ { text: `>>${plan.originalMessage}`, chatId, source: "telegram", type: "text", senderName: "", messageId: "" },
18150
+ channel
18151
+ );
18152
+ return;
18153
+ } else if (data === "exec:reject") {
18154
+ const plan = getPendingPlan(chatId);
18155
+ if (!plan) {
18156
+ await channel.sendText(chatId, "\u26A0\uFE0F Plan expired or already processed.", { parseMode: "plain" });
18157
+ return;
18158
+ }
18159
+ removePendingPlan(chatId);
18160
+ setRejectionMode(chatId);
18161
+ await channel.sendText(chatId, "\u270F\uFE0F Plan rejected. Send your feedback and I'll revise the plan.", { parseMode: "plain" });
18162
+ return;
18163
+ } else if (data === "exec:yolo") {
18164
+ const plan = getPendingPlan(chatId);
18165
+ if (!plan) {
18166
+ await channel.sendText(chatId, "\u26A0\uFE0F Plan expired or already processed.", { parseMode: "plain" });
18167
+ return;
18168
+ }
18169
+ removePendingPlan(chatId);
18170
+ setExecMode(chatId, "yolo");
18171
+ await channel.sendText(chatId, "\u26A1 Switched to YOLO mode. Executing without approval gate...", { parseMode: "plain" });
18172
+ const { handleMessage: handleMessage2 } = await Promise.resolve().then(() => (init_router(), router_exports));
18173
+ await handleMessage2(
18174
+ { text: `>>${plan.originalMessage}`, chatId, source: "telegram", type: "text", senderName: "", messageId: "" },
18175
+ channel
18176
+ );
18177
+ return;
18178
+ } else if (data.startsWith("execmode:")) {
18179
+ const mode = data.split(":")[1];
18180
+ if (mode === "approved" || mode === "yolo") {
18181
+ setExecMode(chatId, mode);
18182
+ const desc = mode === "approved" ? "AI will show a plan for approval before acting." : "AI will execute immediately without showing a plan.";
18183
+ await channel.sendText(chatId, `Execution mode set to <b>${mode}</b>.
18184
+ ${desc}`, { parseMode: "html" });
18185
+ }
18186
+ return;
17797
18187
  } else if (data.startsWith("model_sig:")) {
17798
18188
  const value = data.slice(10);
17799
18189
  setModelSignature(chatId, value);
@@ -18553,6 +18943,7 @@ var init_callbacks = __esm({
18553
18943
  init_guard();
18554
18944
  init_pagination();
18555
18945
  init_stt();
18946
+ init_gate();
18556
18947
  init_helpers();
18557
18948
  init_response();
18558
18949
  init_shell();
@@ -18712,6 +19103,33 @@ async function handleText(msg, channel) {
18712
19103
  if (hasSqPrefix) {
18713
19104
  text = sqCleanText;
18714
19105
  }
19106
+ if (getRejectionMode(chatId)) {
19107
+ clearRejectionMode(chatId);
19108
+ await channel.sendTyping?.(chatId);
19109
+ const response = await askAgent(chatId, `Plan rejected. Feedback: "${text}". Revise your plan.`, {
19110
+ cwd: getCwd(chatId),
19111
+ model: model2,
19112
+ permMode: "yolo",
19113
+ agentMode: effectiveAgentMode
19114
+ });
19115
+ if (response.text) {
19116
+ storePendingPlan(chatId, response.text, text);
19117
+ if (typeof channel.sendKeyboard === "function") {
19118
+ await channel.sendKeyboard(chatId, `\u{1F50D} ${response.text}`, [
19119
+ [
19120
+ { label: "\u2705 Approve", data: "exec:approve", style: "success" },
19121
+ { label: "\u274C Reject", data: "exec:reject", style: "danger" }
19122
+ ],
19123
+ [
19124
+ { label: "\u26A1 Skip & YOLO", data: "exec:yolo" }
19125
+ ]
19126
+ ]);
19127
+ } else {
19128
+ await sendResponse(chatId, channel, response.text, void 0);
19129
+ }
19130
+ }
19131
+ return;
19132
+ }
18715
19133
  {
18716
19134
  const { getDiscussionMode: getDiscussionMode2, clearDiscussionMode: clearDiscussionMode2, setDiscussionMode: reenterDiscussion, getInsightById: getInsightById2, updateInsightProposal: updateInsightProposal2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
18717
19135
  const discussInsightId = getDiscussionMode2(chatId);
@@ -18788,6 +19206,61 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
18788
19206
  return;
18789
19207
  }
18790
19208
  }
19209
+ const execMode = getExecMode(chatId);
19210
+ if (shouldRequireApproval({
19211
+ execMode,
19212
+ intent,
19213
+ bootstrapTier: bootstrapTier ?? "full",
19214
+ messageText: text,
19215
+ isSideQuest: hasSqPrefix
19216
+ })) {
19217
+ const planDirective = buildPlanningDirective();
19218
+ let typingActive2 = true;
19219
+ const typingLoop2 = async () => {
19220
+ while (typingActive2) {
19221
+ try {
19222
+ await channel.sendTyping?.(chatId);
19223
+ } catch {
19224
+ }
19225
+ await new Promise((r) => setTimeout(r, 4e3));
19226
+ }
19227
+ };
19228
+ typingLoop2().catch(() => {
19229
+ });
19230
+ try {
19231
+ const planResponse = await askAgent(chatId, cleanText || text, {
19232
+ cwd: getCwd(chatId),
19233
+ model: model2,
19234
+ permMode: "yolo",
19235
+ bootstrapTier: bootstrapTier ?? "full",
19236
+ agentMode: effectiveAgentMode,
19237
+ planningDirective: planDirective
19238
+ });
19239
+ typingActive2 = false;
19240
+ if (planResponse.text) {
19241
+ storePendingPlan(chatId, planResponse.text, cleanText || text);
19242
+ if (typeof channel.sendKeyboard === "function") {
19243
+ await channel.sendKeyboard(chatId, `\u{1F50D} ${planResponse.text}`, [
19244
+ [
19245
+ { label: "\u2705 Approve", data: "exec:approve", style: "success" },
19246
+ { label: "\u274C Reject", data: "exec:reject", style: "danger" }
19247
+ ],
19248
+ [
19249
+ { label: "\u26A1 Skip & YOLO", data: "exec:yolo" }
19250
+ ]
19251
+ ]);
19252
+ } else {
19253
+ await sendResponse(chatId, channel, planResponse.text, void 0);
19254
+ }
19255
+ } else {
19256
+ await channel.sendText(chatId, "(No plan generated \u2014 proceeding normally)", { parseMode: "plain" });
19257
+ }
19258
+ } catch (err) {
19259
+ typingActive2 = false;
19260
+ await channel.sendText(chatId, `\u26A0\uFE0F Planning error: ${err.message}`, { parseMode: "plain" });
19261
+ }
19262
+ return;
19263
+ }
18791
19264
  let typingActive = true;
18792
19265
  const typingLoop = async () => {
18793
19266
  while (typingActive) {
@@ -18968,6 +19441,7 @@ var init_router = __esm({
18968
19441
  init_wizard();
18969
19442
  init_classify2();
18970
19443
  init_store3();
19444
+ init_gate();
18971
19445
  init_helpers();
18972
19446
  init_response();
18973
19447
  init_shell();
@@ -19228,6 +19702,8 @@ async function runWithRetry(job, model2, runId, t0) {
19228
19702
  if (job.jobType === "reflection") {
19229
19703
  const { runNightlyReflection: runNightlyReflection2 } = await Promise.resolve().then(() => (init_analyze(), analyze_exports));
19230
19704
  const { formatNightlySummary: formatNightlySummary2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
19705
+ const { getPendingInsightCount: getPendingInsightCount2, getActiveReflectionChatIds: getActiveReflectionChatIds2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
19706
+ const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
19231
19707
  const timeoutMs2 = job.timeout ? job.timeout * 1e3 : void 0;
19232
19708
  const { results } = await runNightlyReflection2({
19233
19709
  timeoutMs: timeoutMs2,
@@ -19240,7 +19716,13 @@ async function runWithRetry(job, model2, runId, t0) {
19240
19716
  const allInsights = results.flatMap(
19241
19717
  (r) => r.insights.map((ins) => ({ id: ++seq, ...ins }))
19242
19718
  );
19243
- return { text: formatNightlySummary2(allInsights) };
19719
+ const db3 = getDb2();
19720
+ const activeChats2 = getActiveReflectionChatIds2(db3);
19721
+ let totalPending = 0;
19722
+ for (const cid of activeChats2) {
19723
+ totalPending += getPendingInsightCount2(db3, cid);
19724
+ }
19725
+ return { text: formatNightlySummary2(allInsights, totalPending) };
19244
19726
  }
19245
19727
  if (job.thinking && job.thinking !== "auto") {
19246
19728
  setThinkingLevel(chatId, job.thinking);
@@ -19346,7 +19828,7 @@ var init_cron = __esm({
19346
19828
  });
19347
19829
 
19348
19830
  // src/agents/runners/wrap-backend.ts
19349
- import { join as join19 } from "path";
19831
+ import { join as join20 } from "path";
19350
19832
  function buildMcpCommands(backendId) {
19351
19833
  const exe = backendId === "cursor" ? "agent" : backendId;
19352
19834
  return {
@@ -19440,7 +19922,7 @@ function wrapBackendAdapter(adapter) {
19440
19922
  const configPath = writeMcpConfigFile(server);
19441
19923
  return ["--mcp-config", configPath];
19442
19924
  },
19443
- getSkillPath: () => join19(SKILLS_PATH, `agent-${adapter.id}.md`)
19925
+ getSkillPath: () => join20(SKILLS_PATH, `agent-${adapter.id}.md`)
19444
19926
  };
19445
19927
  }
19446
19928
  var BACKEND_CAPABILITIES;
@@ -19491,18 +19973,18 @@ var init_wrap_backend = __esm({
19491
19973
  });
19492
19974
 
19493
19975
  // 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";
19976
+ import { readFileSync as readFileSync10, readdirSync as readdirSync9, existsSync as existsSync19, mkdirSync as mkdirSync9, watchFile, unwatchFile } from "fs";
19977
+ import { join as join21 } from "path";
19496
19978
  import { execFileSync as execFileSync2 } from "child_process";
19497
19979
  function resolveExecutable(config2) {
19498
- if (existsSync18(config2.executable)) return config2.executable;
19980
+ if (existsSync19(config2.executable)) return config2.executable;
19499
19981
  try {
19500
19982
  return execFileSync2("which", [config2.executable], { encoding: "utf-8" }).trim();
19501
19983
  } catch {
19502
19984
  }
19503
19985
  for (const fallback of config2.executableFallbacks ?? []) {
19504
19986
  const resolved = fallback.replace(/^~/, process.env.HOME ?? "");
19505
- if (existsSync18(resolved)) return resolved;
19987
+ if (existsSync19(resolved)) return resolved;
19506
19988
  }
19507
19989
  return config2.executable;
19508
19990
  }
@@ -19628,7 +20110,7 @@ function configToRunner(config2) {
19628
20110
  prepareMcpInjection() {
19629
20111
  return [];
19630
20112
  },
19631
- getSkillPath: () => join20(SKILLS_PATH, `agent-${config2.id}.md`)
20113
+ getSkillPath: () => join21(SKILLS_PATH, `agent-${config2.id}.md`)
19632
20114
  };
19633
20115
  }
19634
20116
  function loadRunnerConfig(filePath) {
@@ -19641,14 +20123,14 @@ function loadRunnerConfig(filePath) {
19641
20123
  }
19642
20124
  }
19643
20125
  function loadAllRunnerConfigs() {
19644
- if (!existsSync18(RUNNERS_PATH)) {
19645
- mkdirSync8(RUNNERS_PATH, { recursive: true });
20126
+ if (!existsSync19(RUNNERS_PATH)) {
20127
+ mkdirSync9(RUNNERS_PATH, { recursive: true });
19646
20128
  return [];
19647
20129
  }
19648
- const files = readdirSync8(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
20130
+ const files = readdirSync9(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
19649
20131
  const configs = [];
19650
20132
  for (const file of files) {
19651
- const config2 = loadRunnerConfig(join20(RUNNERS_PATH, file));
20133
+ const config2 = loadRunnerConfig(join21(RUNNERS_PATH, file));
19652
20134
  if (config2) configs.push(config2);
19653
20135
  }
19654
20136
  return configs;
@@ -19669,16 +20151,16 @@ function registerConfigRunners() {
19669
20151
  return count;
19670
20152
  }
19671
20153
  function watchRunnerConfigs(onChange) {
19672
- if (!existsSync18(RUNNERS_PATH)) return;
20154
+ if (!existsSync19(RUNNERS_PATH)) return;
19673
20155
  for (const prev of watchedFiles) {
19674
- if (!existsSync18(prev)) {
20156
+ if (!existsSync19(prev)) {
19675
20157
  unwatchFile(prev);
19676
20158
  watchedFiles.delete(prev);
19677
20159
  }
19678
20160
  }
19679
- const files = readdirSync8(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
20161
+ const files = readdirSync9(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
19680
20162
  for (const file of files) {
19681
- const fullPath = join20(RUNNERS_PATH, file);
20163
+ const fullPath = join21(RUNNERS_PATH, file);
19682
20164
  if (watchedFiles.has(fullPath)) continue;
19683
20165
  watchedFiles.add(fullPath);
19684
20166
  watchFile(fullPath, { interval: 5e3 }, () => {
@@ -20076,6 +20558,7 @@ var init_telegram2 = __esm({
20076
20558
  { command: "summarizer", description: "Configure session summarization model" },
20077
20559
  // Permissions & tools
20078
20560
  { command: "permissions", description: "Permission mode (yolo/safe/readonly/plan)" },
20561
+ { command: "mode", description: "Execution gate (approved/yolo)" },
20079
20562
  { command: "tools", description: "Configure which tools the agent can use" },
20080
20563
  { command: "verbose", description: "Tool visibility (off/normal/verbose)" },
20081
20564
  { command: "cwd", description: "Set or show working directory" },
@@ -20512,19 +20995,19 @@ var init_telegram2 = __esm({
20512
20995
  });
20513
20996
 
20514
20997
  // src/skills/bootstrap.ts
20515
- import { existsSync as existsSync19 } from "fs";
20998
+ import { existsSync as existsSync20 } from "fs";
20516
20999
  import { readdir as readdir6, readFile as readFile8, writeFile as writeFile5, copyFile } from "fs/promises";
20517
- import { join as join21, dirname as dirname3 } from "path";
21000
+ import { join as join22, dirname as dirname4 } from "path";
20518
21001
  import { fileURLToPath as fileURLToPath2 } from "url";
20519
21002
  async function copyAgentManifestSkills() {
20520
- if (!existsSync19(PKG_SKILLS)) return;
21003
+ if (!existsSync20(PKG_SKILLS)) return;
20521
21004
  try {
20522
21005
  const entries = await readdir6(PKG_SKILLS, { withFileTypes: true });
20523
21006
  for (const entry of entries) {
20524
21007
  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;
21008
+ const src = join22(PKG_SKILLS, entry.name);
21009
+ const dest = join22(SKILLS_PATH, entry.name);
21010
+ if (existsSync20(dest)) continue;
20528
21011
  await copyFile(src, dest);
20529
21012
  log(`[skills] Bootstrapped ${entry.name} to ${SKILLS_PATH}`);
20530
21013
  }
@@ -20534,8 +21017,8 @@ async function copyAgentManifestSkills() {
20534
21017
  }
20535
21018
  async function bootstrapSkills() {
20536
21019
  await copyAgentManifestSkills();
20537
- const usmDir = join21(SKILLS_PATH, USM_DIR_NAME);
20538
- if (existsSync19(usmDir)) return;
21020
+ const usmDir = join22(SKILLS_PATH, USM_DIR_NAME);
21021
+ if (existsSync20(usmDir)) return;
20539
21022
  try {
20540
21023
  const entries = await readdir6(SKILLS_PATH);
20541
21024
  const dirs = entries.filter((e) => !e.startsWith("."));
@@ -20557,8 +21040,8 @@ async function bootstrapSkills() {
20557
21040
  }
20558
21041
  }
20559
21042
  async function patchUsmForCcClaw(usmDir) {
20560
- const skillPath = join21(usmDir, "SKILL.md");
20561
- if (!existsSync19(skillPath)) return;
21043
+ const skillPath = join22(usmDir, "SKILL.md");
21044
+ if (!existsSync20(skillPath)) return;
20562
21045
  try {
20563
21046
  let content = await readFile8(skillPath, "utf-8");
20564
21047
  let patched = false;
@@ -20603,8 +21086,8 @@ var init_bootstrap = __esm({
20603
21086
  USM_REPO = "jacob-bd/universal-skills-manager";
20604
21087
  USM_DIR_NAME = "universal-skills-manager";
20605
21088
  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");
21089
+ PKG_ROOT = join22(dirname4(fileURLToPath2(import.meta.url)), "..", "..");
21090
+ PKG_SKILLS = join22(PKG_ROOT, "skills");
20608
21091
  }
20609
21092
  });
20610
21093
 
@@ -20826,13 +21309,13 @@ __export(ai_skill_exports, {
20826
21309
  generateAiSkill: () => generateAiSkill,
20827
21310
  installAiSkill: () => installAiSkill
20828
21311
  });
20829
- import { existsSync as existsSync20, writeFileSync as writeFileSync7, mkdirSync as mkdirSync9 } from "fs";
20830
- import { join as join22 } from "path";
21312
+ import { existsSync as existsSync21, writeFileSync as writeFileSync7, mkdirSync as mkdirSync10 } from "fs";
21313
+ import { join as join23 } from "path";
20831
21314
  import { homedir as homedir7 } from "os";
20832
21315
  function generateAiSkill() {
20833
21316
  const version = VERSION;
20834
21317
  let systemState = "";
20835
- if (existsSync20(DB_PATH)) {
21318
+ if (existsSync21(DB_PATH)) {
20836
21319
  try {
20837
21320
  const { openDatabaseReadOnly: openDatabaseReadOnly2 } = (init_store5(), __toCommonJS(store_exports5));
20838
21321
  const readDb = openDatabaseReadOnly2();
@@ -21236,10 +21719,10 @@ function installAiSkill() {
21236
21719
  const failed = [];
21237
21720
  for (const [backend2, dirs] of Object.entries(BACKEND_SKILL_DIRS2)) {
21238
21721
  for (const dir of dirs) {
21239
- const skillDir = join22(dir, "cc-claw-cli");
21240
- const skillPath = join22(skillDir, "SKILL.md");
21722
+ const skillDir = join23(dir, "cc-claw-cli");
21723
+ const skillPath = join23(skillDir, "SKILL.md");
21241
21724
  try {
21242
- mkdirSync9(skillDir, { recursive: true });
21725
+ mkdirSync10(skillDir, { recursive: true });
21243
21726
  writeFileSync7(skillPath, skill, "utf-8");
21244
21727
  installed.push(skillPath);
21245
21728
  } catch {
@@ -21256,11 +21739,11 @@ var init_ai_skill = __esm({
21256
21739
  init_paths();
21257
21740
  init_version();
21258
21741
  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")]
21742
+ "cc-claw": [join23(homedir7(), ".cc-claw", "workspace", "skills")],
21743
+ claude: [join23(homedir7(), ".claude", "skills")],
21744
+ gemini: [join23(homedir7(), ".gemini", "skills")],
21745
+ codex: [join23(homedir7(), ".agents", "skills")],
21746
+ cursor: [join23(homedir7(), ".cursor", "skills"), join23(homedir7(), ".cursor", "skills-cursor")]
21264
21747
  };
21265
21748
  }
21266
21749
  });
@@ -21270,23 +21753,23 @@ var index_exports = {};
21270
21753
  __export(index_exports, {
21271
21754
  main: () => main
21272
21755
  });
21273
- import { mkdirSync as mkdirSync10, existsSync as existsSync21, renameSync, statSync as statSync5, readFileSync as readFileSync12 } from "fs";
21274
- import { join as join23 } from "path";
21756
+ import { mkdirSync as mkdirSync11, existsSync as existsSync22, renameSync as renameSync2, statSync as statSync6, readFileSync as readFileSync12 } from "fs";
21757
+ import { join as join24 } from "path";
21275
21758
  import dotenv from "dotenv";
21276
21759
  function migrateLayout() {
21277
21760
  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")]
21761
+ [join24(CC_CLAW_HOME, "cc-claw.db"), join24(DATA_PATH, "cc-claw.db")],
21762
+ [join24(CC_CLAW_HOME, "cc-claw.db-shm"), join24(DATA_PATH, "cc-claw.db-shm")],
21763
+ [join24(CC_CLAW_HOME, "cc-claw.db-wal"), join24(DATA_PATH, "cc-claw.db-wal")],
21764
+ [join24(CC_CLAW_HOME, "cc-claw.log"), join24(LOGS_PATH, "cc-claw.log")],
21765
+ [join24(CC_CLAW_HOME, "cc-claw.log.1"), join24(LOGS_PATH, "cc-claw.log.1")],
21766
+ [join24(CC_CLAW_HOME, "cc-claw.error.log"), join24(LOGS_PATH, "cc-claw.error.log")],
21767
+ [join24(CC_CLAW_HOME, "cc-claw.error.log.1"), join24(LOGS_PATH, "cc-claw.error.log.1")]
21285
21768
  ];
21286
21769
  for (const [from, to] of moves) {
21287
- if (existsSync21(from) && !existsSync21(to)) {
21770
+ if (existsSync22(from) && !existsSync22(to)) {
21288
21771
  try {
21289
- renameSync(from, to);
21772
+ renameSync2(from, to);
21290
21773
  } catch {
21291
21774
  }
21292
21775
  }
@@ -21295,11 +21778,11 @@ function migrateLayout() {
21295
21778
  function rotateLogs() {
21296
21779
  for (const file of [LOG_PATH, ERROR_LOG_PATH]) {
21297
21780
  try {
21298
- const { size } = statSync5(file);
21781
+ const { size } = statSync6(file);
21299
21782
  if (size > LOG_MAX_BYTES) {
21300
21783
  const archivePath = `${file}.1`;
21301
21784
  try {
21302
- renameSync(file, archivePath);
21785
+ renameSync2(file, archivePath);
21303
21786
  } catch {
21304
21787
  }
21305
21788
  log(`[cc-claw] Rotated ${file} (was ${(size / 1024 / 1024).toFixed(1)}MB)`);
@@ -21347,6 +21830,12 @@ async function main() {
21347
21830
  }
21348
21831
  setBootTime();
21349
21832
  log("[cc-claw] Database initialized (sessions preserved for resume)");
21833
+ try {
21834
+ const { migrateAllSlots: migrateAllSlots2 } = await Promise.resolve().then(() => (init_symlink_manager(), symlink_manager_exports));
21835
+ migrateAllSlots2(CC_CLAW_HOME);
21836
+ } catch (err) {
21837
+ warn(`[cc-claw] Slot symlink migration failed: ${err instanceof Error ? err.message : String(err)}`);
21838
+ }
21350
21839
  if (process.env.TELEGRAM_BOT_TOKEN) {
21351
21840
  channelRegistry.register(new TelegramChannel());
21352
21841
  }
@@ -21423,11 +21912,11 @@ async function main() {
21423
21912
  bootstrapSkills().catch((err) => error("[cc-claw] Skill bootstrap failed:", err));
21424
21913
  try {
21425
21914
  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");
21915
+ const { writeFileSync: writeFileSync12, mkdirSync: mkdirSync18 } = await import("fs");
21916
+ const { join: join30 } = await import("path");
21917
+ const skillDir = join30(SKILLS_PATH, "cc-claw-cli");
21918
+ mkdirSync18(skillDir, { recursive: true });
21919
+ writeFileSync12(join30(skillDir, "SKILL.md"), generateAiSkill2(), "utf-8");
21431
21920
  log("[cc-claw] AI skill updated");
21432
21921
  } catch {
21433
21922
  }
@@ -21500,10 +21989,10 @@ var init_index = __esm({
21500
21989
  init_health3();
21501
21990
  init_image_gen();
21502
21991
  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 });
21992
+ if (!existsSync22(dir)) mkdirSync11(dir, { recursive: true });
21504
21993
  }
21505
21994
  migrateLayout();
21506
- if (existsSync21(ENV_PATH)) {
21995
+ if (existsSync22(ENV_PATH)) {
21507
21996
  dotenv.config({ path: ENV_PATH });
21508
21997
  } else {
21509
21998
  console.error(`[cc-claw] Config not found at ${ENV_PATH} \u2014 run 'cc-claw setup' first`);
@@ -21524,12 +22013,12 @@ __export(api_client_exports, {
21524
22013
  apiPost: () => apiPost,
21525
22014
  isDaemonRunning: () => isDaemonRunning
21526
22015
  });
21527
- import { readFileSync as readFileSync13, existsSync as existsSync22 } from "fs";
22016
+ import { readFileSync as readFileSync13, existsSync as existsSync23 } from "fs";
21528
22017
  import { request as httpRequest, Agent } from "http";
21529
22018
  function getToken() {
21530
22019
  if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
21531
22020
  try {
21532
- if (existsSync22(TOKEN_PATH)) return readFileSync13(TOKEN_PATH, "utf-8").trim();
22021
+ if (existsSync23(TOKEN_PATH)) return readFileSync13(TOKEN_PATH, "utf-8").trim();
21533
22022
  } catch {
21534
22023
  }
21535
22024
  return null;
@@ -21628,10 +22117,10 @@ __export(service_exports, {
21628
22117
  serviceStatus: () => serviceStatus,
21629
22118
  uninstallService: () => uninstallService
21630
22119
  });
21631
- import { existsSync as existsSync23, mkdirSync as mkdirSync11, writeFileSync as writeFileSync8, unlinkSync as unlinkSync6 } from "fs";
22120
+ import { existsSync as existsSync24, mkdirSync as mkdirSync12, writeFileSync as writeFileSync8, unlinkSync as unlinkSync6 } from "fs";
21632
22121
  import { execFileSync as execFileSync3, execSync as execSync6 } from "child_process";
21633
22122
  import { homedir as homedir8, platform } from "os";
21634
- import { join as join24, dirname as dirname4 } from "path";
22123
+ import { join as join25, dirname as dirname5 } from "path";
21635
22124
  function xmlEscape(s) {
21636
22125
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
21637
22126
  }
@@ -21640,23 +22129,23 @@ function resolveExecutable2(name) {
21640
22129
  return execFileSync3("which", [name], { encoding: "utf-8" }).trim();
21641
22130
  } catch {
21642
22131
  const fallback = process.argv[1];
21643
- if (fallback && existsSync23(fallback)) return fallback;
22132
+ if (fallback && existsSync24(fallback)) return fallback;
21644
22133
  throw new Error(`Cannot find '${name}' executable. Install globally: npm install -g cc-claw`);
21645
22134
  }
21646
22135
  }
21647
22136
  function getPathDirs() {
21648
- const nodeBin = dirname4(process.execPath);
22137
+ const nodeBin = dirname5(process.execPath);
21649
22138
  const home = homedir8();
21650
22139
  const dirs = /* @__PURE__ */ new Set([
21651
22140
  nodeBin,
21652
- join24(home, ".local", "bin"),
22141
+ join25(home, ".local", "bin"),
21653
22142
  "/usr/local/bin",
21654
22143
  "/usr/bin",
21655
22144
  "/bin"
21656
22145
  ]);
21657
22146
  try {
21658
22147
  const prefix = execSync6("npm config get prefix", { encoding: "utf-8" }).trim();
21659
- if (prefix) dirs.add(join24(prefix, "bin"));
22148
+ if (prefix) dirs.add(join25(prefix, "bin"));
21660
22149
  } catch {
21661
22150
  }
21662
22151
  return [...dirs].join(":");
@@ -21714,10 +22203,10 @@ function generatePlist() {
21714
22203
  </plist>`;
21715
22204
  }
21716
22205
  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)) {
22206
+ const agentsDir = dirname5(PLIST_PATH);
22207
+ if (!existsSync24(agentsDir)) mkdirSync12(agentsDir, { recursive: true });
22208
+ if (!existsSync24(LOGS_PATH)) mkdirSync12(LOGS_PATH, { recursive: true });
22209
+ if (existsSync24(PLIST_PATH)) {
21721
22210
  try {
21722
22211
  execFileSync3("launchctl", ["unload", PLIST_PATH]);
21723
22212
  } catch {
@@ -21729,7 +22218,7 @@ function installMacOS() {
21729
22218
  console.log(" Service loaded and starting.");
21730
22219
  }
21731
22220
  function uninstallMacOS() {
21732
- if (!existsSync23(PLIST_PATH)) {
22221
+ if (!existsSync24(PLIST_PATH)) {
21733
22222
  console.log(" No service found to uninstall.");
21734
22223
  return;
21735
22224
  }
@@ -21804,8 +22293,8 @@ WantedBy=default.target
21804
22293
  `;
21805
22294
  }
21806
22295
  function installLinux() {
21807
- if (!existsSync23(SYSTEMD_DIR)) mkdirSync11(SYSTEMD_DIR, { recursive: true });
21808
- if (!existsSync23(LOGS_PATH)) mkdirSync11(LOGS_PATH, { recursive: true });
22296
+ if (!existsSync24(SYSTEMD_DIR)) mkdirSync12(SYSTEMD_DIR, { recursive: true });
22297
+ if (!existsSync24(LOGS_PATH)) mkdirSync12(LOGS_PATH, { recursive: true });
21809
22298
  writeFileSync8(UNIT_PATH, generateUnit());
21810
22299
  console.log(` Installed: ${UNIT_PATH}`);
21811
22300
  execFileSync3("systemctl", ["--user", "daemon-reload"]);
@@ -21814,7 +22303,7 @@ function installLinux() {
21814
22303
  console.log(" Service enabled and started.");
21815
22304
  }
21816
22305
  function uninstallLinux() {
21817
- if (!existsSync23(UNIT_PATH)) {
22306
+ if (!existsSync24(UNIT_PATH)) {
21818
22307
  console.log(" No service found to uninstall.");
21819
22308
  return;
21820
22309
  }
@@ -21839,7 +22328,7 @@ function statusLinux() {
21839
22328
  }
21840
22329
  }
21841
22330
  function installService() {
21842
- if (!existsSync23(join24(CC_CLAW_HOME, ".env"))) {
22331
+ if (!existsSync24(join25(CC_CLAW_HOME, ".env"))) {
21843
22332
  console.error(` Config not found at ${CC_CLAW_HOME}/.env`);
21844
22333
  console.error(" Run 'cc-claw setup' before installing the service.");
21845
22334
  process.exitCode = 1;
@@ -21868,9 +22357,9 @@ var init_service = __esm({
21868
22357
  "use strict";
21869
22358
  init_paths();
21870
22359
  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");
22360
+ PLIST_PATH = join25(homedir8(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
22361
+ SYSTEMD_DIR = join25(homedir8(), ".config", "systemd", "user");
22362
+ UNIT_PATH = join25(SYSTEMD_DIR, "cc-claw.service");
21874
22363
  }
21875
22364
  });
21876
22365
 
@@ -22067,7 +22556,7 @@ var status_exports = {};
22067
22556
  __export(status_exports, {
22068
22557
  statusCommand: () => statusCommand
22069
22558
  });
22070
- import { existsSync as existsSync24, statSync as statSync6 } from "fs";
22559
+ import { existsSync as existsSync25, statSync as statSync7 } from "fs";
22071
22560
  async function statusCommand(globalOpts, localOpts) {
22072
22561
  try {
22073
22562
  const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
@@ -22107,7 +22596,7 @@ async function statusCommand(globalOpts, localOpts) {
22107
22596
  const cwdRow = readDb.prepare("SELECT cwd FROM chat_cwd WHERE chat_id = ?").get(chatId);
22108
22597
  const voiceRow = readDb.prepare("SELECT enabled FROM chat_voice WHERE chat_id = ?").get(chatId);
22109
22598
  const usageRow = readDb.prepare("SELECT * FROM chat_usage WHERE chat_id = ?").get(chatId);
22110
- const dbStat = existsSync24(DB_PATH) ? statSync6(DB_PATH) : null;
22599
+ const dbStat = existsSync25(DB_PATH) ? statSync7(DB_PATH) : null;
22111
22600
  let daemonRunning = false;
22112
22601
  let daemonInfo = {};
22113
22602
  try {
@@ -22196,12 +22685,12 @@ var doctor_exports = {};
22196
22685
  __export(doctor_exports, {
22197
22686
  doctorCommand: () => doctorCommand
22198
22687
  });
22199
- import { existsSync as existsSync25, statSync as statSync7, accessSync, constants } from "fs";
22688
+ import { existsSync as existsSync26, statSync as statSync8, accessSync, constants } from "fs";
22200
22689
  import { execFileSync as execFileSync4 } from "child_process";
22201
22690
  async function doctorCommand(globalOpts, localOpts) {
22202
22691
  const checks = [];
22203
- if (existsSync25(DB_PATH)) {
22204
- const size = statSync7(DB_PATH).size;
22692
+ if (existsSync26(DB_PATH)) {
22693
+ const size = statSync8(DB_PATH).size;
22205
22694
  checks.push({ name: "Database", status: "ok", message: `${DB_PATH} (${(size / 1024).toFixed(0)}KB)` });
22206
22695
  try {
22207
22696
  const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
@@ -22230,7 +22719,7 @@ async function doctorCommand(globalOpts, localOpts) {
22230
22719
  } else {
22231
22720
  checks.push({ name: "Database", status: "error", message: `Not found at ${DB_PATH}`, fix: "cc-claw setup" });
22232
22721
  }
22233
- if (existsSync25(ENV_PATH)) {
22722
+ if (existsSync26(ENV_PATH)) {
22234
22723
  checks.push({ name: "Environment", status: "ok", message: `.env loaded` });
22235
22724
  } else {
22236
22725
  checks.push({ name: "Environment", status: "error", message: "No .env found", fix: "cc-claw setup" });
@@ -22285,7 +22774,7 @@ async function doctorCommand(globalOpts, localOpts) {
22285
22774
  } catch {
22286
22775
  }
22287
22776
  const tokenPath = `${DATA_PATH}/api-token`;
22288
- if (existsSync25(tokenPath)) {
22777
+ if (existsSync26(tokenPath)) {
22289
22778
  try {
22290
22779
  accessSync(tokenPath, constants.R_OK);
22291
22780
  checks.push({ name: "API token", status: "ok", message: "token file readable" });
@@ -22310,7 +22799,7 @@ async function doctorCommand(globalOpts, localOpts) {
22310
22799
  }
22311
22800
  } catch {
22312
22801
  }
22313
- if (existsSync25(ERROR_LOG_PATH)) {
22802
+ if (existsSync26(ERROR_LOG_PATH)) {
22314
22803
  try {
22315
22804
  const { readFileSync: readFileSync22 } = await import("fs");
22316
22805
  const logContent = readFileSync22(ERROR_LOG_PATH, "utf-8");
@@ -22436,10 +22925,10 @@ var logs_exports = {};
22436
22925
  __export(logs_exports, {
22437
22926
  logsCommand: () => logsCommand
22438
22927
  });
22439
- import { existsSync as existsSync26, readFileSync as readFileSync16, watchFile as watchFile2, unwatchFile as unwatchFile2 } from "fs";
22928
+ import { existsSync as existsSync27, readFileSync as readFileSync16, watchFile as watchFile2, unwatchFile as unwatchFile2 } from "fs";
22440
22929
  async function logsCommand(opts) {
22441
22930
  const logFile = opts.error ? ERROR_LOG_PATH : LOG_PATH;
22442
- if (!existsSync26(logFile)) {
22931
+ if (!existsSync27(logFile)) {
22443
22932
  outputError("LOG_NOT_FOUND", `Log file not found: ${logFile}`);
22444
22933
  process.exit(1);
22445
22934
  }
@@ -22491,11 +22980,11 @@ __export(gemini_exports, {
22491
22980
  geminiReorder: () => geminiReorder,
22492
22981
  geminiRotation: () => geminiRotation
22493
22982
  });
22494
- import { existsSync as existsSync27, mkdirSync as mkdirSync12, writeFileSync as writeFileSync9, readFileSync as readFileSync17, chmodSync } from "fs";
22495
- import { join as join25 } from "path";
22983
+ import { existsSync as existsSync28, mkdirSync as mkdirSync13, writeFileSync as writeFileSync9, readFileSync as readFileSync17, chmodSync } from "fs";
22984
+ import { join as join26 } from "path";
22496
22985
  import { createInterface as createInterface5 } from "readline";
22497
22986
  function requireDb() {
22498
- if (!existsSync27(DB_PATH)) {
22987
+ if (!existsSync28(DB_PATH)) {
22499
22988
  outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
22500
22989
  process.exit(1);
22501
22990
  }
@@ -22520,8 +23009,8 @@ async function resolveSlotId(idOrLabel) {
22520
23009
  function resolveOAuthEmail(configHome) {
22521
23010
  if (!configHome) return null;
22522
23011
  try {
22523
- const accountsPath = join25(configHome, ".gemini", "google_accounts.json");
22524
- if (!existsSync27(accountsPath)) return null;
23012
+ const accountsPath = join26(configHome, ".gemini", "google_accounts.json");
23013
+ if (!existsSync28(accountsPath)) return null;
22525
23014
  const accounts = JSON.parse(readFileSync17(accountsPath, "utf-8"));
22526
23015
  return accounts.active || null;
22527
23016
  } catch {
@@ -22604,14 +23093,14 @@ async function geminiAddKey(globalOpts, opts) {
22604
23093
  }
22605
23094
  async function geminiAddAccount(globalOpts, opts) {
22606
23095
  await requireWriteDb();
22607
- const slotsDir = join25(CC_CLAW_HOME, "gemini-slots");
22608
- if (!existsSync27(slotsDir)) mkdirSync12(slotsDir, { recursive: true });
23096
+ const slotsDir = join26(CC_CLAW_HOME, "gemini-slots");
23097
+ if (!existsSync28(slotsDir)) mkdirSync13(slotsDir, { recursive: true });
22609
23098
  const { addGeminiSlot: addGeminiSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
22610
23099
  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({
23100
+ const slotDir = join26(slotsDir, `slot-${tempId}`);
23101
+ mkdirSync13(slotDir, { recursive: true, mode: 448 });
23102
+ mkdirSync13(join26(slotDir, ".gemini"), { recursive: true });
23103
+ writeFileSync9(join26(slotDir, ".gemini", "settings.json"), JSON.stringify({
22615
23104
  security: { auth: { selectedType: "oauth-personal" } }
22616
23105
  }, null, 2));
22617
23106
  console.log("");
@@ -22628,8 +23117,8 @@ async function geminiAddAccount(globalOpts, opts) {
22628
23117
  });
22629
23118
  } catch {
22630
23119
  }
22631
- const oauthPath = join25(slotDir, ".gemini", "oauth_creds.json");
22632
- if (!existsSync27(oauthPath)) {
23120
+ const oauthPath = join26(slotDir, ".gemini", "oauth_creds.json");
23121
+ if (!existsSync28(oauthPath)) {
22633
23122
  console.log(error2("\n No OAuth credentials found. Sign-in may have failed."));
22634
23123
  console.log(" The slot directory is preserved at: " + slotDir);
22635
23124
  console.log(" Re-run: cc-claw gemini add-account\n");
@@ -22637,7 +23126,7 @@ async function geminiAddAccount(globalOpts, opts) {
22637
23126
  }
22638
23127
  let accountEmail = "unknown";
22639
23128
  try {
22640
- const accounts = JSON.parse(__require("fs").readFileSync(join25(slotDir, ".gemini", "google_accounts.json"), "utf-8"));
23129
+ const accounts = JSON.parse(__require("fs").readFileSync(join26(slotDir, ".gemini", "google_accounts.json"), "utf-8"));
22641
23130
  accountEmail = accounts.active || accountEmail;
22642
23131
  } catch {
22643
23132
  }
@@ -22648,6 +23137,13 @@ async function geminiAddAccount(globalOpts, opts) {
22648
23137
  configHome: slotDir,
22649
23138
  priority: opts.priority ? parseInt(opts.priority, 10) : 0
22650
23139
  });
23140
+ try {
23141
+ const { setupSlotSymlinks: setupSlotSymlinks2, getPrimaryDir: getPrimaryDir2 } = await Promise.resolve().then(() => (init_symlink_manager(), symlink_manager_exports));
23142
+ const primaryDir = getPrimaryDir2("gemini");
23143
+ if (primaryDir) setupSlotSymlinks2("gemini", slotDir, primaryDir);
23144
+ } catch (err) {
23145
+ console.log(warning(` Warning: could not set up state symlinks \u2014 ${err instanceof Error ? err.message : String(err)}`));
23146
+ }
22651
23147
  output(
22652
23148
  { id, type: "oauth", label: opts.label || accountEmail, configHome: slotDir },
22653
23149
  () => success(`
@@ -22749,11 +23245,11 @@ __export(backend_cmd_factory_exports, {
22749
23245
  makeReorder: () => makeReorder,
22750
23246
  registerBackendSlotCommands: () => registerBackendSlotCommands
22751
23247
  });
22752
- import { existsSync as existsSync28, mkdirSync as mkdirSync13, readFileSync as readFileSync18 } from "fs";
22753
- import { join as join26 } from "path";
23248
+ import { existsSync as existsSync29, mkdirSync as mkdirSync14, readFileSync as readFileSync18 } from "fs";
23249
+ import { join as join27 } from "path";
22754
23250
  import { createInterface as createInterface6 } from "readline";
22755
23251
  function requireDb2() {
22756
- if (!existsSync28(DB_PATH)) {
23252
+ if (!existsSync29(DB_PATH)) {
22757
23253
  outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
22758
23254
  process.exit(1);
22759
23255
  }
@@ -22842,11 +23338,11 @@ function makeAddAccount(backend2, displayName) {
22842
23338
  process.exit(1);
22843
23339
  }
22844
23340
  await requireWriteDb2();
22845
- const slotsDir = join26(CC_CLAW_HOME, config2.slotsSubdir);
22846
- if (!existsSync28(slotsDir)) mkdirSync13(slotsDir, { recursive: true });
23341
+ const slotsDir = join27(CC_CLAW_HOME, config2.slotsSubdir);
23342
+ if (!existsSync29(slotsDir)) mkdirSync14(slotsDir, { recursive: true });
22847
23343
  const tempId = Date.now();
22848
- const slotDir = join26(slotsDir, `slot-${tempId}`);
22849
- mkdirSync13(slotDir, { recursive: true, mode: 448 });
23344
+ const slotDir = join27(slotsDir, `slot-${tempId}`);
23345
+ mkdirSync14(slotDir, { recursive: true, mode: 448 });
22850
23346
  if (config2.preSetup) config2.preSetup(slotDir);
22851
23347
  console.log("");
22852
23348
  console.log(` Opening ${displayName} CLI for sign-in...`);
@@ -22884,6 +23380,13 @@ function makeAddAccount(backend2, displayName) {
22884
23380
  configHome: slotDir,
22885
23381
  priority: opts.priority ? parseInt(opts.priority, 10) : 0
22886
23382
  });
23383
+ try {
23384
+ const { setupSlotSymlinks: setupSlotSymlinks2, getPrimaryDir: getPrimaryDir2 } = await Promise.resolve().then(() => (init_symlink_manager(), symlink_manager_exports));
23385
+ const primaryDir = getPrimaryDir2(backend2);
23386
+ if (primaryDir) setupSlotSymlinks2(backend2, slotDir, primaryDir);
23387
+ } catch (err) {
23388
+ console.log(warning(` Warning: could not set up state symlinks \u2014 ${err instanceof Error ? err.message : String(err)}`));
23389
+ }
22887
23390
  output(
22888
23391
  { id, type: "oauth", backend: backend2, label: accountLabel, configHome: slotDir },
22889
23392
  () => success(`Added ${displayName} subscription slot #${id} (${accountLabel})`)
@@ -23007,12 +23510,12 @@ var init_backend_cmd_factory = __esm({
23007
23510
  envValue: (slotDir) => slotDir,
23008
23511
  envOverrides: { ANTHROPIC_API_KEY: void 0 },
23009
23512
  preSetup: (slotDir) => {
23010
- mkdirSync13(join26(slotDir, ".claude"), { recursive: true });
23513
+ mkdirSync14(join27(slotDir, ".claude"), { recursive: true });
23011
23514
  },
23012
23515
  verifyCredentials: (slotDir) => {
23013
- const claudeJson = join26(slotDir, ".claude.json");
23014
- const claudeJsonNested = join26(slotDir, ".claude", ".claude.json");
23015
- if (existsSync28(claudeJson)) {
23516
+ const claudeJson = join27(slotDir, ".claude.json");
23517
+ const claudeJsonNested = join27(slotDir, ".claude", ".claude.json");
23518
+ if (existsSync29(claudeJson)) {
23016
23519
  try {
23017
23520
  const data = JSON.parse(readFileSync18(claudeJson, "utf-8"));
23018
23521
  return Boolean(data.oauthAccount);
@@ -23020,7 +23523,7 @@ var init_backend_cmd_factory = __esm({
23020
23523
  return false;
23021
23524
  }
23022
23525
  }
23023
- if (existsSync28(claudeJsonNested)) {
23526
+ if (existsSync29(claudeJsonNested)) {
23024
23527
  try {
23025
23528
  const data = JSON.parse(readFileSync18(claudeJsonNested, "utf-8"));
23026
23529
  return Boolean(data.oauthAccount);
@@ -23043,8 +23546,8 @@ var init_backend_cmd_factory = __esm({
23043
23546
  } catch {
23044
23547
  }
23045
23548
  try {
23046
- const claudeJson = join26(slotDir, ".claude.json");
23047
- if (existsSync28(claudeJson)) {
23549
+ const claudeJson = join27(slotDir, ".claude.json");
23550
+ if (existsSync29(claudeJson)) {
23048
23551
  const data = JSON.parse(readFileSync18(claudeJson, "utf-8"));
23049
23552
  if (data.oauthAccount?.emailAddress) return data.oauthAccount.emailAddress;
23050
23553
  }
@@ -23060,11 +23563,11 @@ var init_backend_cmd_factory = __esm({
23060
23563
  envValue: (slotDir) => slotDir,
23061
23564
  envOverrides: { OPENAI_API_KEY: void 0 },
23062
23565
  verifyCredentials: (slotDir) => {
23063
- return existsSync28(join26(slotDir, "auth.json"));
23566
+ return existsSync29(join27(slotDir, "auth.json"));
23064
23567
  },
23065
23568
  extractLabel: (slotDir) => {
23066
23569
  try {
23067
- const authData = JSON.parse(readFileSync18(join26(slotDir, "auth.json"), "utf-8"));
23570
+ const authData = JSON.parse(readFileSync18(join27(slotDir, "auth.json"), "utf-8"));
23068
23571
  if (authData.email) return authData.email;
23069
23572
  if (authData.account_name) return authData.account_name;
23070
23573
  if (authData.user?.email) return authData.user.email;
@@ -23084,12 +23587,12 @@ __export(backend_exports, {
23084
23587
  backendList: () => backendList,
23085
23588
  backendSet: () => backendSet
23086
23589
  });
23087
- import { existsSync as existsSync29 } from "fs";
23590
+ import { existsSync as existsSync30 } from "fs";
23088
23591
  async function backendList(globalOpts) {
23089
23592
  const { getAvailableAdapters: getAvailableAdapters3 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
23090
23593
  const chatId = resolveChatId(globalOpts);
23091
23594
  let activeBackend = null;
23092
- if (existsSync29(DB_PATH)) {
23595
+ if (existsSync30(DB_PATH)) {
23093
23596
  const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
23094
23597
  const readDb = openDatabaseReadOnly2();
23095
23598
  try {
@@ -23120,7 +23623,7 @@ async function backendList(globalOpts) {
23120
23623
  }
23121
23624
  async function backendGet(globalOpts) {
23122
23625
  const chatId = resolveChatId(globalOpts);
23123
- if (!existsSync29(DB_PATH)) {
23626
+ if (!existsSync30(DB_PATH)) {
23124
23627
  outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
23125
23628
  process.exit(1);
23126
23629
  }
@@ -23164,13 +23667,13 @@ __export(model_exports, {
23164
23667
  modelList: () => modelList,
23165
23668
  modelSet: () => modelSet
23166
23669
  });
23167
- import { existsSync as existsSync30 } from "fs";
23670
+ import { existsSync as existsSync31 } from "fs";
23168
23671
  async function modelList(globalOpts) {
23169
23672
  const chatId = resolveChatId(globalOpts);
23170
23673
  const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
23171
23674
  const { getAdapter: getAdapter4, getAllAdapters: getAllAdapters5 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
23172
23675
  let backendId = "claude";
23173
- if (existsSync30(DB_PATH)) {
23676
+ if (existsSync31(DB_PATH)) {
23174
23677
  const readDb = openDatabaseReadOnly2();
23175
23678
  try {
23176
23679
  const row = readDb.prepare("SELECT backend FROM chat_backend WHERE chat_id = ?").get(chatId);
@@ -23203,7 +23706,7 @@ async function modelList(globalOpts) {
23203
23706
  }
23204
23707
  async function modelGet(globalOpts) {
23205
23708
  const chatId = resolveChatId(globalOpts);
23206
- if (!existsSync30(DB_PATH)) {
23709
+ if (!existsSync31(DB_PATH)) {
23207
23710
  outputError("DB_NOT_FOUND", "Database not found.");
23208
23711
  process.exit(1);
23209
23712
  }
@@ -23247,9 +23750,9 @@ __export(memory_exports2, {
23247
23750
  memoryList: () => memoryList,
23248
23751
  memorySearch: () => memorySearch
23249
23752
  });
23250
- import { existsSync as existsSync31 } from "fs";
23753
+ import { existsSync as existsSync32 } from "fs";
23251
23754
  async function memoryList(globalOpts) {
23252
- if (!existsSync31(DB_PATH)) {
23755
+ if (!existsSync32(DB_PATH)) {
23253
23756
  outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
23254
23757
  process.exit(1);
23255
23758
  }
@@ -23273,7 +23776,7 @@ async function memoryList(globalOpts) {
23273
23776
  });
23274
23777
  }
23275
23778
  async function memorySearch(globalOpts, query) {
23276
- if (!existsSync31(DB_PATH)) {
23779
+ if (!existsSync32(DB_PATH)) {
23277
23780
  outputError("DB_NOT_FOUND", "Database not found.");
23278
23781
  process.exit(1);
23279
23782
  }
@@ -23295,7 +23798,7 @@ async function memorySearch(globalOpts, query) {
23295
23798
  });
23296
23799
  }
23297
23800
  async function memoryHistory(globalOpts, opts) {
23298
- if (!existsSync31(DB_PATH)) {
23801
+ if (!existsSync32(DB_PATH)) {
23299
23802
  outputError("DB_NOT_FOUND", "Database not found.");
23300
23803
  process.exit(1);
23301
23804
  }
@@ -23343,7 +23846,7 @@ __export(cron_exports2, {
23343
23846
  cronList: () => cronList,
23344
23847
  cronRuns: () => cronRuns
23345
23848
  });
23346
- import { existsSync as existsSync32 } from "fs";
23849
+ import { existsSync as existsSync33 } from "fs";
23347
23850
  function parseFallbacks(raw) {
23348
23851
  return raw.slice(0, 3).map((f) => {
23349
23852
  const [backend2, ...rest] = f.split(":");
@@ -23364,7 +23867,7 @@ function parseAndValidateTimeout(raw) {
23364
23867
  return val;
23365
23868
  }
23366
23869
  async function cronList(globalOpts) {
23367
- if (!existsSync32(DB_PATH)) {
23870
+ if (!existsSync33(DB_PATH)) {
23368
23871
  outputError("DB_NOT_FOUND", "Database not found.");
23369
23872
  process.exit(1);
23370
23873
  }
@@ -23402,7 +23905,7 @@ async function cronList(globalOpts) {
23402
23905
  });
23403
23906
  }
23404
23907
  async function cronHealth(globalOpts) {
23405
- if (!existsSync32(DB_PATH)) {
23908
+ if (!existsSync33(DB_PATH)) {
23406
23909
  outputError("DB_NOT_FOUND", "Database not found.");
23407
23910
  process.exit(1);
23408
23911
  }
@@ -23561,7 +24064,7 @@ async function cronEdit(globalOpts, id, opts) {
23561
24064
  }
23562
24065
  }
23563
24066
  async function cronRuns(globalOpts, jobId, opts) {
23564
- if (!existsSync32(DB_PATH)) {
24067
+ if (!existsSync33(DB_PATH)) {
23565
24068
  outputError("DB_NOT_FOUND", "Database not found.");
23566
24069
  process.exit(1);
23567
24070
  }
@@ -23608,9 +24111,9 @@ __export(agents_exports, {
23608
24111
  runnersList: () => runnersList,
23609
24112
  tasksList: () => tasksList
23610
24113
  });
23611
- import { existsSync as existsSync33 } from "fs";
24114
+ import { existsSync as existsSync34 } from "fs";
23612
24115
  async function agentsList(globalOpts) {
23613
- if (!existsSync33(DB_PATH)) {
24116
+ if (!existsSync34(DB_PATH)) {
23614
24117
  outputError("DB_NOT_FOUND", "Database not found.");
23615
24118
  process.exit(1);
23616
24119
  }
@@ -23641,7 +24144,7 @@ async function agentsList(globalOpts) {
23641
24144
  });
23642
24145
  }
23643
24146
  async function tasksList(globalOpts) {
23644
- if (!existsSync33(DB_PATH)) {
24147
+ if (!existsSync34(DB_PATH)) {
23645
24148
  outputError("DB_NOT_FOUND", "Database not found.");
23646
24149
  process.exit(1);
23647
24150
  }
@@ -23769,18 +24272,18 @@ __export(db_exports, {
23769
24272
  dbPath: () => dbPath,
23770
24273
  dbStats: () => dbStats
23771
24274
  });
23772
- import { existsSync as existsSync34, statSync as statSync8, copyFileSync as copyFileSync2, mkdirSync as mkdirSync14 } from "fs";
23773
- import { dirname as dirname5 } from "path";
24275
+ import { existsSync as existsSync35, statSync as statSync9, copyFileSync as copyFileSync3, mkdirSync as mkdirSync15 } from "fs";
24276
+ import { dirname as dirname6 } from "path";
23774
24277
  async function dbStats(globalOpts) {
23775
- if (!existsSync34(DB_PATH)) {
24278
+ if (!existsSync35(DB_PATH)) {
23776
24279
  outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
23777
24280
  process.exit(1);
23778
24281
  }
23779
24282
  const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
23780
24283
  const readDb = openDatabaseReadOnly2();
23781
- const mainSize = statSync8(DB_PATH).size;
24284
+ const mainSize = statSync9(DB_PATH).size;
23782
24285
  const walPath = DB_PATH + "-wal";
23783
- const walSize = existsSync34(walPath) ? statSync8(walPath).size : 0;
24286
+ const walSize = existsSync35(walPath) ? statSync9(walPath).size : 0;
23784
24287
  const tableNames = readDb.prepare(
23785
24288
  "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '%_fts%' ORDER BY name"
23786
24289
  ).all();
@@ -23814,17 +24317,17 @@ async function dbPath(globalOpts) {
23814
24317
  output({ path: DB_PATH }, (d) => d.path);
23815
24318
  }
23816
24319
  async function dbBackup(globalOpts, destPath) {
23817
- if (!existsSync34(DB_PATH)) {
24320
+ if (!existsSync35(DB_PATH)) {
23818
24321
  outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
23819
24322
  process.exit(1);
23820
24323
  }
23821
24324
  const dest = destPath ?? `${DB_PATH}.backup-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
23822
24325
  try {
23823
- mkdirSync14(dirname5(dest), { recursive: true });
23824
- copyFileSync2(DB_PATH, dest);
24326
+ mkdirSync15(dirname6(dest), { recursive: true });
24327
+ copyFileSync3(DB_PATH, dest);
23825
24328
  const walPath = DB_PATH + "-wal";
23826
- if (existsSync34(walPath)) copyFileSync2(walPath, dest + "-wal");
23827
- output({ path: dest, sizeBytes: statSync8(dest).size }, (d) => {
24329
+ if (existsSync35(walPath)) copyFileSync3(walPath, dest + "-wal");
24330
+ output({ path: dest, sizeBytes: statSync9(dest).size }, (d) => {
23828
24331
  const b = d;
23829
24332
  return `
23830
24333
  ${success("Backup created:")} ${b.path} (${(b.sizeBytes / 1024).toFixed(0)}KB)
@@ -23852,9 +24355,9 @@ __export(usage_exports, {
23852
24355
  usageCost: () => usageCost,
23853
24356
  usageTokens: () => usageTokens
23854
24357
  });
23855
- import { existsSync as existsSync35 } from "fs";
24358
+ import { existsSync as existsSync36 } from "fs";
23856
24359
  function ensureDb() {
23857
- if (!existsSync35(DB_PATH)) {
24360
+ if (!existsSync36(DB_PATH)) {
23858
24361
  outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
23859
24362
  process.exit(1);
23860
24363
  }
@@ -24044,9 +24547,9 @@ __export(config_exports2, {
24044
24547
  configList: () => configList,
24045
24548
  configSet: () => configSet
24046
24549
  });
24047
- import { existsSync as existsSync36, readFileSync as readFileSync19 } from "fs";
24550
+ import { existsSync as existsSync37, readFileSync as readFileSync19 } from "fs";
24048
24551
  async function configList(globalOpts) {
24049
- if (!existsSync36(DB_PATH)) {
24552
+ if (!existsSync37(DB_PATH)) {
24050
24553
  outputError("DB_NOT_FOUND", "Database not found.");
24051
24554
  process.exit(1);
24052
24555
  }
@@ -24080,7 +24583,7 @@ async function configGet(globalOpts, key) {
24080
24583
  outputError("INVALID_KEY", `Unknown config key "${key}". Valid keys: ${RUNTIME_KEYS.join(", ")}`);
24081
24584
  process.exit(1);
24082
24585
  }
24083
- if (!existsSync36(DB_PATH)) {
24586
+ if (!existsSync37(DB_PATH)) {
24084
24587
  outputError("DB_NOT_FOUND", "Database not found.");
24085
24588
  process.exit(1);
24086
24589
  }
@@ -24126,7 +24629,7 @@ async function configSet(globalOpts, key, value) {
24126
24629
  }
24127
24630
  }
24128
24631
  async function configEnv(_globalOpts) {
24129
- if (!existsSync36(ENV_PATH)) {
24632
+ if (!existsSync37(ENV_PATH)) {
24130
24633
  outputError("ENV_NOT_FOUND", `No .env file at ${ENV_PATH}. Run cc-claw setup.`);
24131
24634
  process.exit(1);
24132
24635
  }
@@ -24180,9 +24683,9 @@ __export(session_exports, {
24180
24683
  sessionGet: () => sessionGet,
24181
24684
  sessionNew: () => sessionNew
24182
24685
  });
24183
- import { existsSync as existsSync37 } from "fs";
24686
+ import { existsSync as existsSync38 } from "fs";
24184
24687
  async function sessionGet(globalOpts) {
24185
- if (!existsSync37(DB_PATH)) {
24688
+ if (!existsSync38(DB_PATH)) {
24186
24689
  outputError("DB_NOT_FOUND", "Database not found.");
24187
24690
  process.exit(1);
24188
24691
  }
@@ -24243,9 +24746,9 @@ __export(permissions_exports, {
24243
24746
  verboseGet: () => verboseGet,
24244
24747
  verboseSet: () => verboseSet
24245
24748
  });
24246
- import { existsSync as existsSync38 } from "fs";
24749
+ import { existsSync as existsSync39 } from "fs";
24247
24750
  function ensureDb2() {
24248
- if (!existsSync38(DB_PATH)) {
24751
+ if (!existsSync39(DB_PATH)) {
24249
24752
  outputError("DB_NOT_FOUND", "Database not found.");
24250
24753
  process.exit(1);
24251
24754
  }
@@ -24392,9 +24895,9 @@ __export(cwd_exports, {
24392
24895
  cwdGet: () => cwdGet,
24393
24896
  cwdSet: () => cwdSet
24394
24897
  });
24395
- import { existsSync as existsSync39 } from "fs";
24898
+ import { existsSync as existsSync40 } from "fs";
24396
24899
  async function cwdGet(globalOpts) {
24397
- if (!existsSync39(DB_PATH)) {
24900
+ if (!existsSync40(DB_PATH)) {
24398
24901
  outputError("DB_NOT_FOUND", "Database not found.");
24399
24902
  process.exit(1);
24400
24903
  }
@@ -24456,9 +24959,9 @@ __export(voice_exports, {
24456
24959
  voiceGet: () => voiceGet,
24457
24960
  voiceSet: () => voiceSet
24458
24961
  });
24459
- import { existsSync as existsSync40 } from "fs";
24962
+ import { existsSync as existsSync41 } from "fs";
24460
24963
  async function voiceGet(globalOpts) {
24461
- if (!existsSync40(DB_PATH)) {
24964
+ if (!existsSync41(DB_PATH)) {
24462
24965
  outputError("DB_NOT_FOUND", "Database not found.");
24463
24966
  process.exit(1);
24464
24967
  }
@@ -24507,9 +25010,9 @@ __export(heartbeat_exports, {
24507
25010
  heartbeatGet: () => heartbeatGet,
24508
25011
  heartbeatSet: () => heartbeatSet
24509
25012
  });
24510
- import { existsSync as existsSync41 } from "fs";
25013
+ import { existsSync as existsSync42 } from "fs";
24511
25014
  async function heartbeatGet(globalOpts) {
24512
- if (!existsSync41(DB_PATH)) {
25015
+ if (!existsSync42(DB_PATH)) {
24513
25016
  outputError("DB_NOT_FOUND", "Database not found.");
24514
25017
  process.exit(1);
24515
25018
  }
@@ -24618,9 +25121,9 @@ __export(summarizer_exports, {
24618
25121
  summarizerGet: () => summarizerGet,
24619
25122
  summarizerSet: () => summarizerSet
24620
25123
  });
24621
- import { existsSync as existsSync42 } from "fs";
25124
+ import { existsSync as existsSync43 } from "fs";
24622
25125
  async function summarizerGet(globalOpts) {
24623
- if (!existsSync42(DB_PATH)) {
25126
+ if (!existsSync43(DB_PATH)) {
24624
25127
  outputError("DB_NOT_FOUND", "Database not found.");
24625
25128
  process.exit(1);
24626
25129
  }
@@ -24664,9 +25167,9 @@ __export(thinking_exports, {
24664
25167
  thinkingGet: () => thinkingGet,
24665
25168
  thinkingSet: () => thinkingSet
24666
25169
  });
24667
- import { existsSync as existsSync43 } from "fs";
25170
+ import { existsSync as existsSync44 } from "fs";
24668
25171
  async function thinkingGet(globalOpts) {
24669
- if (!existsSync43(DB_PATH)) {
25172
+ if (!existsSync44(DB_PATH)) {
24670
25173
  outputError("DB_NOT_FOUND", "Database not found.");
24671
25174
  process.exit(1);
24672
25175
  }
@@ -24710,9 +25213,9 @@ __export(chats_exports, {
24710
25213
  chatsList: () => chatsList,
24711
25214
  chatsRemoveAlias: () => chatsRemoveAlias
24712
25215
  });
24713
- import { existsSync as existsSync44 } from "fs";
25216
+ import { existsSync as existsSync45 } from "fs";
24714
25217
  async function chatsList(_globalOpts) {
24715
- if (!existsSync44(DB_PATH)) {
25218
+ if (!existsSync45(DB_PATH)) {
24716
25219
  outputError("DB_NOT_FOUND", "Database not found.");
24717
25220
  process.exit(1);
24718
25221
  }
@@ -24840,9 +25343,9 @@ var mcps_exports2 = {};
24840
25343
  __export(mcps_exports2, {
24841
25344
  mcpsList: () => mcpsList
24842
25345
  });
24843
- import { existsSync as existsSync45 } from "fs";
25346
+ import { existsSync as existsSync46 } from "fs";
24844
25347
  async function mcpsList(_globalOpts) {
24845
- if (!existsSync45(DB_PATH)) {
25348
+ if (!existsSync46(DB_PATH)) {
24846
25349
  outputError("DB_NOT_FOUND", "Database not found.");
24847
25350
  process.exit(1);
24848
25351
  }
@@ -24879,11 +25382,11 @@ __export(chat_exports2, {
24879
25382
  chatSend: () => chatSend
24880
25383
  });
24881
25384
  import { request as httpRequest2 } from "http";
24882
- import { readFileSync as readFileSync20, existsSync as existsSync46 } from "fs";
25385
+ import { readFileSync as readFileSync20, existsSync as existsSync47 } from "fs";
24883
25386
  function getToken2() {
24884
25387
  if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
24885
25388
  try {
24886
- if (existsSync46(TOKEN_PATH2)) return readFileSync20(TOKEN_PATH2, "utf-8").trim();
25389
+ if (existsSync47(TOKEN_PATH2)) return readFileSync20(TOKEN_PATH2, "utf-8").trim();
24887
25390
  } catch {
24888
25391
  }
24889
25392
  return null;
@@ -25162,8 +25665,8 @@ var completion_exports = {};
25162
25665
  __export(completion_exports, {
25163
25666
  completionCommand: () => completionCommand
25164
25667
  });
25165
- import { writeFileSync as writeFileSync10, mkdirSync as mkdirSync15 } from "fs";
25166
- import { join as join27 } from "path";
25668
+ import { writeFileSync as writeFileSync10, mkdirSync as mkdirSync16 } from "fs";
25669
+ import { join as join28 } from "path";
25167
25670
  import { homedir as homedir9 } from "os";
25168
25671
  async function completionCommand(opts) {
25169
25672
  const shell = opts.shell ?? detectShell();
@@ -25179,10 +25682,10 @@ async function completionCommand(opts) {
25179
25682
  process.exit(1);
25180
25683
  }
25181
25684
  if (opts.install) {
25182
- const dir = join27(homedir9(), ".config", "cc-claw", "completions");
25183
- mkdirSync15(dir, { recursive: true });
25685
+ const dir = join28(homedir9(), ".config", "cc-claw", "completions");
25686
+ mkdirSync16(dir, { recursive: true });
25184
25687
  const filename = shell === "zsh" ? "_cc-claw" : shell === "fish" ? "cc-claw.fish" : "cc-claw.bash";
25185
- const filepath = join27(dir, filename);
25688
+ const filepath = join28(dir, filename);
25186
25689
  writeFileSync10(filepath, script, "utf-8");
25187
25690
  console.log(`\u2713 Completion script written to ${filepath}
25188
25691
  `);
@@ -25353,9 +25856,9 @@ __export(evolve_exports2, {
25353
25856
  evolveStatus: () => evolveStatus,
25354
25857
  evolveUndo: () => evolveUndo
25355
25858
  });
25356
- import { existsSync as existsSync47 } from "fs";
25859
+ import { existsSync as existsSync48 } from "fs";
25357
25860
  function ensureDb3() {
25358
- if (!existsSync47(DB_PATH)) {
25861
+ if (!existsSync48(DB_PATH)) {
25359
25862
  outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
25360
25863
  process.exit(1);
25361
25864
  }
@@ -25771,10 +26274,10 @@ var init_evolve3 = __esm({
25771
26274
 
25772
26275
  // src/setup.ts
25773
26276
  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";
26277
+ import { existsSync as existsSync49, writeFileSync as writeFileSync11, readFileSync as readFileSync21, copyFileSync as copyFileSync4, mkdirSync as mkdirSync17, statSync as statSync10 } from "fs";
25775
26278
  import { execFileSync as execFileSync5 } from "child_process";
25776
26279
  import { createInterface as createInterface8 } from "readline";
25777
- import { join as join28 } from "path";
26280
+ import { join as join29 } from "path";
25778
26281
  function divider2() {
25779
26282
  console.log(dim("\u2500".repeat(55)));
25780
26283
  }
@@ -25849,10 +26352,10 @@ async function setup() {
25849
26352
  }
25850
26353
  console.log("");
25851
26354
  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 });
26355
+ if (!existsSync49(dir)) mkdirSync17(dir, { recursive: true });
25853
26356
  }
25854
26357
  const env = {};
25855
- const envSource = existsSync48(ENV_PATH) ? ENV_PATH : existsSync48(".env") ? ".env" : null;
26358
+ const envSource = existsSync49(ENV_PATH) ? ENV_PATH : existsSync49(".env") ? ".env" : null;
25856
26359
  if (envSource) {
25857
26360
  console.log(yellow(` Found existing config at ${envSource} \u2014 your values will be preserved`));
25858
26361
  console.log(yellow(" unless you enter new ones. Just press Enter to keep existing values.\n"));
@@ -25862,13 +26365,13 @@ async function setup() {
25862
26365
  if (match) env[match[1].trim()] = match[2].trim();
25863
26366
  }
25864
26367
  }
25865
- const cwdDb = join28(process.cwd(), "cc-claw.db");
25866
- if (existsSync48(cwdDb) && !existsSync48(DB_PATH)) {
25867
- const { size } = statSync9(cwdDb);
26368
+ const cwdDb = join29(process.cwd(), "cc-claw.db");
26369
+ if (existsSync49(cwdDb) && !existsSync49(DB_PATH)) {
26370
+ const { size } = statSync10(cwdDb);
25868
26371
  console.log(yellow(` Found existing database at ${cwdDb} (${(size / 1024).toFixed(0)}KB)`));
25869
26372
  const migrate = await confirm("Copy database to ~/.cc-claw/? (preserves memories & history)", true);
25870
26373
  if (migrate) {
25871
- copyFileSync3(cwdDb, DB_PATH);
26374
+ copyFileSync4(cwdDb, DB_PATH);
25872
26375
  console.log(green(` Database copied to ${DB_PATH}`));
25873
26376
  }
25874
26377
  console.log("");