claude-use 2.3.1 → 2.4.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 (3) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.cjs +90 -71
  3. package/package.json +3 -3
package/README.md CHANGED
@@ -530,7 +530,7 @@ scripts/
530
530
  build.mts # esbuild bundle -> node --build-sea=<config> (see Build (Node SEA) below); --bundle-only stops after the bundle, for npm publishing
531
531
  gen-schema.mts # z.toJSONSchema() per exported schema -> schema/*.schema.json
532
532
  gen-schema-core.ts # shared schema-generation logic used by gen-schema.mts
533
- stamp-schema-ids.mjs # rewrites $id to the real version-pinned release URL at publish time
533
+ stamp-schema-ids.mts # rewrites $id to the real version-pinned release URL at publish time
534
534
  .github/workflows/
535
535
  ci.yml # one workflow: check (every push/PR) plus the whole release pipeline, gated to
536
536
  # tag pushes only — five platform builds, npm publish, GitHub Release, and the
package/dist/cli.cjs CHANGED
@@ -221824,7 +221824,7 @@ var program = new Command();
221824
221824
  // package.json
221825
221825
  var package_default = {
221826
221826
  name: "claude-use",
221827
- version: "2.3.1",
221827
+ version: "2.4.1",
221828
221828
  description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
221829
221829
  license: "Apache-2.0",
221830
221830
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -221839,7 +221839,7 @@ var package_default = {
221839
221839
  "claude",
221840
221840
  "cli"
221841
221841
  ],
221842
- packageManager: "pnpm@11.6.0",
221842
+ packageManager: "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c",
221843
221843
  type: "module",
221844
221844
  engines: {
221845
221845
  node: ">=22.12.0"
@@ -221878,7 +221878,7 @@ var package_default = {
221878
221878
  devDependencies: {
221879
221879
  "@commitlint/cli": "^21.2.2",
221880
221880
  "@commitlint/config-conventional": "^21.2.2",
221881
- "@eslint/js": "^10.0.1",
221881
+ "@exadev/eslint-config": "2.12.1",
221882
221882
  "@semantic-release/changelog": "^7.0.0",
221883
221883
  "@semantic-release/git": "^11.0.1",
221884
221884
  "@semantic-release/npm": "^13.1.5",
@@ -241865,7 +241865,7 @@ function readJson(filePath, schema, storeFs = nodeStoreFs) {
241865
241865
  function writeTextAtomic(filePath, contents, storeFs = nodeStoreFs) {
241866
241866
  const dir = import_node_path2.default.dirname(filePath);
241867
241867
  storeFs.mkdirSync(dir);
241868
- const tempPath = import_node_path2.default.join(dir, `.${import_node_path2.default.basename(filePath)}.${process.pid}.${(0, import_node_crypto.randomUUID)()}.tmp`);
241868
+ const tempPath = import_node_path2.default.join(dir, `.${import_node_path2.default.basename(filePath)}.${String(process.pid)}.${(0, import_node_crypto.randomUUID)()}.tmp`);
241869
241869
  storeFs.writeFileUtf8(tempPath, contents);
241870
241870
  try {
241871
241871
  storeFs.renameSync(tempPath, filePath);
@@ -242352,8 +242352,11 @@ function parseDuration(value) {
242352
242352
  throw new Error(`"${value}" is not a valid duration. Expected a count followed by ms, s, m, h, d, or w.`);
242353
242353
  }
242354
242354
  const [, count, unit] = parts;
242355
+ if (count === void 0 || unit === void 0) {
242356
+ throw new Error(`"${value}" is not a valid duration.`);
242357
+ }
242355
242358
  const multiplier = MILLISECONDS_PER_UNIT[unit];
242356
- if (count === void 0 || multiplier === void 0) {
242359
+ if (multiplier === void 0) {
242357
242360
  throw new Error(`"${value}" is not a valid duration.`);
242358
242361
  }
242359
242362
  return Number(count) * multiplier;
@@ -242429,7 +242432,7 @@ function splitOnWildcards(pattern) {
242429
242432
  while (index < pattern.length) {
242430
242433
  const token = WILDCARD_TOKENS.find((candidate) => pattern.startsWith(candidate, index));
242431
242434
  if (token === void 0) {
242432
- literal2 += pattern[index];
242435
+ literal2 += pattern.charAt(index);
242433
242436
  index += 1;
242434
242437
  continue;
242435
242438
  }
@@ -242496,7 +242499,7 @@ function detectEncodingAmbiguity(fragments, options) {
242496
242499
  const lossy = lossyCharacters(literalText);
242497
242500
  if (lossy.length > 0) {
242498
242501
  const matched = options.existingNames?.filter((name) => name === encoded).length;
242499
- const suffix = matched === void 0 ? "" : ` It currently matches ${matched} existing project directory name(s).`;
242502
+ const suffix = matched === void 0 ? "" : ` It currently matches ${String(matched)} existing project directory name(s).`;
242500
242503
  ambiguities.push({
242501
242504
  fragment,
242502
242505
  encoded,
@@ -242649,9 +242652,6 @@ function flattenLayers(layers, options) {
242649
242652
  for (const layer of layers) {
242650
242653
  if (layer.categories !== void 0) {
242651
242654
  for (const [name, value] of Object.entries(layer.categories)) {
242652
- if (value === void 0) {
242653
- continue;
242654
- }
242655
242655
  if (!isOverridableCategory(name)) {
242656
242656
  continue;
242657
242657
  }
@@ -242870,7 +242870,7 @@ function reportOverriddenExactKeys(winner, params, relPath) {
242870
242870
  diagnostics.push({
242871
242871
  code: "EXACT_ENTRY_OVERRIDDEN_BY_LATER_GLOB",
242872
242872
  severity: "info",
242873
- message: `For "${relPath}", the exact key "${candidate.rawKey}" from layer ${candidate.layer} is overridden by the glob "${winner.rawKey}" from the later layer ${winner.layer}. A later layer always wins, so a local rule can only ever tighten what an earlier, shared configuration opened.`,
242873
+ message: `For "${relPath}", the exact key "${candidate.rawKey}" from layer ${String(candidate.layer)} is overridden by the glob "${winner.rawKey}" from the later layer ${String(winner.layer)}. A later layer always wins, so a local rule can only ever tighten what an earlier, shared configuration opened.`,
242874
242874
  subject: relPath,
242875
242875
  layer: winner.layer
242876
242876
  });
@@ -242891,7 +242891,7 @@ function dedupeDiagnostics(diagnostics) {
242891
242891
  const seen = /* @__PURE__ */ new Set();
242892
242892
  const unique = [];
242893
242893
  for (const diagnostic of diagnostics) {
242894
- const key = `${diagnostic.code}\0${diagnostic.subject ?? ""}\0${diagnostic.layer ?? ""}\0${diagnostic.message}`;
242894
+ const key = `${diagnostic.code} ${diagnostic.subject ?? ""} ${diagnostic.layer === void 0 ? "" : String(diagnostic.layer)} ${diagnostic.message}`;
242895
242895
  if (seen.has(key)) {
242896
242896
  continue;
242897
242897
  }
@@ -243041,7 +243041,7 @@ var DEFAULT_MAX_ATTEMPTS = 200;
243041
243041
  var IdentityLockBusyError = class extends CliError {
243042
243042
  constructor(identity, lockPath, holderPid) {
243043
243043
  super(
243044
- `Another claude-use resync is already running for identity "${identity}"` + (holderPid === void 0 ? "" : ` (pid ${holderPid})`) + `. Its lock at ${lockPath} was still held after the full retry budget; nothing was changed.`
243044
+ `Another claude-use resync is already running for identity "${identity}"` + (holderPid === void 0 ? "" : ` (pid ${String(holderPid)})`) + `. Its lock at ${lockPath} was still held after the full retry budget; nothing was changed.`
243045
243045
  );
243046
243046
  this.identity = identity;
243047
243047
  this.lockPath = lockPath;
@@ -243190,25 +243190,21 @@ function buildEntryFacts(params) {
243190
243190
  entries
243191
243191
  };
243192
243192
  }
243193
- function listSubtree(fs9, root, rel, out) {
243193
+ function listSubtree(fs9, root, rel) {
243194
243194
  const absolute = import_node_path8.default.join(root, rel);
243195
243195
  const stat = fs9.lstat(absolute);
243196
243196
  if (stat === void 0) {
243197
- return;
243197
+ return [];
243198
243198
  }
243199
243199
  if (stat.kind === "symlink") {
243200
- out.push({ rel, kind: "symlink" });
243201
- return;
243200
+ return [{ rel, kind: "symlink" }];
243202
243201
  }
243203
243202
  if (stat.kind === "dir") {
243204
- out.push({ rel, kind: "dir" });
243205
- for (const name of [...fs9.readdir(absolute)].sort()) {
243206
- listSubtree(fs9, root, `${rel}/${name}`, out);
243207
- }
243208
- return;
243203
+ const children = [...fs9.readdir(absolute)].sort().flatMap((name) => listSubtree(fs9, root, `${rel}/${name}`));
243204
+ return [{ rel, kind: "dir" }, ...children];
243209
243205
  }
243210
243206
  const contentHash = fs9.hashFile(absolute);
243211
- out.push({ rel, kind: "file", ...contentHash === void 0 ? {} : { contentHash } });
243207
+ return [{ rel, kind: "file", ...contentHash === void 0 ? {} : { contentHash } }];
243212
243208
  }
243213
243209
  function topLevelScopeRoots(roots) {
243214
243210
  const sorted = [...new Set(roots)].sort();
@@ -243228,11 +243224,7 @@ function reconciliationScope(fs9, farmRoot, manifest) {
243228
243224
  return [...fs9.readdir(farmRoot)].filter((name) => name !== FARM_MANIFEST_FILENAME && fs9.lstat(import_node_path8.default.join(farmRoot, name))?.kind === "dir").sort();
243229
243225
  }
243230
243226
  function collectFarmListing(fs9, farmRoot, scopeRoots) {
243231
- const out = [];
243232
- for (const root of scopeRoots) {
243233
- listSubtree(fs9, farmRoot, root, out);
243234
- }
243235
- return out;
243227
+ return scopeRoots.flatMap((root) => listSubtree(fs9, farmRoot, root));
243236
243228
  }
243237
243229
  function collectCanonicalCounterparts(fs9, claudeHome, farmListing) {
243238
243230
  const out = [];
@@ -243438,7 +243430,7 @@ function executeReconciliation(params) {
243438
243430
  adopted.push(action.rel);
243439
243431
  continue;
243440
243432
  }
243441
- const preserved = `${canonical}.farm-conflict-${params.nowMs}`;
243433
+ const preserved = `${canonical}.farm-conflict-${String(params.nowMs)}`;
243442
243434
  params.fs.mkdirp(import_node_path8.default.dirname(canonical));
243443
243435
  params.fs.copyRecursive(from, preserved);
243444
243436
  conflicts.push(action.rel);
@@ -243451,7 +243443,10 @@ function sameLinks(a2, b) {
243451
243443
  }
243452
243444
  return a2.every((link, index) => {
243453
243445
  const other = b[index];
243454
- return other?.rel === link.rel && other?.target === link.target;
243446
+ if (other === void 0) {
243447
+ return false;
243448
+ }
243449
+ return other.rel === link.rel && other.target === link.target;
243455
243450
  });
243456
243451
  }
243457
243452
  function sameStrings(a2, b) {
@@ -243572,16 +243567,16 @@ function recoveryDiagnostics(recovery, identity) {
243572
243567
  }
243573
243568
  const parts = [];
243574
243569
  if (recovery.removedScratch.length > 0) {
243575
- parts.push(`removed ${recovery.removedScratch.length} abandoned scratch tree(s)`);
243570
+ parts.push(`removed ${String(recovery.removedScratch.length)} abandoned scratch tree(s)`);
243576
243571
  }
243577
243572
  if (recovery.restoredFrom !== void 0) {
243578
243573
  parts.push(`restored the farm from ${recovery.restoredFrom}, which a previous launch was killed mid-swap`);
243579
243574
  }
243580
243575
  if (recovery.completed.length > 0) {
243581
- parts.push(`finished carrying local state out of ${recovery.completed.length} superseded farm(s)`);
243576
+ parts.push(`finished carrying local state out of ${String(recovery.completed.length)} superseded farm(s)`);
243582
243577
  }
243583
243578
  if (recovery.autoResolved.length > 0) {
243584
- parts.push(`discarded ${recovery.autoResolved.length} superseded runtime entr${recovery.autoResolved.length === 1 ? "y" : "ies"} (${recovery.autoResolved.join(", ")}) \u2014 disposable per-machine state, safe to drop without asking`);
243579
+ parts.push(`discarded ${String(recovery.autoResolved.length)} superseded runtime entr${recovery.autoResolved.length === 1 ? "y" : "ies"} (${recovery.autoResolved.join(", ")}) \u2014 disposable per-machine state, safe to drop without asking`);
243585
243580
  }
243586
243581
  if (recovery.retained.length > 0) {
243587
243582
  parts.push(
@@ -243886,8 +243881,9 @@ var realFarmFs = {
243886
243881
  }
243887
243882
  }
243888
243883
  };
243884
+ var INT32_BYTE_LENGTH = 4;
243889
243885
  function realSleepSync(ms) {
243890
- Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
243886
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(INT32_BYTE_LENGTH)), 0, 0, ms);
243891
243887
  }
243892
243888
  function realIsProcessAlive(pid) {
243893
243889
  try {
@@ -243900,7 +243896,7 @@ function realIsProcessAlive(pid) {
243900
243896
  var realRunPort = {
243901
243897
  run(command, args) {
243902
243898
  const result = (0, import_node_child_process2.spawnSync)(command, [...args], { encoding: "utf8" });
243903
- return { status: result.status, stdout: result.stdout ?? "", stderr: result.stderr ?? "" };
243899
+ return { status: result.status, stdout: result.stdout, stderr: result.stderr };
243904
243900
  }
243905
243901
  };
243906
243902
  function resolveGitBranch(run, cwd) {
@@ -243929,10 +243925,17 @@ var realProcPort = {
243929
243925
  exit: (code) => process.exit(code)
243930
243926
  };
243931
243927
  var realLogPort = {
243932
- info: (message) => console.log(message),
243933
- warn: (message) => console.warn(message),
243934
- error: (message) => console.error(message)
243928
+ info: (message) => {
243929
+ console.log(message);
243930
+ },
243931
+ warn: (message) => {
243932
+ console.warn(message);
243933
+ },
243934
+ error: (message) => {
243935
+ console.error(message);
243936
+ }
243935
243937
  };
243938
+ var EXECUTE_BITS_MASK = 73;
243936
243939
  function listVersionsDir(dir) {
243937
243940
  let entries;
243938
243941
  try {
@@ -243949,7 +243952,7 @@ function listVersionsDir(dir) {
243949
243952
  return {
243950
243953
  name: entry.name,
243951
243954
  isFile: true,
243952
- isExecutable: (stat.mode & 73) !== 0,
243955
+ isExecutable: (stat.mode & EXECUTE_BITS_MASK) !== 0,
243953
243956
  sizeBytes: stat.size
243954
243957
  };
243955
243958
  });
@@ -243975,7 +243978,7 @@ function resolveExecutableCandidate(dir, name, env) {
243975
243978
  return void 0;
243976
243979
  }
243977
243980
  const mode = env.statFileMode(candidate);
243978
- return mode !== void 0 && (mode & 73) !== 0 ? candidate : void 0;
243981
+ return mode !== void 0 && (mode & EXECUTE_BITS_MASK) !== 0 ? candidate : void 0;
243979
243982
  }
243980
243983
  function realStatFileMode(candidate) {
243981
243984
  try {
@@ -243995,9 +243998,9 @@ function findExecutableInDir(dir, name) {
243995
243998
  statFileMode: realStatFileMode
243996
243999
  });
243997
244000
  }
243998
- function searchPathForExecutable(pathDirs, name, findExecutableInDir2) {
244001
+ function searchPathForExecutable(pathDirs, name, findExecutable) {
243999
244002
  for (const dir of pathDirs) {
244000
- const found = findExecutableInDir2(dir, name);
244003
+ const found = findExecutable(dir, name);
244001
244004
  if (found !== void 0) {
244002
244005
  return found;
244003
244006
  }
@@ -244085,7 +244088,7 @@ function formatDecision(decision) {
244085
244088
  reason = "unclassified entry (no category recognises it)";
244086
244089
  break;
244087
244090
  case "entry-rule":
244088
- reason = decision.rule === void 0 ? "an entries rule" : `entries rule "${decision.rule.rawKey}" from layer ${decision.rule.layer}`;
244091
+ reason = decision.rule === void 0 ? "an entries rule" : `entries rule "${decision.rule.rawKey}" from layer ${String(decision.rule.layer)}`;
244089
244092
  break;
244090
244093
  case "category-override":
244091
244094
  reason = `category "${decision.category ?? "?"}" overridden by a layer`;
@@ -244094,7 +244097,7 @@ function formatDecision(decision) {
244094
244097
  reason = `category "${decision.category ?? "?"}" shipped default`;
244095
244098
  break;
244096
244099
  }
244097
- const eliminatedNote = decision.eliminated !== void 0 && decision.eliminated.length > 0 ? ` [${decision.eliminated.length} more specific rule(s) eliminated by a failing when-condition]` : "";
244100
+ const eliminatedNote = decision.eliminated !== void 0 && decision.eliminated.length > 0 ? ` [${String(decision.eliminated.length)} more specific rule(s) eliminated by a failing when-condition]` : "";
244098
244101
  return `${decision.relPath}: ${status} \u2014 ${reason}${eliminatedNote}`;
244099
244102
  }
244100
244103
  function parseKeychainServiceName(stderr) {
@@ -244107,7 +244110,7 @@ function lookupKeychainService(run, farmRoot) {
244107
244110
  return {
244108
244111
  checked: true,
244109
244112
  found: false,
244110
- note: `No Keychain entry found for account "${farmRoot}" (security exited ${result.status ?? "with no status"}).`
244113
+ note: `No Keychain entry found for account "${farmRoot}" (security exited ${result.status === null ? "with no status" : String(result.status)}).`
244111
244114
  };
244112
244115
  }
244113
244116
  const serviceName = parseKeychainServiceName(result.stderr);
@@ -244214,7 +244217,7 @@ function formatCheckReport(report) {
244214
244217
  lines.push(`Configuration profile: ${report.configProfileName ?? "(none)"} (${report.configProfileSource})`);
244215
244218
  lines.push("", "Layers (shallowest/earliest first):");
244216
244219
  for (const layer of report.resolved.assembled.layers) {
244217
- lines.push(` [${layer.id}] ${layer.kind}: ${layer.source}`);
244220
+ lines.push(` [${String(layer.id)}] ${layer.kind}: ${layer.source}`);
244218
244221
  }
244219
244222
  lines.push("", "Resolved entries:");
244220
244223
  if (report.decisionLines.length === 0) {
@@ -244247,7 +244250,7 @@ function formatCheckReport(report) {
244247
244250
  lines.push("", "Settings exposure (names and counts only, never values):");
244248
244251
  for (const exposure of report.settingsExposure) {
244249
244252
  lines.push(
244250
- ` ${exposure.file}: ${exposure.envKeyNames.length} env key(s) [${exposure.envKeyNames.join(", ")}], ${exposure.hookEventNames.length} hook event(s) [${exposure.hookEventNames.join(", ")}], ${exposure.hookCommandCount} hook command(s)`
244253
+ ` ${exposure.file}: ${String(exposure.envKeyNames.length)} env key(s) [${exposure.envKeyNames.join(", ")}], ${String(exposure.hookEventNames.length)} hook event(s) [${exposure.hookEventNames.join(", ")}], ${String(exposure.hookCommandCount)} hook command(s)`
244251
244254
  );
244252
244255
  }
244253
244256
  }
@@ -245801,7 +245804,9 @@ async function runIdentityWizard(prompts, paths, name) {
245801
245804
  options: [
245802
245805
  { value: "create", label: "Create and configure a profile" },
245803
245806
  { value: "skip", label: "Skip for now" }
245804
- ]
245807
+ ],
245808
+ // Most identities need no profile of their own at all — they're meant to fall through to whatever the global default (or a directory rule) already resolves to, and a profile only earns its keep once an identity genuinely needs to diverge from that. Defaulting the cursor to "skip" makes the common, no-profile-needed case the one a bare Enter confirms, without reordering the options and making "skip" read as the first, most prominent choice on screen.
245809
+ initialValue: "skip"
245805
245810
  });
245806
245811
  if (!prompts.isCancel(profileChoice) && profileChoice === "create") {
245807
245812
  const result = await runProfileWizard(prompts, { paths, defaultNewName: name });
@@ -245927,7 +245932,7 @@ function registerIdentityCommand(program2, paths) {
245927
245932
  });
245928
245933
  if (result.autoResolved.length > 0) {
245929
245934
  console.log(
245930
- `Auto-resolved ${result.autoResolved.length} disposable runtime entr${result.autoResolved.length === 1 ? "y" : "ies"} with no prompt (${result.autoResolved.join(", ")}) \u2014 per-process/per-machine state, never worth asking about.`
245935
+ `Auto-resolved ${String(result.autoResolved.length)} disposable runtime entr${result.autoResolved.length === 1 ? "y" : "ies"} with no prompt (${result.autoResolved.join(", ")}) \u2014 per-process/per-machine state, never worth asking about.`
245931
245936
  );
245932
245937
  }
245933
245938
  if (result.resolved.length === 0) {
@@ -245940,7 +245945,7 @@ function registerIdentityCommand(program2, paths) {
245940
245945
  console.log(` ${conflict.name}: ${conflict.choice}`);
245941
245946
  }
245942
245947
  console.log(
245943
- `Resolved ${result.resolved.length} conflict(s) \u2014 ${result.removed.length} superseded director(ies) fully cleared, ${result.retained.length} still retained pending a skipped conflict.`
245948
+ `Resolved ${String(result.resolved.length)} conflict(s) \u2014 ${String(result.removed.length)} superseded director(ies) fully cleared, ${String(result.retained.length)} still retained pending a skipped conflict.`
245944
245949
  );
245945
245950
  });
245946
245951
  identity.command("list").description("List every identity, marking the active one.").action(() => {
@@ -246037,6 +246042,9 @@ function addDirectoryRule(paths, rulePath, options) {
246037
246042
  writeDirectoryRules(paths, { ...current, rules: [...current.rules, updated] });
246038
246043
  } else {
246039
246044
  const existingRule = current.rules[existingIndex];
246045
+ if (existingRule === void 0) {
246046
+ throw new Error(`Directory rule at index ${String(existingIndex)} unexpectedly missing.`);
246047
+ }
246040
246048
  updated = {
246041
246049
  ...existingRule,
246042
246050
  ...options.configProfile !== void 0 ? { configProfile: options.configProfile } : {},
@@ -246073,9 +246081,9 @@ function registerRulesCommand(program2, paths) {
246073
246081
  console.log(`No configuration profile named "${profileName}" was created; the rule pins identity only.`);
246074
246082
  profileName = void 0;
246075
246083
  } else {
246076
- if (result.name !== options.profile) {
246084
+ if (result.name !== profileName) {
246077
246085
  console.log(
246078
- `Created configuration profile "${result.name}" instead of "${options.profile}". The rule selects that name.`
246086
+ `Created configuration profile "${result.name}" instead of "${profileName}". The rule selects that name.`
246079
246087
  );
246080
246088
  }
246081
246089
  profileName = result.name;
@@ -246117,16 +246125,17 @@ function isKnownOptionValue(value, options) {
246117
246125
  return options.some((option) => option.value === value);
246118
246126
  }
246119
246127
  var realPromptsPort = {
246120
- select: (params) => select({
246128
+ select: async (params) => select({
246121
246129
  message: params.message,
246122
- options: toClackOptions(params.options)
246130
+ options: toClackOptions(params.options),
246131
+ ...params.initialValue === void 0 ? {} : { initialValue: params.initialValue }
246123
246132
  }).then((value) => {
246124
246133
  if (typeof value === "symbol" || isKnownOptionValue(value, params.options)) {
246125
246134
  return value;
246126
246135
  }
246127
246136
  throw new Error(`@clack/prompts select() returned a value not present in the given options: ${value}`);
246128
246137
  }),
246129
- multiselect: (params) => multiselect({
246138
+ multiselect: async (params) => multiselect({
246130
246139
  message: params.message,
246131
246140
  options: toClackOptions(params.options),
246132
246141
  ...params.initialValues === void 0 ? {} : { initialValues: [...params.initialValues] }
@@ -246136,7 +246145,7 @@ var realPromptsPort = {
246136
246145
  }
246137
246146
  throw new Error(`@clack/prompts multiselect() returned a value not present in the given options: ${value.join(", ")}`);
246138
246147
  }),
246139
- text: (params) => text({
246148
+ text: async (params) => text({
246140
246149
  message: params.message,
246141
246150
  ...params.placeholder === void 0 ? {} : { placeholder: params.placeholder },
246142
246151
  ...params.validate === void 0 ? {} : {
@@ -246181,6 +246190,8 @@ function describeWriteTarget(target) {
246181
246190
  return `directory rule for "${target.rulePath}"`;
246182
246191
  case "config-profile":
246183
246192
  return `configuration profile "${target.profileName}"`;
246193
+ default:
246194
+ return target;
246184
246195
  }
246185
246196
  }
246186
246197
  function writeCategoryPatch(paths, target, patch) {
@@ -246194,10 +246205,10 @@ function writeCategoryPatch(paths, target, patch) {
246194
246205
  case "directory-rule": {
246195
246206
  const rules = readDirectoryRules(paths);
246196
246207
  const index = rules.rules.findIndex((rule) => rule.path === target.rulePath);
246197
- if (index === -1) {
246208
+ const existingRule = index === -1 ? void 0 : rules.rules[index];
246209
+ if (existingRule === void 0) {
246198
246210
  throw new Error(`Directory rule for "${target.rulePath}" no longer exists.`);
246199
246211
  }
246200
- const existingRule = rules.rules[index];
246201
246212
  const merged = { ...existingRule.categories, ...patch };
246202
246213
  const nextRules = [...rules.rules];
246203
246214
  nextRules[index] = { ...existingRule, categories: merged };
@@ -246220,10 +246231,10 @@ function writeEntriesPatch(paths, target, patch) {
246220
246231
  case "directory-rule": {
246221
246232
  const rules = readDirectoryRules(paths);
246222
246233
  const index = rules.rules.findIndex((rule) => rule.path === target.rulePath);
246223
- if (index === -1) {
246234
+ const existingRule = index === -1 ? void 0 : rules.rules[index];
246235
+ if (existingRule === void 0) {
246224
246236
  throw new Error(`Directory rule for "${target.rulePath}" no longer exists.`);
246225
246237
  }
246226
- const existingRule = rules.rules[index];
246227
246238
  const merged = { ...existingRule.entries, ...patch };
246228
246239
  const nextRules = [...rules.rules];
246229
246240
  nextRules[index] = { ...existingRule, entries: merged };
@@ -246351,7 +246362,7 @@ function validateProfileName(value, existingNames) {
246351
246362
  if (!PROFILE_NAME_RE.test(value)) {
246352
246363
  return "Names must start with a letter or digit, and contain only letters, digits, dots, dashes, underscores, and at signs.";
246353
246364
  }
246354
- if (existingNames?.includes(value)) {
246365
+ if (existingNames?.includes(value) ?? false) {
246355
246366
  return `A configuration profile named "${value}" already exists.`;
246356
246367
  }
246357
246368
  return void 0;
@@ -246549,7 +246560,9 @@ function registerConfigureCommand(program2, paths) {
246549
246560
  "Interactively toggle an identity's shared categories, or a specific path's entries overrides, writing to whichever file the 3-tier precedence selects."
246550
246561
  ).action(async (identityName, pathArg) => {
246551
246562
  await runConfigure(
246552
- { paths, prompts: realPromptsPort, log: { info: (message) => console.log(message) } },
246563
+ { paths, prompts: realPromptsPort, log: { info: (message) => {
246564
+ console.log(message);
246565
+ } } },
246553
246566
  {
246554
246567
  identityName,
246555
246568
  ...pathArg === void 0 ? {} : { path: pathArg },
@@ -246564,6 +246577,7 @@ function registerConfigureCommand(program2, paths) {
246564
246577
  // src/claudeShim.ts
246565
246578
  var import_node_fs7 = __toESM(require("node:fs"), 1);
246566
246579
  var import_node_path18 = __toESM(require("node:path"), 1);
246580
+ var EXECUTABLE_FILE_MODE = 493;
246567
246581
  var ClaudeShimStateSchema = external_exports.strictObject({
246568
246582
  targetPath: external_exports.string().min(1),
246569
246583
  method: external_exports.enum(["hardlink", "copy"]),
@@ -246655,7 +246669,7 @@ function enableClaudeShim(params, linkFs = nodeLinkFs) {
246655
246669
  throw error62;
246656
246670
  }
246657
246671
  linkFs.copyFile(realContentPath, targetPath);
246658
- linkFs.chmod(targetPath, 493);
246672
+ linkFs.chmod(targetPath, EXECUTABLE_FILE_MODE);
246659
246673
  method = "copy";
246660
246674
  }
246661
246675
  const newState = { targetPath, method, installedAtMs: Date.now() };
@@ -246992,6 +247006,8 @@ function severityPrefix(severity) {
246992
247006
  return "[WARN]";
246993
247007
  case "fail":
246994
247008
  return "[FAIL]";
247009
+ default:
247010
+ return severity;
246995
247011
  }
246996
247012
  }
246997
247013
  function formatDoctorReport(report) {
@@ -247008,7 +247024,7 @@ function formatDoctorReport(report) {
247008
247024
  }
247009
247025
  }
247010
247026
  const failCount = report.findings.filter((finding) => finding.severity === "fail").length;
247011
- lines.push("", report.ok ? "All checks passed." : `${failCount} check(s) failed.`);
247027
+ lines.push("", report.ok ? "All checks passed." : `${String(failCount)} check(s) failed.`);
247012
247028
  return lines;
247013
247029
  }
247014
247030
  function realpathOrSelf(target) {
@@ -247113,6 +247129,9 @@ function parseLauncherArgv(argv) {
247113
247129
  const rest = [];
247114
247130
  for (let index = 0; index < remaining.length; index += 1) {
247115
247131
  const token = remaining[index];
247132
+ if (token === void 0) {
247133
+ continue;
247134
+ }
247116
247135
  const matched = matchValuedFlag(token);
247117
247136
  if (matched === void 0) {
247118
247137
  rest.push(token);
@@ -247267,13 +247286,13 @@ function splitExtraFlags(value) {
247267
247286
 
247268
247287
  // src/launcher/spawn.ts
247269
247288
  var import_node_os5 = __toESM(require("node:os"), 1);
247289
+ var SIGNAL_EXIT_CODE_OFFSET = 128;
247270
247290
  function exitCodeFor(result) {
247271
247291
  if (result.status !== null) {
247272
247292
  return result.status;
247273
247293
  }
247274
247294
  if (result.signal !== null) {
247275
- const signalNumber = import_node_os5.default.constants.signals[result.signal];
247276
- return signalNumber === void 0 ? 1 : 128 + signalNumber;
247295
+ return SIGNAL_EXIT_CODE_OFFSET + import_node_os5.default.constants.signals[result.signal];
247277
247296
  }
247278
247297
  return 1;
247279
247298
  }
@@ -247326,7 +247345,7 @@ function runLauncher(params) {
247326
247345
  } catch (error62) {
247327
247346
  if (error62 instanceof IdentityLockBusyError) {
247328
247347
  log.error(error62.message);
247329
- return proc.exit(1);
247348
+ proc.exit(1);
247330
247349
  }
247331
247350
  throw error62;
247332
247351
  }
@@ -247351,7 +247370,7 @@ function runLauncher(params) {
247351
247370
  });
247352
247371
  if (!guardResult.ok) {
247353
247372
  log.error(guardResult.message);
247354
- return proc.exit(1);
247373
+ proc.exit(1);
247355
247374
  }
247356
247375
  const configProfileDecision = decideConfigProfile({
247357
247376
  env,
@@ -247387,7 +247406,7 @@ function runLauncher(params) {
247387
247406
  } catch (error62) {
247388
247407
  if (error62 instanceof IdentityLockBusyError) {
247389
247408
  log.error(error62.message);
247390
- return proc.exit(1);
247409
+ proc.exit(1);
247391
247410
  }
247392
247411
  throw error62;
247393
247412
  }
@@ -247399,7 +247418,7 @@ function runLauncher(params) {
247399
247418
  }
247400
247419
  }
247401
247420
  log.info(
247402
- result.noOp ? `claude-use: farm at ${result.farmRoot} already matches the resolved cascade` : `claude-use: farm at ${result.farmRoot} resynced (${result.manifest.links.length} link(s), ${result.manifest.materialised.length} built director(ies)${result.adopted.length === 0 ? "" : `, ${result.adopted.length} adopted into ${farm.claudeHome}`})`
247421
+ result.noOp ? `claude-use: farm at ${result.farmRoot} already matches the resolved cascade` : `claude-use: farm at ${result.farmRoot} resynced (${String(result.manifest.links.length)} link(s), ${String(result.manifest.materialised.length)} built director(ies)${result.adopted.length === 0 ? "" : `, ${String(result.adopted.length)} adopted into ${farm.claudeHome}`})`
247403
247422
  );
247404
247423
  cascadeLaunch = result.resolved.flattened.launch;
247405
247424
  }
@@ -247464,7 +247483,7 @@ function buildFarmRuntime(paths) {
247464
247483
  ...cliOverride === void 0 ? {} : { cliOverride }
247465
247484
  }).input,
247466
247485
  now: () => Date.now(),
247467
- uniqueSuffix: `${process.pid}.${(0, import_node_crypto4.randomUUID)()}`,
247486
+ uniqueSuffix: `${String(process.pid)}.${(0, import_node_crypto4.randomUUID)()}`,
247468
247487
  lock: { pid: process.pid, isProcessAlive: realIsProcessAlive, sleep: realSleepSync }
247469
247488
  },
247470
247489
  ...selections.identity === void 0 ? {} : { directoryIdentity: selections.identity },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-use",
3
- "version": "2.3.1",
3
+ "version": "2.4.1",
4
4
  "description": "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Joseph Mearman <joseph@mearman.co.uk>",
@@ -15,7 +15,7 @@
15
15
  "claude",
16
16
  "cli"
17
17
  ],
18
- "packageManager": "pnpm@11.6.0",
18
+ "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c",
19
19
  "type": "module",
20
20
  "engines": {
21
21
  "node": ">=22.12.0"
@@ -54,7 +54,7 @@
54
54
  "devDependencies": {
55
55
  "@commitlint/cli": "^21.2.2",
56
56
  "@commitlint/config-conventional": "^21.2.2",
57
- "@eslint/js": "^10.0.1",
57
+ "@exadev/eslint-config": "2.12.1",
58
58
  "@semantic-release/changelog": "^7.0.0",
59
59
  "@semantic-release/git": "^11.0.1",
60
60
  "@semantic-release/npm": "^13.1.5",