cc-claw 0.11.1 → 0.11.2

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 +430 -253
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -72,7 +72,7 @@ var VERSION;
72
72
  var init_version = __esm({
73
73
  "src/version.ts"() {
74
74
  "use strict";
75
- VERSION = true ? "0.11.1" : (() => {
75
+ VERSION = true ? "0.11.2" : (() => {
76
76
  try {
77
77
  return JSON.parse(readFileSync(join2(process.cwd(), "package.json"), "utf-8")).version ?? "unknown";
78
78
  } catch {
@@ -1545,6 +1545,7 @@ function initDatabase() {
1545
1545
  cron TEXT,
1546
1546
  at_time TEXT,
1547
1547
  every_ms INTEGER,
1548
+ title TEXT,
1548
1549
  description TEXT NOT NULL,
1549
1550
  chat_id TEXT NOT NULL,
1550
1551
  backend TEXT,
@@ -1581,6 +1582,7 @@ function initDatabase() {
1581
1582
  cron TEXT,
1582
1583
  at_time TEXT,
1583
1584
  every_ms INTEGER,
1585
+ title TEXT,
1584
1586
  description TEXT NOT NULL,
1585
1587
  chat_id TEXT NOT NULL,
1586
1588
  backend TEXT,
@@ -1675,6 +1677,11 @@ function initDatabase() {
1675
1677
  db.exec("ALTER TABLE jobs ADD COLUMN fallbacks TEXT");
1676
1678
  } catch {
1677
1679
  }
1680
+ try {
1681
+ db.exec("ALTER TABLE jobs ADD COLUMN title TEXT");
1682
+ } catch {
1683
+ }
1684
+ backfillJobTitles(db);
1678
1685
  }
1679
1686
  } catch {
1680
1687
  }
@@ -2521,14 +2528,15 @@ function getBackendUsageInWindow(backend2, windowType) {
2521
2528
  }
2522
2529
  function insertJob(params) {
2523
2530
  const result = db.prepare(`
2524
- INSERT INTO jobs (schedule_type, cron, at_time, every_ms, description, chat_id,
2531
+ INSERT INTO jobs (schedule_type, cron, at_time, every_ms, title, description, chat_id,
2525
2532
  backend, model, thinking, timeout, fallbacks, session_type, channel, target, delivery_mode, timezone)
2526
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2533
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2527
2534
  `).run(
2528
2535
  params.scheduleType,
2529
2536
  params.cron ?? null,
2530
2537
  params.atTime ?? null,
2531
2538
  params.everyMs ?? null,
2539
+ params.title ?? null,
2532
2540
  params.description,
2533
2541
  params.chatId,
2534
2542
  params.backend ?? null,
@@ -2544,6 +2552,26 @@ function insertJob(params) {
2544
2552
  );
2545
2553
  return getJobById(Number(result.lastInsertRowid));
2546
2554
  }
2555
+ function backfillJobTitles(database) {
2556
+ const rows = database.prepare("SELECT id, description FROM jobs WHERE title IS NULL AND active = 1").all();
2557
+ if (rows.length === 0) return;
2558
+ const preamblePatterns = [
2559
+ /^you\s+must\s+call\s+the\s+\w+\s+tool\b[^.]*\.\s*/i,
2560
+ /^important:\s*[^.]*\.\s*/i,
2561
+ /^always\s+use\s+[^.]*\.\s*/i,
2562
+ /^note:\s*[^.]*\.\s*/i
2563
+ ];
2564
+ for (const row of rows) {
2565
+ let text = row.description;
2566
+ for (const pat of preamblePatterns) {
2567
+ text = text.replace(pat, "");
2568
+ }
2569
+ text = text.trim();
2570
+ const firstSentence = text.match(/^[^.!?\n]{5,60}[.!?]?/)?.[0] ?? text.slice(0, 60);
2571
+ const title = firstSentence.length > 60 ? firstSentence.slice(0, 57) + "\u2026" : firstSentence;
2572
+ database.prepare("UPDATE jobs SET title = ? WHERE id = ?").run(title, row.id);
2573
+ }
2574
+ }
2547
2575
  function mapJobRow(row) {
2548
2576
  if (!row) return void 0;
2549
2577
  row.fallbacks = row.fallbacks ? JSON.parse(row.fallbacks) : [];
@@ -2588,6 +2616,7 @@ function updateJob(id, fields) {
2588
2616
  cron: "cron",
2589
2617
  atTime: "at_time",
2590
2618
  everyMs: "every_ms",
2619
+ title: "title",
2591
2620
  description: "description",
2592
2621
  backend: "backend",
2593
2622
  model: "model",
@@ -3032,7 +3061,7 @@ var init_store5 = __esm({
3032
3061
  ALL_TOOLS = ["Read", "Glob", "Grep", "Bash", "Write", "Edit", "WebFetch", "WebSearch", "Agent", "AskUserQuestion"];
3033
3062
  JOB_SELECT = `
3034
3063
  SELECT id, schedule_type as scheduleType, cron, at_time as atTime, every_ms as everyMs,
3035
- description, chat_id as chatId, backend, model, thinking, timeout, fallbacks,
3064
+ title, description, chat_id as chatId, backend, model, thinking, timeout, fallbacks,
3036
3065
  session_type as sessionType, channel, target, delivery_mode as deliveryMode,
3037
3066
  timezone, enabled, active, created_at as createdAt, last_run_at as lastRunAt,
3038
3067
  next_run_at as nextRunAt, consecutive_failures as consecutiveFailures
@@ -6566,8 +6595,45 @@ __export(analyze_exports, {
6566
6595
  });
6567
6596
  import { spawn as spawn4 } from "child_process";
6568
6597
  import { createInterface as createInterface3 } from "readline";
6569
- import { readFileSync as readFileSync6 } from "fs";
6598
+ import { readFileSync as readFileSync6, existsSync as existsSync11, readdirSync as readdirSync5, statSync as statSync3 } from "fs";
6570
6599
  import { join as join10 } from "path";
6600
+ import { homedir as homedir4 } from "os";
6601
+ function discoverReflectionTargets() {
6602
+ const ccClawHome = join10(homedir4(), ".cc-claw");
6603
+ const targets = [];
6604
+ try {
6605
+ const skillsDir = join10(ccClawHome, "workspace", "skills");
6606
+ if (existsSync11(skillsDir)) {
6607
+ for (const entry of readdirSync5(skillsDir)) {
6608
+ const entryPath = join10(skillsDir, entry);
6609
+ if (!statSync3(entryPath).isDirectory()) continue;
6610
+ const skillFile = join10(entryPath, "SKILL.md");
6611
+ if (!existsSync11(skillFile)) continue;
6612
+ let desc = "skill";
6613
+ try {
6614
+ const content = readFileSync6(skillFile, "utf-8").slice(0, 500);
6615
+ const descMatch = content.match(/description:\s*["']?([^"'\n]+)/);
6616
+ if (descMatch) desc = descMatch[1].trim().slice(0, 80);
6617
+ } catch {
6618
+ }
6619
+ targets.push({ path: `workspace/skills/${entry}/SKILL.md`, description: desc });
6620
+ }
6621
+ }
6622
+ } catch {
6623
+ }
6624
+ try {
6625
+ const contextDir = join10(ccClawHome, "workspace", "context");
6626
+ if (existsSync11(contextDir)) {
6627
+ for (const entry of readdirSync5(contextDir)) {
6628
+ if (!entry.endsWith(".md")) continue;
6629
+ const name = entry.replace(/\.md$/, "");
6630
+ targets.push({ path: `workspace/context/${entry}`, description: `context file: ${name}` });
6631
+ }
6632
+ }
6633
+ } catch {
6634
+ }
6635
+ return targets;
6636
+ }
6571
6637
  function buildAnalysisPrompt(params) {
6572
6638
  const {
6573
6639
  signals,
@@ -6627,7 +6693,31 @@ ${categoryList}`);
6627
6693
  sections.push(`- [#${ins.id}] (${ins.category}) ${ins.insight}`);
6628
6694
  }
6629
6695
  }
6630
- const targetOptions = codebaseEnabled ? "identity/SOUL.md | identity/USER.md | codebase" : "identity/SOUL.md | identity/USER.md";
6696
+ const { availableTargets } = params;
6697
+ const targetList = [
6698
+ "identity/SOUL.md \u2014 personality, tone, stable behavioral rules, communication style",
6699
+ "identity/USER.md \u2014 user preferences, personal info, timezone, language, profile"
6700
+ ];
6701
+ if (availableTargets) {
6702
+ for (const t of availableTargets) {
6703
+ targetList.push(`${t.path} \u2014 ${t.description}`);
6704
+ }
6705
+ }
6706
+ if (codebaseEnabled) {
6707
+ targetList.push("codebase \u2014 code-level recommendation (advisory only)");
6708
+ }
6709
+ sections.push(`[Target File Routing]
6710
+ Available targets:
6711
+ ${targetList.map((t) => `- ${t}`).join("\n")}
6712
+
6713
+ Choose the MOST SPECIFIC target for each insight:
6714
+ - Workflow or process improvements \u2192 the relevant skill file
6715
+ - Tool usage patterns or domain-specific steps \u2192 the relevant skill file
6716
+ - User preference or profile info \u2192 USER.md
6717
+ - Personality, tone, general behavior \u2192 SOUL.md
6718
+ - Domain knowledge or reference material \u2192 a context file
6719
+ - If no matching skill/context file exists, fall back to SOUL.md or USER.md`);
6720
+ const targetOptions = targetList.map((t) => t.split(" \u2014 ")[0]).join(" | ");
6631
6721
  sections.push(`[Output Format]
6632
6722
  For each insight, output EXACTLY this format. Separate multiple insights with "---" on its own line.
6633
6723
 
@@ -6823,6 +6913,7 @@ async function runAnalysis(chatId, opts = {}) {
6823
6913
  const applied = getAppliedInsights(db3, chatId);
6824
6914
  const rejected = getRejectedInsights(db3, chatId);
6825
6915
  const codebaseEnabled = process.env.REFLECTION_CODEBASE_RECOMMENDATIONS === "1";
6916
+ const availableTargets = discoverReflectionTargets();
6826
6917
  const prompt = buildAnalysisPrompt({
6827
6918
  signals: signals.map((s) => ({
6828
6919
  signalType: s.signalType,
@@ -6844,7 +6935,8 @@ async function runAnalysis(chatId, opts = {}) {
6844
6935
  insight: i.insight,
6845
6936
  category: i.category
6846
6937
  })),
6847
- codebaseEnabled
6938
+ codebaseEnabled,
6939
+ availableTargets
6848
6940
  });
6849
6941
  const resolved = resolveReflectionAdapter(chatId);
6850
6942
  if (!resolved) {
@@ -6948,7 +7040,7 @@ __export(apply_exports, {
6948
7040
  isTargetAllowed: () => isTargetAllowed,
6949
7041
  rollbackInsight: () => rollbackInsight
6950
7042
  });
6951
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync3, existsSync as existsSync11, mkdirSync as mkdirSync3 } from "fs";
7043
+ import { readFileSync as readFileSync7, writeFileSync as writeFileSync3, existsSync as existsSync12, mkdirSync as mkdirSync3 } from "fs";
6952
7044
  import { join as join11, dirname as dirname2 } from "path";
6953
7045
  function isTargetAllowed(relativePath) {
6954
7046
  if (relativePath.includes("..")) return false;
@@ -7016,7 +7108,7 @@ async function applyInsight(insightId) {
7016
7108
  }
7017
7109
  const absolutePath = join11(CC_CLAW_HOME, insight.targetFile);
7018
7110
  if (insight.proposedAction === "append" && insight.targetFile === "identity/SOUL.md") {
7019
- if (existsSync11(absolutePath)) {
7111
+ if (existsSync12(absolutePath)) {
7020
7112
  const currentContent = readFileSync7(absolutePath, "utf-8");
7021
7113
  const lineCount = currentContent.split("\n").length;
7022
7114
  if (lineCount >= SOUL_LINE_CAP) {
@@ -7036,7 +7128,7 @@ async function applyInsight(insightId) {
7036
7128
  };
7037
7129
  }
7038
7130
  let original = "";
7039
- if (existsSync11(absolutePath)) {
7131
+ if (existsSync12(absolutePath)) {
7040
7132
  original = readFileSync7(absolutePath, "utf-8");
7041
7133
  } else if (insight.proposedAction !== "create") {
7042
7134
  return { success: false, message: `Target file "${insight.targetFile}" does not exist` };
@@ -7045,7 +7137,7 @@ async function applyInsight(insightId) {
7045
7137
  const backupPath = absolutePath + `.bak.${timestamp}`;
7046
7138
  try {
7047
7139
  const parentDir = dirname2(absolutePath);
7048
- if (!existsSync11(parentDir)) {
7140
+ if (!existsSync12(parentDir)) {
7049
7141
  mkdirSync3(parentDir, { recursive: true });
7050
7142
  }
7051
7143
  if (original) {
@@ -7151,7 +7243,7 @@ function computeLineDrift(baseline, absolutePath) {
7151
7243
  if (!baseline) return 0;
7152
7244
  let current = "";
7153
7245
  try {
7154
- if (existsSync11(absolutePath)) {
7246
+ if (existsSync12(absolutePath)) {
7155
7247
  current = readFileSync7(absolutePath, "utf-8");
7156
7248
  }
7157
7249
  } catch {
@@ -7203,7 +7295,7 @@ __export(server_exports, {
7203
7295
  });
7204
7296
  import { createServer } from "http";
7205
7297
  import { randomBytes } from "crypto";
7206
- import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as existsSync12 } from "fs";
7298
+ import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as existsSync13 } from "fs";
7207
7299
  function createSubAgentToken(agentId) {
7208
7300
  const token = `sub:${agentId.slice(0, 8)}:${randomBytes(16).toString("hex")}`;
7209
7301
  subAgentTokens.set(token, agentId);
@@ -7374,7 +7466,7 @@ function startDashboard() {
7374
7466
  if (url.pathname === "/api/orchestrator/spawn" && req.method === "POST") {
7375
7467
  try {
7376
7468
  const body = JSON.parse(await readBody(req));
7377
- if (body.cwd && !existsSync12(body.cwd)) {
7469
+ if (body.cwd && !existsSync13(body.cwd)) {
7378
7470
  return jsonResponse(res, { error: `Directory not found: ${body.cwd}` }, 400);
7379
7471
  }
7380
7472
  if (!body.permMode || body.permMode === "inherit") {
@@ -9674,18 +9766,18 @@ var init_wrap_backend = __esm({
9674
9766
  });
9675
9767
 
9676
9768
  // src/agents/runners/config-loader.ts
9677
- import { readFileSync as readFileSync8, readdirSync as readdirSync5, existsSync as existsSync13, mkdirSync as mkdirSync5, watchFile, unwatchFile } from "fs";
9769
+ import { readFileSync as readFileSync8, readdirSync as readdirSync6, existsSync as existsSync14, mkdirSync as mkdirSync5, watchFile, unwatchFile } from "fs";
9678
9770
  import { join as join13 } from "path";
9679
9771
  import { execFileSync } from "child_process";
9680
9772
  function resolveExecutable(config2) {
9681
- if (existsSync13(config2.executable)) return config2.executable;
9773
+ if (existsSync14(config2.executable)) return config2.executable;
9682
9774
  try {
9683
9775
  return execFileSync("which", [config2.executable], { encoding: "utf-8" }).trim();
9684
9776
  } catch {
9685
9777
  }
9686
9778
  for (const fallback of config2.executableFallbacks ?? []) {
9687
9779
  const resolved = fallback.replace(/^~/, process.env.HOME ?? "");
9688
- if (existsSync13(resolved)) return resolved;
9780
+ if (existsSync14(resolved)) return resolved;
9689
9781
  }
9690
9782
  return config2.executable;
9691
9783
  }
@@ -9824,11 +9916,11 @@ function loadRunnerConfig(filePath) {
9824
9916
  }
9825
9917
  }
9826
9918
  function loadAllRunnerConfigs() {
9827
- if (!existsSync13(RUNNERS_PATH)) {
9919
+ if (!existsSync14(RUNNERS_PATH)) {
9828
9920
  mkdirSync5(RUNNERS_PATH, { recursive: true });
9829
9921
  return [];
9830
9922
  }
9831
- const files = readdirSync5(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
9923
+ const files = readdirSync6(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
9832
9924
  const configs = [];
9833
9925
  for (const file of files) {
9834
9926
  const config2 = loadRunnerConfig(join13(RUNNERS_PATH, file));
@@ -9852,14 +9944,14 @@ function registerConfigRunners() {
9852
9944
  return count;
9853
9945
  }
9854
9946
  function watchRunnerConfigs(onChange) {
9855
- if (!existsSync13(RUNNERS_PATH)) return;
9947
+ if (!existsSync14(RUNNERS_PATH)) return;
9856
9948
  for (const prev of watchedFiles) {
9857
- if (!existsSync13(prev)) {
9949
+ if (!existsSync14(prev)) {
9858
9950
  unwatchFile(prev);
9859
9951
  watchedFiles.delete(prev);
9860
9952
  }
9861
9953
  }
9862
- const files = readdirSync5(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
9954
+ const files = readdirSync6(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
9863
9955
  for (const file of files) {
9864
9956
  const fullPath = join13(RUNNERS_PATH, file);
9865
9957
  if (watchedFiles.has(fullPath)) continue;
@@ -10568,7 +10660,7 @@ __export(discover_exports, {
10568
10660
  });
10569
10661
  import { readdir, readFile as readFile2 } from "fs/promises";
10570
10662
  import { createHash } from "crypto";
10571
- import { homedir as homedir4 } from "os";
10663
+ import { homedir as homedir5 } from "os";
10572
10664
  import { join as join14 } from "path";
10573
10665
  function invalidateSkillCache() {
10574
10666
  cachedSkills = null;
@@ -10587,7 +10679,7 @@ async function discoverAllSkills() {
10587
10679
  const rawSkills = [];
10588
10680
  rawSkills.push(...await scanSkillDir(SKILLS_PATH, "cc-claw"));
10589
10681
  for (const backendId of getAllBackendIds()) {
10590
- const dirs = BACKEND_SKILL_DIRS[backendId] ?? [join14(homedir4(), `.${backendId}`, "skills")];
10682
+ const dirs = BACKEND_SKILL_DIRS[backendId] ?? [join14(homedir5(), `.${backendId}`, "skills")];
10591
10683
  for (const dir of dirs) {
10592
10684
  rawSkills.push(...await scanSkillDir(dir, backendId));
10593
10685
  }
@@ -10718,15 +10810,15 @@ var init_discover = __esm({
10718
10810
  init_backends();
10719
10811
  SKILL_FILE_CANDIDATES = ["SKILL.md", "skill.md"];
10720
10812
  BACKEND_SKILL_DIRS = {
10721
- claude: [join14(homedir4(), ".claude", "skills")],
10722
- gemini: [join14(homedir4(), ".gemini", "skills")],
10813
+ claude: [join14(homedir5(), ".claude", "skills")],
10814
+ gemini: [join14(homedir5(), ".gemini", "skills")],
10723
10815
  codex: [
10724
- join14(homedir4(), ".agents", "skills"),
10725
- join14(homedir4(), ".codex", "skills")
10816
+ join14(homedir5(), ".agents", "skills"),
10817
+ join14(homedir5(), ".codex", "skills")
10726
10818
  ],
10727
10819
  cursor: [
10728
- join14(homedir4(), ".cursor", "skills"),
10729
- join14(homedir4(), ".cursor", "skills-cursor")
10820
+ join14(homedir5(), ".cursor", "skills"),
10821
+ join14(homedir5(), ".cursor", "skills-cursor")
10730
10822
  ]
10731
10823
  };
10732
10824
  CACHE_TTL_MS2 = 3e5;
@@ -10742,7 +10834,7 @@ __export(install_exports, {
10742
10834
  installSkillFromGitHub: () => installSkillFromGitHub
10743
10835
  });
10744
10836
  import { mkdir, readdir as readdir2, readFile as readFile3, cp } from "fs/promises";
10745
- import { existsSync as existsSync14 } from "fs";
10837
+ import { existsSync as existsSync15 } from "fs";
10746
10838
  import { join as join15, basename } from "path";
10747
10839
  import { execSync as execSync6 } from "child_process";
10748
10840
  async function installSkillFromGitHub(urlOrShorthand) {
@@ -10761,7 +10853,7 @@ async function installSkillFromGitHub(urlOrShorthand) {
10761
10853
  stdio: "pipe",
10762
10854
  timeout: 3e4
10763
10855
  });
10764
- if (!existsSync14(join15(tmpDir, ".git"))) {
10856
+ if (!existsSync15(join15(tmpDir, ".git"))) {
10765
10857
  return { success: false, error: "Git clone failed: no .git directory produced" };
10766
10858
  }
10767
10859
  const searchRoot = subPath ? join15(tmpDir, subPath) : tmpDir;
@@ -10771,7 +10863,7 @@ async function installSkillFromGitHub(urlOrShorthand) {
10771
10863
  }
10772
10864
  const skillFolderName = basename(skillDir);
10773
10865
  const destDir = join15(SKILLS_PATH, skillFolderName);
10774
- if (existsSync14(destDir)) {
10866
+ if (existsSync15(destDir)) {
10775
10867
  log(`[skill-install] Overwriting existing skill at ${destDir}`);
10776
10868
  }
10777
10869
  await mkdir(destDir, { recursive: true });
@@ -10818,14 +10910,14 @@ function parseGitHubUrl(input) {
10818
10910
  async function findSkillDir(root) {
10819
10911
  const candidates = ["SKILL.md", "skill.md"];
10820
10912
  for (const c of candidates) {
10821
- if (existsSync14(join15(root, c))) return root;
10913
+ if (existsSync15(join15(root, c))) return root;
10822
10914
  }
10823
10915
  try {
10824
10916
  const entries = await readdir2(root, { withFileTypes: true });
10825
10917
  for (const entry of entries) {
10826
10918
  if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
10827
10919
  for (const c of candidates) {
10828
- if (existsSync14(join15(root, entry.name, c))) {
10920
+ if (existsSync15(join15(root, entry.name, c))) {
10829
10921
  return join15(root, entry.name);
10830
10922
  }
10831
10923
  }
@@ -10845,7 +10937,7 @@ async function findSkillDir(root) {
10845
10937
  for (const sub of subEntries) {
10846
10938
  if (!sub.isDirectory() || sub.name.startsWith(".")) continue;
10847
10939
  for (const c of candidates) {
10848
- if (existsSync14(join15(root, entry.name, sub.name, c))) {
10940
+ if (existsSync15(join15(root, entry.name, sub.name, c))) {
10849
10941
  return join15(root, entry.name, sub.name);
10850
10942
  }
10851
10943
  }
@@ -10864,7 +10956,7 @@ var init_install = __esm({
10864
10956
  });
10865
10957
 
10866
10958
  // src/bootstrap/profile.ts
10867
- import { readFileSync as readFileSync9, writeFileSync as writeFileSync5, existsSync as existsSync15 } from "fs";
10959
+ import { readFileSync as readFileSync9, writeFileSync as writeFileSync5, existsSync as existsSync16 } from "fs";
10868
10960
  import { join as join16 } from "path";
10869
10961
  function hasActiveProfile(chatId) {
10870
10962
  return activeProfiles.has(chatId);
@@ -10994,7 +11086,7 @@ function extractUserUpdates(text) {
10994
11086
  return { cleanText, updates };
10995
11087
  }
10996
11088
  function appendToUserProfile(key, value) {
10997
- if (!existsSync15(USER_PATH2)) return;
11089
+ if (!existsSync16(USER_PATH2)) return;
10998
11090
  const content = readFileSync9(USER_PATH2, "utf-8");
10999
11091
  const line = `- **${key}**: ${value}`;
11000
11092
  if (content.includes(line)) return;
@@ -11016,7 +11108,7 @@ var init_profile = __esm({
11016
11108
  });
11017
11109
 
11018
11110
  // src/bootstrap/heartbeat.ts
11019
- import { readFileSync as readFileSync10, existsSync as existsSync16 } from "fs";
11111
+ import { readFileSync as readFileSync10, existsSync as existsSync17 } from "fs";
11020
11112
  import { join as join17 } from "path";
11021
11113
  function initHeartbeat(channelReg) {
11022
11114
  registry2 = channelReg;
@@ -11155,7 +11247,7 @@ ${healthLines.join("\n")}`);
11155
11247
  sections.push(`[Active watches]
11156
11248
  ${watchLines.join("\n")}`);
11157
11249
  }
11158
- if (existsSync16(HEARTBEAT_MD_PATH)) {
11250
+ if (existsSync17(HEARTBEAT_MD_PATH)) {
11159
11251
  try {
11160
11252
  const custom = readFileSync10(HEARTBEAT_MD_PATH, "utf-8").trim();
11161
11253
  if (custom) {
@@ -11386,7 +11478,7 @@ var init_classify = __esm({
11386
11478
  });
11387
11479
 
11388
11480
  // src/media/image-gen.ts
11389
- import { mkdirSync as mkdirSync6, existsSync as existsSync17 } from "fs";
11481
+ import { mkdirSync as mkdirSync6, existsSync as existsSync18 } from "fs";
11390
11482
  import { writeFile as writeFile2 } from "fs/promises";
11391
11483
  import { join as join18 } from "path";
11392
11484
  async function generateImage(prompt) {
@@ -11435,7 +11527,7 @@ async function generateImage(prompt) {
11435
11527
  if (!imageData) {
11436
11528
  throw new Error(textResponse ?? "Gemini did not generate an image. The prompt may have been filtered.");
11437
11529
  }
11438
- if (!existsSync17(IMAGE_OUTPUT_DIR)) {
11530
+ if (!existsSync18(IMAGE_OUTPUT_DIR)) {
11439
11531
  mkdirSync6(IMAGE_OUTPUT_DIR, { recursive: true });
11440
11532
  }
11441
11533
  const ext = mimeType.includes("jpeg") || mimeType.includes("jpg") ? "jpg" : "png";
@@ -12166,11 +12258,31 @@ async function finalizeJob(chatId, channel) {
12166
12258
  const pending = pendingJobs.get(chatId);
12167
12259
  if (!pending) return;
12168
12260
  const editJobId = pending._editJobId;
12261
+ let title = pending.title ?? null;
12262
+ if (!title && !editJobId) {
12263
+ try {
12264
+ const { askAgent: askAgent2 } = await Promise.resolve().then(() => (init_agent(), agent_exports));
12265
+ const resp = await askAgent2(chatId, `Summarize this scheduled task in 5-8 words for a job list title. Output ONLY the title, nothing else:
12266
+
12267
+ ${pending.task}`, {
12268
+ bootstrapTier: "chat",
12269
+ maxTurns: 1,
12270
+ timeoutMs: 15e3
12271
+ });
12272
+ const generated = resp.text?.trim().replace(/^["']|["']$/g, "");
12273
+ if (generated && generated.length <= 60) title = generated;
12274
+ } catch {
12275
+ }
12276
+ if (!title) {
12277
+ title = pending.task.length > 60 ? pending.task.slice(0, 57) + "\u2026" : pending.task;
12278
+ }
12279
+ }
12169
12280
  const jobParams = {
12170
12281
  scheduleType: pending.scheduleType ?? "cron",
12171
12282
  cron: pending.cron,
12172
12283
  atTime: pending.at ?? null,
12173
12284
  everyMs: pending.everyMs ?? null,
12285
+ title,
12174
12286
  description: pending.task,
12175
12287
  backend: pending.backend ?? null,
12176
12288
  model: pending.model ?? null,
@@ -12194,6 +12306,7 @@ async function finalizeJob(chatId, channel) {
12194
12306
  chatId,
12195
12307
  `Job #${editJobId} updated!
12196
12308
 
12309
+ Title: ${jobParams.title ?? "\u2014"}
12197
12310
  Task: ${jobParams.description}
12198
12311
  Schedule: ${jobParams.cron ?? "N/A"}
12199
12312
  Timezone: ${jobParams.timezone}`,
@@ -12208,6 +12321,7 @@ Timezone: ${jobParams.timezone}`,
12208
12321
  chatId,
12209
12322
  `Job #${job.id} created!
12210
12323
 
12324
+ Title: ${job.title ?? "\u2014"}
12211
12325
  Task: ${job.description}
12212
12326
  Schedule: ${job.cron ?? "N/A"}
12213
12327
  Timezone: ${job.timezone}
@@ -12808,8 +12922,10 @@ var init_propose = __esm({
12808
12922
 
12809
12923
  // src/router.ts
12810
12924
  import { readFile as readFile5, writeFile as writeFile3, unlink as unlink2, mkdir as mkdir2, readdir as readdir3, stat } from "fs/promises";
12925
+ import { existsSync as existsSync19 } from "fs";
12811
12926
  import { randomUUID as randomUUID3 } from "crypto";
12812
12927
  import { resolve as resolvePath, join as join19 } from "path";
12928
+ import { homedir as homedir6 } from "os";
12813
12929
  function parseMcpListOutput(output2) {
12814
12930
  const results = [];
12815
12931
  const seen = /* @__PURE__ */ new Set();
@@ -14527,8 +14643,8 @@ ${agentLines.join("\n")}`, buttons);
14527
14643
  lines.push(` \u2705 <b>cc-claw</b> <i>Agent orchestrator (spawn, tasks, inbox)</i>`);
14528
14644
  }
14529
14645
  const { execFile: execFile5 } = await import("child_process");
14530
- const { homedir: homedir7 } = await import("os");
14531
- const discoveryCwd = homedir7();
14646
+ const { homedir: homedir9 } = await import("os");
14647
+ const discoveryCwd = homedir9();
14532
14648
  const runnerResults = await Promise.allSettled(
14533
14649
  getAllRunners().map((runner) => {
14534
14650
  const listCmd = runner.getMcpListCommand();
@@ -14911,26 +15027,6 @@ async function handleText(msg, channel) {
14911
15027
  await handleWizardText(chatId, text, channel);
14912
15028
  return;
14913
15029
  }
14914
- const discussingInsightId = activeProposalDiscussion.get(chatId);
14915
- if (discussingInsightId !== void 0) {
14916
- if (text.toLowerCase() === "done") {
14917
- activeProposalDiscussion.delete(chatId);
14918
- const { getInsightById: getInsightById2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
14919
- const { formatProposalCard: formatProposalCard2, buildProposalKeyboard: buildProposalKeyboard2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
14920
- const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
14921
- const insight = getInsightById2(getDb2(), discussingInsightId);
14922
- if (insight && insight.status === "pending") {
14923
- const card = formatProposalCard2(insight);
14924
- const kb = buildProposalKeyboard2(insight.id, insight.category);
14925
- await channel.sendKeyboard(chatId, "Discussion complete. Updated proposal:\n\n" + card, kb);
14926
- } else {
14927
- await channel.sendText(chatId, "Discussion ended.", { parseMode: "plain" });
14928
- }
14929
- return;
14930
- }
14931
- await handleProposalDiscussion(chatId, discussingInsightId, text, channel);
14932
- return;
14933
- }
14934
15030
  const rememberMatch = text.match(/^remember\s+(?:that\s+)?(.+)/i);
14935
15031
  if (rememberMatch) {
14936
15032
  const content = rememberMatch[1];
@@ -15158,65 +15254,6 @@ After installing, restart the service: cc-claw service restart`;
15158
15254
  }
15159
15255
  return `Error: ${msg}`;
15160
15256
  }
15161
- async function handleProposalDiscussion(chatId, insightId, userQuestion, channel) {
15162
- const { getInsightById: getInsightById2, updateInsightProposal: updateInsightProposal2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
15163
- const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
15164
- const insight = getInsightById2(getDb2(), insightId);
15165
- if (!insight) {
15166
- activeProposalDiscussion.delete(chatId);
15167
- await channel.sendText(chatId, "Proposal not found. Discussion ended.", { parseMode: "plain" });
15168
- return;
15169
- }
15170
- const prompt = [
15171
- `You are reviewing a self-learning proposal with the user. They want to discuss it before deciding whether to apply, modify, or reject it.`,
15172
- ``,
15173
- `Current proposal:`,
15174
- `- Category: ${insight.category}`,
15175
- `- Insight: ${insight.insight}`,
15176
- `- Why: ${insight.why ?? "not specified"}`,
15177
- `- Target file: ${insight.targetFile ?? "not specified"}`,
15178
- `- Proposed action: ${insight.proposedAction ?? "not specified"}`,
15179
- `- Proposed diff: ${insight.proposedDiff ?? "none"}`,
15180
- `- Confidence: ${Math.round(insight.confidence * 100)}%`,
15181
- ``,
15182
- `The user asks: "${userQuestion}"`,
15183
- ``,
15184
- `Answer their question honestly. If they suggest retargeting to a different file or modifying the proposal, agree if it makes sense and output one of these markers:`,
15185
- `- [RETARGET:filepath] \u2014 to change the target file (e.g., [RETARGET:skills/newsroom/SKILL.md])`,
15186
- `- [REVISE_DIFF:new diff text] \u2014 to update the proposed change`,
15187
- `- [REVISE_ACTION:action] \u2014 to change the action type (append/replace/etc.)`,
15188
- ``,
15189
- `Only output markers when the user explicitly asks for a change. Otherwise just discuss.`,
15190
- `Keep responses concise \u2014 this is a quick review conversation, not an essay.`
15191
- ].join("\n");
15192
- try {
15193
- await channel.sendTyping?.(chatId);
15194
- const response = await askAgent(chatId, prompt, {
15195
- bootstrapTier: "chat",
15196
- maxTurns: 1,
15197
- timeoutMs: 6e4
15198
- });
15199
- const responseText = response.text ?? "";
15200
- const retargetMatch = responseText.match(/\[RETARGET:([^\]]+)\]/);
15201
- const reviseDiffMatch = responseText.match(/\[REVISE_DIFF:([^\]]+)\]/);
15202
- const reviseActionMatch = responseText.match(/\[REVISE_ACTION:([^\]]+)\]/);
15203
- if (retargetMatch || reviseDiffMatch || reviseActionMatch) {
15204
- const newTarget = retargetMatch?.[1]?.trim() ?? insight.targetFile ?? "";
15205
- const newDiff = reviseDiffMatch?.[1]?.trim() ?? insight.proposedDiff ?? null;
15206
- const newAction = reviseActionMatch?.[1]?.trim() ?? insight.proposedAction ?? null;
15207
- updateInsightProposal2(getDb2(), insightId, newTarget, newDiff, newAction);
15208
- }
15209
- const cleanText = responseText.replace(/\[RETARGET:[^\]]+\]/g, "").replace(/\[REVISE_DIFF:[^\]]+\]/g, "").replace(/\[REVISE_ACTION:[^\]]+\]/g, "").trim();
15210
- if (cleanText) {
15211
- await channel.sendText(chatId, cleanText);
15212
- }
15213
- await channel.sendKeyboard(chatId, "Continue discussing, or type 'done' to finish.", [
15214
- [{ label: "Done \u2014 show updated proposal", data: `evolve:discuss-done:${insightId}` }]
15215
- ]);
15216
- } catch (err) {
15217
- await channel.sendText(chatId, `Discussion error: ${err.message}`, { parseMode: "plain" });
15218
- }
15219
- }
15220
15257
  async function handleSideQuest(parentChatId, msg, channel) {
15221
15258
  const sqId = `sq:${parentChatId}:${randomUUID3()}`;
15222
15259
  const active = activeSideQuests.get(parentChatId) ?? /* @__PURE__ */ new Set();
@@ -15791,7 +15828,7 @@ async function sendJobsBoard(chatId, channel, page) {
15791
15828
  pageSize: 10,
15792
15829
  callbackPrefix: "job:",
15793
15830
  renderItem: (j) => ({
15794
- label: `#${j.id}: ${j.description.slice(0, 30)}`,
15831
+ label: `#${j.id}: ${(j.title ?? j.description).slice(0, 30)}`,
15795
15832
  data: `job:view:${j.id}`,
15796
15833
  style: "primary"
15797
15834
  }),
@@ -15801,7 +15838,7 @@ async function sendJobsBoard(chatId, channel, page) {
15801
15838
  for (const j of pageJobs) {
15802
15839
  const emoji = getJobStatusEmoji(j);
15803
15840
  const schedule2 = getJobScheduleText(j);
15804
- const desc = j.description.length > 24 ? j.description.slice(0, 24) + "\u2026" : j.description;
15841
+ const desc = j.title ?? (j.description.length > 24 ? j.description.slice(0, 24) + "\u2026" : j.description);
15805
15842
  lines.push(`${emoji} ${desc} \xB7 ${schedule2}`);
15806
15843
  }
15807
15844
  lines.push("");
@@ -15836,8 +15873,9 @@ async function sendJobDetail(chatId, jobId, channel) {
15836
15873
  const runs = getJobRuns(jobId, 1);
15837
15874
  const lastRunStatus = runs.length > 0 ? runs[0].status : null;
15838
15875
  const lines = [
15839
- `Job #${job.id}: ${job.description}`,
15876
+ `Job #${job.id}: ${job.title ?? job.description}`,
15840
15877
  buildSectionHeader("", 22),
15878
+ ...job.title ? [`Task: ${job.description.length > 80 ? job.description.slice(0, 77) + "\u2026" : job.description}`] : [],
15841
15879
  `Runs: ${schedule2}${tz}`,
15842
15880
  `Backend: ${backend2} | Model: ${model2}`,
15843
15881
  `Last run: ${lastRun}${lastRunStatus ? ` (${lastRunStatus})` : ""}`,
@@ -15944,7 +15982,7 @@ async function sendJobPicker(chatId, channel, action) {
15944
15982
  const actionLabel = action.charAt(0).toUpperCase() + action.slice(1);
15945
15983
  const style = action === "run" ? "success" : action === "cancel" ? "danger" : void 0;
15946
15984
  const buttons = jobs.map((j) => [{
15947
- label: `#${j.id}: ${j.description.slice(0, 30)}`,
15985
+ label: `#${j.id}: ${(j.title ?? j.description).slice(0, 30)}`,
15948
15986
  data: action === "cancel" ? `job:cancel:${j.id}` : `job:${action}:${j.id}`,
15949
15987
  ...style ? { style } : {}
15950
15988
  }]);
@@ -16602,24 +16640,159 @@ Result: ${task.result.slice(0, 500)}` : ""
16602
16640
  }
16603
16641
  case "discuss": {
16604
16642
  const insId = parseInt(idStr, 10);
16605
- activeProposalDiscussion.set(chatId, insId);
16606
- await channel.sendKeyboard(chatId, `Discussing proposal #${insId}. Send your questions \u2014 type "done" when finished.`, [
16607
- [{ label: "Done", data: `evolve:discuss-done:${insId}` }]
16643
+ await channel.sendKeyboard(chatId, [
16644
+ "What would you like to do with this proposal?",
16645
+ "",
16646
+ "Why this file? \u2014 ask the AI to explain its reasoning",
16647
+ "Retarget \u2014 move this change to a different file (e.g., a skill instead of SOUL.md)",
16648
+ "Revise \u2014 ask the AI to rewrite the proposed change"
16649
+ ].join("\n"), [
16650
+ [
16651
+ { label: "Why this file?", data: `evolve:discuss-why:${insId}`, style: "primary" },
16652
+ { label: "Retarget", data: `evolve:discuss-retarget:${insId}` }
16653
+ ],
16654
+ [
16655
+ { label: "Revise the change", data: `evolve:discuss-revise:${insId}` },
16656
+ { label: "Back", data: `evolve:discuss-back:${insId}` }
16657
+ ]
16608
16658
  ]);
16609
16659
  break;
16610
16660
  }
16611
- case "discuss-done": {
16612
- activeProposalDiscussion.delete(chatId);
16613
- const { getInsightById: getIns } = await Promise.resolve().then(() => (init_store4(), store_exports4));
16614
- const { formatProposalCard: fmtCard, buildProposalKeyboard: buildKb } = await Promise.resolve().then(() => (init_propose(), propose_exports));
16615
- const { getDb: getDatabase } = await Promise.resolve().then(() => (init_store5(), store_exports5));
16616
- const ins = getIns(getDatabase(), parseInt(idStr, 10));
16617
- if (ins && ins.status === "pending") {
16618
- const card = fmtCard(ins);
16619
- const kb = buildKb(ins.id, ins.category);
16620
- await channel.sendKeyboard(chatId, "Updated proposal:\n\n" + card, kb);
16621
- } else {
16622
- await channel.sendText(chatId, "Discussion ended.", { parseMode: "plain" });
16661
+ case "discuss-why": {
16662
+ const { getInsightById: gwIns } = await Promise.resolve().then(() => (init_store4(), store_exports4));
16663
+ const { getDb: gwDb } = await Promise.resolve().then(() => (init_store5(), store_exports5));
16664
+ const gwInsight = gwIns(gwDb(), parseInt(idStr, 10));
16665
+ if (!gwInsight) {
16666
+ await channel.sendText(chatId, "Proposal not found.", { parseMode: "plain" });
16667
+ break;
16668
+ }
16669
+ await channel.sendTyping?.(chatId);
16670
+ const whyPrompt = [
16671
+ `Explain in 2-3 sentences why you chose "${gwInsight.targetFile}" as the target file for this insight:`,
16672
+ `"${gwInsight.insight}"`,
16673
+ `Consider what other files could work (skills, context files, USER.md) and explain your reasoning.`
16674
+ ].join("\n");
16675
+ try {
16676
+ const whyResp = await askAgent(chatId, whyPrompt, { bootstrapTier: "chat", maxTurns: 1, timeoutMs: 6e4 });
16677
+ await channel.sendText(chatId, whyResp.text ?? "No response.");
16678
+ } catch (e) {
16679
+ await channel.sendText(chatId, `Error: ${e.message}`, { parseMode: "plain" });
16680
+ }
16681
+ await channel.sendKeyboard(chatId, "What next?", [
16682
+ [
16683
+ { label: "OK, Apply", data: `evolve:apply:${idStr}`, style: "success" },
16684
+ { label: "Retarget instead", data: `evolve:discuss-retarget:${idStr}` }
16685
+ ],
16686
+ [
16687
+ { label: "Reject", data: `evolve:reject:${idStr}`, style: "danger" },
16688
+ { label: "Back", data: `evolve:discuss-back:${idStr}` }
16689
+ ]
16690
+ ]);
16691
+ break;
16692
+ }
16693
+ case "discuss-retarget": {
16694
+ const { getInsightById: rtIns } = await Promise.resolve().then(() => (init_store4(), store_exports4));
16695
+ const { getDb: rtDb } = await Promise.resolve().then(() => (init_store5(), store_exports5));
16696
+ const rtInsight = rtIns(rtDb(), parseInt(idStr, 10));
16697
+ if (!rtInsight) {
16698
+ await channel.sendText(chatId, "Proposal not found.", { parseMode: "plain" });
16699
+ break;
16700
+ }
16701
+ const currentTarget = rtInsight.targetFile ?? "unknown";
16702
+ const targets = [
16703
+ { label: "SOUL.md", path: "identity/SOUL.md" },
16704
+ { label: "USER.md", path: "identity/USER.md" }
16705
+ ];
16706
+ const skillDirs = [
16707
+ join19(homedir6(), ".cc-claw", "workspace", "skills")
16708
+ ];
16709
+ try {
16710
+ const { readdirSync: readdirSync7, statSync: statSync9 } = await import("fs");
16711
+ for (const dir of skillDirs) {
16712
+ if (!existsSync19(dir)) continue;
16713
+ for (const entry of readdirSync7(dir)) {
16714
+ if (statSync9(join19(dir, entry)).isDirectory()) {
16715
+ targets.push({ label: `skills/${entry}`, path: `workspace/skills/${entry}/SKILL.md` });
16716
+ }
16717
+ }
16718
+ }
16719
+ } catch {
16720
+ }
16721
+ const rows = targets.filter((t) => t.path !== currentTarget).map((t) => [{ label: t.label, data: `evolve:discuss-retarget-to:${idStr}:${t.path}` }]);
16722
+ rows.push([{ label: "Cancel", data: `evolve:discuss-back:${idStr}` }]);
16723
+ await channel.sendKeyboard(chatId, `Current target: ${currentTarget}
16724
+
16725
+ Pick a different file for this change. Identity files (SOUL/USER) shape personality; skills teach specific workflows.`, rows);
16726
+ break;
16727
+ }
16728
+ case "discuss-retarget-to": {
16729
+ const retargetParts = data.split(":");
16730
+ const rtId = parseInt(retargetParts[2], 10);
16731
+ const newPath = retargetParts.slice(3).join(":");
16732
+ const { getInsightById: rt2Ins, updateInsightProposal: rt2Update } = await Promise.resolve().then(() => (init_store4(), store_exports4));
16733
+ const { formatProposalCard: rt2Card, buildProposalKeyboard: rt2Kb } = await Promise.resolve().then(() => (init_propose(), propose_exports));
16734
+ const { getDb: rt2Db } = await Promise.resolve().then(() => (init_store5(), store_exports5));
16735
+ const rt2Insight = rt2Ins(rt2Db(), rtId);
16736
+ if (!rt2Insight) {
16737
+ await channel.sendText(chatId, "Proposal not found.", { parseMode: "plain" });
16738
+ break;
16739
+ }
16740
+ rt2Update(rt2Db(), rtId, newPath, rt2Insight.proposedDiff, rt2Insight.proposedAction);
16741
+ const updatedIns = rt2Ins(rt2Db(), rtId);
16742
+ if (updatedIns) {
16743
+ const card = rt2Card(updatedIns);
16744
+ const kb = rt2Kb(updatedIns.id, updatedIns.category);
16745
+ await channel.sendKeyboard(chatId, `Retargeted to ${newPath}. Updated proposal:
16746
+
16747
+ ` + card, kb);
16748
+ }
16749
+ break;
16750
+ }
16751
+ case "discuss-revise": {
16752
+ const { getInsightById: rvIns } = await Promise.resolve().then(() => (init_store4(), store_exports4));
16753
+ const { getDb: rvDb } = await Promise.resolve().then(() => (init_store5(), store_exports5));
16754
+ const rvInsight = rvIns(rvDb(), parseInt(idStr, 10));
16755
+ if (!rvInsight) {
16756
+ await channel.sendText(chatId, "Proposal not found.", { parseMode: "plain" });
16757
+ break;
16758
+ }
16759
+ await channel.sendTyping?.(chatId);
16760
+ const revisePrompt = [
16761
+ `Revise this proposed change to be more specific and actionable:`,
16762
+ `Current insight: "${rvInsight.insight}"`,
16763
+ `Current diff: ${rvInsight.proposedDiff ?? "none"}`,
16764
+ `Target: ${rvInsight.targetFile}`,
16765
+ ``,
16766
+ `Output ONLY the revised diff lines (starting with + for additions, - for removals). No explanation.`
16767
+ ].join("\n");
16768
+ try {
16769
+ const rvResp = await askAgent(chatId, revisePrompt, { bootstrapTier: "chat", maxTurns: 1, timeoutMs: 6e4 });
16770
+ const newDiff = rvResp.text?.trim() ?? rvInsight.proposedDiff;
16771
+ if (newDiff) {
16772
+ const { updateInsightProposal: rvUpdate } = await Promise.resolve().then(() => (init_store4(), store_exports4));
16773
+ rvUpdate(rvDb(), parseInt(idStr, 10), rvInsight.targetFile ?? "", newDiff, rvInsight.proposedAction);
16774
+ }
16775
+ const updatedRv = rvIns(rvDb(), parseInt(idStr, 10));
16776
+ if (updatedRv) {
16777
+ const { formatProposalCard: rvCard, buildProposalKeyboard: rvKb } = await Promise.resolve().then(() => (init_propose(), propose_exports));
16778
+ const card = rvCard(updatedRv);
16779
+ const kb = rvKb(updatedRv.id, updatedRv.category);
16780
+ await channel.sendKeyboard(chatId, "Revised proposal:\n\n" + card, kb);
16781
+ }
16782
+ } catch (e) {
16783
+ await channel.sendText(chatId, `Revision error: ${e.message}`, { parseMode: "plain" });
16784
+ }
16785
+ break;
16786
+ }
16787
+ case "discuss-back": {
16788
+ const { getInsightById: bkIns } = await Promise.resolve().then(() => (init_store4(), store_exports4));
16789
+ const { formatProposalCard: bkCard, buildProposalKeyboard: bkKb } = await Promise.resolve().then(() => (init_propose(), propose_exports));
16790
+ const { getDb: bkDb } = await Promise.resolve().then(() => (init_store5(), store_exports5));
16791
+ const bkInsight = bkIns(bkDb(), parseInt(idStr, 10));
16792
+ if (bkInsight && bkInsight.status === "pending") {
16793
+ const card = bkCard(bkInsight);
16794
+ const kb = bkKb(bkInsight.id, bkInsight.category);
16795
+ await channel.sendKeyboard(chatId, card, kb);
16623
16796
  }
16624
16797
  break;
16625
16798
  }
@@ -16681,13 +16854,13 @@ Result: ${task.result.slice(0, 500)}` : ""
16681
16854
  const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
16682
16855
  const current = getReflectionStatus2(getDb2(), chatId);
16683
16856
  if (current === "frozen") {
16684
- const { readFileSync: readFileSync21, existsSync: existsSync45 } = await import("fs");
16857
+ const { readFileSync: readFileSync21, existsSync: existsSync47 } = await import("fs");
16685
16858
  const { join: join26 } = await import("path");
16686
16859
  const { CC_CLAW_HOME: CC_CLAW_HOME3 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
16687
16860
  const soulPath = join26(CC_CLAW_HOME3, "identity/SOUL.md");
16688
16861
  const userPath = join26(CC_CLAW_HOME3, "identity/USER.md");
16689
- const soul = existsSync45(soulPath) ? readFileSync21(soulPath, "utf-8") : "";
16690
- const user = existsSync45(userPath) ? readFileSync21(userPath, "utf-8") : "";
16862
+ const soul = existsSync47(soulPath) ? readFileSync21(soulPath, "utf-8") : "";
16863
+ const user = existsSync47(userPath) ? readFileSync21(userPath, "utf-8") : "";
16691
16864
  setReflectionStatus2(getDb2(), chatId, "active", soul, user);
16692
16865
  const { logActivity: logActivity2 } = await Promise.resolve().then(() => (init_store3(), store_exports3));
16693
16866
  logActivity2(getDb2(), { chatId, source: "telegram", eventType: "reflection_unfrozen", summary: "Reflection enabled" });
@@ -17281,7 +17454,7 @@ Use /skills <page> to navigate (e.g. /skills 2)` : "";
17281
17454
  const header2 = totalPages > 1 ? `${skills2.length} skills (page ${safePage}/${totalPages}). Select one to invoke:` : `${skills2.length} skills available. Select one to invoke:`;
17282
17455
  await channel.sendKeyboard(chatId, header2, buttons);
17283
17456
  }
17284
- var PERM_MODES, VERBOSE_LEVELS, HELP_CATEGORIES, USAGE_WINDOW_MAP, MEDIA_INCOMING_PATH, TONE_PATTERNS, pendingInterrupts, bypassBusyCheck, activeSideQuests, MAX_SIDE_QUESTS, activeProposalDiscussion, pendingFallbackMessages, dashboardClawWarnings, pendingSummaryUndo, pendingNewchatUndo, CLI_INSTALL_HINTS, BLOCKED_PATH_PATTERNS2, ALLOWED_REACTION_EMOJIS, SKILLS_PER_PAGE;
17457
+ var PERM_MODES, VERBOSE_LEVELS, HELP_CATEGORIES, USAGE_WINDOW_MAP, MEDIA_INCOMING_PATH, TONE_PATTERNS, pendingInterrupts, bypassBusyCheck, activeSideQuests, MAX_SIDE_QUESTS, pendingFallbackMessages, dashboardClawWarnings, pendingSummaryUndo, pendingNewchatUndo, CLI_INSTALL_HINTS, BLOCKED_PATH_PATTERNS2, ALLOWED_REACTION_EMOJIS, SKILLS_PER_PAGE;
17285
17458
  var init_router = __esm({
17286
17459
  "src/router.ts"() {
17287
17460
  "use strict";
@@ -17422,7 +17595,6 @@ var init_router = __esm({
17422
17595
  bypassBusyCheck = /* @__PURE__ */ new Set();
17423
17596
  activeSideQuests = /* @__PURE__ */ new Map();
17424
17597
  MAX_SIDE_QUESTS = 2;
17425
- activeProposalDiscussion = /* @__PURE__ */ new Map();
17426
17598
  pendingFallbackMessages = /* @__PURE__ */ new Map();
17427
17599
  dashboardClawWarnings = /* @__PURE__ */ new Map();
17428
17600
  pendingSummaryUndo = /* @__PURE__ */ new Map();
@@ -17522,19 +17694,19 @@ var init_router = __esm({
17522
17694
  });
17523
17695
 
17524
17696
  // src/skills/bootstrap.ts
17525
- import { existsSync as existsSync18 } from "fs";
17697
+ import { existsSync as existsSync20 } from "fs";
17526
17698
  import { readdir as readdir4, readFile as readFile6, writeFile as writeFile4, copyFile } from "fs/promises";
17527
17699
  import { join as join20, dirname as dirname3 } from "path";
17528
17700
  import { fileURLToPath as fileURLToPath2 } from "url";
17529
17701
  async function copyAgentManifestSkills() {
17530
- if (!existsSync18(PKG_SKILLS)) return;
17702
+ if (!existsSync20(PKG_SKILLS)) return;
17531
17703
  try {
17532
17704
  const entries = await readdir4(PKG_SKILLS, { withFileTypes: true });
17533
17705
  for (const entry of entries) {
17534
17706
  if (!entry.isFile() || !entry.name.startsWith("agent-") || !entry.name.endsWith(".md")) continue;
17535
17707
  const src = join20(PKG_SKILLS, entry.name);
17536
17708
  const dest = join20(SKILLS_PATH, entry.name);
17537
- if (existsSync18(dest)) continue;
17709
+ if (existsSync20(dest)) continue;
17538
17710
  await copyFile(src, dest);
17539
17711
  log(`[skills] Bootstrapped ${entry.name} to ${SKILLS_PATH}`);
17540
17712
  }
@@ -17545,7 +17717,7 @@ async function copyAgentManifestSkills() {
17545
17717
  async function bootstrapSkills() {
17546
17718
  await copyAgentManifestSkills();
17547
17719
  const usmDir = join20(SKILLS_PATH, USM_DIR_NAME);
17548
- if (existsSync18(usmDir)) return;
17720
+ if (existsSync20(usmDir)) return;
17549
17721
  try {
17550
17722
  const entries = await readdir4(SKILLS_PATH);
17551
17723
  const dirs = entries.filter((e) => !e.startsWith("."));
@@ -17568,7 +17740,7 @@ async function bootstrapSkills() {
17568
17740
  }
17569
17741
  async function patchUsmForCcClaw(usmDir) {
17570
17742
  const skillPath = join20(usmDir, "SKILL.md");
17571
- if (!existsSync18(skillPath)) return;
17743
+ if (!existsSync20(skillPath)) return;
17572
17744
  try {
17573
17745
  let content = await readFile6(skillPath, "utf-8");
17574
17746
  let patched = false;
@@ -17828,13 +18000,13 @@ __export(ai_skill_exports, {
17828
18000
  generateAiSkill: () => generateAiSkill,
17829
18001
  installAiSkill: () => installAiSkill
17830
18002
  });
17831
- import { existsSync as existsSync19, writeFileSync as writeFileSync6, mkdirSync as mkdirSync7 } from "fs";
18003
+ import { existsSync as existsSync21, writeFileSync as writeFileSync6, mkdirSync as mkdirSync7 } from "fs";
17832
18004
  import { join as join21 } from "path";
17833
- import { homedir as homedir5 } from "os";
18005
+ import { homedir as homedir7 } from "os";
17834
18006
  function generateAiSkill() {
17835
18007
  const version = VERSION;
17836
18008
  let systemState = "";
17837
- if (existsSync19(DB_PATH)) {
18009
+ if (existsSync21(DB_PATH)) {
17838
18010
  try {
17839
18011
  const { openDatabaseReadOnly: openDatabaseReadOnly2 } = (init_store5(), __toCommonJS(store_exports5));
17840
18012
  const readDb = openDatabaseReadOnly2();
@@ -18250,11 +18422,11 @@ var init_ai_skill = __esm({
18250
18422
  init_paths();
18251
18423
  init_version();
18252
18424
  BACKEND_SKILL_DIRS2 = {
18253
- "cc-claw": [join21(homedir5(), ".cc-claw", "workspace", "skills")],
18254
- claude: [join21(homedir5(), ".claude", "skills")],
18255
- gemini: [join21(homedir5(), ".gemini", "skills")],
18256
- codex: [join21(homedir5(), ".agents", "skills")],
18257
- cursor: [join21(homedir5(), ".cursor", "skills"), join21(homedir5(), ".cursor", "skills-cursor")]
18425
+ "cc-claw": [join21(homedir7(), ".cc-claw", "workspace", "skills")],
18426
+ claude: [join21(homedir7(), ".claude", "skills")],
18427
+ gemini: [join21(homedir7(), ".gemini", "skills")],
18428
+ codex: [join21(homedir7(), ".agents", "skills")],
18429
+ cursor: [join21(homedir7(), ".cursor", "skills"), join21(homedir7(), ".cursor", "skills-cursor")]
18258
18430
  };
18259
18431
  }
18260
18432
  });
@@ -18264,7 +18436,7 @@ var index_exports = {};
18264
18436
  __export(index_exports, {
18265
18437
  main: () => main
18266
18438
  });
18267
- import { mkdirSync as mkdirSync8, existsSync as existsSync20, renameSync, statSync as statSync3, readFileSync as readFileSync12 } from "fs";
18439
+ import { mkdirSync as mkdirSync8, existsSync as existsSync22, renameSync, statSync as statSync4, readFileSync as readFileSync12 } from "fs";
18268
18440
  import { join as join22 } from "path";
18269
18441
  import dotenv from "dotenv";
18270
18442
  function migrateLayout() {
@@ -18278,7 +18450,7 @@ function migrateLayout() {
18278
18450
  [join22(CC_CLAW_HOME, "cc-claw.error.log.1"), join22(LOGS_PATH, "cc-claw.error.log.1")]
18279
18451
  ];
18280
18452
  for (const [from, to] of moves) {
18281
- if (existsSync20(from) && !existsSync20(to)) {
18453
+ if (existsSync22(from) && !existsSync22(to)) {
18282
18454
  try {
18283
18455
  renameSync(from, to);
18284
18456
  } catch {
@@ -18289,7 +18461,7 @@ function migrateLayout() {
18289
18461
  function rotateLogs() {
18290
18462
  for (const file of [LOG_PATH, ERROR_LOG_PATH]) {
18291
18463
  try {
18292
- const { size } = statSync3(file);
18464
+ const { size } = statSync4(file);
18293
18465
  if (size > LOG_MAX_BYTES) {
18294
18466
  const archivePath = `${file}.1`;
18295
18467
  try {
@@ -18485,10 +18657,10 @@ var init_index = __esm({
18485
18657
  init_bootstrap2();
18486
18658
  init_health3();
18487
18659
  for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
18488
- if (!existsSync20(dir)) mkdirSync8(dir, { recursive: true });
18660
+ if (!existsSync22(dir)) mkdirSync8(dir, { recursive: true });
18489
18661
  }
18490
18662
  migrateLayout();
18491
- if (existsSync20(ENV_PATH)) {
18663
+ if (existsSync22(ENV_PATH)) {
18492
18664
  dotenv.config({ path: ENV_PATH });
18493
18665
  } else {
18494
18666
  console.error(`[cc-claw] Config not found at ${ENV_PATH} \u2014 run 'cc-claw setup' first`);
@@ -18509,12 +18681,12 @@ __export(api_client_exports, {
18509
18681
  apiPost: () => apiPost,
18510
18682
  isDaemonRunning: () => isDaemonRunning
18511
18683
  });
18512
- import { readFileSync as readFileSync13, existsSync as existsSync21 } from "fs";
18684
+ import { readFileSync as readFileSync13, existsSync as existsSync23 } from "fs";
18513
18685
  import { request as httpRequest } from "http";
18514
18686
  function getToken() {
18515
18687
  if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
18516
18688
  try {
18517
- if (existsSync21(TOKEN_PATH)) return readFileSync13(TOKEN_PATH, "utf-8").trim();
18689
+ if (existsSync23(TOKEN_PATH)) return readFileSync13(TOKEN_PATH, "utf-8").trim();
18518
18690
  } catch {
18519
18691
  }
18520
18692
  return null;
@@ -18609,9 +18781,9 @@ __export(service_exports, {
18609
18781
  serviceStatus: () => serviceStatus,
18610
18782
  uninstallService: () => uninstallService
18611
18783
  });
18612
- import { existsSync as existsSync22, mkdirSync as mkdirSync9, writeFileSync as writeFileSync7, unlinkSync as unlinkSync4 } from "fs";
18784
+ import { existsSync as existsSync24, mkdirSync as mkdirSync9, writeFileSync as writeFileSync7, unlinkSync as unlinkSync4 } from "fs";
18613
18785
  import { execFileSync as execFileSync2, execSync as execSync7 } from "child_process";
18614
- import { homedir as homedir6, platform } from "os";
18786
+ import { homedir as homedir8, platform } from "os";
18615
18787
  import { join as join23, dirname as dirname4 } from "path";
18616
18788
  function resolveExecutable2(name) {
18617
18789
  try {
@@ -18622,7 +18794,7 @@ function resolveExecutable2(name) {
18622
18794
  }
18623
18795
  function getPathDirs() {
18624
18796
  const nodeBin = dirname4(process.execPath);
18625
- const home = homedir6();
18797
+ const home = homedir8();
18626
18798
  const dirs = /* @__PURE__ */ new Set([
18627
18799
  nodeBin,
18628
18800
  join23(home, ".local", "bin"),
@@ -18640,7 +18812,7 @@ function getPathDirs() {
18640
18812
  function generatePlist() {
18641
18813
  const ccClawBin = resolveExecutable2("cc-claw");
18642
18814
  const pathDirs = getPathDirs();
18643
- const home = homedir6();
18815
+ const home = homedir8();
18644
18816
  return `<?xml version="1.0" encoding="UTF-8"?>
18645
18817
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
18646
18818
  <plist version="1.0">
@@ -18684,9 +18856,9 @@ function generatePlist() {
18684
18856
  }
18685
18857
  function installMacOS() {
18686
18858
  const agentsDir = dirname4(PLIST_PATH);
18687
- if (!existsSync22(agentsDir)) mkdirSync9(agentsDir, { recursive: true });
18688
- if (!existsSync22(LOGS_PATH)) mkdirSync9(LOGS_PATH, { recursive: true });
18689
- if (existsSync22(PLIST_PATH)) {
18859
+ if (!existsSync24(agentsDir)) mkdirSync9(agentsDir, { recursive: true });
18860
+ if (!existsSync24(LOGS_PATH)) mkdirSync9(LOGS_PATH, { recursive: true });
18861
+ if (existsSync24(PLIST_PATH)) {
18690
18862
  try {
18691
18863
  execFileSync2("launchctl", ["unload", PLIST_PATH]);
18692
18864
  } catch {
@@ -18698,7 +18870,7 @@ function installMacOS() {
18698
18870
  console.log(" Service loaded and starting.");
18699
18871
  }
18700
18872
  function uninstallMacOS() {
18701
- if (!existsSync22(PLIST_PATH)) {
18873
+ if (!existsSync24(PLIST_PATH)) {
18702
18874
  console.log(" No service found to uninstall.");
18703
18875
  return;
18704
18876
  }
@@ -18765,15 +18937,15 @@ Restart=on-failure
18765
18937
  RestartSec=10
18766
18938
  WorkingDirectory=${CC_CLAW_HOME}
18767
18939
  Environment=PATH=${pathDirs}
18768
- Environment=HOME=${homedir6()}
18940
+ Environment=HOME=${homedir8()}
18769
18941
 
18770
18942
  [Install]
18771
18943
  WantedBy=default.target
18772
18944
  `;
18773
18945
  }
18774
18946
  function installLinux() {
18775
- if (!existsSync22(SYSTEMD_DIR)) mkdirSync9(SYSTEMD_DIR, { recursive: true });
18776
- if (!existsSync22(LOGS_PATH)) mkdirSync9(LOGS_PATH, { recursive: true });
18947
+ if (!existsSync24(SYSTEMD_DIR)) mkdirSync9(SYSTEMD_DIR, { recursive: true });
18948
+ if (!existsSync24(LOGS_PATH)) mkdirSync9(LOGS_PATH, { recursive: true });
18777
18949
  writeFileSync7(UNIT_PATH, generateUnit());
18778
18950
  console.log(` Installed: ${UNIT_PATH}`);
18779
18951
  execFileSync2("systemctl", ["--user", "daemon-reload"]);
@@ -18782,7 +18954,7 @@ function installLinux() {
18782
18954
  console.log(" Service enabled and started.");
18783
18955
  }
18784
18956
  function uninstallLinux() {
18785
- if (!existsSync22(UNIT_PATH)) {
18957
+ if (!existsSync24(UNIT_PATH)) {
18786
18958
  console.log(" No service found to uninstall.");
18787
18959
  return;
18788
18960
  }
@@ -18807,7 +18979,7 @@ function statusLinux() {
18807
18979
  }
18808
18980
  }
18809
18981
  function installService() {
18810
- if (!existsSync22(join23(CC_CLAW_HOME, ".env"))) {
18982
+ if (!existsSync24(join23(CC_CLAW_HOME, ".env"))) {
18811
18983
  console.error(` Config not found at ${CC_CLAW_HOME}/.env`);
18812
18984
  console.error(" Run 'cc-claw setup' before installing the service.");
18813
18985
  process.exitCode = 1;
@@ -18836,8 +19008,8 @@ var init_service = __esm({
18836
19008
  "use strict";
18837
19009
  init_paths();
18838
19010
  PLIST_LABEL = "com.cc-claw";
18839
- PLIST_PATH = join23(homedir6(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
18840
- SYSTEMD_DIR = join23(homedir6(), ".config", "systemd", "user");
19011
+ PLIST_PATH = join23(homedir8(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
19012
+ SYSTEMD_DIR = join23(homedir8(), ".config", "systemd", "user");
18841
19013
  UNIT_PATH = join23(SYSTEMD_DIR, "cc-claw.service");
18842
19014
  }
18843
19015
  });
@@ -19035,7 +19207,7 @@ var status_exports = {};
19035
19207
  __export(status_exports, {
19036
19208
  statusCommand: () => statusCommand
19037
19209
  });
19038
- import { existsSync as existsSync23, statSync as statSync4 } from "fs";
19210
+ import { existsSync as existsSync25, statSync as statSync5 } from "fs";
19039
19211
  async function statusCommand(globalOpts, localOpts) {
19040
19212
  try {
19041
19213
  const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
@@ -19075,7 +19247,7 @@ async function statusCommand(globalOpts, localOpts) {
19075
19247
  const cwdRow = readDb.prepare("SELECT cwd FROM chat_cwd WHERE chat_id = ?").get(chatId);
19076
19248
  const voiceRow = readDb.prepare("SELECT enabled FROM chat_voice WHERE chat_id = ?").get(chatId);
19077
19249
  const usageRow = readDb.prepare("SELECT * FROM chat_usage WHERE chat_id = ?").get(chatId);
19078
- const dbStat = existsSync23(DB_PATH) ? statSync4(DB_PATH) : null;
19250
+ const dbStat = existsSync25(DB_PATH) ? statSync5(DB_PATH) : null;
19079
19251
  let daemonRunning = false;
19080
19252
  let daemonInfo = {};
19081
19253
  if (localOpts.deep) {
@@ -19166,12 +19338,12 @@ var doctor_exports = {};
19166
19338
  __export(doctor_exports, {
19167
19339
  doctorCommand: () => doctorCommand
19168
19340
  });
19169
- import { existsSync as existsSync24, statSync as statSync5, accessSync, constants } from "fs";
19341
+ import { existsSync as existsSync26, statSync as statSync6, accessSync, constants } from "fs";
19170
19342
  import { execFileSync as execFileSync3 } from "child_process";
19171
19343
  async function doctorCommand(globalOpts, localOpts) {
19172
19344
  const checks = [];
19173
- if (existsSync24(DB_PATH)) {
19174
- const size = statSync5(DB_PATH).size;
19345
+ if (existsSync26(DB_PATH)) {
19346
+ const size = statSync6(DB_PATH).size;
19175
19347
  checks.push({ name: "Database", status: "ok", message: `${DB_PATH} (${(size / 1024).toFixed(0)}KB)` });
19176
19348
  try {
19177
19349
  const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
@@ -19200,7 +19372,7 @@ async function doctorCommand(globalOpts, localOpts) {
19200
19372
  } else {
19201
19373
  checks.push({ name: "Database", status: "error", message: `Not found at ${DB_PATH}`, fix: "cc-claw setup" });
19202
19374
  }
19203
- if (existsSync24(ENV_PATH)) {
19375
+ if (existsSync26(ENV_PATH)) {
19204
19376
  checks.push({ name: "Environment", status: "ok", message: `.env loaded` });
19205
19377
  } else {
19206
19378
  checks.push({ name: "Environment", status: "error", message: "No .env found", fix: "cc-claw setup" });
@@ -19244,7 +19416,7 @@ async function doctorCommand(globalOpts, localOpts) {
19244
19416
  checks.push({ name: "Daemon", status: "warning", message: "could not probe" });
19245
19417
  }
19246
19418
  const tokenPath = `${DATA_PATH}/api-token`;
19247
- if (existsSync24(tokenPath)) {
19419
+ if (existsSync26(tokenPath)) {
19248
19420
  try {
19249
19421
  accessSync(tokenPath, constants.R_OK);
19250
19422
  checks.push({ name: "API token", status: "ok", message: "token file readable" });
@@ -19269,7 +19441,7 @@ async function doctorCommand(globalOpts, localOpts) {
19269
19441
  }
19270
19442
  } catch {
19271
19443
  }
19272
- if (existsSync24(ERROR_LOG_PATH)) {
19444
+ if (existsSync26(ERROR_LOG_PATH)) {
19273
19445
  try {
19274
19446
  const { readFileSync: readFileSync21 } = await import("fs");
19275
19447
  const logContent = readFileSync21(ERROR_LOG_PATH, "utf-8");
@@ -19395,10 +19567,10 @@ var logs_exports = {};
19395
19567
  __export(logs_exports, {
19396
19568
  logsCommand: () => logsCommand
19397
19569
  });
19398
- import { existsSync as existsSync25, readFileSync as readFileSync16, watchFile as watchFile2, unwatchFile as unwatchFile2 } from "fs";
19570
+ import { existsSync as existsSync27, readFileSync as readFileSync16, watchFile as watchFile2, unwatchFile as unwatchFile2 } from "fs";
19399
19571
  async function logsCommand(opts) {
19400
19572
  const logFile = opts.error ? ERROR_LOG_PATH : LOG_PATH;
19401
- if (!existsSync25(logFile)) {
19573
+ if (!existsSync27(logFile)) {
19402
19574
  outputError("LOG_NOT_FOUND", `Log file not found: ${logFile}`);
19403
19575
  process.exit(1);
19404
19576
  }
@@ -19450,11 +19622,11 @@ __export(gemini_exports, {
19450
19622
  geminiReorder: () => geminiReorder,
19451
19623
  geminiRotation: () => geminiRotation
19452
19624
  });
19453
- import { existsSync as existsSync26, mkdirSync as mkdirSync10, writeFileSync as writeFileSync8, readFileSync as readFileSync17, chmodSync } from "fs";
19625
+ import { existsSync as existsSync28, mkdirSync as mkdirSync10, writeFileSync as writeFileSync8, readFileSync as readFileSync17, chmodSync } from "fs";
19454
19626
  import { join as join24 } from "path";
19455
19627
  import { createInterface as createInterface5 } from "readline";
19456
19628
  function requireDb() {
19457
- if (!existsSync26(DB_PATH)) {
19629
+ if (!existsSync28(DB_PATH)) {
19458
19630
  outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
19459
19631
  process.exit(1);
19460
19632
  }
@@ -19480,7 +19652,7 @@ function resolveOAuthEmail(configHome) {
19480
19652
  if (!configHome) return null;
19481
19653
  try {
19482
19654
  const accountsPath = join24(configHome, ".gemini", "google_accounts.json");
19483
- if (!existsSync26(accountsPath)) return null;
19655
+ if (!existsSync28(accountsPath)) return null;
19484
19656
  const accounts = JSON.parse(readFileSync17(accountsPath, "utf-8"));
19485
19657
  return accounts.active || null;
19486
19658
  } catch {
@@ -19564,7 +19736,7 @@ async function geminiAddKey(globalOpts, opts) {
19564
19736
  async function geminiAddAccount(globalOpts, opts) {
19565
19737
  await requireWriteDb();
19566
19738
  const slotsDir = join24(CC_CLAW_HOME, "gemini-slots");
19567
- if (!existsSync26(slotsDir)) mkdirSync10(slotsDir, { recursive: true });
19739
+ if (!existsSync28(slotsDir)) mkdirSync10(slotsDir, { recursive: true });
19568
19740
  const { addGeminiSlot: addGeminiSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
19569
19741
  const tempId = Date.now();
19570
19742
  const slotDir = join24(slotsDir, `slot-${tempId}`);
@@ -19588,7 +19760,7 @@ async function geminiAddAccount(globalOpts, opts) {
19588
19760
  } catch {
19589
19761
  }
19590
19762
  const oauthPath = join24(slotDir, ".gemini", "oauth_creds.json");
19591
- if (!existsSync26(oauthPath)) {
19763
+ if (!existsSync28(oauthPath)) {
19592
19764
  console.log(error2("\n No OAuth credentials found. Sign-in may have failed."));
19593
19765
  console.log(" The slot directory is preserved at: " + slotDir);
19594
19766
  console.log(" Re-run: cc-claw gemini add-account\n");
@@ -19702,12 +19874,12 @@ __export(backend_exports, {
19702
19874
  backendList: () => backendList,
19703
19875
  backendSet: () => backendSet
19704
19876
  });
19705
- import { existsSync as existsSync27 } from "fs";
19877
+ import { existsSync as existsSync29 } from "fs";
19706
19878
  async function backendList(globalOpts) {
19707
19879
  const { getAvailableAdapters: getAvailableAdapters2 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
19708
19880
  const chatId = resolveChatId(globalOpts);
19709
19881
  let activeBackend = null;
19710
- if (existsSync27(DB_PATH)) {
19882
+ if (existsSync29(DB_PATH)) {
19711
19883
  const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
19712
19884
  const readDb = openDatabaseReadOnly2();
19713
19885
  try {
@@ -19738,7 +19910,7 @@ async function backendList(globalOpts) {
19738
19910
  }
19739
19911
  async function backendGet(globalOpts) {
19740
19912
  const chatId = resolveChatId(globalOpts);
19741
- if (!existsSync27(DB_PATH)) {
19913
+ if (!existsSync29(DB_PATH)) {
19742
19914
  outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
19743
19915
  process.exit(1);
19744
19916
  }
@@ -19782,13 +19954,13 @@ __export(model_exports, {
19782
19954
  modelList: () => modelList,
19783
19955
  modelSet: () => modelSet
19784
19956
  });
19785
- import { existsSync as existsSync28 } from "fs";
19957
+ import { existsSync as existsSync30 } from "fs";
19786
19958
  async function modelList(globalOpts) {
19787
19959
  const chatId = resolveChatId(globalOpts);
19788
19960
  const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
19789
19961
  const { getAdapter: getAdapter2, getAllAdapters: getAllAdapters3 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
19790
19962
  let backendId = "claude";
19791
- if (existsSync28(DB_PATH)) {
19963
+ if (existsSync30(DB_PATH)) {
19792
19964
  const readDb = openDatabaseReadOnly2();
19793
19965
  try {
19794
19966
  const row = readDb.prepare("SELECT backend FROM chat_backend WHERE chat_id = ?").get(chatId);
@@ -19821,7 +19993,7 @@ async function modelList(globalOpts) {
19821
19993
  }
19822
19994
  async function modelGet(globalOpts) {
19823
19995
  const chatId = resolveChatId(globalOpts);
19824
- if (!existsSync28(DB_PATH)) {
19996
+ if (!existsSync30(DB_PATH)) {
19825
19997
  outputError("DB_NOT_FOUND", "Database not found.");
19826
19998
  process.exit(1);
19827
19999
  }
@@ -19865,9 +20037,9 @@ __export(memory_exports, {
19865
20037
  memoryList: () => memoryList,
19866
20038
  memorySearch: () => memorySearch
19867
20039
  });
19868
- import { existsSync as existsSync29 } from "fs";
20040
+ import { existsSync as existsSync31 } from "fs";
19869
20041
  async function memoryList(globalOpts) {
19870
- if (!existsSync29(DB_PATH)) {
20042
+ if (!existsSync31(DB_PATH)) {
19871
20043
  outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
19872
20044
  process.exit(1);
19873
20045
  }
@@ -19891,7 +20063,7 @@ async function memoryList(globalOpts) {
19891
20063
  });
19892
20064
  }
19893
20065
  async function memorySearch(globalOpts, query) {
19894
- if (!existsSync29(DB_PATH)) {
20066
+ if (!existsSync31(DB_PATH)) {
19895
20067
  outputError("DB_NOT_FOUND", "Database not found.");
19896
20068
  process.exit(1);
19897
20069
  }
@@ -19913,7 +20085,7 @@ async function memorySearch(globalOpts, query) {
19913
20085
  });
19914
20086
  }
19915
20087
  async function memoryHistory(globalOpts, opts) {
19916
- if (!existsSync29(DB_PATH)) {
20088
+ if (!existsSync31(DB_PATH)) {
19917
20089
  outputError("DB_NOT_FOUND", "Database not found.");
19918
20090
  process.exit(1);
19919
20091
  }
@@ -19961,7 +20133,7 @@ __export(cron_exports2, {
19961
20133
  cronList: () => cronList,
19962
20134
  cronRuns: () => cronRuns
19963
20135
  });
19964
- import { existsSync as existsSync30 } from "fs";
20136
+ import { existsSync as existsSync32 } from "fs";
19965
20137
  function parseFallbacks(raw) {
19966
20138
  return raw.slice(0, 3).map((f) => {
19967
20139
  const [backend2, ...rest] = f.split(":");
@@ -19982,7 +20154,7 @@ function parseAndValidateTimeout(raw) {
19982
20154
  return val;
19983
20155
  }
19984
20156
  async function cronList(globalOpts) {
19985
- if (!existsSync30(DB_PATH)) {
20157
+ if (!existsSync32(DB_PATH)) {
19986
20158
  outputError("DB_NOT_FOUND", "Database not found.");
19987
20159
  process.exit(1);
19988
20160
  }
@@ -20001,7 +20173,7 @@ async function cronList(globalOpts) {
20001
20173
  const schedule2 = j.cron ?? (j.at_time ? `at ${j.at_time}` : j.every_ms ? `every ${j.every_ms / 1e3}s` : "?");
20002
20174
  const tz = j.timezone !== "UTC" ? ` (${j.timezone})` : "";
20003
20175
  lines.push(` ${statusDot(status)} #${j.id} [${status}] ${schedule2}${tz}`);
20004
- lines.push(` ${j.description}`);
20176
+ lines.push(` ${j.title ?? j.description}`);
20005
20177
  if (j.backend) lines.push(` Backend: ${j.backend}${j.model ? ` / ${j.model}` : ""}`);
20006
20178
  if (j.fallbacks) {
20007
20179
  try {
@@ -20020,7 +20192,7 @@ async function cronList(globalOpts) {
20020
20192
  });
20021
20193
  }
20022
20194
  async function cronHealth(globalOpts) {
20023
- if (!existsSync30(DB_PATH)) {
20195
+ if (!existsSync32(DB_PATH)) {
20024
20196
  outputError("DB_NOT_FOUND", "Database not found.");
20025
20197
  process.exit(1);
20026
20198
  }
@@ -20080,6 +20252,7 @@ async function cronCreate(globalOpts, opts) {
20080
20252
  cron: opts.cron ?? null,
20081
20253
  atTime: opts.at ?? null,
20082
20254
  everyMs,
20255
+ title: opts.title ?? null,
20083
20256
  description: opts.description,
20084
20257
  chatId,
20085
20258
  backend: opts.backend ?? null,
@@ -20134,6 +20307,10 @@ async function cronEdit(globalOpts, id, opts) {
20134
20307
  const db3 = getDb2();
20135
20308
  const updates = [];
20136
20309
  const values = [];
20310
+ if (opts.title) {
20311
+ updates.push("title = ?");
20312
+ values.push(opts.title);
20313
+ }
20137
20314
  if (opts.description) {
20138
20315
  updates.push("description = ?");
20139
20316
  values.push(opts.description);
@@ -20200,7 +20377,7 @@ async function cronEdit(globalOpts, id, opts) {
20200
20377
  }
20201
20378
  }
20202
20379
  async function cronRuns(globalOpts, jobId, opts) {
20203
- if (!existsSync30(DB_PATH)) {
20380
+ if (!existsSync32(DB_PATH)) {
20204
20381
  outputError("DB_NOT_FOUND", "Database not found.");
20205
20382
  process.exit(1);
20206
20383
  }
@@ -20247,9 +20424,9 @@ __export(agents_exports, {
20247
20424
  runnersList: () => runnersList,
20248
20425
  tasksList: () => tasksList
20249
20426
  });
20250
- import { existsSync as existsSync31 } from "fs";
20427
+ import { existsSync as existsSync33 } from "fs";
20251
20428
  async function agentsList(globalOpts) {
20252
- if (!existsSync31(DB_PATH)) {
20429
+ if (!existsSync33(DB_PATH)) {
20253
20430
  outputError("DB_NOT_FOUND", "Database not found.");
20254
20431
  process.exit(1);
20255
20432
  }
@@ -20280,7 +20457,7 @@ async function agentsList(globalOpts) {
20280
20457
  });
20281
20458
  }
20282
20459
  async function tasksList(globalOpts) {
20283
- if (!existsSync31(DB_PATH)) {
20460
+ if (!existsSync33(DB_PATH)) {
20284
20461
  outputError("DB_NOT_FOUND", "Database not found.");
20285
20462
  process.exit(1);
20286
20463
  }
@@ -20408,18 +20585,18 @@ __export(db_exports, {
20408
20585
  dbPath: () => dbPath,
20409
20586
  dbStats: () => dbStats
20410
20587
  });
20411
- import { existsSync as existsSync32, statSync as statSync6, copyFileSync as copyFileSync2, mkdirSync as mkdirSync11 } from "fs";
20588
+ import { existsSync as existsSync34, statSync as statSync7, copyFileSync as copyFileSync2, mkdirSync as mkdirSync11 } from "fs";
20412
20589
  import { dirname as dirname5 } from "path";
20413
20590
  async function dbStats(globalOpts) {
20414
- if (!existsSync32(DB_PATH)) {
20591
+ if (!existsSync34(DB_PATH)) {
20415
20592
  outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
20416
20593
  process.exit(1);
20417
20594
  }
20418
20595
  const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
20419
20596
  const readDb = openDatabaseReadOnly2();
20420
- const mainSize = statSync6(DB_PATH).size;
20597
+ const mainSize = statSync7(DB_PATH).size;
20421
20598
  const walPath = DB_PATH + "-wal";
20422
- const walSize = existsSync32(walPath) ? statSync6(walPath).size : 0;
20599
+ const walSize = existsSync34(walPath) ? statSync7(walPath).size : 0;
20423
20600
  const tableNames = readDb.prepare(
20424
20601
  "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '%_fts%' ORDER BY name"
20425
20602
  ).all();
@@ -20453,7 +20630,7 @@ async function dbPath(globalOpts) {
20453
20630
  output({ path: DB_PATH }, (d) => d.path);
20454
20631
  }
20455
20632
  async function dbBackup(globalOpts, destPath) {
20456
- if (!existsSync32(DB_PATH)) {
20633
+ if (!existsSync34(DB_PATH)) {
20457
20634
  outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
20458
20635
  process.exit(1);
20459
20636
  }
@@ -20462,8 +20639,8 @@ async function dbBackup(globalOpts, destPath) {
20462
20639
  mkdirSync11(dirname5(dest), { recursive: true });
20463
20640
  copyFileSync2(DB_PATH, dest);
20464
20641
  const walPath = DB_PATH + "-wal";
20465
- if (existsSync32(walPath)) copyFileSync2(walPath, dest + "-wal");
20466
- output({ path: dest, sizeBytes: statSync6(dest).size }, (d) => {
20642
+ if (existsSync34(walPath)) copyFileSync2(walPath, dest + "-wal");
20643
+ output({ path: dest, sizeBytes: statSync7(dest).size }, (d) => {
20467
20644
  const b = d;
20468
20645
  return `
20469
20646
  ${success("Backup created:")} ${b.path} (${(b.sizeBytes / 1024).toFixed(0)}KB)
@@ -20491,9 +20668,9 @@ __export(usage_exports, {
20491
20668
  usageCost: () => usageCost,
20492
20669
  usageTokens: () => usageTokens
20493
20670
  });
20494
- import { existsSync as existsSync33 } from "fs";
20671
+ import { existsSync as existsSync35 } from "fs";
20495
20672
  function ensureDb() {
20496
- if (!existsSync33(DB_PATH)) {
20673
+ if (!existsSync35(DB_PATH)) {
20497
20674
  outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
20498
20675
  process.exit(1);
20499
20676
  }
@@ -20683,9 +20860,9 @@ __export(config_exports, {
20683
20860
  configList: () => configList,
20684
20861
  configSet: () => configSet
20685
20862
  });
20686
- import { existsSync as existsSync34, readFileSync as readFileSync18 } from "fs";
20863
+ import { existsSync as existsSync36, readFileSync as readFileSync18 } from "fs";
20687
20864
  async function configList(globalOpts) {
20688
- if (!existsSync34(DB_PATH)) {
20865
+ if (!existsSync36(DB_PATH)) {
20689
20866
  outputError("DB_NOT_FOUND", "Database not found.");
20690
20867
  process.exit(1);
20691
20868
  }
@@ -20719,7 +20896,7 @@ async function configGet(globalOpts, key) {
20719
20896
  outputError("INVALID_KEY", `Unknown config key "${key}". Valid keys: ${RUNTIME_KEYS.join(", ")}`);
20720
20897
  process.exit(1);
20721
20898
  }
20722
- if (!existsSync34(DB_PATH)) {
20899
+ if (!existsSync36(DB_PATH)) {
20723
20900
  outputError("DB_NOT_FOUND", "Database not found.");
20724
20901
  process.exit(1);
20725
20902
  }
@@ -20765,7 +20942,7 @@ async function configSet(globalOpts, key, value) {
20765
20942
  }
20766
20943
  }
20767
20944
  async function configEnv(_globalOpts) {
20768
- if (!existsSync34(ENV_PATH)) {
20945
+ if (!existsSync36(ENV_PATH)) {
20769
20946
  outputError("ENV_NOT_FOUND", `No .env file at ${ENV_PATH}. Run cc-claw setup.`);
20770
20947
  process.exit(1);
20771
20948
  }
@@ -20819,9 +20996,9 @@ __export(session_exports, {
20819
20996
  sessionGet: () => sessionGet,
20820
20997
  sessionNew: () => sessionNew
20821
20998
  });
20822
- import { existsSync as existsSync35 } from "fs";
20999
+ import { existsSync as existsSync37 } from "fs";
20823
21000
  async function sessionGet(globalOpts) {
20824
- if (!existsSync35(DB_PATH)) {
21001
+ if (!existsSync37(DB_PATH)) {
20825
21002
  outputError("DB_NOT_FOUND", "Database not found.");
20826
21003
  process.exit(1);
20827
21004
  }
@@ -20882,9 +21059,9 @@ __export(permissions_exports, {
20882
21059
  verboseGet: () => verboseGet,
20883
21060
  verboseSet: () => verboseSet
20884
21061
  });
20885
- import { existsSync as existsSync36 } from "fs";
21062
+ import { existsSync as existsSync38 } from "fs";
20886
21063
  function ensureDb2() {
20887
- if (!existsSync36(DB_PATH)) {
21064
+ if (!existsSync38(DB_PATH)) {
20888
21065
  outputError("DB_NOT_FOUND", "Database not found.");
20889
21066
  process.exit(1);
20890
21067
  }
@@ -21031,9 +21208,9 @@ __export(cwd_exports, {
21031
21208
  cwdGet: () => cwdGet,
21032
21209
  cwdSet: () => cwdSet
21033
21210
  });
21034
- import { existsSync as existsSync37 } from "fs";
21211
+ import { existsSync as existsSync39 } from "fs";
21035
21212
  async function cwdGet(globalOpts) {
21036
- if (!existsSync37(DB_PATH)) {
21213
+ if (!existsSync39(DB_PATH)) {
21037
21214
  outputError("DB_NOT_FOUND", "Database not found.");
21038
21215
  process.exit(1);
21039
21216
  }
@@ -21095,9 +21272,9 @@ __export(voice_exports, {
21095
21272
  voiceGet: () => voiceGet,
21096
21273
  voiceSet: () => voiceSet
21097
21274
  });
21098
- import { existsSync as existsSync38 } from "fs";
21275
+ import { existsSync as existsSync40 } from "fs";
21099
21276
  async function voiceGet(globalOpts) {
21100
- if (!existsSync38(DB_PATH)) {
21277
+ if (!existsSync40(DB_PATH)) {
21101
21278
  outputError("DB_NOT_FOUND", "Database not found.");
21102
21279
  process.exit(1);
21103
21280
  }
@@ -21146,9 +21323,9 @@ __export(heartbeat_exports, {
21146
21323
  heartbeatGet: () => heartbeatGet,
21147
21324
  heartbeatSet: () => heartbeatSet
21148
21325
  });
21149
- import { existsSync as existsSync39 } from "fs";
21326
+ import { existsSync as existsSync41 } from "fs";
21150
21327
  async function heartbeatGet(globalOpts) {
21151
- if (!existsSync39(DB_PATH)) {
21328
+ if (!existsSync41(DB_PATH)) {
21152
21329
  outputError("DB_NOT_FOUND", "Database not found.");
21153
21330
  process.exit(1);
21154
21331
  }
@@ -21258,9 +21435,9 @@ __export(chats_exports, {
21258
21435
  chatsList: () => chatsList,
21259
21436
  chatsRemoveAlias: () => chatsRemoveAlias
21260
21437
  });
21261
- import { existsSync as existsSync40 } from "fs";
21438
+ import { existsSync as existsSync42 } from "fs";
21262
21439
  async function chatsList(_globalOpts) {
21263
- if (!existsSync40(DB_PATH)) {
21440
+ if (!existsSync42(DB_PATH)) {
21264
21441
  outputError("DB_NOT_FOUND", "Database not found.");
21265
21442
  process.exit(1);
21266
21443
  }
@@ -21388,9 +21565,9 @@ var mcps_exports = {};
21388
21565
  __export(mcps_exports, {
21389
21566
  mcpsList: () => mcpsList
21390
21567
  });
21391
- import { existsSync as existsSync41 } from "fs";
21568
+ import { existsSync as existsSync43 } from "fs";
21392
21569
  async function mcpsList(_globalOpts) {
21393
- if (!existsSync41(DB_PATH)) {
21570
+ if (!existsSync43(DB_PATH)) {
21394
21571
  outputError("DB_NOT_FOUND", "Database not found.");
21395
21572
  process.exit(1);
21396
21573
  }
@@ -21427,11 +21604,11 @@ __export(chat_exports, {
21427
21604
  chatSend: () => chatSend
21428
21605
  });
21429
21606
  import { request as httpRequest2 } from "http";
21430
- import { readFileSync as readFileSync19, existsSync as existsSync42 } from "fs";
21607
+ import { readFileSync as readFileSync19, existsSync as existsSync44 } from "fs";
21431
21608
  function getToken2() {
21432
21609
  if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
21433
21610
  try {
21434
- if (existsSync42(TOKEN_PATH2)) return readFileSync19(TOKEN_PATH2, "utf-8").trim();
21611
+ if (existsSync44(TOKEN_PATH2)) return readFileSync19(TOKEN_PATH2, "utf-8").trim();
21435
21612
  } catch {
21436
21613
  }
21437
21614
  return null;
@@ -21871,9 +22048,9 @@ __export(evolve_exports, {
21871
22048
  evolveStatus: () => evolveStatus,
21872
22049
  evolveUndo: () => evolveUndo
21873
22050
  });
21874
- import { existsSync as existsSync43 } from "fs";
22051
+ import { existsSync as existsSync45 } from "fs";
21875
22052
  function ensureDb3() {
21876
- if (!existsSync43(DB_PATH)) {
22053
+ if (!existsSync45(DB_PATH)) {
21877
22054
  outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
21878
22055
  process.exit(1);
21879
22056
  }
@@ -22235,7 +22412,7 @@ var init_evolve = __esm({
22235
22412
 
22236
22413
  // src/setup.ts
22237
22414
  var setup_exports = {};
22238
- import { existsSync as existsSync44, writeFileSync as writeFileSync9, readFileSync as readFileSync20, copyFileSync as copyFileSync3, mkdirSync as mkdirSync12, statSync as statSync7 } from "fs";
22415
+ import { existsSync as existsSync46, writeFileSync as writeFileSync9, readFileSync as readFileSync20, copyFileSync as copyFileSync3, mkdirSync as mkdirSync12, statSync as statSync8 } from "fs";
22239
22416
  import { execFileSync as execFileSync4 } from "child_process";
22240
22417
  import { createInterface as createInterface7 } from "readline";
22241
22418
  import { join as join25 } from "path";
@@ -22313,10 +22490,10 @@ async function setup() {
22313
22490
  }
22314
22491
  console.log("");
22315
22492
  for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
22316
- if (!existsSync44(dir)) mkdirSync12(dir, { recursive: true });
22493
+ if (!existsSync46(dir)) mkdirSync12(dir, { recursive: true });
22317
22494
  }
22318
22495
  const env = {};
22319
- const envSource = existsSync44(ENV_PATH) ? ENV_PATH : existsSync44(".env") ? ".env" : null;
22496
+ const envSource = existsSync46(ENV_PATH) ? ENV_PATH : existsSync46(".env") ? ".env" : null;
22320
22497
  if (envSource) {
22321
22498
  console.log(yellow(` Found existing config at ${envSource} \u2014 your values will be preserved`));
22322
22499
  console.log(yellow(" unless you enter new ones. Just press Enter to keep existing values.\n"));
@@ -22327,8 +22504,8 @@ async function setup() {
22327
22504
  }
22328
22505
  }
22329
22506
  const cwdDb = join25(process.cwd(), "cc-claw.db");
22330
- if (existsSync44(cwdDb) && !existsSync44(DB_PATH)) {
22331
- const { size } = statSync7(cwdDb);
22507
+ if (existsSync46(cwdDb) && !existsSync46(DB_PATH)) {
22508
+ const { size } = statSync8(cwdDb);
22332
22509
  console.log(yellow(` Found existing database at ${cwdDb} (${(size / 1024).toFixed(0)}KB)`));
22333
22510
  const migrate = await confirm("Copy database to ~/.cc-claw/? (preserves memories & history)", true);
22334
22511
  if (migrate) {
@@ -22747,7 +22924,7 @@ function registerCronCommands(cmd) {
22747
22924
  const { cronList: cronList2 } = await Promise.resolve().then(() => (init_cron2(), cron_exports2));
22748
22925
  await cronList2(program.opts());
22749
22926
  });
22750
- cmd.command("create").description("Create a scheduled job").requiredOption("--description <text>", "Job description").option("--prompt <text>", "Agent prompt (defaults to description)").option("--cron <expr>", "Cron expression (e.g. '0 9 * * *')").option("--at <iso8601>", "One-shot time").option("--every <interval>", "Repeat interval (e.g. 30m, 1h)").option("--backend <name>", "Backend for this job").option("--model <name>", "Model for this job").option("--thinking <level>", "Thinking level").option("--timeout <seconds>", "Job timeout in seconds (30-3600)").option("--fallback <backend:model>", "Fallback backend:model (repeatable, max 3)", (val, prev) => [...prev, val], []).option("--timezone <tz>", "IANA timezone", "UTC").option("--session-type <type>", "Session type (isolated/main)", "isolated").option("--delivery <mode>", "Delivery mode (announce/webhook/none)", "announce").option("--channel <name>", "Delivery channel").option("--target <id>", "Delivery target").option("--cwd <path>", "Working directory").action(async (opts) => {
22927
+ cmd.command("create").description("Create a scheduled job").requiredOption("--description <text>", "Job description").option("--title <text>", "Short title for job list (auto-generated if omitted)").option("--prompt <text>", "Agent prompt (defaults to description)").option("--cron <expr>", "Cron expression (e.g. '0 9 * * *')").option("--at <iso8601>", "One-shot time").option("--every <interval>", "Repeat interval (e.g. 30m, 1h)").option("--backend <name>", "Backend for this job").option("--model <name>", "Model for this job").option("--thinking <level>", "Thinking level").option("--timeout <seconds>", "Job timeout in seconds (30-3600)").option("--fallback <backend:model>", "Fallback backend:model (repeatable, max 3)", (val, prev) => [...prev, val], []).option("--timezone <tz>", "IANA timezone", "UTC").option("--session-type <type>", "Session type (isolated/main)", "isolated").option("--delivery <mode>", "Delivery mode (announce/webhook/none)", "announce").option("--channel <name>", "Delivery channel").option("--target <id>", "Delivery target").option("--cwd <path>", "Working directory").action(async (opts) => {
22751
22928
  const { cronCreate: cronCreate2 } = await Promise.resolve().then(() => (init_cron2(), cron_exports2));
22752
22929
  await cronCreate2(program.opts(), opts);
22753
22930
  });
@@ -22767,7 +22944,7 @@ function registerCronCommands(cmd) {
22767
22944
  const { cronAction: cronAction2 } = await Promise.resolve().then(() => (init_cron2(), cron_exports2));
22768
22945
  await cronAction2(program.opts(), "run", id);
22769
22946
  });
22770
- cmd.command("edit <id>").description("Edit a job (same flags as create)").option("--description <text>").option("--cron <expr>").option("--at <iso8601>").option("--every <interval>").option("--backend <name>").option("--model <name>").option("--thinking <level>").option("--timeout <seconds>", "Job timeout in seconds (30-3600)").option("--fallback <backend:model>", "Fallback backend:model (repeatable, max 3)", (val, prev) => [...prev, val], []).option("--timezone <tz>").action(async (id, opts) => {
22947
+ cmd.command("edit <id>").description("Edit a job (same flags as create)").option("--title <text>", "Short title for job list").option("--description <text>").option("--cron <expr>").option("--at <iso8601>").option("--every <interval>").option("--backend <name>").option("--model <name>").option("--thinking <level>").option("--timeout <seconds>", "Job timeout in seconds (30-3600)").option("--fallback <backend:model>", "Fallback backend:model (repeatable, max 3)", (val, prev) => [...prev, val], []).option("--timezone <tz>").action(async (id, opts) => {
22771
22948
  const { cronEdit: cronEdit2 } = await Promise.resolve().then(() => (init_cron2(), cron_exports2));
22772
22949
  await cronEdit2(program.opts(), id, opts);
22773
22950
  });