Vous devez manuellement charger vos secrets avant chaque commande — un source .env, un export VAULT_TOKEN=..., un eval $(op signin) — et vous finissez par tout mettre dans .zshrc par paresse. Lade (prononcé /leɪd/) est une CLI open source qui injecte automatiquement les secrets dans vos processus grâce à des hooks shell transparents. Quand vous entrez dans un répertoire projet, Lade charge les secrets. Quand la commande se termine, il les nettoie.
Ce guide vous apprend à installer Lade, configurer les sources de secrets, utiliser les hooks shell automatiques et personnaliser l’injection par commande et par utilisateur. Il s’adresse aux développeurs qui veulent que leurs secrets soient toujours disponibles sans jamais être exposés.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Ce qu’est Lade et comment fonctionnent les hooks shell
- Comment configurer un fichier
lade.ymlavec le raw loader, le file loader et les vault loaders - Comment filtrer les secrets par commande grâce aux regex
- Comment gérer les secrets par utilisateur dans une équipe
- Comment générer des fichiers de secrets temporaires (YAML, JSON) nettoyés automatiquement
- L’injection manuelle avec
lade injectpour les scripts et la CI
Qu’est-ce que Lade ?
Section intitulée « Qu’est-ce que Lade ? »Lade est une CLI cross-platform (Linux, macOS) développé en Rust. Il intercepte chaque commande que vous tapez dans le shell grâce à des hooks (preexec/precmd) et injecte les secrets correspondants dans les variables d’environnement du processus — puis les supprime quand la commande se termine.
L’analogie est simple : Lade est un assistant invisible qui prépare vos secrets juste avant que vous en ayez besoin et qui range tout derrière vous. Contrairement à un fichier .env qui reste sur le disque indéfiniment, les secrets de Lade n’existent que pendant la durée de la commande.
| Aspect | Détail |
|---|---|
| Objectif | Injecter les secrets automatiquement via des hooks shell, les nettoyer après exécution |
| Approche | Hooks shell (preexec/precmd) + injection par regex de commande |
| Loaders | Raw (valeurs en clair), File (JSON/YAML/TOML/INI), Vault, Infisical, 1Password, Doppler, Passbolt |
| Filtrage | Par regex de commande (ex: terraform.*, python.*, .* pour tout) |
| Per-user | Secrets différents selon l’utilisateur (équipe) |
| Sortie fichier | Génération de fichiers YAML/JSON temporaires, supprimés après exécution |
| Licence | Apache-2.0 |
| Langage | Rust |
Comment fonctionnent les hooks ?
Section intitulée « Comment fonctionnent les hooks ? »Lade utilise les mécanismes natifs de votre shell pour intercepter chaque commande :
-
Avant l’exécution (preexec) : Lade remonte l’arborescence de répertoires à la recherche de fichiers
lade.yml, agrège les secrets qui correspondent à la commande que vous êtes sur le point d’exécuter, et les injecte dans les variables d’environnement. -
Après l’exécution (precmd) : Lade supprime toutes les variables d’environnement qu’il a injectées — les secrets ne persistent jamais dans la session shell.
Ce mécanisme fonctionne avec Zsh, Bash et Fish.
Prérequis
Section intitulée « Prérequis »- Un système Linux ou macOS
- Un shell compatible : Zsh, Bash ou Fish
- Rust/Cargo pour l’installation via Cargo (recommandé)
- Optionnel : un vault (HashiCorp Vault, 1Password CLI, Infisical, Doppler, Passbolt)
Installation
Section intitulée « Installation »-
Installer Lade
Fenêtre de terminal # Via Cargo (recommandé)cargo install lade --locked# Ou via le script d'installationcurl -fsSL https://raw.githubusercontent.com/zifeo/lade/main/installer.sh | bash -
Installer les hooks shell
Cette commande ajoute les hooks dans votre profil shell (
.zshrc,.bashrcouconfig.fish) :Fenêtre de terminal lade install -
Redémarrer votre shell
Fenêtre de terminal exec $SHELL -
Vérifier l’installation
Fenêtre de terminal lade --versionRésultat attendu :
lade 0.13.0
Configurer le premier lade.yml
Section intitulée « Configurer le premier lade.yml »Le fichier lade.yml se place à la racine de votre projet. Sa structure est simple : une regex de commande comme clé, et les secrets comme valeurs.
Structure de base
Section intitulée « Structure de base ».*: DB_HOST: localhost DB_PORT: "5432" DB_USER: devuser DB_PASSWORD: s3cr3t_p4ssw0rd API_KEY: sk-test-1234567890abcdefLa clé .* est une regex qui matche toutes les commandes. Chaque variable est injectée dans l’environnement de chaque commande exécutée dans ce répertoire (ou ses sous-répertoires).
Filtrer par commande
Section intitulée « Filtrer par commande »La puissance de Lade réside dans le filtrage par regex de commande. Vous pouvez injecter des secrets différents selon l’outil utilisé :
# Secrets communs à toutes les commandes.*: DB_HOST: localhost DB_PORT: "5432" DB_USER: devuser
# Secrets pour Terraform uniquementterraform.*: TF_VAR_db_password: s3cr3t_terraform AWS_REGION: eu-west-1 AWS_ACCESS_KEY_ID: AKIAIOSFODNN7EXAMPLE
# Secrets pour Python/Node uniquementpython.*|node.*: API_KEY: sk-test-1234567890abcdef DB_PASSWORD: s3cr3t_p4ssw0rdAvec cette configuration :
terraform planreçoitDB_HOST,DB_PORT,DB_USER,TF_VAR_db_password,AWS_REGIONetAWS_ACCESS_KEY_IDpython3 app.pyreçoitDB_HOST,DB_PORT,DB_USER,API_KEYetDB_PASSWORDlsreçoit uniquementDB_HOST,DB_PORTetDB_USER
Cette approche limite l’exposition : Terraform n’a pas accès à l’API key, et Python n’a pas accès aux credentials AWS.
Les loaders
Section intitulée « Les loaders »Lade supporte 7 loaders pour récupérer les secrets depuis différentes sources.
Raw loader (valeurs en clair)
Section intitulée « Raw loader (valeurs en clair) »Le loader par défaut injecte les valeurs telles quelles. Préfixer une valeur par ! force l’utilisation du raw loader (utile pour les valeurs qui commencent par un protocole comme vault://) :
.*: SIMPLE_VALUE: hello_world ESCAPED_VALUE: "!vault://this-is-not-a-vault-ref"File loader
Section intitulée « File loader »Le file loader lit les secrets depuis un fichier JSON, YAML, TOML ou INI local. Le paramètre query utilise la syntaxe JMESPath pour extraire des champs spécifiques :
.*: DB_HOST: "file://secrets.json?query=.database.host" DB_PORT: "file://secrets.json?query=.database.port" DB_PASSWORD: "file://secrets.json?query=.database.password"Avec le fichier secrets.json :
{ "database": { "host": "db.prod.example.com", "port": 5432, "password": "pr0d_p4ss" }}Le chemin peut être relatif au répertoire du lade.yml, commencer par ~ ou $HOME, ou être absolu.
Vault loader (HashiCorp Vault)
Section intitulée « Vault loader (HashiCorp Vault) ».*: DB_PASSWORD: "vault://vault.company.com/secret/myapp/DB_PASSWORD" API_KEY: "vault://vault.company.com/secret/myapp/API_KEY"Le format est vault://DOMAINE/MOUNT/CLE/CHAMP. L’authentification utilise le CLI vault local (vous devez être connecté via vault login).
Infisical loader
Section intitulée « Infisical loader ».*: DB_PASSWORD: "infisical://app.infisical.com/PROJECT_ID/production/DB_PASSWORD"Le format est infisical://DOMAINE/PROJECT_ID/ENVIRONNEMENT/NOM_SECRET. Lade ajoute automatiquement /api au domaine. L’authentification utilise le CLI infisical local.
1Password loader
Section intitulée « 1Password loader ».*: DB_PASSWORD: "op://my.1password.eu/DevVault/Database/password" API_KEY: "op://my.1password.eu/DevVault/APIKeys/production"Le format est op://DOMAINE/VAULT/ITEM/CHAMP. L’authentification utilise soit une session op active, soit un OP_SERVICE_ACCOUNT_TOKEN (pour la CI).
Pour utiliser un token de service stocké dans un autre vault (lookup récursif) :
.*: .: 1password_service_account: "vault://vault.company.com/secret/1password/service-token" SECRET: "op://my.1password.eu/DevVault/Item/field"Doppler loader
Section intitulée « Doppler loader ».*: DB_PASSWORD: "doppler://api.doppler.com/my-project/production/DB_PASSWORD"Passbolt loader
Section intitulée « Passbolt loader ».*: DB_PASSWORD: "passbolt://passbolt.company.com/RESOURCE_ID/password"Tableau récapitulatif des loaders
Section intitulée « Tableau récapitulatif des loaders »| Loader | URI | CLI requis | Authentification |
|---|---|---|---|
| Raw | Valeur directe | Non | Aucune |
| File | file://chemin?query=.champ | Non | Aucune |
| Vault | vault://domaine/mount/clé/champ | vault | vault login |
| Infisical | infisical://domaine/projet/env/secret | infisical | infisical login |
| 1Password | op://domaine/vault/item/champ | op | Session ou service account |
| Doppler | doppler://domaine/projet/env/secret | doppler | doppler login |
| Passbolt | passbolt://domaine/resource_id/champ | Aucun (API) | Credentials Passbolt |
Injection manuelle avec lade inject
Section intitulée « Injection manuelle avec lade inject »Pour les scripts non-interactifs et les pipelines CI, utilisez lade inject :
# Injecter les secrets et lancer une commandelade inject -- python3 app.py
# Équivalent à "teller run" pour les utilisateurs de Tellerlade inject -- npm start
# Avec un chemin absolu si nécessairelade inject -- /usr/bin/python3 app.pyRésultat :
Lade loaded: DB_PASSWORD, API_KEY, DB_HOST, DB_PORT, DB_USER.Connexion à localhost:5432User: devuserAPI Key: configuréeLade affiche les noms des variables chargées (sans les valeurs) sur stderr, puis exécute la commande.
Secrets par utilisateur
Section intitulée « Secrets par utilisateur »Quand plusieurs membres d’une équipe partagent le même projet, chacun peut avoir des secrets différents. Lade résout automatiquement l’utilisateur courant :
.*: DB_HOST: localhost DB_PORT: "5432" DB_PASSWORD: alice: alice_db_password bob: bob_db_password .: default_passwordAvec cette configuration :
- bob reçoit
DB_PASSWORD=bob_db_password - alice reçoit
DB_PASSWORD=alice_db_password - Tout autre utilisateur reçoit
DB_PASSWORD=default_password - Si la clé
"."est absente, les autres utilisateurs ne reçoivent rien
Gérer l’utilisateur Lade
Section intitulée « Gérer l’utilisateur Lade »# Voir l'utilisateur courantlade user
# Changer d'utilisateur (utile pour tester)lade user alice
# Revenir à l'utilisateur OSlade user --resetSortie en fichier
Section intitulée « Sortie en fichier »Par défaut, Lade injecte les secrets en variables d’environnement. Vous pouvez aussi les écrire dans un fichier temporaire (YAML ou JSON) qui sera automatiquement supprimé après l’exécution de la commande :
.*: .: file: secrets.yml DB_HOST: localhost DB_PORT: "5432" DB_PASSWORD: s3cr3t_p4ssw0rdQuand vous exécutez une commande, Lade :
- Crée le fichier
secrets.ymlavec les secrets - Exécute la commande
- Supprime le fichier
secrets.yml
Le format du fichier est déterminé par l’extension (.yml/.yaml pour YAML, .json pour JSON).
Hooks shell : activer et désactiver
Section intitulée « Hooks shell : activer et désactiver »Les hooks sont gérés par les commandes on et off :
# Désactiver les hooks (temporaire, session courante)eval "$(lade off)"
# Réactiver les hookseval "$(lade on)"
# Installer les hooks (permanent, modifie .zshrc/.bashrc)lade install
# Désinstaller les hooks (permanent)lade uninstallLa commande eval "$(lade off)" est utile pour déboguer : si une commande échoue de façon inattendue, désactivez les hooks pour vérifier si Lade est en cause.
Intégration CI/CD
Section intitulée « Intégration CI/CD »GitLab CI
Section intitulée « GitLab CI »deploy: stage: deploy image: rust:1.78-slim before_script: - cargo install lade --locked script: - lade inject -- ./deploy.sh variables: VAULT_TOKEN: $CI_VAULT_TOKENGitHub Actions
Section intitulée « GitHub Actions »name: Deployon: [push]
jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Install Lade run: cargo install lade --locked
- name: Deploy with secrets run: lade inject -- ./deploy.sh env: VAULT_TOKEN: ${{ secrets.VAULT_TOKEN }}Comparaison Lade vs Teller
Section intitulée « Comparaison Lade vs Teller »| Critère | Lade | Teller |
|---|---|---|
| Injection | Hooks shell automatiques ou lade inject | teller run (toujours explicite) |
| Nettoyage | Automatique après chaque commande | Les secrets persistent dans le processus |
| Filtrage | Par regex de commande | Tous les secrets sont injectés |
| Per-user | Oui, natif | Non |
| Scan secrets | Non | Oui (teller scan) |
| Redact logs | Non | Oui (teller redact) |
| Export | Non (sortie fichier uniquement) | JSON, YAML, env, CSV |
| Template | Non | Oui (moteur Tera) |
| Providers | Vault, 1Password, Infisical, Doppler, Passbolt, File | Vault, AWS SM, AWS SSM, GCP SM, Consul, dotenv |
| Héritage config | Récursif (remonte l’arborescence) | Fichier unique .teller.yml |
En résumé : Lade est idéal pour le workflow développeur quotidien grâce aux hooks transparents et au filtrage par commande. Teller excelle pour le scanning de secrets et la manipulation programmatique (export, redact, template, copy).
Dépannage
Section intitulée « Dépannage »| Symptôme | Cause probable | Solution |
|---|---|---|
lade: command not found | Binaire pas dans le PATH | Vérifier avec which lade ou ajouter ~/.cargo/bin au PATH |
| Secrets non injectés en shell interactif | Hooks non installés | Exécuter lade install puis redémarrer le shell |
| Secrets non injectés en script | Hooks inactifs en non-interactif | Utiliser lade inject -- <commande> |
command failed avec lade inject | Commande non trouvée dans le PATH | Utiliser le chemin absolu : /usr/bin/python3 |
| Mauvais secret per-user | Utilisateur Lade différent de l’OS | Vérifier avec lade user, réinitialiser avec lade user --reset |
Conflit entre fichiers lade.yml | Héritage récursif des répertoires parents | Le lade.yml le plus proche du CWD a priorité |
vault:// non résolu | CLI vault non authentifié | Exécuter vault login avant d’utiliser Lade |
op:// non résolu | CLI op non authentifié | Exécuter eval $(op signin) ou configurer un OP_SERVICE_ACCOUNT_TOKEN |
| Fichier de sortie non créé | Bloc .: absent ou mal formaté | Vérifier que .: { file: secrets.yml } est sous le bon regex |
Lade loaded: mais variables absentes | Regex de commande ne matche pas | Vérifier que le regex matche la commande (.*: pour tout matcher) |
À retenir
Section intitulée « À retenir »-
Lade injecte les secrets automatiquement grâce à des hooks shell — vous tapez simplement votre commande, sans wrapper ni préfixe.
-
Les secrets sont nettoyés après chaque commande : ils n’existent que pendant la durée de vie du processus enfant.
-
Le filtrage par regex de commande permet de n’exposer que les secrets nécessaires à chaque outil : Terraform reçoit les credentials AWS, Python reçoit les clés API, rien de plus.
-
Les secrets par utilisateur permettent à chaque membre de l’équipe d’avoir ses propres credentials tout en partageant le même
lade.ymldans Git. -
7 loaders couvrent les principaux vaults du marché : Vault, 1Password, Infisical, Doppler, Passbolt, plus un file loader et un raw loader.
-
lade injectest l’équivalent deteller runpour les environnements non-interactifs (CI/CD, scripts).