cc-claw 0.16.0 → 0.16.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 +175 -36
  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.0" : (() => {
36
+ VERSION = true ? "0.16.1" : (() => {
37
37
  try {
38
38
  return JSON.parse(readFileSync(join(process.cwd(), "package.json"), "utf-8")).version ?? "unknown";
39
39
  } catch {
@@ -9932,11 +9932,11 @@ var init_evolve = __esm({
9932
9932
  const body = JSON.parse(await readBody(req));
9933
9933
  const { setReflectionStatus: setReflectionStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
9934
9934
  const { existsSync: fileExists, readFileSync: fileRead } = await import("fs");
9935
- const { join: join28 } = await import("path");
9935
+ const { join: join29 } = await import("path");
9936
9936
  const { CC_CLAW_HOME: home } = await Promise.resolve().then(() => (init_paths(), paths_exports));
9937
9937
  const chatId = body.chatId || (process.env.ALLOWED_CHAT_ID ?? "").split(",")[0]?.trim() || "default";
9938
- const soulPath = join28(home, "identity/SOUL.md");
9939
- const userPath = join28(home, "identity/USER.md");
9938
+ const soulPath = join29(home, "identity/SOUL.md");
9939
+ const userPath = join29(home, "identity/USER.md");
9940
9940
  const soul = fileExists(soulPath) ? fileRead(soulPath, "utf-8") : "";
9941
9941
  const user = fileExists(userPath) ? fileRead(userPath, "utf-8") : "";
9942
9942
  setReflectionStatus2(getDb(), chatId, "active", soul, user);
@@ -15902,13 +15902,13 @@ async function handleEvolveCallback(chatId, data, channel) {
15902
15902
  const { getReflectionStatus: getReflectionStatus2, setReflectionStatus: setReflectionStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
15903
15903
  const current = getReflectionStatus2(getDb(), chatId);
15904
15904
  if (current === "frozen") {
15905
- const { readFileSync: readFileSync21, existsSync: existsSync49 } = await import("fs");
15906
- const { join: join28 } = await import("path");
15905
+ const { readFileSync: readFileSync22, existsSync: existsSync49 } = await import("fs");
15906
+ const { join: join29 } = await import("path");
15907
15907
  const { CC_CLAW_HOME: CC_CLAW_HOME3 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
15908
- const soulPath = join28(CC_CLAW_HOME3, "identity/SOUL.md");
15909
- const userPath = join28(CC_CLAW_HOME3, "identity/USER.md");
15910
- const soul = existsSync49(soulPath) ? readFileSync21(soulPath, "utf-8") : "";
15911
- const user = existsSync49(userPath) ? readFileSync21(userPath, "utf-8") : "";
15908
+ const soulPath = join29(CC_CLAW_HOME3, "identity/SOUL.md");
15909
+ const userPath = join29(CC_CLAW_HOME3, "identity/USER.md");
15910
+ const soul = existsSync49(soulPath) ? readFileSync22(soulPath, "utf-8") : "";
15911
+ const user = existsSync49(userPath) ? readFileSync22(userPath, "utf-8") : "";
15912
15912
  setReflectionStatus2(getDb(), chatId, "active", soul, user);
15913
15913
  const { logActivity: logActivity2 } = await Promise.resolve().then(() => (init_store3(), store_exports3));
15914
15914
  logActivity2(getDb(), { chatId, source: "telegram", eventType: "reflection_unfrozen", summary: "Reflection enabled" });
@@ -20041,6 +20041,8 @@ var init_telegram2 = __esm({
20041
20041
  { command: "claude", description: "Switch to Claude backend" },
20042
20042
  { command: "gemini", description: "Switch to Gemini backend" },
20043
20043
  { command: "gemini_accounts", description: "Manage Gemini credentials & rotation" },
20044
+ { command: "claude_accounts", description: "Manage Claude credentials & rotation" },
20045
+ { command: "codex_accounts", description: "Manage Codex credentials & rotation" },
20044
20046
  { command: "codex", description: "Switch to Codex backend" },
20045
20047
  { command: "cursor", description: "Switch to Cursor backend" },
20046
20048
  { command: "model", description: "Switch model for active backend" },
@@ -21395,11 +21397,11 @@ async function main() {
21395
21397
  bootstrapSkills().catch((err) => error("[cc-claw] Skill bootstrap failed:", err));
21396
21398
  try {
21397
21399
  const { generateAiSkill: generateAiSkill2 } = await Promise.resolve().then(() => (init_ai_skill(), ai_skill_exports));
21398
- const { writeFileSync: writeFileSync12, mkdirSync: mkdirSync16 } = await import("fs");
21399
- const { join: join28 } = await import("path");
21400
- const skillDir = join28(SKILLS_PATH, "cc-claw-cli");
21401
- mkdirSync16(skillDir, { recursive: true });
21402
- writeFileSync12(join28(skillDir, "SKILL.md"), generateAiSkill2(), "utf-8");
21400
+ const { writeFileSync: writeFileSync12, mkdirSync: mkdirSync17 } = await import("fs");
21401
+ const { join: join29 } = await import("path");
21402
+ const skillDir = join29(SKILLS_PATH, "cc-claw-cli");
21403
+ mkdirSync17(skillDir, { recursive: true });
21404
+ writeFileSync12(join29(skillDir, "SKILL.md"), generateAiSkill2(), "utf-8");
21403
21405
  log("[cc-claw] AI skill updated");
21404
21406
  } catch {
21405
21407
  }
@@ -22284,8 +22286,8 @@ async function doctorCommand(globalOpts, localOpts) {
22284
22286
  }
22285
22287
  if (existsSync25(ERROR_LOG_PATH)) {
22286
22288
  try {
22287
- const { readFileSync: readFileSync21 } = await import("fs");
22288
- const logContent = readFileSync21(ERROR_LOG_PATH, "utf-8");
22289
+ const { readFileSync: readFileSync22 } = await import("fs");
22290
+ const logContent = readFileSync22(ERROR_LOG_PATH, "utf-8");
22289
22291
  const recentLines = logContent.split("\n").filter(Boolean).slice(-100);
22290
22292
  const last24h = Date.now() - 864e5;
22291
22293
  const recentErrors = recentLines.filter((line) => {
@@ -22711,6 +22713,7 @@ var init_gemini2 = __esm({
22711
22713
  // src/cli/commands/backend-cmd-factory.ts
22712
22714
  var backend_cmd_factory_exports = {};
22713
22715
  __export(backend_cmd_factory_exports, {
22716
+ makeAddAccount: () => makeAddAccount,
22714
22717
  makeAddKey: () => makeAddKey,
22715
22718
  makeDisable: () => makeDisable,
22716
22719
  makeEnable: () => makeEnable,
@@ -22720,7 +22723,8 @@ __export(backend_cmd_factory_exports, {
22720
22723
  makeReorder: () => makeReorder,
22721
22724
  registerBackendSlotCommands: () => registerBackendSlotCommands
22722
22725
  });
22723
- import { existsSync as existsSync28 } from "fs";
22726
+ import { existsSync as existsSync28, mkdirSync as mkdirSync13, readFileSync as readFileSync18 } from "fs";
22727
+ import { join as join26 } from "path";
22724
22728
  import { createInterface as createInterface6 } from "readline";
22725
22729
  function requireDb2() {
22726
22730
  if (!existsSync28(DB_PATH)) {
@@ -22757,7 +22761,7 @@ function makeList(backend2, displayName) {
22757
22761
  readDb.close();
22758
22762
  if (slots.length === 0) {
22759
22763
  output({ slots: [] }, () => `No ${displayName} credential slots configured.
22760
- Add one with: cc-claw ${backend2} add-key`);
22764
+ Add one with: cc-claw ${backend2} add-account or cc-claw ${backend2} add-key`);
22761
22765
  return;
22762
22766
  }
22763
22767
  output(slots, (data) => {
@@ -22804,6 +22808,62 @@ function makeAddKey(backend2, displayName) {
22804
22808
  );
22805
22809
  };
22806
22810
  }
22811
+ function makeAddAccount(backend2, displayName) {
22812
+ return async function addAccount(_globalOpts, opts) {
22813
+ const config2 = ADD_ACCOUNT_CONFIGS[backend2];
22814
+ if (!config2) {
22815
+ outputError("UNSUPPORTED", `add-account is not supported for ${displayName}. Use add-key instead.`);
22816
+ process.exit(1);
22817
+ }
22818
+ await requireWriteDb2();
22819
+ const slotsDir = join26(CC_CLAW_HOME, config2.slotsSubdir);
22820
+ if (!existsSync28(slotsDir)) mkdirSync13(slotsDir, { recursive: true });
22821
+ const tempId = Date.now();
22822
+ const slotDir = join26(slotsDir, `slot-${tempId}`);
22823
+ mkdirSync13(slotDir, { recursive: true, mode: 448 });
22824
+ if (config2.preSetup) config2.preSetup(slotDir);
22825
+ console.log("");
22826
+ console.log(` Opening ${displayName} CLI for sign-in...`);
22827
+ console.log(` Sign in with the account you want for this slot.`);
22828
+ console.log(` After sign-in completes, return here.`);
22829
+ console.log("");
22830
+ const { execSync: execSync8 } = await import("child_process");
22831
+ const loginEnv = {
22832
+ ...process.env,
22833
+ [config2.envKey]: config2.envValue(slotDir),
22834
+ ...config2.envOverrides
22835
+ };
22836
+ try {
22837
+ execSync8(config2.loginCommand.join(" "), {
22838
+ stdio: "inherit",
22839
+ env: loginEnv,
22840
+ cwd: slotDir
22841
+ });
22842
+ } catch {
22843
+ }
22844
+ if (!config2.verifyCredentials(slotDir)) {
22845
+ console.log(error2(`
22846
+ No credentials found. Sign-in may have failed.`));
22847
+ console.log(` The slot directory is preserved at: ${slotDir}`);
22848
+ console.log(` Re-run: cc-claw ${backend2} add-account
22849
+ `);
22850
+ process.exit(1);
22851
+ }
22852
+ const accountLabel = opts.label || config2.extractLabel(slotDir);
22853
+ const { addBackendSlot: addBackendSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
22854
+ const id = addBackendSlot2({
22855
+ backend: backend2,
22856
+ slotType: "oauth",
22857
+ label: accountLabel,
22858
+ configHome: slotDir,
22859
+ priority: opts.priority ? parseInt(opts.priority, 10) : 0
22860
+ });
22861
+ output(
22862
+ { id, type: "oauth", backend: backend2, label: accountLabel, configHome: slotDir },
22863
+ () => success(`Added ${displayName} subscription slot #${id} (${accountLabel})`)
22864
+ );
22865
+ };
22866
+ }
22807
22867
  function makeRemove(backend2, displayName) {
22808
22868
  return async function remove(_globalOpts, idOrLabel) {
22809
22869
  await requireWriteDb2();
@@ -22906,13 +22966,88 @@ function registerBackendSlotCommands(parentCommand, backend2, displayName, globa
22906
22966
  });
22907
22967
  return cmd;
22908
22968
  }
22909
- var dbInitialized2;
22969
+ var dbInitialized2, ADD_ACCOUNT_CONFIGS;
22910
22970
  var init_backend_cmd_factory = __esm({
22911
22971
  "src/cli/commands/backend-cmd-factory.ts"() {
22912
22972
  "use strict";
22913
22973
  init_format2();
22914
22974
  init_paths();
22915
22975
  dbInitialized2 = false;
22976
+ ADD_ACCOUNT_CONFIGS = {
22977
+ claude: {
22978
+ slotsSubdir: "claude-slots",
22979
+ loginCommand: ["claude", "auth", "login", "--claudeai"],
22980
+ envKey: "HOME",
22981
+ envValue: (slotDir) => slotDir,
22982
+ envOverrides: { ANTHROPIC_API_KEY: void 0 },
22983
+ preSetup: (slotDir) => {
22984
+ mkdirSync13(join26(slotDir, ".claude"), { recursive: true });
22985
+ },
22986
+ verifyCredentials: (slotDir) => {
22987
+ const claudeJson = join26(slotDir, ".claude.json");
22988
+ const claudeJsonNested = join26(slotDir, ".claude", ".claude.json");
22989
+ if (existsSync28(claudeJson)) {
22990
+ try {
22991
+ const data = JSON.parse(readFileSync18(claudeJson, "utf-8"));
22992
+ return Boolean(data.oauthAccount);
22993
+ } catch {
22994
+ return false;
22995
+ }
22996
+ }
22997
+ if (existsSync28(claudeJsonNested)) {
22998
+ try {
22999
+ const data = JSON.parse(readFileSync18(claudeJsonNested, "utf-8"));
23000
+ return Boolean(data.oauthAccount);
23001
+ } catch {
23002
+ return false;
23003
+ }
23004
+ }
23005
+ return false;
23006
+ },
23007
+ extractLabel: (slotDir) => {
23008
+ try {
23009
+ const { execSync: execSync8 } = __require("child_process");
23010
+ const out = execSync8("claude auth status", {
23011
+ encoding: "utf-8",
23012
+ env: { ...process.env, HOME: slotDir, ANTHROPIC_API_KEY: void 0 },
23013
+ timeout: 1e4
23014
+ });
23015
+ const parsed = JSON.parse(out);
23016
+ if (parsed.email) return parsed.email;
23017
+ } catch {
23018
+ }
23019
+ try {
23020
+ const claudeJson = join26(slotDir, ".claude.json");
23021
+ if (existsSync28(claudeJson)) {
23022
+ const data = JSON.parse(readFileSync18(claudeJson, "utf-8"));
23023
+ if (data.oauthAccount?.emailAddress) return data.oauthAccount.emailAddress;
23024
+ }
23025
+ } catch {
23026
+ }
23027
+ return "subscription";
23028
+ }
23029
+ },
23030
+ codex: {
23031
+ slotsSubdir: "codex-slots",
23032
+ loginCommand: ["codex", "login"],
23033
+ envKey: "CODEX_HOME",
23034
+ envValue: (slotDir) => slotDir,
23035
+ envOverrides: { OPENAI_API_KEY: void 0 },
23036
+ verifyCredentials: (slotDir) => {
23037
+ return existsSync28(join26(slotDir, "auth.json"));
23038
+ },
23039
+ extractLabel: (slotDir) => {
23040
+ try {
23041
+ const authData = JSON.parse(readFileSync18(join26(slotDir, "auth.json"), "utf-8"));
23042
+ if (authData.email) return authData.email;
23043
+ if (authData.account_name) return authData.account_name;
23044
+ if (authData.user?.email) return authData.user.email;
23045
+ } catch {
23046
+ }
23047
+ return "subscription";
23048
+ }
23049
+ }
23050
+ };
22916
23051
  }
22917
23052
  });
22918
23053
 
@@ -23608,7 +23743,7 @@ __export(db_exports, {
23608
23743
  dbPath: () => dbPath,
23609
23744
  dbStats: () => dbStats
23610
23745
  });
23611
- import { existsSync as existsSync34, statSync as statSync8, copyFileSync as copyFileSync2, mkdirSync as mkdirSync13 } from "fs";
23746
+ import { existsSync as existsSync34, statSync as statSync8, copyFileSync as copyFileSync2, mkdirSync as mkdirSync14 } from "fs";
23612
23747
  import { dirname as dirname5 } from "path";
23613
23748
  async function dbStats(globalOpts) {
23614
23749
  if (!existsSync34(DB_PATH)) {
@@ -23659,7 +23794,7 @@ async function dbBackup(globalOpts, destPath) {
23659
23794
  }
23660
23795
  const dest = destPath ?? `${DB_PATH}.backup-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
23661
23796
  try {
23662
- mkdirSync13(dirname5(dest), { recursive: true });
23797
+ mkdirSync14(dirname5(dest), { recursive: true });
23663
23798
  copyFileSync2(DB_PATH, dest);
23664
23799
  const walPath = DB_PATH + "-wal";
23665
23800
  if (existsSync34(walPath)) copyFileSync2(walPath, dest + "-wal");
@@ -23883,7 +24018,7 @@ __export(config_exports2, {
23883
24018
  configList: () => configList,
23884
24019
  configSet: () => configSet
23885
24020
  });
23886
- import { existsSync as existsSync36, readFileSync as readFileSync18 } from "fs";
24021
+ import { existsSync as existsSync36, readFileSync as readFileSync19 } from "fs";
23887
24022
  async function configList(globalOpts) {
23888
24023
  if (!existsSync36(DB_PATH)) {
23889
24024
  outputError("DB_NOT_FOUND", "Database not found.");
@@ -23969,7 +24104,7 @@ async function configEnv(_globalOpts) {
23969
24104
  outputError("ENV_NOT_FOUND", `No .env file at ${ENV_PATH}. Run cc-claw setup.`);
23970
24105
  process.exit(1);
23971
24106
  }
23972
- const content = readFileSync18(ENV_PATH, "utf-8");
24107
+ const content = readFileSync19(ENV_PATH, "utf-8");
23973
24108
  const entries = {};
23974
24109
  const secretPatterns = /TOKEN|KEY|SECRET|PASSWORD|CREDENTIALS/i;
23975
24110
  for (const line of content.split("\n")) {
@@ -24718,11 +24853,11 @@ __export(chat_exports2, {
24718
24853
  chatSend: () => chatSend
24719
24854
  });
24720
24855
  import { request as httpRequest2 } from "http";
24721
- import { readFileSync as readFileSync19, existsSync as existsSync46 } from "fs";
24856
+ import { readFileSync as readFileSync20, existsSync as existsSync46 } from "fs";
24722
24857
  function getToken2() {
24723
24858
  if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
24724
24859
  try {
24725
- if (existsSync46(TOKEN_PATH2)) return readFileSync19(TOKEN_PATH2, "utf-8").trim();
24860
+ if (existsSync46(TOKEN_PATH2)) return readFileSync20(TOKEN_PATH2, "utf-8").trim();
24726
24861
  } catch {
24727
24862
  }
24728
24863
  return null;
@@ -25001,8 +25136,8 @@ var completion_exports = {};
25001
25136
  __export(completion_exports, {
25002
25137
  completionCommand: () => completionCommand
25003
25138
  });
25004
- import { writeFileSync as writeFileSync10, mkdirSync as mkdirSync14 } from "fs";
25005
- import { join as join26 } from "path";
25139
+ import { writeFileSync as writeFileSync10, mkdirSync as mkdirSync15 } from "fs";
25140
+ import { join as join27 } from "path";
25006
25141
  import { homedir as homedir9 } from "os";
25007
25142
  async function completionCommand(opts) {
25008
25143
  const shell = opts.shell ?? detectShell();
@@ -25018,10 +25153,10 @@ async function completionCommand(opts) {
25018
25153
  process.exit(1);
25019
25154
  }
25020
25155
  if (opts.install) {
25021
- const dir = join26(homedir9(), ".config", "cc-claw", "completions");
25022
- mkdirSync14(dir, { recursive: true });
25156
+ const dir = join27(homedir9(), ".config", "cc-claw", "completions");
25157
+ mkdirSync15(dir, { recursive: true });
25023
25158
  const filename = shell === "zsh" ? "_cc-claw" : shell === "fish" ? "cc-claw.fish" : "cc-claw.bash";
25024
- const filepath = join26(dir, filename);
25159
+ const filepath = join27(dir, filename);
25025
25160
  writeFileSync10(filepath, script, "utf-8");
25026
25161
  console.log(`\u2713 Completion script written to ${filepath}
25027
25162
  `);
@@ -25610,10 +25745,10 @@ var init_evolve3 = __esm({
25610
25745
 
25611
25746
  // src/setup.ts
25612
25747
  var setup_exports = {};
25613
- import { existsSync as existsSync48, writeFileSync as writeFileSync11, readFileSync as readFileSync20, copyFileSync as copyFileSync3, mkdirSync as mkdirSync15, statSync as statSync9 } from "fs";
25748
+ import { existsSync as existsSync48, writeFileSync as writeFileSync11, readFileSync as readFileSync21, copyFileSync as copyFileSync3, mkdirSync as mkdirSync16, statSync as statSync9 } from "fs";
25614
25749
  import { execFileSync as execFileSync5 } from "child_process";
25615
25750
  import { createInterface as createInterface8 } from "readline";
25616
- import { join as join27 } from "path";
25751
+ import { join as join28 } from "path";
25617
25752
  function divider2() {
25618
25753
  console.log(dim("\u2500".repeat(55)));
25619
25754
  }
@@ -25688,20 +25823,20 @@ async function setup() {
25688
25823
  }
25689
25824
  console.log("");
25690
25825
  for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
25691
- if (!existsSync48(dir)) mkdirSync15(dir, { recursive: true });
25826
+ if (!existsSync48(dir)) mkdirSync16(dir, { recursive: true });
25692
25827
  }
25693
25828
  const env = {};
25694
25829
  const envSource = existsSync48(ENV_PATH) ? ENV_PATH : existsSync48(".env") ? ".env" : null;
25695
25830
  if (envSource) {
25696
25831
  console.log(yellow(` Found existing config at ${envSource} \u2014 your values will be preserved`));
25697
25832
  console.log(yellow(" unless you enter new ones. Just press Enter to keep existing values.\n"));
25698
- const existing = readFileSync20(envSource, "utf-8");
25833
+ const existing = readFileSync21(envSource, "utf-8");
25699
25834
  for (const line of existing.split("\n")) {
25700
25835
  const match = line.match(/^([^#=]+)=(.*)$/);
25701
25836
  if (match) env[match[1].trim()] = match[2].trim();
25702
25837
  }
25703
25838
  }
25704
- const cwdDb = join27(process.cwd(), "cc-claw.db");
25839
+ const cwdDb = join28(process.cwd(), "cc-claw.db");
25705
25840
  if (existsSync48(cwdDb) && !existsSync48(DB_PATH)) {
25706
25841
  const { size } = statSync9(cwdDb);
25707
25842
  console.log(yellow(` Found existing database at ${cwdDb} (${(size / 1024).toFixed(0)}KB)`));
@@ -26087,6 +26222,10 @@ function registerUnifiedSlotCommands(parentCmd, backendId, displayName) {
26087
26222
  const { makeAddKey: makeAddKey2 } = await Promise.resolve().then(() => (init_backend_cmd_factory(), backend_cmd_factory_exports));
26088
26223
  await makeAddKey2(backendId, displayName)(program.opts(), opts);
26089
26224
  });
26225
+ cmd.command("add-account").description("Add a subscription/OAuth slot (opens browser for sign-in)").option("--label <name>", "Friendly label for this slot").option("--priority <n>", "Priority (lower = preferred)", "0").action(async (opts) => {
26226
+ const { makeAddAccount: makeAddAccount2 } = await Promise.resolve().then(() => (init_backend_cmd_factory(), backend_cmd_factory_exports));
26227
+ await makeAddAccount2(backendId, displayName)(program.opts(), opts);
26228
+ });
26090
26229
  cmd.command("remove <id-or-label>").description("Remove a credential slot (by ID or label)").action(async (id) => {
26091
26230
  const { makeRemove: makeRemove2 } = await Promise.resolve().then(() => (init_backend_cmd_factory(), backend_cmd_factory_exports));
26092
26231
  await makeRemove2(backendId, displayName)(program.opts(), id);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-claw",
3
- "version": "0.16.0",
3
+ "version": "0.16.1",
4
4
  "description": "CC-Claw: Personal AI assistant on Telegram — multi-backend (Claude, Gemini, Codex, Cursor), sub-agent orchestration, MCP management",
5
5
  "type": "module",
6
6
  "main": "dist/cli.js",