subconscious-cli 6.3.0 → 6.3.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.
@@ -410,23 +410,35 @@ function readQuietly(file) {
410
410
  }
411
411
  }
412
412
 
413
+ /** A free name beside `dir` for a leftover folder: `<dir>.old-<time>`. */
414
+ function asideName(dir) {
415
+ const stamp = new Date().toISOString().replace(/[:.]/g, '-');
416
+ for (let n = 0; ; n++) {
417
+ const name = `${dir}.old-${stamp}${n ? `-${n}` : ''}`;
418
+ if (!lstatOrUndefined(name)) return name;
419
+ }
420
+ }
421
+
413
422
  /**
414
423
  * Make sure `dir` is a subc dir: an earlier launch's marker, or a new or
415
- * empty folder that is claimed now. Returns why a folder is not one, or
416
- * `undefined`. A Claude config folder that subc did not make is never
417
- * prepared, wherever it sits.
424
+ * empty folder that is claimed now. A Claude config there without the
425
+ * marker is left by an earlier subc build: it is renamed aside, never
426
+ * deleted, and a fresh dir is claimed. When the user's own
427
+ * CLAUDE_CONFIG_DIR is `dir` (`userDir`), it is theirs and is refused.
428
+ * Returns why a folder is not a subc dir, or `undefined`.
418
429
  */
419
- function claimDir(dir) {
430
+ function claimDir(dir, userDir, warnings) {
420
431
  const marker = path.join(dir, WRITTEN_FILE);
421
432
  if (lstatOrUndefined(marker)) return undefined;
422
- const existing = lstatOrUndefined(dir);
423
- if (existing) {
424
- const holdsConfig = ['settings.json', '.claude.json', 'projects'].some(
425
- (name) => lstatOrUndefined(path.join(dir, name)),
426
- );
427
- if (holdsConfig) {
428
- return `${dir} holds a Claude config that subc did not make. If it is an old subc folder, rename it and launch again.`;
433
+ if (lstatOrUndefined(dir) && looksLikeClaudeConfig(dir)) {
434
+ if (userDir) {
435
+ return `${dir} holds a Claude config that subc did not make`;
429
436
  }
437
+ const aside = asideName(dir);
438
+ fs.renameSync(dir, aside);
439
+ warnings.push(
440
+ `Moved an old subc Claude config folder to ${aside}; subc sessions now start from your own Claude setup.`,
441
+ );
430
442
  }
431
443
  fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
432
444
  writeJsonAtomic(marker, {}, 0o600);
@@ -452,7 +464,8 @@ function readWritten(dir) {
452
464
  * .claude.json inside their CLAUDE_CONFIG_DIR).
453
465
  *
454
466
  * @param {{ dir: string, home?: string, source?: string, stateFile?: string,
455
- * launchEnvNames?: Iterable<string> }} options
467
+ * launchEnvNames?: Iterable<string>, userDir?: boolean }} options
468
+ * `userDir` means the user's own CLAUDE_CONFIG_DIR is `dir`.
456
469
  * @returns {{ warnings: string[], refused: boolean }} `refused` means the
457
470
  * dir aliases the user's own config; the launch must not run on it.
458
471
  */
@@ -462,14 +475,15 @@ export function prepareClaudeConfigDir({
462
475
  source = path.join(home, '.claude'),
463
476
  stateFile = path.join(home, '.claude.json'),
464
477
  launchEnvNames = [],
478
+ userDir = false,
465
479
  }) {
466
480
  const warnings = [];
467
481
  let unsafe = unsafeDirReason(dir, source, stateFile);
468
482
  if (!unsafe) {
469
483
  try {
470
- unsafe = claimDir(dir);
484
+ unsafe = claimDir(dir, userDir, warnings);
471
485
  } catch (error) {
472
- unsafe = `could not create it: ${error.message}`;
486
+ unsafe = `could not prepare it: ${error.message}`;
473
487
  }
474
488
  }
475
489
  if (unsafe) {
@@ -529,6 +543,17 @@ function looksLikeClaudeConfig(folder) {
529
543
  );
530
544
  }
531
545
 
546
+ /** Whether the user's own env names `dir` as their Claude config folder. */
547
+ function pointsAt(inputEnv, dir) {
548
+ return [SOURCE_ENV, 'CLAUDE_CONFIG_DIR'].some((name) => {
549
+ const value = inputEnv[name]?.trim();
550
+ if (!value || !path.isAbsolute(value)) return false;
551
+ if (path.resolve(value) === path.resolve(dir)) return true;
552
+ const id = identity(value);
553
+ return Boolean(id) && id === identity(dir);
554
+ });
555
+ }
556
+
532
557
  /**
533
558
  * The user's own Claude config folder for a launch: the one carried from an
534
559
  * outer subc session, else their CLAUDE_CONFIG_DIR, else ~/.claude. The subc
@@ -615,6 +640,7 @@ export function prepareClaudeLaunch(agent, launchEnv, inputEnv, options = {}) {
615
640
  source,
616
641
  stateFile,
617
642
  launchEnvNames,
643
+ userDir: pointsAt(inputEnv, dir),
618
644
  });
619
645
  return {
620
646
  warnings: [...warnings, ...prepared.warnings],
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "subconscious-cli",
3
- "version": "6.3.0",
3
+ "version": "6.3.1",
4
4
  "description": "CLI for Subconscious — run Subconscious Code, Claude Code, Codex, OpenCode, DeepSeek Harness, Copilot, and Pi",
5
5
  "bin": {
6
6
  "subc": "bin/cli.js"