
Trouvez les secrets en texte clair sur votre Mac et placez-les derrière Touch ID, injectés juste à temps sans casser les outils qui les lisent. Gratuit et local-first.
Identifiants just-in-time pour votre machine de développement.
Documentation · Démarrage rapide · Outils pris en charge · Référence des commandes · Sécurité
Statut : macOS uniquement (Apple Silicon), et encore en développement.
Vos secrets sont stockés en clair partout sur votre machine : fichiers .env,
~/.aws/credentials, exports ~/.zshrc, jetons .npmrc, configs MCP. Tout ce
qui s'exécute sous votre identité peut les lire. Un mauvais curl | sh, un npm install douteux, ou l'un des agents IA qui tournent désormais dans votre éditeur avec vos permissions complètes.
jit déplace chaque secret dans un coffre-fort chiffré local protégé par Touch ID, et
réécrit les fichiers pour que vos outils continuent de fonctionner. Sur le disque, il ne reste qu'un leurre. La
valeur réelle n'apparaît qu'en mémoire, pour le processus spécifique qui l'a demandée,
après une invite biométrique. Le résultat : vous déverrouillez une fois, jit demande avant de remettre
un identifiant à un outil (ou à un agent), et un leurre reste sur le disque le reste du
temps.
| lancé par Code | lancé par claude |
|---|---|
![]() | ![]() |
Ce qu'il ne fait pas : il ne rend pas sûr un compte déjà compromis, et il ne protège pas un secret une fois qu'il est en mémoire dans le processus qui l'a demandé. Les limites sont énoncées sur une page, d'emblée : les limites délibérées.
Pas d'extension noyau, pas de pilote de système de fichiers, pas de FUSE. Trois mécanismes, choisis selon ce que l'outil peut faire :
execve. L'image propre de jit
est remplacée par votre commande, donc la valeur vit dans ce seul processus et jit
disparaît de la mémoire.credential_process, helpers d'identifiants docker et git, plugins d'exécution kubectl,
helper d'identifiants de Terraform. L'outil demande, jit répond, aucun
fichier impliqué.Le montage est un FIFO POSIX, créé avec mkfifo(2) en mode 0600. Un programme
appelant open(".env") bloque dans le noyau jusqu'à ce qu'un écrivain se connecte. Le
service en arrière-plan est cet écrivain : il ouvre le chemin O_WRONLY, ce qui
libère le lecteur, écrit les octets déchiffrés depuis la mémoire dans le tampon du tube
du noyau, ferme, puis revient à open(2) pour le lecteur suivant. Rien
ne touche le disque. Ce qui est écrit est décidé à chaque lecture : des leurres pour un lecteur
ambiant, des valeurs réelles uniquement dans une exécution que vous avez autorisée.
L'identité de l'appelant explique et audite, elle ne décide jamais. Les noms de processus sont forgeables, et un lecteur FIFO qui se ferme rapidement peut échapper entièrement à l'identification. L'humain qui répond à l'invite est la barrière ; le nom du processus ne fait que vous dire à quoi répondre. Détails complets dans comment cela fonctionne et montages en direct.
brew install jitpass/tap/jitpass
C'est la voie recommandée, et pour un outil de sécurité, la raison compte.
Les versions sont signées avec un Apple Developer ID et notarisées par Apple.
Homebrew met en quarantaine ce qu'il télécharge, donc Gatekeeper vérifie le binaire
par rapport à son ticket de notarisation avant qu'il ne soit autorisé à s'exécuter. Pour vérifier
vous-même plutôt que de nous croire sur parole, exécutez jit doctor : sa ligne
jit indique signed CZC6BH93GJ, la même vérification que jit upgrade effectue avant
d'installer quoi que ce soit.
curl -sL https://dl.jitpass.com/jitpass/jit/releases/latest/download/jitpass_darwin_arm64.tar.gz | tar -xz jit
shasum -a 256 jit # comparez avec checksums.txt sur la page des versions
codesign -dv --verify --verbose=2 ./jit # attendez-vous à : Developer ID, TeamIdentifier=CZC6BH93GJ
sudo mv jit /usr/local/bin/
Ceci est destiné aux personnes sans Homebrew, et c'est réellement la voie la plus
faible : curl ne définit pas de bit de quarantaine, donc Gatekeeper ne consulte jamais le
ticket de notarisation, et il en va de même pour go install. Le binaire est
toujours signé et toujours notarisé, donc les deux lignes ci-dessus vous permettent de vérifier les deux
avant de l'exécuter, mais vous devez réellement les exécuter. Si vous avez Homebrew,
utilisez Homebrew.
Apple Silicon uniquement. Sur un Mac Intel, compilez depuis les sources avec
go install github.com/jitpass/jit/cmd/jit@latest.
Choisissez une seule voie. Si vous avez installé depuis l'archive tar auparavant et que vous passez à
Homebrew, supprimez l'ancienne copie après le brew install (sudo rm /usr/local/bin/jit) ; sinon deux jit se retrouvent sur PATH et se mettent à jour séparément, et
jit doctor le signalera.
Mise à jour : brew upgrade jitpass, ou jit upgrade : une
auto-mise à jour vérifiée (signature Developer-ID et somme de contrôle toutes deux vérifiées avant le
remplacement, redémarre le service). Dans les deux cas, votre coffre-fort reste intact.
Homebrew installe la complétion shell avec le binaire, donc jit <TAB> complète
les sous-commandes, les drapeaux, les chemins de coffre-fort et les noms d'outils enveloppables dès le départ.
Installé depuis l'archive tar ou depuis les sources, ajoutez-la vous-même :
echo 'source <(jit completion zsh)' >> ~/.zshrc && exec zsh
Dans tous les cas, jit doctor vous indique si la complétion n'atteint pas votre shell.
jit scan # lecture seule. ne modifie aucun fichier scanné, n'affiche aucune valeur réelle.
jit vault init # crée le coffre-fort (clé maîtresse dans votre trousseau de connexion)
jit migrate --dry-run # aperçu de tout le plan de correction à l'échelle de la machine
jit migrate # l'applique : affiche le plan, demande [y/N], un Touch ID
jit migrate ~/code/myapp # ou corrigez juste un projet
jit run -- npm run dev # exécutez votre outil ; les valeurs réelles sont injectées dans ce processus uniquement
jit scan sans chemin balaie tout votre répertoire personnel, donc laissez-lui un moment sur un
grand. Pour aller directement à un endroit, pointez-le vers un chemin : jit scan ~/.aws.
Au quotidien, c'est surtout jit run -- <cmd>. Pour les CLI qui portent leur propre jeton de
connexion (gh, glab, stripe, et plus), vous faites jit wrap gh une fois puis continuez à
taper gh comme d'habitude pour toujours.
Vous ne savez pas si quelque chose nécessite jit wrap, jit migrate, ou rien ? Vous
n'avez pas besoin de le savoir. jit scan répartit tout ce qu'il trouve entre ce que jit
protégera (une seule commande - les wraps inclus) et ce que vous seul pouvez corriger, et
jit migrate nu exécute tout ce plan :
$ jit scan
VOS SECRETS : 7 — 0 protégés par jit (0%)
▱▱▱▱▱▱▱▱▱▱ vers 100% : une commande +71% · 2 secrets que vous seul pouvez corriger +29%
jit protégera ceux-ci — 5 secrets dans 4 fichiers, 0% → 71%
→ jit migrate
~/.zshrc STRIPE_API_KEY, DB_PASSWORD
~/.config/gh/hosts.yml jeton GitHub CLI · wraps gh
...
vous seul pouvez protéger ceux-ci — 2 secrets, 71% → 100%
[faites pivoter, puis supprimez chaque copie]
! Un mot de passe de base de données de production dans 2 fichiers
→ faites-le pivoter maintenant, puis supprimez chaque copie
(jit scan --full donne toujours l'inventaire classique par catégorie avec
les sévérités, y compris la section Jetons CLI enveloppables.)
Migrez l'identifiant une fois, puis continuez à utiliser l'outil comme vous l'avez toujours fait.
# AWS (et Terraform, et chaque SDK AWS)
jit migrate ~/.aws/credentials # les clés passent dans le coffre-fort ; plus de fichier en clair
aws s3 ls # se résout depuis le coffre-fort à la demande. pas de préfixe, pas de drapeau.
terraform apply # mêmes identifiants, même commande
# Identifiants par défaut de l'application GCP (un identifiant à l'échelle de la machine)
jit migrate ~/.config/gcloud/application_default_credentials.json
terraform apply # le fournisseur google lit ADC ; fonctionne après une invite Touch ID
# Docker / docker-compose
jit migrate ~/.docker/config.json # les connexions au registre passent dans le coffre-fort
jit run -- docker compose up # jit les injecte pour cette exécution
docker login ghcr.io # fonctionne toujours ; le helper stocke dans le coffre-fort
# Exports shell qui se trouvaient dans ~/.zshrc
jit migrate ~/.zshrc # laisse un hook d'une ligne ; les nouveaux shells ont juste les variables
./deploy.sh # les scripts qui lisent ces variables fonctionnent sans modification
# Jetons que vous avez tapés à l'invite, désormais dans votre historique shell
jit migrate ~/.zsh_history # chacun passe dans le coffre-fort ; vos commandes restent, les secrets non
jit guard history # et empêchez le suivant d'être enregistré du tout (zsh)
# (`jit migrate` nu propose aussi cela, dans le plan qu'il vous demande de confirmer)
# Une CLI qui porte son propre jeton (gh, stripe, glab)
jit wrap gh # une seule fois
gh pr list # jeton injecté à chaque appel, pour toujours
La première fois que chaque outil accède à un identifiant réel, jit demande une fois et
mémorise votre réponse jusqu'au verrouillage du coffre-fort. Voir Deux moments Touch ID, pas un
pour savoir comment cela se superpose au déverrouillage du coffre-fort, ce que fait --trust, et comment
désactiver les invites par outil.
Pourquoi certains outils ne nécessitent aucune configuration tandis que d'autres prennent un jit run ? Une règle : l'outil
peut-il demander le secret à jit lui-même ? AWS (via credential_process), votre
shell à la connexion, et les connexions au registre docker (via un helper d'identifiants) le peuvent tous,
donc vous ne tapez rien de plus. Les outils qui ne lisent qu'un fichier à l'exécution (docker
compose, SDK simples) ne peuvent pas demander, donc jit run leur remet la valeur.
Les fichiers d'identifiants globaux à la machine (GCP ADC, sops, npm, netrc) fonctionnent de la même
manière au quotidien : exécutez votre outil et approuvez l'invite par processus. Ajoutez jit run --with <name> uniquement lorsque vous voulez que ce soit explicite : pour les scripts et CI où il n'y a
pas d'invite à laquelle répondre, ou lorsque vous voulez une barrière dure que la propre configuration d'un projet ne peut
jamais atteindre. Outils pris en charge liste exactement quoi taper pour
chaque outil, et comment chacun est livré.
jit demande votre empreinte à deux moments différents, pour deux tâches différentes :
jit après son verrouillage, un
Touch ID ouvre le coffre-fort pour toute la session (5 minutes d'activité, puis il se
reverrouille ; et jamais plus de 8 heures, quelle que soit votre activité). Vous déverrouillez
une fois, pas une fois par commande.jit demande avant de le remettre et
nomme ce qui demande. C'est ce qui empêche un programme que vous n'avez pas lancé d'utiliser
silencieusement vos clés pendant que le coffre-fort est ouvert.$ aws s3 ls
Touch ID -> déverrouillez votre coffre-fort # barrière 1 : ouvre le coffre-fort pour 5 min
Touch ID -> aws veut votre identifiant aws # barrière 2 : cet outil, cet identifiant
...vos buckets...
$ aws s3 cp ./file s3://bucket/ # même outil, même session : pas d'invite
$ terraform apply
Touch ID -> terraform veut votre identifiant aws # un outil différent : il demande de lui-même
La barrière 2 est ce qui empêche un coffre-fort déverrouillé d'être un libre-service : même après
avoir utilisé aws vous-même, un npm install douteux accédant à ces mêmes clés
déclenche toujours une invite le nommant, pour que vous puissiez dire non.
Vous ne voulez pas de la deuxième barrière ? Désactivez-la ; le verrouillage du coffre-fort reste (la désactiver elle-même prend un Touch ID, puisqu'elle rouvre la fenêtre qu'elle ferme) :
jit service consent off # les outils se résolvent silencieusement pendant que le coffre-fort est déverrouillé
jit service consent on # demander à nouveau par outil (le défaut)
Vous lancez quelque chose qui nécessite plusieurs identifiants à la fois ? jit run --trust -- terraform apply approuve tous les outils de cette exécution d'un seul geste. Détails complets :
consentement par processus.
jit grantLes deux barrières supposent qu'un humain est là pour répondre. Un agent IA qui travaille toute la nuit, une longue compilation, un travail planifié : l'écran se verrouille, la session tombe, et l'exécution cale sur une invite que personne ne verra. Une autorisation de processus déplace votre décision plus tôt au lieu de la supprimer - un Touch ID, donné pendant que vous êtes encore là, qui nomme exactement ce que vous signez :
$ jit grant --process claude --profile jamf --for 8h
Touch ID -> laisser claude sous iTerm2 utiliser 2 secrets (jamf) sans surveillance pendant 8h
✓ accordé g-7f3a2c81 claude -> jamf jusqu'à 17:42
└ couvre claude sous iTerm2 : 1 en cours d'exécution, tout démarré avant 17:42
Pendant les 8 heures suivantes, chaque claude sous le terminal dans lequel vous avez tapé cela
(et ce qu'il lance) obtient ces secrets sans invites - à travers le verrouillage d'écran et
tout, y compris les sessions que vous démarrez plus tard : un nouvel onglet, le prochain claude, un
script qui se déclenche à 3h du matin. C'est votre terminal qui est nommé, pas un nom qui est
fiable : un programme qui s'appelle claude ailleurs sur la machine
ne descend pas de cet arbre et n'hérite de rien. L'autorisation se termine à son
échéance, lorsque vous quittez ce terminal, ou au moment où vous tapez jit grant revoke (qui ne nécessite aucune empreinte - retirer l'accès est toujours gratuit). Vous voulez
un processus exact à la place, disparu à sa sortie ? --pid. Chaque octroi atterrit dans
la piste d'audit comme son propre événement, donc le lendemain matin vous pouvez lire
exactement ce que votre agent a touché pendant que vous dormiez. Détails complets :
autorisations de processus.
L'agent dans votre éditeur s'exécute comme vous, avec vos permissions, et lit des fichiers
pour vous toute la journée. C'est tout son but, et c'est aussi pourquoi un .env en clair
dans votre dépôt est désormais un risque très différent de ce qu'il était il y a deux ans.
jit traite les agents comme des citoyens de première classe, sur quatre fronts :
jit migrate ~/.claude.json # configs de serveurs MCP : les clés passent dans le coffre-fort,
# chaque serveur se lance désormais via `jit run`
jit wrap claude # les CLI IA elles-mêmes : claude, codex, gemini,
# cursor-agent, copilot, cline, opencode, kiro-cli
jit grant --process claude --profile myapp --for 8h
# laissez-le travailler toute la nuit sans invite à laquelle personne ne répond
jit audit --parent claude # relisez exactement ce qu'il a touché pendant que vous dormiez
claude, chacun
nommé. Un agent lisant silencieusement ~/.aws/credentials est une invite, pas un
succès silencieux.jit run. Une config MCP migrée contient des chemins de
coffre-fort, pas des clés, donc le fichier de config lui-même est sûr à avoir sur le disque et sûr
à remettre à l'agent qui le lit..env et le lit à froid obtient des valeurs factices, et la lecture est journalisée.jit audit --parent claude montre chaque secret qu'un agent a utilisé, chaque
invite qu'il a déclenchée, et chacune que vous avez refusée.Plus dans Outils MCP / IA et consentement par processus.
Chaque commande jit et chaque déverrouillage atterrit dans un journal durable que vous relisez avec
jit audit, du plus récent au plus ancien, une ligne key=value par événement, donc il se grep comme un
vrai journal de service. Les arguments de commande sont masqués, donc le journal prouve qu'une commande a été exécutée
sans jamais stocker le secret qu'elle portait.
$ jit audit --since 1h
time=2026-07-24 10:15:04 level=info kind=cmd status=ok dur=312ms cmd="jit migrate ~/.aws/credentials" user=meni parent=claude
time=2026-07-24 10:16:22 level=info kind=use op="read a secret" cmd="aws s3 ls" parent=claude secrets=aws/default
time=2026-07-24 10:31:09 level=warn kind=unlock status=denied method=touchid-or-passcode cmd="node postinstall.js" parent=npm secrets=aws/default
La ligne du milieu est l'histoire que jit existe pour raconter : aws/default a été lu par aws s3 ls, lancé par claude. La dernière est une invite que vous avez refusée : un node postinstall.js sous npm accédant à ces mêmes clés, refusé. jit journalise aussi
ce que le service a refusé à son socket (un processus que le noyau dit n'être pas
le vôtre, sondant l'agent) comme kind=error.
Affinez avec des drapeaux au lieu de grep : --kind, --status ok|failed|denied,
--since/--until (un âge comme 2h/3d ou une date), --parent claude,
--secret aws, --user, --grep <regexp>. Ajoutez --follow (-f) pour diffuser les nouveaux
événements en direct comme tail -f, ou --format json pour un dump analysable par machine. Les deux
moitiés sont des fichiers durables à côté du coffre-fort, donc il répond pour la semaine dernière aussi facilement
que pour la dernière heure.
Fichiers .env, exports shell, AWS et Terraform, kubeconfig, connexions au registre Docker,
GCP ADC, jetons .npmrc / .netrc, configs de serveurs MCP, fichiers de jetons
nus, identifiants enregistrés dans votre historique shell, CLI enveloppables (gh,
stripe, vercel, …), et CLI SSO qui frappent des identifiants à la connexion
(clisso). Dans chaque cas, le fichier continue de fonctionner et la valeur réelle vient
du coffre-fort à la demande.
Le catalogue complet, groupé par exactement quoi taper pour chaque outil, est
Outils pris en charge : il suit le code à mesure que des outils sont ajoutés ou
retirés. Tout ce qui n'est pas listé peut encore être enveloppé avec
jit wrap add.
Vous gardez déjà vos secrets dans 1Password ? Avec sa CLI installée,
jit migrate lie au lieu de copier : une
valeur qui vit déjà dans 1Password est placée dans le coffre-fort comme sa référence op://,
donc 1Password reste le système de référence et jit livre la valeur
just-in-time à travers chaque mécanisme ci-dessus (jit vault link fait la même chose
pour un secret à la main).
jit ne détruit jamais un identifiant. Migrer déplace la valeur dans le coffre-fort et
laisse un hook fonctionnel là où elle était (un .env leurre, une ligne eval "$(jit export)"
dans votre config shell, credential_process = jit … dans ~/.aws/config, ou un
shim PATH), donc vos outils continuent de la résoudre à la demande. L'identifiant existe
toujours, juste chiffré au lieu d'être en clair.
Et chaque changement est réversible. Avant de toucher un fichier, jit le sauvegarde chiffré
dans le coffre-fort, donc jit migrate undo le remet octet pour octet :
jit migrate ~/code/myapp # a appliqué la correction, un Touch ID
# vous avez changé d'avis, ou quelque chose a cassé ?
jit migrate undo ~/code/myapp # chaque fichier touché restauré, octet pour octet
La documentation vit sous docs/, organisée par tâche :
git commit -s), pas de CLALicence PolyForm Perimeter 1.0.0 - gratuite pour un usage personnel et interne à l'entreprise uniquement.