sops-setup
Set up SOPS + age encryption for sharing .env files securely across machines. Detects existing state, installs tools, generates age keys, creates .sops.yaml, and encrypts .env files as YAML (avoids SOPS dotenv bug #1435). Use when user mentions "sops setup", "encrypt env", "share secrets", "secure env files", "sops age setup", "env encryption", "setup sops", "share env across machines".
What this skill does
# 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)](https://github.com/getsops/sops/issues/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:
```bash
python3 ${CLAUDE_SKILL_DIR}/scripts/detect_sops.py <project-root>
```
## Two-Phase Workflow
### Phase 1: Detect
1. **Run the detector** on the project root:
```bash
python3 ${CLAUDE_SKILL_DIR}/scripts/detect_sops.py <project-root>
```
2. **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.
1. **Install tools** (if `tools.sops.installed` or `tools.age.installed` is false):
- Show install commands based on `os` field:
- **macOS**: `brew install sops age`
- **Linux**: Show download URLs for latest binaries from GitHub releases
- After user confirms installation, re-run detector to verify
2. **Generate age key** (if `age_key.exists` is false):
- 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)
3. **Generate backup key** (recommended):
- Use `AskUserQuestion` — offer to create an offline backup key for disaster recovery
- If yes:
```bash
age-keygen 2>&1 | tee /dev/stderr | grep "public key:" | awk '{print $NF}'
```
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.**
- The backup public key will be added to `.sops.yaml` alongside the machine key
4. **Create `.sops.yaml`** (if `project.sops_yaml.exists` is false):
- Write `.sops.yaml` with machine key + backup key (if generated):
```yaml
creation_rules:
- path_regex: (^|/)\.env\.[^/]+\.enc\.yaml$
age: >-
<machine-public-key>,
<backup-public-key>
```
- If `.sops.yaml` already exists but is missing this machine's key, offer to add it
5. **Set up `.gitattributes`** for diff-friendly encrypted files:
- Add to `.gitattributes`:
```
*.enc.yaml diff=sopsdiffer
```
- Configure git:
```bash
git config diff.sopsdiffer.textconv "sops decrypt"
```
- This makes `git diff` show decrypted content for encrypted files
6. **Update `.gitignore`** (if needed):
- Ensure `.env*` patterns are ignored (secrets must not be committed in plaintext)
- Ensure `*.enc.yaml` is NOT ignored (encrypted files should be committed)
- Show proposed changes and confirm with user before writing
7. **Encrypt files** (if `project.env_files` is non-empty):
- Use `AskUserQuestion` (multiSelect: true) — show detected `.env*` files
- For each selected file, convert dotenv→YAML then encrypt:
```bash
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
```
Example: `.env.local` → `.env.local.enc.yaml`
- Verify each encrypted file was created successfully
8. **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 `AskUserQuestion`** for every decision. Do not assume user preferences.
- **YAML format only** — never use `--input-type dotenv`. Use the dotenv_yaml.py helper for conversion.
- **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](WORKFLOW.md) for detailed per-step flows
- **Examples**: See [EXAMPLES.md](EXAMPLES.md) for example setup sessions
- **Troubleshooting**: See [TROUBLESHOOTING.md](TROUBLESHOOTING.md) for common issues
- **Detection Script**: See [scripts/detect_sops.py](scripts/detect_sops.py) for detection logic
- **Converter**: See [scripts/dotenv_yaml.py](scripts/dotenv_yaml.py) for dotenv↔YAML conversion
- **Best Practices**: See [references/sops-best-practices.md](references/sops-best-practices.md) for research
Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.