feat: add configuration management and MCP secrets workflows (closes #16204)

Major additions to address critical gaps in Claude Code configuration:

## New Documentation Sections

1. Section 3.2.1 "Version Control & Backup" (guide/ultimate-guide.md:4085)
   - Configuration hierarchy: global → project → local
   - Git strategy for ~/.claude (symlinks approach)
   - Backup strategies: Git remote, cloud sync, cron
   - Multi-machine sync workflows
   - Disaster recovery procedures
   - Documented .claude/settings.local.json (previously undocumented)

2. Section 8.3.1 "MCP Secrets Management" (guide/ultimate-guide.md:8113)
   - Three practical approaches: OS Keychain, .env, Secret Vaults
   - Secrets rotation workflow
   - Pre-commit secret detection
   - Verification checklist
   - Best practices summary

## New Templates

1. sync-claude-config.sh (examples/scripts/)
   - Commands: setup, sync, backup, restore, validate
   - .env parsing + envsubst for variable substitution
   - Git repo creation with symlinks
   - Validation checks (secrets not in Git)

2. pre-commit-secrets.sh (examples/hooks/bash/)
   - Detects 10+ secret patterns (OpenAI, GitHub, AWS, etc.)
   - Whitelist system for false positives
   - Clear error messages with remediation steps

3. settings.local.json.example (examples/config/)
   - Machine-specific overrides template
   - Example use cases and patterns

## Resource Evaluation

- Added docs/resource-evaluations/ratinaud-config-management-evaluation.md
- Score: 5/5 (CRITICAL)
- Validated via 3 Perplexity searches + technical-writer agent challenge
- Community demand: GitHub #16204 + brianlovin/claude-config

## Updated References

- machine-readable/reference.yaml: 22 new entries
- Configuration management sections
- MCP secrets workflows
- Community resources (Ratinaud, brianlovin, GitHub issue)

## Impact

- Security: Pre-commit hook prevents secret leaks
- Productivity: Multi-machine sync reduces manual reconfig
- Team coordination: Onboarding workflow for ~/.claude setup
- Disaster recovery: Backup/restore strategies documented

Credits:
- Martin Ratinaud (504 sessions, LinkedIn post)
- brianlovin/claude-config (community example)
- GitHub Issue #16204 (community request)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Florian BRUNIAUX 2026-02-02 18:17:42 +01:00
parent 5b69db64a9
commit 0630fcd883
6 changed files with 1591 additions and 0 deletions

View file

@ -0,0 +1,163 @@
#!/bin/bash
# pre-commit-secrets.sh - Pre-commit hook to detect secrets in staged files
# Version: 1.0.0
# Purpose: Prevent accidental commits of API keys, tokens, and credentials
#
# Installation:
# cp examples/hooks/bash/pre-commit-secrets.sh .git/hooks/pre-commit
# chmod +x .git/hooks/pre-commit
#
# Test:
# echo "GITHUB_TOKEN=ghp_test" > test.txt
# git add test.txt
# git commit -m "Test"
# # Should fail with secret detection error
set -euo pipefail
# Colors
RED='\033[0;31m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Secret patterns (extended regex)
declare -A PATTERNS=(
["OpenAI API Key"]="sk-[A-Za-z0-9]{48}"
["GitHub Token (ghp)"]="ghp_[A-Za-z0-9]{36}"
["GitHub Token (gho)"]="gho_[A-Za-z0-9]{36}"
["GitHub Token (ghu)"]="ghu_[A-Za-z0-9]{36}"
["GitHub Token (ghs)"]="ghs_[A-Za-z0-9]{36}"
["GitHub Token (ghr)"]="ghr_[A-Za-z0-9]{36}"
["AWS Access Key"]="AKIA[A-Z0-9]{16}"
["AWS Secret Key"]="[A-Za-z0-9/+=]{40}"
["Anthropic API Key"]="sk-ant-[A-Za-z0-9-]{95,}"
["Generic API Key"]="api[_-]?key[\"']?\s*[:=]\s*[\"']?[A-Za-z0-9]{20,}"
["Generic Secret"]="secret[\"']?\s*[:=]\s*[\"']?[A-Za-z0-9]{20,}"
["Generic Token"]="token[\"']?\s*[:=]\s*[\"']?[A-Za-z0-9]{20,}"
["Database URL with Password"]="(postgres|mysql|mongodb)://[^:]+:[^@]+@"
["Private Key"]="-----BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY-----"
["JWT Token"]="eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}"
)
# Whitelisted patterns (safe to ignore)
WHITELIST=(
"your_token_here"
"your_key_here"
"example.com"
"localhost"
"placeholder"
"XXXXXX"
"\${env:" # Template variable syntax
"sk-ant-example" # Example in documentation
)
# Files to always skip (even if staged)
SKIP_FILES=(
"*.md" # Documentation often contains example secrets
"*.txt" # Same for text files
"*example*"
"*template*"
"*.sample"
)
# Check if a file should be skipped
should_skip_file() {
local file=$1
for pattern in "${SKIP_FILES[@]}"; do
# Convert glob to regex
local regex="${pattern//\*/.*}"
if [[ $file =~ $regex ]]; then
return 0 # Skip this file
fi
done
return 1 # Don't skip
}
# Check if a match is whitelisted
is_whitelisted() {
local match=$1
for whitelist in "${WHITELIST[@]}"; do
if [[ $match == *"$whitelist"* ]]; then
return 0 # Whitelisted
fi
done
return 1 # Not whitelisted
}
# Main secret detection logic
detect_secrets() {
local files
files=$(git diff --cached --name-only --diff-filter=ACM)
if [ -z "$files" ]; then
exit 0 # No staged files
fi
local found_secrets=0
local secrets_report=""
# Iterate through staged files
while IFS= read -r file; do
# Skip if file should be ignored
if should_skip_file "$file"; then
continue
fi
# Skip if file doesn't exist (deleted)
if [ ! -f "$file" ]; then
continue
fi
# Get staged content
local content
content=$(git show ":$file" 2>/dev/null || continue)
# Check each pattern
for pattern_name in "${!PATTERNS[@]}"; do
local pattern="${PATTERNS[$pattern_name]}"
local matches
matches=$(echo "$content" | grep -noE "$pattern" || true)
if [ -n "$matches" ]; then
# Check each match against whitelist
while IFS= read -r match; do
local line_num="${match%%:*}"
local matched_text="${match#*:}"
if ! is_whitelisted "$matched_text"; then
found_secrets=1
secrets_report+=" ${file}:${line_num} - ${pattern_name}\n"
secrets_report+=" Content: ${matched_text:0:50}...\n"
fi
done <<< "$matches"
fi
done
done <<< "$files"
# Report findings
if [ $found_secrets -eq 1 ]; then
echo -e "${RED}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${RED}✗ COMMIT BLOCKED: Secrets detected in staged files${NC}"
echo -e "${RED}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
echo -e "${YELLOW}Found potential secrets:${NC}"
echo -e "$secrets_report"
echo ""
echo -e "${YELLOW}Remediation steps:${NC}"
echo " 1. Remove secrets from files"
echo " 2. Use environment variables: \${env:VAR_NAME}"
echo " 3. Store secrets in ~/.claude/.env (gitignored)"
echo " 4. See: guide/ultimate-guide.md Section 8.3.1"
echo ""
echo -e "${YELLOW}If this is a false positive:${NC}"
echo " - Edit .git/hooks/pre-commit and add to WHITELIST array"
echo " - Or skip hook: git commit --no-verify (USE WITH CAUTION)"
echo ""
exit 1
fi
exit 0
}
# Run detection
detect_secrets