← RETOUR À L'INDEX
/tutoriels/ claude-code / claude-code-setup-—-backup-sécurisé-de-la-config-claude-code.md

claude-code-setup — Backup sécurisé de la config Claude Code

Mettre en place un repo GitHub privé pour sauvegarder la configuration Claude Code (settings, hooks, skills) avec chiffrement GPG et nettoyage PII, en évitant les 3 failles classiques.

CAT · CLAUDE CODE LECTURE · 5 min PUBLIÉ · 2026-05-15

[TUTO-16] claude-code-setup — Backup sécurisé de la config Claude Code

Objectif

Configurer un backup automatique de ~/.claude/ vers un repo GitHub privé, chiffré GPG pour les fichiers sensibles, avec nettoyage des PII avant commit. Ce tuto couvre les 3 failles classiques : secrets commités, dry-run silencieusement ignoré, et path traversal via .backupinclude.

Prérequis

  • Claude Code WSL2 installé (voir TUTO-09)
  • Clé GPG disponible (gpg --list-secret-keys)
  • Repo GitHub privé claude-code-setup créé

Étape 0 — Ce qui ne doit JAMAIS être committé

Avant d’écrire la moindre ligne de script, identifier les données à protéger :

FichierRisqueTraitement
~/.claude.jsonemailAddress, accountUuid, userID, anonymousId, githubRepoPaths, oauthAccount, overageCreditGrantCacheNettoyage jq + chiffrement GPG
~/.claude/.credentialsToken AnthropicJamais committé — exclure absolument
~/.claude/settings.jsonTokens MCP (ctx7sk-, Bearer…)Scan + nettoyage avant commit
~/.claude/hooks/Scripts shell — pas de secrets si bien écritsCommitter en clair

⚠️ Sécurité : .credentials est le token Anthropic. Le committer même chiffré augmente la surface d’exposition sans bénéfice — il se régénère via claude auth login. L’exclure est non négociable.


Étape 1 — Nettoyage PII de claude.json

Le nettoyage jq doit couvrir les champs PII structurels et les patterns de tokens :

jq '
walk(
  if type == "object" then
    with_entries(
      if (.key | test(
        "^(emailAddress|accountUuid|organizationUuid|userID|anonymousId|
           oauthAccount|overageCreditGrantCache|githubRepoPaths|clientDataCache|
           groveConfigCache|changelogLastFetched|firstStartTime|
           claudeCodeFirstTokenDate|lastPlanModeUse|numStartups|
           companion|additionalModelOptionsCache)$"; "xi"
      )) then .value = "REDACTED"
      else .
      end
    )
  else . end
) |
walk(
  if type == "string" then
    gsub("(?:sk-ant-|ghp_|ghs_|gho_|ghr_|github_pat_|ctx7sk-|Bearer\\s)[A-Za-z0-9_\\-]+";
         "REDACTED")
  else . end
)
' ~/.claude.json > /tmp/claude.template.json

⚠️ Sécurité : les patterns de tokens évoluent — GitHub ajoute des formats régulièrement (gho_, ghr_, github_pat_ depuis 2021). Vérifier la liste à chaque rotation de token.

Vérification obligatoire après nettoyage :

# Aucun email, UUID ou token ne doit rester
jq '[paths(scalars)] | map(
  select(test("email|uuid|Id|account|credit|billing|paths|anonymous|grove|changelog"; "i"))
)' /tmp/claude.template.json

# Aucun pattern de token résiduel
grep -iE "sk-ant-|ghp_|ghs_|gho_|ctx7sk-|Bearer " /tmp/claude.template.json \
  && echo "🔴 SECRETS DÉTECTÉS — NE PAS COMMITTER" \
  || echo "✅ Template propre"

Étape 2 — Implémenter —dry-run dès le début

Un script de backup sans --dry-run utilisable est une fausse sécurité. Pattern à placer en tête du script, avant set -euo pipefail :

DRY_RUN=false
[[ "${1:-}" == "--dry-run" ]] && DRY_RUN=true

