elliot-stack 1.0.20 → 1.0.22

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/bin/install.cjs +71 -7
  2. package/package.json +1 -1
package/bin/install.cjs CHANGED
@@ -11,13 +11,74 @@ const readline = require('readline');
11
11
  const HOME = os.homedir();
12
12
  const CLAUDE_DIR = path.join(HOME, '.claude');
13
13
  const SKILLS_DIR = path.join(CLAUDE_DIR, 'skills');
14
- const BACKUP_DIR = path.join(CLAUDE_DIR, '.estack-backup');
14
+ const BACKUP_DIR = path.join(HOME, '.estack-backup');
15
15
  const CHECKSUMS_FILE = path.join(CLAUDE_DIR, '.estack-checksums.json');
16
16
  const SETTINGS_FILE = path.join(CLAUDE_DIR, 'settings.json');
17
17
  const PACKAGE_SKILLS_DIR = path.join(__dirname, '..', 'skills');
18
18
  const HOOKS_DIR = path.join(CLAUDE_DIR, 'hooks');
19
19
  const PACKAGE_HOOKS_DIR = path.join(__dirname, '..', 'hooks');
20
20
 
21
+ // ── Migrate backup dir from old location (inside .claude) to user root ──────
22
+ (function migrateBackupDir() {
23
+ const OLD_BACKUP_DIR = path.join(CLAUDE_DIR, '.estack-backup');
24
+ if (!fs.existsSync(OLD_BACKUP_DIR)) return;
25
+ if (fs.existsSync(BACKUP_DIR)) return; // new location already exists, leave both alone
26
+ const silent = process.argv.includes('--silent');
27
+ const isDryRun = process.argv.includes('--dry-run') ||
28
+ (!__dirname.includes('node_modules') && !process.argv.includes('--install'));
29
+ if (isDryRun) {
30
+ if (!silent) {
31
+ process.stderr.write(
32
+ 'estack: [dry run] Would move backup dir from ~/.claude/.estack-backup/ to ~/.estack-backup/\n'
33
+ );
34
+ }
35
+ return;
36
+ }
37
+ try {
38
+ fs.renameSync(OLD_BACKUP_DIR, BACKUP_DIR);
39
+ if (!silent) {
40
+ process.stderr.write(
41
+ 'estack: moved backup dir from ~/.claude/.estack-backup/ to ~/.estack-backup/\n'
42
+ );
43
+ }
44
+ } catch (e) {
45
+ // rename across drives/filesystems — fall back to copy+delete
46
+ try {
47
+ copyDirRaw(OLD_BACKUP_DIR, BACKUP_DIR);
48
+ removeDirRaw(OLD_BACKUP_DIR);
49
+ if (!silent) {
50
+ process.stderr.write(
51
+ 'estack: migrated backup dir from ~/.claude/.estack-backup/ to ~/.estack-backup/\n'
52
+ );
53
+ }
54
+ } catch (e2) {
55
+ process.stderr.write(
56
+ 'estack: WARNING — could not migrate backup dir from ' + OLD_BACKUP_DIR +
57
+ ' to ' + BACKUP_DIR + ': ' + e2.message + '\n'
58
+ );
59
+ }
60
+ }
61
+ })();
62
+
63
+ function copyDirRaw(src, dest) {
64
+ fs.mkdirSync(dest, { recursive: true });
65
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
66
+ const s = path.join(src, entry.name);
67
+ const d = path.join(dest, entry.name);
68
+ if (entry.isDirectory()) copyDirRaw(s, d);
69
+ else fs.copyFileSync(s, d);
70
+ }
71
+ }
72
+
73
+ function removeDirRaw(dir) {
74
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
75
+ const full = path.join(dir, entry.name);
76
+ if (entry.isDirectory()) removeDirRaw(full);
77
+ else fs.unlinkSync(full);
78
+ }
79
+ fs.rmdirSync(dir);
80
+ }
81
+
21
82
  // ── Flags ──────────────────────────────────────────────────────────────────
