Create a vault and lock your source
This page covers the core loop you'll use every day: turning a repo into a vault (your source files, encrypted in place), locking, and unlocking. Locking replaces .ts / .py / .rs files with opaque binary blobs that you commit instead. Unlocking reverses it.
init, lock, and unlock all require a signed-in CLI (sealrepo login — free account, no card; see Install & sign in). The vault is bound to the account that created it, so a different account can't unlock it. The one exception is sealrepo unlock --recovery, which works offline with no sign-in.sealrepo init. The first lock removes plaintext files from disk; if something goes wrong, your git history is the safety net.Initialize the vault
From inside the repo you want to protect:
In your-repo/$cd your-repo$sealrepo initDetected ecosystem: node (package.json found)locked dir: vendor/will encrypt: **/*.ts, **/*.js, src/**will leave alone: node_modules, dist, .gitChoose a passphrase (you'll type this whenever you unlock):Passphrase: ●●●●●●●●●●●●Confirm: ●●●●●●●●●●●●✓Vault initialized.✓Recovery code (write this down — only chance):correct-horse-battery-staple-purple-mountain-19-bridge-jazz⚠If you lose BOTH the passphrase AND the recovery code, your⚠code is unrecoverable. Even we can't read it.Two secrets, two placesStore the passphrase in your password manager. Store the recovery codesomewhere completely different — a Yubikey, a sealed envelope in a safe, a 1Password vault you don't share with your team. If one place is compromised, the other still saves you.Lock your source
sealrepo lockencrypts every matching file with AES-256-GCM, writes the ciphertext into thevendor/directory (or whateverlockedDiryour preset uses), and removes the plaintext files from disk.Locking$sealrepo locklocking /home/you/your-repoencrypting (137) src/internal/billing.ts ⠋✓locked 137 files into vendor/stubs placed: package.json, README.mdYour working tree now looks like this — note the random-looking blob names with no file extensions. That's by design:
file(1)sees only "data", AI scanners see only random bytes.What's now in git$ls vendor/_01/ _0d/ _15/ _2a/ _3f/ _6b/ ...$ls vendor/_01/_8a3f9c1e2d4b$file vendor/_01/_8a3f9c1e2d4bvendor/_01/_8a3f9c1e2d4b: dataCommit and push
The locked blobs commit cleanly. Your normal git workflow is unchanged:
Normal git, normal push$git add .$git commit -m "Initial seal"$git pushAdd a pre-commit hookRunsealrepo install-hookto install a git pre-commit hook. Starting in 1.4.1 the hook is strict by default: anygit commitwhile the project is unlocked is refused, so plaintext source can never reach your git history by accident. Runsealrepo lockfirst, then commit the updated locked blobs. (Need the old behavior for a CI job?sealrepo install-hook --lenientinstalls the pre-1.4.1 "block only on drift" script.)Get your code back when you need it
On any trusted machine signed in to your account — your laptop after a fresh clone, a CI runner, or a teammate you've granted access — pull the repo and unlock:
On a fresh checkout$git clone [email protected]:you/your-repo.git$cd your-repo$sealrepo unlockPassphrase: ●●●●●●●●●●●●unlocking /home/you/your-repodecrypting (137) vendor/_01/_8a3f9c1e2d4b ⠋✓unlocked 137 files (locked at 2026-05-19T00:14:22Z)Your source files are back. Edit, build, run — everything works as before. When you're done, run
sealrepo lockagain and commit the new blobs.Lost the passphrase?Use the recovery code:sealrepo unlock --recoveryprompts for the recovery code instead — it works offline, with no sign-in. Then immediately set a new passphrase withsealrepo rotate.