1. Start in 5 minutes
SealBox is a command-line tool. Once it's installed, a few commands in your project folder are all it takes.
Install
$ pip install sealbox # or: pipx install sealbox $ sealbox -V # print the version: sealbox 0.3.0
Check your project
init changes no files. It looks at the project and lists the next steps in order:
$ cd my-project $ sealbox init sealbox 0.3.0 · project: C:\my-project · This project has no vault yet · No team (single user) → sealbox team init --github <name> ⚠ Exposed secrets in 3 file(s) → sealbox seal Next steps: 1) sealbox seal 2) sealbox recovery setup
Seal, back up, run
$ sealbox seal # move secrets into the vault $ sealbox recovery setup # recovery code (once) $ sealbox exec -- python app.py # run your program with the secrets $ git add .sealbox $ git commit -m "vault"
Tip: Whenever you're stuck, type sealbox status. Every problem line comes with the command that fixes it. For details on a command, use sealbox help seal. Typos get corrected too: sealbox sael answers "Did you mean: seal?".
2. Core concepts
Five ideas are enough to understand SealBox. We'll explain each with an analogy from home.
The big picture: Imagine you've hired a cleaner (the agent). To do the job, they need to go into every room. You don't leave your jewellery on the table; you put it in the safe, and you leave a note on the table saying "jewellery is in the safe". The cleaner sees the note but never the jewellery. SealBox does that for your code.
🔐 Vault
.sealbox/project.vault. Every secret sits here, encrypted with AES-256-GCM. Because it's encrypted, it can go into the repo.
🗝 Vault key (DEK)
The single key that opens the vault. It's never on disk: it's kept in Windows Credential Manager, the macOS Keychain or the Linux Secret Service.
Analogy: the key to the safe. In your pocket, not on the table.🏷 Placeholder
A random name like __SECURE_TCKN_103d…__. It's written in place of personal data such as emails, national IDs and IBANs.
🌱 Environment variable
Instead of a password, the code says os.environ["DB_PASSWORD"]. The value is handed in from outside while the program runs.
✅ Approval window
When a program asks for secrets, this window shows which values will be handed over. There's no setting to skip it.
Analogy: being asked every time someone opens the safe.🧯 Recovery code
A backup code that opens the vault if the key is lost. You can split it into 3 shares; any 2 are enough.
Analogy: the spare key at grandma's.What goes where?
| What was found | What happens |
|---|---|
| Password, token or API key in code (a whole string) | Moves to the vault; the code becomes os.environ["X"] / process.env.X / System.getenv("X") |
| The same value repeated in a comment | Redacted with a placeholder |
| Email, national ID, phone, IBAN, name | Redacted with a placeholder (use vault expose if needed) |
.env file | Secret lines go to the vault, .env is deleted, .env.sealed stays |
| JSON / YAML / TOML config | Redacted, and the report tells you which environment variable to read |
| Part of a URL, or an unsupported language | Left alone with a [!] warning; move it by hand |
3. Seal your first project
Just look first
--check touches nothing. If there are exposed secrets it exits with code 1, so you can use it in CI too.
$ sealbox seal --check .env → .env.sealed: 1 value(s) moved to the vault (DB_PASSWORD) 3 file(s) scanned (0.0 s). There are unredacted secrets on disk. Run 'sealbox seal'.
Seal
$ sealbox seal # the whole project $ sealbox seal src/config.py # a single file
Run it from the project root. If you run it from a subfolder like src and there's a .env, .git or vault above it, SealBox stops, because the .env up there would be left exposed. If you chose that folder on purpose, pass -w ..
What happens to your files?
Each language reads the secret its own standard way. The logic of your code doesn't change:
# before KEY = "sk_live_51N…" # after KEY = os.environ["KEY"]
// before const key = "sk_live_51N…" // after const key = process.env.KEY
// before String key = "sk_live_51N…"; // after String key = System.getenv("KEY");
Reverting a file and sealing it again doesn't create duplicates in the vault, because the same value always maps to the same entry.
Java note: A static final constant is now filled at runtime instead of compile time. Code that uses such a constant in a switch case or an annotation won't compile after the move. That rarely happens with secrets.
4. Run your program with the vault
Analogy: exec works like a doorman. Your program says "I need the password". The doorman asks you, "Shall I hand over these 4 values?" If you say yes, the values are given only for that run and taken back when it ends.
$ sealbox exec -- python app.py # Python $ sealbox exec -- npm start # Node.js $ sealbox exec -- java Main.java # Java $ sealbox exec -- mvn spring-boot:run # Maven / Gradle
- Everything after
--is your normal command. - An approval window opens first. There's deliberately no flag or environment variable that skips it.
- If a known secret appears in your program's output, it's printed as
[REDACTED:..].
Note: The output goes through a pipe, so interactive or colourful terminal programs may behave a little differently. The filter doesn't catch secrets printed reversed or in pieces. The approval window is the real protection.
If your program uses redacted data
Data like emails or national IDs is redacted with a placeholder, because usually it isn't needed at runtime. If your program really uses it, turn it into an environment variable:
$ sealbox vault expose __SECURE_EMAIL_8f2c…__ $ sealbox vault expose __SECURE_EMAIL_8f2c…__ --as ADMIN_EMAIL
5. Manage values in the vault
Values are never printed to the terminal on their own. Showing and deleting both ask for approval.
$ sealbox vault list # names and placeholders (no values) $ sealbox vault reveal DB_PASSWORD # show it in the approval window $ sealbox vault reveal __SECURE_TCKN_…__ # look at redacted data $ sealbox vault set DB_PASSWORD # change or add $ sealbox vault remove --unused # delete unused entries
Reverting a file doesn't delete anything from the vault. If a value changed, the old one is left orphaned, and vault remove --unused cleans it up. An entry still used by a placeholder or variable name in some file isn't deleted (use --force to insist).
6. Add a teammate
Analogy: You copy the vault key and give each teammate a box locked with their own padlock. Anyone can see the boxes, since they sit in the repo. But each box opens only with its owner's key, and that key is their SSH key on GitHub.
Preparation (everyone, once)
You need a passphrase-protected SSH key on your computer, with its public half added to your GitHub account. Keys without a passphrase are rejected, because any program on the machine (agents included) could read them.
$ ssh-keygen -t ed25519 # set a passphrase when asked $ ssh-keygen -p -f ~/.ssh/id_ed25519 # add a passphrase to an existing key # add the contents of ~/.ssh/id_ed25519.pub under GitHub → Settings → SSH keys
You (owner)
$ sealbox team init --github my-name # create the team, you're the owner $ sealbox team add teammate # github.com/teammate.keys $ sealbox team add alice --owner # let her add and remove people too $ git add .sealbox $ git commit -m "add teammate to the vault" $ git push
Your teammate
$ git pull $ sealbox exec -- python app.py # the SSH passphrase is asked in a window the first time
After the first open, the key is cached in the Windows store and isn't asked for again.
Removing someone
$ sealbox team remove teammate # the vault key is rotated $ sealbox team list # members and SSH fingerprints
Remember: A removed person can still open the old vault from git history with the old key. That's why team remove lists the values they may have seen. Change those passwords at their source (database, API dashboard).
Check .gitignore: If the root .gitignore excludes the whole .sealbox/ folder, the vault never reaches the repo. The team commands and status warn you about this.
7. If you lose the key
Analogy: There's always some way to lose your house key: Windows gets reset, you change computers, a profile breaks. The recovery code is a spare key kept somewhere you trust. Split it into 3 shares and one can stay with your mum, one in a safe, one on a USB stick. Any 2 of them open the door.
Today, while everything works (once)
$ sealbox recovery setup # the code appears in a window; write it down $ sealbox recovery shares # optional: split into 2-of-3 shares $ sealbox recovery export D:\project.sapkit # optional: a USB / cloud kit
The code and the shares are never printed to the terminal; they're only shown in a window. Recovery copies live under ~/.sealbox/recovery/, so they never enter the repo. There's one code per user, and new projects are tied to it without asking you for the code again.
When a bad day comes
| Situation | What to do |
|---|---|
| Windows was reset, the project folder is still there | Enter the code or 2 shares with sealbox recovery restore |
| You're on a team and an owner rotated the key | Nothing. The new key is picked up automatically via SSH |
| New computer, and the vault folder is gone too | sealbox recovery restore --kit D:\project.sapkit |
| No code, no kit, no team | sealbox vault reset: a new empty vault is created and the old one is set aside. Get the secrets again from their services |
Unlock order: Windows store → (with a team) SSH key → an error message with a recovery suggestion. If you're not sure what to do, sealbox status tells you.
8. Working in VS Code
The extension doesn't do the work itself. It wires buttons to the sealbox command, so the command has to be installed first.
Install
pip install sealbox(or install it into your project's.venv).- In VS Code open Extensions (Ctrl+Shift+X) → search SealBox → Install. Or use the Marketplace page. In Cursor, Windsurf or VSCodium it comes from Open VSX.
- If you have a
.vsixfile:code --install-extension sealbox-0.3.0.vsix
The extension looks in the .venv of the project folder and its parents first, then on PATH. If it's somewhere else, put its path in the sealbox.executable setting.
Daily flow
- Type. When you write a password into a file and save, that spot gets a yellow squiggle.
- Click the lightbulb. Choose "Move this file's secrets into the vault". The value goes to the vault and the code becomes
os.environ[...]. - Hover. A "Show value" link appears on a
__SECURE_..__placeholder or onos.environ["X"]. The value shows after the approval window. If you choose "Copy", the clipboard is cleared after 30 seconds. - Run. Use "SealBox: Run program with the vault" from the Command Palette. If you run with the plain ▶ and get a
KeyError, the extension suggests it for you. - Check the status bar. It shows how many secrets are in the vault and how many people share it, and warns when there's no recovery code. Click it to open the menu.
Command Palette (Ctrl+Shift+P → "SealBox")
| Command | Equivalent |
|---|---|
| SealBox: Menu | Every action in one list |
| SealBox: Scan project (any exposed secrets?) | seal --check |
| SealBox: Move this file's secrets into the vault | seal <file> |
| SealBox: Move all project secrets into the vault | seal |
| SealBox: Run program with the vault | exec -- … |
| SealBox: Show a value from the vault | vault reveal |
| SealBox: Give redacted data to the program at runtime | vault expose |
| SealBox: Delete unused entries from the vault | vault remove --unused |
| SealBox: Add a teammate (GitHub user) | team add |
| SealBox: Create a recovery code | recovery setup |
| SealBox: Reopen the vault with a recovery code | recovery restore |
Security: The recovery code, the shares and your SSH passphrase never pass through the extension. They're all shown or asked for in separate windows that Python opens. The extension only reads the output of seal --check --json, which has lines, columns and categories, but no values.
9. Secret checks in CI
seal --check exits with code 1 when it finds exposed secrets. Use it as a gatekeeper on pull requests:
name: sealbox
on: [push, pull_request]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install sealbox
- run: sealbox seal --check
This step doesn't open the vault and needs no key. It only checks whether there are unredacted secrets on disk. Add --json for a machine-readable report.
10. FAQ
Is SealBox a proxy?
No. Agents read files straight from disk, and a proxy in between would never see that. SealBox removes secrets from your files for good.
Is it safe to put the vault in the repo?
Yes, it's designed for that. project.vault is encrypted with AES-256-GCM, and its key isn't in the repo. .sealbox/.gitignore keeps backups and lock files out.
What about secrets I've already committed?
They stay in git history; SealBox doesn't rewrite it. sealbox history tells you which vault values appear in old commits and whether they were pushed. Change those values at their source, and run sealbox hook install so it doesn't happen again.
Does it find every secret?
No. Regex can miss secrets that are split up, encoded (\u0040, hex, ROT13) or buried in prose. Review the report and add custom_rules if needed. For names, use the person_names list.
Can I use it in Turkish?
sealbox --lang tr … or SEALBOX_LANG=tr. The default is your computer's language. The extension follows VS Code's language too.
I installed it under the old name (secure-ai-proxy).
You don't need to do anything. Old .secure_proxy/ folders and secure_proxy.toml are still read, and the old credential-store entry moves to the new name on first open.