22
83
  const SILENT = process.argv.includes('--silent');
23
84
  const STARTUP = process.argv.includes('--startup');
@@ -37,6 +98,9 @@ const DEPRECATED_SKILLS = [
37
98
 
38
99
  // ── Helpers ────────────────────────────────────────────────────────────────
39
100
 
101
+ const HASH_IGNORE_DIRS = new Set(['__pycache__', '.git', 'node_modules']);
102
+ const HASH_IGNORE_EXTS = new Set(['.pyc', '.pyo']);
103
+
40
104
  function walkDir(dir, base) {
41
105
  base = base || dir;
42
106
  const entries = fs.readdirSync(dir, { withFileTypes: true }).sort((a, b) =>
@@ -46,8 +110,8 @@ function walkDir(dir, base) {
46
110
  for (const entry of entries) {
47
111
  const full = path.join(dir, entry.name);
48
112
  if (entry.isDirectory()) {
49
- files.push(...walkDir(full, base));
50
- } else {
113
+ if (!HASH_IGNORE_DIRS.has(entry.name)) files.push(...walkDir(full, base));
114
+ } else if (!HASH_IGNORE_EXTS.has(path.extname(entry.name))) {
51
115
  files.push(path.relative(base, full));
52
116
  }
53
117
  }
@@ -560,7 +624,7 @@ async function main() {
560
624
  if (modifiedAction === 'merge') {
561
625
  if (!DRY_RUN) backupSkill(name);
562
626
  mergedSkills.push(name);
563
- console.log((DRY_RUN ? ' [dry run] Would back up ' : ' Backed up ') + name + ' → ~/.claude/.estack-backup/' + name);
627
+ console.log((DRY_RUN ? ' [dry run] Would back up ' : ' Backed up ') + name + ' → ~/.estack-backup/' + name);
564
628
  }
565
629
  // overwrite or merge — fall through to install
566
630
  } else if (!needsUpdate.includes(name) && fs.existsSync(path.join(SKILLS_DIR, name))) {
@@ -595,7 +659,7 @@ async function main() {
595
659
  if (modifiedAction === 'merge') {
596
660
  if (!DRY_RUN) backupHook(filename);
597
661
  mergedHooks.push(filename);
598
- console.log((DRY_RUN ? ' [dry run] Would back up hook ' : ' Backed up hook ') + filename + ' → ~/.claude/.estack-backup/hooks/' + filename);
662
+ console.log((DRY_RUN ? ' [dry run] Would back up hook ' : ' Backed up hook ') + filename + ' → ~/.estack-backup/hooks/' + filename);
599
663
  }
600
664
  // overwrite or merge — fall through to install
601
665
  } else if (!hooksNeedingUpdate.includes(filename) && fs.existsSync(path.join(HOOKS_DIR, filename))) {
@@ -647,12 +711,12 @@ async function main() {
647
711
  if (mergedSkills.length > 0) {
648
712
  console.log('\nLocal changes backed up for: ' + mergedSkills.join(', '));
649
713
  console.log('Ask Claude to merge your changes:');
650
- console.log(' "Merge my estack changes from ~/.claude/.estack-backup/"');
714
+ console.log(' "Merge my estack changes from ~/.estack-backup/"');
651
715
  }
652
716
 
653
717
  if (mergedHooks.length > 0) {
654
718
  console.log('\nLocal hook changes backed up for: ' + mergedHooks.join(', '));
655
- console.log('Backed up to ~/.claude/.estack-backup/hooks/');
719
+ console.log('Backed up to ~/.estack-backup/hooks/');
656
720
  }
657
721
 
658
722
  if (DRY_RUN) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "elliot-stack",
3
- "version": "1.0.20",
3
+ "version": "1.0.22",
4
4
  "description": "Elliot's skill stack for Claude Code — install via npx elliot-stack@latest",
5
5
  "bin": {
6
6
  "elliot-stack": "bin/install.cjs"