# Wrapper pour les commandes avec effet de bord
run() {
  if $DRY_RUN; then
    echo "[DRY-RUN] $*" >&2
  else
    "$@"
  fi
}

Utilisation dans le script :

run git push origin main
run gpg --encrypt --output "$DEST.gpg" "$SOURCE"

Test de validation :

bash backup-to-github.sh --dry-run 2>&1 | grep "DRY-RUN"
# Vérifier qu'AUCUN nouveau commit n'apparaît sur GitHub après ce run
git log --oneline -3  # le hash ne doit pas avoir changé

⚠️ Sécurité : un --dry-run silencieusement ignoré est pire qu’une absence de dry-run. Il donne une fausse confiance lors des tests — tester le vrai comportement du flag avant de considérer le script prêt pour la production.


Étape 3 — Protéger le répertoire skills/ avec .backupinclude

Ne pas sauvegarder tous les skills aveuglément — certains (ECC, génériques) n’ont aucune valeur et gonflent le repo inutilement.

Créer ~/.claude/skills/.backupinclude listant un skill par ligne :

rust-patterns
tdd-workflow
comfyui-image-gen

Dans le script de backup :

SKILLS_DIR="$HOME/.claude/skills"
BACKUP_SKILLS_DIR="$REPO_DIR/skills"

while IFS= read -r skill_dir; do
  # Validation : interdire les path traversal
  if [[ "$skill_dir" == *..* || "$skill_dir" == /* || "$skill_dir" == */* ]]; then
    log "DANGER : entrée rejetée (path traversal potentiel) : '$skill_dir'"
    continue
  fi

  src="$SKILLS_DIR/$skill_dir"
  [[ -d "$src" ]] || { log "AVERTISSEMENT : skill introuvable : '$skill_dir'"; continue; }
  run rsync -a --delete "$src/" "$BACKUP_SKILLS_DIR/$skill_dir/"
done < "$SKILLS_DIR/.backupinclude"

⚠️ Sécurité : une entrée ../../.ssh dans .backupinclude permet à un attaquant qui contrôle ce fichier d’exfiltrer n’importe quel répertoire du système. La validation *..* || /* bloque cette classe d’attaque. Vérifier le contenu de .backupinclude avant chaque modification.


Étape 4 — Chiffrer les fichiers sensibles avec GPG

Pour claude.template.json et settings.json après scan :

GPG_RECIPIENT="ton@email.fr"

# Chiffrement asymétrique (clé publique du destinataire)
gpg --recipient "$GPG_RECIPIENT" \
    --encrypt \
    --armor \
    --output "$REPO_DIR/claude.template.json.gpg" \
    /tmp/claude.template.json

# Vérification : le fichier clair n'est PAS dans le repo
ls "$REPO_DIR" | grep -v ".gpg" | grep "claude"
# Attendu : aucune ligne (seul le .gpg est présent)

⚠️ Sécurité : si la clé GPG est perdue, le backup est irrécupérable. Exporter la clé privée vers un support offline (clé USB chiffrée, papier) : gpg --armor --export-secret-keys ton@email.fr > cle-privee-offline.asc


Checklist ☑ finale

  • ~/.claude/.credentials absent du repo (vérifier : ls "$REPO_DIR" | grep credentials)
  • claude.template.json : 0 PII résiduel (test jq ci-dessus)
  • --dry-run fonctionnel : aucun push réel après exécution
  • .backupinclude : validation path traversal active
  • Clé GPG exportée hors-machine pour restauration

Dépannage

ProblèmeVérification
jq walk() non disponibleMettre à jour jq : sudo apt install jq (version ≥ 1.6)
GPG chiffrement échouegpg --list-keys → vérifier que la clé publique est importée
--dry-run ne filtre pas tous les appelsVérifier que chaque commande avec effet de bord utilise run()
Skill non trouvé dans .backupincludeVérifier l’orthographe exacte du dossier dans ~/.claude/skills/

Références

VR · 2026-05-15 · vraffin.dev FIN DU DOCUMENT