Arkhe-claude-plugins sops-setup
install
source · Clone the upstream repo
git clone https://github.com/joaquimscosta/arkhe-claude-plugins
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/joaquimscosta/arkhe-claude-plugins "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/devtools/skills/sops-setup" ~/.claude/skills/joaquimscosta-arkhe-claude-plugins-sops-setup && rm -rf "$T"
manifest:
plugins/devtools/skills/sops-setup/SKILL.mdsource content
SOPS + age Setup Wizard
Interactive setup for SOPS + age encryption. Detects current state and guides through configuration.
Important: This skill uses YAML format for encrypted files (not dotenv) because SOPS has a known bug (#1435) where the dotenv store corrupts backslash and
\n sequences on decrypt. A helper script handles dotenv↔YAML conversion transparently.
Pre-flight
Run the detection script to understand current state:
python3 ${CLAUDE_SKILL_DIR}/scripts/detect_sops.py <project-root>
Two-Phase Workflow
Phase 1: Detect
-
Run the detector on the project root:
python3 ${CLAUDE_SKILL_DIR}/scripts/detect_sops.py <project-root> -
Summarize findings — show a status table:
Component Status Detail sops binary installed/missing version, path age binary installed/missing version, path age key exists/missing public key (truncated) .sops.yaml exists/missing # of authorized keys .env files N found list of filenames encrypted files N found list of *.enc.yaml files .gitignore ok/needs update env ignored, enc.yaml not ignored
Phase 2: Configure
Walk through each missing component. Skip steps where detection shows everything is already configured.
-
Install tools (if
ortools.sops.installed
is false):tools.age.installed- Show install commands based on
field:os- macOS:
brew install sops age - Linux: Show download URLs for latest binaries from GitHub releases
- macOS:
- After user confirms installation, re-run detector to verify
- Show install commands based on
-
Generate age key (if
is false):age_key.exists- Create directory:
mkdir -p ~/.config/sops/age - Generate key:
age-keygen -o ~/.config/sops/age/keys.txt - Set permissions:
chmod 600 ~/.config/sops/age/keys.txt - Display the public key and tell user to save it somewhere safe (password manager, secure note)
- Create directory:
-
Generate backup key (recommended):
- Use
— offer to create an offline backup key for disaster recoveryAskUserQuestion - If yes:
Display BOTH the public key AND the full output (which includes the private key). Tell user: Copy the entire output (including the private key line starting with AGE-SECRET-KEY-) to a password manager or secure offline storage. This is your recovery key.age-keygen 2>&1 | tee /dev/stderr | grep "public key:" | awk '{print $NF}' - The backup public key will be added to
alongside the machine key.sops.yaml
- Use
-
Create
(if.sops.yaml
is false):project.sops_yaml.exists- Write
with machine key + backup key (if generated):.sops.yamlcreation_rules: - path_regex: (^|/)\.env\.[^/]+\.enc\.yaml$ age: >- <machine-public-key>, <backup-public-key> - If
already exists but is missing this machine's key, offer to add it.sops.yaml
- Write
-
Set up
for diff-friendly encrypted files:.gitattributes- Add to
:.gitattributes*.enc.yaml diff=sopsdiffer - Configure git:
git config diff.sopsdiffer.textconv "sops decrypt" - This makes
show decrypted content for encrypted filesgit diff
- Add to
-
Update
(if needed):.gitignore- Ensure
patterns are ignored (secrets must not be committed in plaintext).env* - Ensure
is NOT ignored (encrypted files should be committed)*.enc.yaml - Show proposed changes and confirm with user before writing
- Ensure
-
Encrypt files (if
is non-empty):project.env_files- Use
(multiSelect: true) — show detectedAskUserQuestion
files.env* - For each selected file, convert dotenv→YAML then encrypt:
Example:python3 ${CLAUDE_SKILL_DIR}/scripts/dotenv_yaml.py to-yaml <file> > <file>.enc.yaml.tmp sops --encrypt <file>.enc.yaml.tmp > <file>.enc.yaml rm <file>.enc.yaml.tmp
→.env.local.env.local.enc.yaml - Verify each encrypted file was created successfully
- Use
-
Confirmation summary — show table of all actions taken:
| Step | Action | Result | |------|--------|--------| | Tools | sops 3.9.4, age 1.2.0 | installed | | Key | Machine key generated | age1abc...def | | Key | Backup key generated | age1xyz...uvw (save offline!) | | Permissions | chmod 600 keys.txt | done | | Config | .sops.yaml created | 2 keys authorized | | Git | .gitattributes updated | sopsdiffer configured | | Git | .gitignore updated | .env* ignored | | Encrypt | .env.local → .env.local.enc.yaml | done | ## Next Steps - Commit .sops.yaml, .gitattributes, and *.enc.yaml files to git - On another machine: clone, install sops+age, place age key, run /devtools:sops-decrypt - To add another machine: /devtools:sops-add-key - To encrypt after editing .env: /devtools:sops-encrypt - To decrypt after pulling: /devtools:sops-decrypt
Key Rules
- Never overwrite existing files without asking. Always offer merge/replace/skip.
- Detect first — skip steps that are already configured.
- Use
for every decision. Do not assume user preferences.AskUserQuestion - YAML format only — never use
. Use the dotenv_yaml.py helper for conversion.--input-type dotenv - chmod 600 on age key files immediately after creation.
- Display public keys after generation — user needs them for multi-machine setup.
- Verify after each step — re-run relevant checks to confirm success.
References
- Workflow: See WORKFLOW.md for detailed per-step flows
- Examples: See EXAMPLES.md for example setup sessions
- Troubleshooting: See TROUBLESHOOTING.md for common issues
- Detection Script: See scripts/detect_sops.py for detection logic
- Converter: See scripts/dotenv_yaml.py for dotenv↔YAML conversion
- Best Practices: See references/sops-best-practices.md for research