@chriscode/hush 5.0.6 → 5.0.7

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.
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAc,WAAW,EAAE,WAAW,EAAU,MAAM,aAAa,CAAC;AAsKhF,wBAAsB,WAAW,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAqFvF"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAc,WAAW,EAAE,WAAW,EAAU,MAAM,aAAa,CAAC;AAsKhF,wBAAsB,WAAW,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAmGvF"}
@@ -145,8 +145,20 @@ export async function initCommand(ctx, options) {
145
145
  const { root } = options;
146
146
  const existingConfig = ctx.config.findProjectRoot(root);
147
147
  if (existingConfig) {
148
- ctx.logger.error(pc.red(`Config already exists: ${existingConfig.configPath}`));
149
- ctx.process.exit(1);
148
+ const sopsPath = ctx.path.join(root, '.sops.yaml');
149
+ if (ctx.fs.existsSync(sopsPath)) {
150
+ ctx.logger.error(pc.red(`Config already exists: ${existingConfig.configPath}`));
151
+ ctx.process.exit(1);
152
+ }
153
+ ctx.logger.log(pc.yellow(`hush.yaml already exists. Completing setup (creating .sops.yaml)...\n`));
154
+ const existingHushConfig = ctx.config.loadConfig(root);
155
+ const project = existingHushConfig.project ?? getProjectFromPackageJson(ctx, root);
156
+ const keyResult = await setupKey(ctx, root, project ?? null);
157
+ if (keyResult) {
158
+ createSopsConfig(ctx, root, keyResult.publicKey);
159
+ ctx.logger.log(pc.green('\nSetup complete. Run "hush encrypt" to encrypt your secrets.'));
160
+ }
161
+ return;
150
162
  }
151
163
  ctx.logger.log(pc.blue('Initializing hush...\n'));
152
164
  const existingEncryptedFiles = findExistingEncryptedFiles(ctx, root);
@@ -1 +1 @@
1
- {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAkvC7D,wBAAsB,YAAY,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA0CzF"}
1
+ {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAg2C7D,wBAAsB,YAAY,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA0CzF"}
@@ -37,6 +37,7 @@ This tells you:
37
37
  | \`No hush.yaml found\` | Hush not initialized | Run \`npx hush init\` |
38
38
  | \`SOPS not installed\` | Missing prerequisite | \`brew install sops\` |
39
39
  | \`age key not found\` | Missing encryption key | \`npx hush keys setup\` |
40
+ | \`age key configured\` but decrypt fails | direnv not loaded | Run \`direnv allow\` in project directory |
40
41
  | \`Project: not set\` | Key management limited | Add \`project:\` to hush.yaml |
41
42
 
42
43
  **Note:** Any \`.env\` file is suspect - Hush uses \`.hush\` files everywhere. Subdirectory \`.hush\` files are templates (safe to commit).
@@ -344,6 +345,39 @@ The dialog shows the pasted value for easy verification.
344
345
 
345
346
  ---
346
347
 
348
+ ## Troubleshooting
349
+
350
+ ### Decrypt fails with "no identity matched any of the recipients"
351
+
352
+ This is the most common issue - SOPS can't find the decryption key.
353
+
354
+ **Cause:** Hush uses per-project keys at \`~/.config/sops/age/keys/{project}.txt\`, but SOPS needs the \`SOPS_AGE_KEY_FILE\` env var to find them.
355
+
356
+ **Fix:**
357
+ \`\`\`bash
358
+ # 1. Verify the key exists
359
+ npx hush keys list
360
+
361
+ # 2. Ensure direnv is set up
362
+ brew install direnv
363
+ echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc # or bash
364
+
365
+ # 3. Allow direnv in the project (loads .envrc)
366
+ cd /path/to/project
367
+ direnv allow
368
+
369
+ # 4. Verify
370
+ npx hush status # Should show "age key configured"
371
+ npx hush inspect # Should now work
372
+ \`\`\`
373
+
374
+ ### Key listed but wrong project
375
+
376
+ If \`npx hush keys list\` shows a key but for the wrong project:
377
+ \`\`\`bash
378
+ npx hush keys setup # Will pull correct key from 1Password or prompt
379
+ \`\`\`
380
+
347
381
  ## Additional Resources
348
382
 
349
383
  - **First-time setup**: [SETUP.md](SETUP.md)
@@ -604,12 +638,49 @@ git commit -m "chore: add Hush secrets management"
604
638
 
605
639
  When a new team member joins:
606
640
 
641
+ ### With 1Password (Recommended)
642
+
643
+ \`\`\`bash
644
+ npx hush keys setup # Auto-pulls key from 1Password
645
+ \`\`\`
646
+
647
+ ### Without 1Password
648
+
607
649
  1. **Get the age private key** from an existing team member
608
- 2. **Save it** to \`~/.config/sops/age/key.txt\`
609
- 3. **Run** \`npx hush run -- npm install\` to verify decryption works
610
- 4. **Start developing** with \`npx hush run -- npm run dev\`
650
+ 2. **Save it** to \`~/.config/sops/age/keys/{project}.txt\` (check \`npx hush status\` for exact path)
651
+ 3. **Set up direnv** to load the key (see below)
652
+ 4. **Verify** with \`npx hush status\` and \`npx hush inspect\`
653
+
654
+ ### Critical: Set Up direnv
655
+
656
+ Hush uses per-project keys. SOPS needs to know where to find them via \`SOPS_AGE_KEY_FILE\`.
657
+
658
+ **1. Install direnv:**
659
+ \`\`\`bash
660
+ brew install direnv # macOS
661
+ # Add to ~/.zshrc or ~/.bashrc:
662
+ eval "$(direnv hook zsh)" # or bash
663
+ \`\`\`
664
+
665
+ **2. Create/verify .envrc in the project:**
666
+ \`\`\`bash
667
+ # .envrc (should already exist if project is set up)
668
+ export SOPS_AGE_KEY_FILE="$HOME/.config/sops/age/keys/{project-slug}.txt"
669
+ \`\`\`
611
670
 
612
- The private key should be shared securely (password manager, encrypted channel, etc.)
671
+ **3. Allow direnv:**
672
+ \`\`\`bash
673
+ cd /path/to/project
674
+ direnv allow
675
+ \`\`\`
676
+
677
+ **4. Verify setup:**
678
+ \`\`\`bash
679
+ npx hush status # Should show "age key configured"
680
+ npx hush inspect # Should decrypt and show masked secrets
681
+ \`\`\`
682
+
683
+ The private key should be shared securely (1Password is ideal, or password manager, encrypted channel)
613
684
 
614
685
  ---
615
686
 
@@ -637,8 +708,47 @@ brew install age # macOS
637
708
  brew install sops # macOS
638
709
  \`\`\`
639
710
 
640
- ### "Error: no matching keys found"
641
- Your age key doesn't match. Get the correct private key from a team member.
711
+ ### "no identity matched any of the recipients" or "Error: no matching keys found"
712
+
713
+ This error means SOPS can't find the decryption key. **Most common cause: direnv not loaded.**
714
+
715
+ **Step 1: Check if the key file exists**
716
+ \`\`\`bash
717
+ npx hush keys list # Shows local and 1Password keys
718
+ \`\`\`
719
+
720
+ If the key is listed but decryption fails, the issue is that SOPS doesn't know where to find it.
721
+
722
+ **Step 2: Set up direnv (CRITICAL for per-project keys)**
723
+
724
+ Hush uses per-project keys at \`~/.config/sops/age/keys/{project}.txt\`. SOPS needs the \`SOPS_AGE_KEY_FILE\` environment variable set to find it.
725
+
726
+ \`\`\`bash
727
+ # Install direnv (if not already installed)
728
+ brew install direnv
729
+
730
+ # Add to your shell (add to ~/.zshrc or ~/.bashrc)
731
+ eval "$(direnv hook zsh)" # or bash
732
+ \`\`\`
733
+
734
+ **Step 3: Create .envrc in the project root**
735
+ \`\`\`bash
736
+ # .envrc
737
+ export SOPS_AGE_KEY_FILE="$HOME/.config/sops/age/keys/{project-slug}.txt"
738
+ \`\`\`
739
+
740
+ Replace \`{project-slug}\` with your project identifier (e.g., \`myorg-myrepo\`). Check \`npx hush status\` to see the expected filename.
741
+
742
+ **Step 4: Allow direnv**
743
+ \`\`\`bash
744
+ direnv allow
745
+ \`\`\`
746
+
747
+ **Step 5: Verify**
748
+ \`\`\`bash
749
+ npx hush status # Should show "age key configured"
750
+ npx hush inspect # Should decrypt and show masked secrets
751
+ \`\`\`
642
752
 
643
753
  ### "hush.yaml not found"
644
754
  Run \`npx hush init\` to generate configuration.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chriscode/hush",
3
- "version": "5.0.6",
3
+ "version": "5.0.7",
4
4
  "description": "SOPS-based secrets management for monorepos. Encrypt once, decrypt everywhere.",
5
5
  "type": "module",
6
6
  "bin": {