claude-use 2.4.0 → 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 +85 -69
  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.4.0",
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
  }
@@ -245929,7 +245932,7 @@ function registerIdentityCommand(program2, paths) {
245929
245932
  });
245930
245933
  if (result.autoResolved.length > 0) {
245931
245934
  console.log(
245932
- `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.`
245933
245936
  );
245934
245937
  }
245935
245938
  if (result.resolved.length === 0) {
@@ -245942,7 +245945,7 @@ function registerIdentityCommand(program2, paths) {
245942
245945
  console.log(` ${conflict.name}: ${conflict.choice}`);
245943
245946
  }
245944
245947
  console.log(
245945
- `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.`
245946
245949
  );
245947
245950
  });
245948
245951
  identity.command("list").description("List every identity, marking the active one.").action(() => {
@@ -246039,6 +246042,9 @@ function addDirectoryRule(paths, rulePath, options) {
246039
246042
  writeDirectoryRules(paths, { ...current, rules: [...current.rules, updated] });
246040
246043
  } else {
246041
246044
  const existingRule = current.rules[existingIndex];
246045
+ if (existingRule === void 0) {
246046
+ throw new Error(`Directory rule at index ${String(existingIndex)} unexpectedly missing.`);
246047
+ }
246042
246048
  updated = {
246043
246049
  ...existingRule,
246044
246050
  ...options.configProfile !== void 0 ? { configProfile: options.configProfile } : {},
@@ -246075,9 +246081,9 @@ function registerRulesCommand(program2, paths) {
246075
246081
  console.log(`No configuration profile named "${profileName}" was created; the rule pins identity only.`);
246076
246082
  profileName = void 0;
246077
246083
  } else {
246078
- if (result.name !== options.profile) {
246084
+ if (result.name !== profileName) {
246079
246085
  console.log(
246080
- `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.`
246081
246087
  );
246082
246088
  }
246083
246089
  profileName = result.name;
@@ -246119,7 +246125,7 @@ function isKnownOptionValue(value, options) {
246119
246125
  return options.some((option) => option.value === value);
246120
246126
  }
246121
246127
  var realPromptsPort = {
246122
- select: (params) => select({
246128
+ select: async (params) => select({
246123
246129
  message: params.message,
246124
246130
  options: toClackOptions(params.options),
246125
246131
  ...params.initialValue === void 0 ? {} : { initialValue: params.initialValue }
@@ -246129,7 +246135,7 @@ var realPromptsPort = {
246129
246135
  }
246130
246136
  throw new Error(`@clack/prompts select() returned a value not present in the given options: ${value}`);
246131
246137
  }),
246132
- multiselect: (params) => multiselect({
246138
+ multiselect: async (params) => multiselect({
246133
246139
  message: params.message,
246134
246140
  options: toClackOptions(params.options),
246135
246141
  ...params.initialValues === void 0 ? {} : { initialValues: [...params.initialValues] }
@@ -246139,7 +246145,7 @@ var realPromptsPort = {
246139
246145
  }
246140
246146
  throw new Error(`@clack/prompts multiselect() returned a value not present in the given options: ${value.join(", ")}`);
246141
246147
  }),
246142
- text: (params) => text({
246148
+ text: async (params) => text({
246143
246149
  message: params.message,
246144
246150
  ...params.placeholder === void 0 ? {} : { placeholder: params.placeholder },
246145
246151
  ...params.validate === void 0 ? {} : {
@@ -246184,6 +246190,8 @@ function describeWriteTarget(target) {
246184
246190
  return `directory rule for "${target.rulePath}"`;
246185
246191
  case "config-profile":
246186
246192
  return `configuration profile "${target.profileName}"`;
246193
+ default:
246194
+ return target;
246187
246195
  }
246188
246196
  }
246189
246197
  function writeCategoryPatch(paths, target, patch) {
@@ -246197,10 +246205,10 @@ function writeCategoryPatch(paths, target, patch) {
246197
246205
  case "directory-rule": {
246198
246206
  const rules = readDirectoryRules(paths);
246199
246207
  const index = rules.rules.findIndex((rule) => rule.path === target.rulePath);
246200
- if (index === -1) {
246208
+ const existingRule = index === -1 ? void 0 : rules.rules[index];
246209
+ if (existingRule === void 0) {
246201
246210
  throw new Error(`Directory rule for "${target.rulePath}" no longer exists.`);
246202
246211
  }
246203
- const existingRule = rules.rules[index];
246204
246212
  const merged = { ...existingRule.categories, ...patch };
246205
246213
  const nextRules = [...rules.rules];
246206
246214
  nextRules[index] = { ...existingRule, categories: merged };
@@ -246223,10 +246231,10 @@ function writeEntriesPatch(paths, target, patch) {
246223
246231
  case "directory-rule": {
246224
246232
  const rules = readDirectoryRules(paths);
246225
246233
  const index = rules.rules.findIndex((rule) => rule.path === target.rulePath);
246226
- if (index === -1) {
246234
+ const existingRule = index === -1 ? void 0 : rules.rules[index];
246235
+ if (existingRule === void 0) {
246227
246236
  throw new Error(`Directory rule for "${target.rulePath}" no longer exists.`);
246228
246237
  }
246229
- const existingRule = rules.rules[index];
246230
246238
  const merged = { ...existingRule.entries, ...patch };
246231
246239
  const nextRules = [...rules.rules];
246232
246240
  nextRules[index] = { ...existingRule, entries: merged };
@@ -246354,7 +246362,7 @@ function validateProfileName(value, existingNames) {
246354
246362
  if (!PROFILE_NAME_RE.test(value)) {
246355
246363
  return "Names must start with a letter or digit, and contain only letters, digits, dots, dashes, underscores, and at signs.";
246356
246364
  }
246357
- if (existingNames?.includes(value)) {
246365
+ if (existingNames?.includes(value) ?? false) {
246358
246366
  return `A configuration profile named "${value}" already exists.`;
246359
246367
  }
246360
246368
  return void 0;
@@ -246552,7 +246560,9 @@ function registerConfigureCommand(program2, paths) {
246552
246560
  "Interactively toggle an identity's shared categories, or a specific path's entries overrides, writing to whichever file the 3-tier precedence selects."
246553
246561
  ).action(async (identityName, pathArg) => {
246554
246562
  await runConfigure(
246555
- { paths, prompts: realPromptsPort, log: { info: (message) => console.log(message) } },
246563
+ { paths, prompts: realPromptsPort, log: { info: (message) => {
246564
+ console.log(message);
246565
+ } } },
246556
246566
  {
246557
246567
  identityName,
246558
246568
  ...pathArg === void 0 ? {} : { path: pathArg },
@@ -246567,6 +246577,7 @@ function registerConfigureCommand(program2, paths) {
246567
246577
  // src/claudeShim.ts
246568
246578
  var import_node_fs7 = __toESM(require("node:fs"), 1);
246569
246579
  var import_node_path18 = __toESM(require("node:path"), 1);
246580
+ var EXECUTABLE_FILE_MODE = 493;
246570
246581
  var ClaudeShimStateSchema = external_exports.strictObject({
246571
246582
  targetPath: external_exports.string().min(1),
246572
246583
  method: external_exports.enum(["hardlink", "copy"]),
@@ -246658,7 +246669,7 @@ function enableClaudeShim(params, linkFs = nodeLinkFs) {
246658
246669
  throw error62;
246659
246670
  }
246660
246671
  linkFs.copyFile(realContentPath, targetPath);
246661
- linkFs.chmod(targetPath, 493);
246672
+ linkFs.chmod(targetPath, EXECUTABLE_FILE_MODE);
246662
246673
  method = "copy";
246663
246674
  }
246664
246675
  const newState = { targetPath, method, installedAtMs: Date.now() };
@@ -246995,6 +247006,8 @@ function severityPrefix(severity) {
246995
247006
  return "[WARN]";
246996
247007
  case "fail":
246997
247008
  return "[FAIL]";
247009
+ default:
247010
+ return severity;
246998
247011
  }
246999
247012
  }
247000
247013
  function formatDoctorReport(report) {
@@ -247011,7 +247024,7 @@ function formatDoctorReport(report) {
247011
247024
  }
247012
247025
  }
247013
247026
  const failCount = report.findings.filter((finding) => finding.severity === "fail").length;
247014
- lines.push("", report.ok ? "All checks passed." : `${failCount} check(s) failed.`);
247027
+ lines.push("", report.ok ? "All checks passed." : `${String(failCount)} check(s) failed.`);
247015
247028
  return lines;
247016
247029
  }
247017
247030
  function realpathOrSelf(target) {
@@ -247116,6 +247129,9 @@ function parseLauncherArgv(argv) {
247116
247129
  const rest = [];
247117
247130
  for (let index = 0; index < remaining.length; index += 1) {
247118
247131
  const token = remaining[index];
247132
+ if (token === void 0) {
247133
+ continue;
247134
+ }
247119
247135
  const matched = matchValuedFlag(token);
247120
247136
  if (matched === void 0) {
247121
247137
  rest.push(token);
@@ -247270,13 +247286,13 @@ function splitExtraFlags(value) {
247270
247286
 
247271
247287
  // src/launcher/spawn.ts
247272
247288
  var import_node_os5 = __toESM(require("node:os"), 1);
247289
+ var SIGNAL_EXIT_CODE_OFFSET = 128;
247273
247290
  function exitCodeFor(result) {
247274
247291
  if (result.status !== null) {
247275
247292
  return result.status;
247276
247293
  }
247277
247294
  if (result.signal !== null) {
247278
- const signalNumber = import_node_os5.default.constants.signals[result.signal];
247279
- return signalNumber === void 0 ? 1 : 128 + signalNumber;
247295
+ return SIGNAL_EXIT_CODE_OFFSET + import_node_os5.default.constants.signals[result.signal];
247280
247296
  }
247281
247297
  return 1;
247282
247298
  }
@@ -247329,7 +247345,7 @@ function runLauncher(params) {
247329
247345
  } catch (error62) {
247330
247346
  if (error62 instanceof IdentityLockBusyError) {
247331
247347
  log.error(error62.message);
247332
- return proc.exit(1);
247348
+ proc.exit(1);
247333
247349
  }
247334
247350
  throw error62;
247335
247351
  }
@@ -247354,7 +247370,7 @@ function runLauncher(params) {
247354
247370
  });
247355
247371
  if (!guardResult.ok) {
247356
247372
  log.error(guardResult.message);
247357
- return proc.exit(1);
247373
+ proc.exit(1);
247358
247374
  }
247359
247375
  const configProfileDecision = decideConfigProfile({
247360
247376
  env,
@@ -247390,7 +247406,7 @@ function runLauncher(params) {
247390
247406
  } catch (error62) {
247391
247407
  if (error62 instanceof IdentityLockBusyError) {
247392
247408
  log.error(error62.message);
247393
- return proc.exit(1);
247409
+ proc.exit(1);
247394
247410
  }
247395
247411
  throw error62;
247396
247412
  }
@@ -247402,7 +247418,7 @@ function runLauncher(params) {
247402
247418
  }
247403
247419
  }
247404
247420
  log.info(
247405
- 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}`})`
247406
247422
  );
247407
247423
  cascadeLaunch = result.resolved.flattened.launch;
247408
247424
  }
@@ -247467,7 +247483,7 @@ function buildFarmRuntime(paths) {
247467
247483
  ...cliOverride === void 0 ? {} : { cliOverride }
247468
247484
  }).input,
247469
247485
  now: () => Date.now(),
247470
- uniqueSuffix: `${process.pid}.${(0, import_node_crypto4.randomUUID)()}`,
247486
+ uniqueSuffix: `${String(process.pid)}.${(0, import_node_crypto4.randomUUID)()}`,
247471
247487
  lock: { pid: process.pid, isProcessAlive: realIsProcessAlive, sleep: realSleepSync }
247472
247488
  },
247473
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.4.0",
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",