🔒 dotprot
Pick up where you left off without worrying about your .env files.
Lock your .env (and anything else you list) into a dedicated 1Password vault,
then restore it on demand. dotprot uploads the exact bytes, verifies the copy
round-trips correctly, and only then removes the file from disk.
Why?
As a software engineer, I like using .env files but my paranoia doesn't allow for me to leave a bunch of .env files on my disk without worrying about it. I'm a big fan of the 1Password password manager and I use its CLI tool extensively. So I thought, why not use a 1Password vault to store my .env files as file attachments? Then it just felt like a no-brainer to create a little easy-to-use wrapper for 1Password CLI to lock .env files away inside of a 1Password vault and then retrieve them when I'm ready to work again.
Quickstart
- Install dotprot
- Change directory to any directory with a
.envfile.- If you don't use
.envthen typedotprot setupand add your file(s) to.prot
- If you don't use
- Sign in to 1Password via
op signin - Type
dotprot
Created .prot (protecting: .env*).
Created 1Password vault ".prot" (6djqbcxlh235372hbuvtuqnr4i).
(one-time setup — future runs reuse it)
locked .env -> 1Password
Locked 1 file(s) into vault ".prot".
- Type
ls -a - Notice
.envis no longer there. - Check your brand new
.protvault in 1Password - 🎉 There it is!
- Type
dotprotagain to bring your .env file back. (A copy stays behind in 1Password)
Contents
How it works
dotprot reads a .prot file in your working directory that lists which files to
protect — globs, one per line, defaulting to .env*. Each protected file is
stored as a 1Password document in a vault named .prot. The document IDs are
written back into your .prot file so the same directory can lock and unlock
repeatedly.
┌─────────────┐ dotprot lock ┌──────────────────────┐
│ ./.env │ ────────────────► │ 1Password ".prot" │
│ (on disk) │ ◄──────────────── │ vault (documents) │
└─────────────┘ dotprot unlock └──────────────────────┘
Requirements
- The 1Password CLI (
op), signed in (op signin).
dotprot never touches your 1Password credentials — it shells out to op, which
handles all authentication. If you're not signed in when you run a command,
dotprot offers to sign you in: at an interactive terminal it asks
Sign in now? [y/N] and, on yes, runs op signin for you (Touch ID, the
desktop-app approval, or an account prompt — whatever your setup uses) before
continuing. In a non-interactive context (CI, a pipe), it doesn't prompt — it
prints Run \op signin` first.` and exits without doing anything.
Install
Homebrew
Cargo
Prebuilt binaries
Download the binary for your platform from the
releases page and put it on
your PATH.
From source
Usage
You don't have to run dotprot setup first. The very first dotprot (or
dotprot lock) in a directory creates the .prot vault automatically if it
doesn't exist, tells you it did, and carries on:
$ dotprot
Created 1Password vault ".prot" (abc123...).
(one-time setup — future runs reuse it)
Created .prot (protecting: .env*).
locked .env -> 1Password
Locked 1 file(s) into vault ".prot".
The toggle
Running bare dotprot figures out which way to go from what's on disk:
| State | What dotprot does |
|---|---|
| Protected files are present | Locks them into 1Password |
| Protected files are missing | Restores them from 1Password |
| Mixed (some present, some missing) | Stops and asks you to be explicit (dotprot lock / dotprot unlock) |
Trying it safely with --keep
Before trusting dotprot to delete anything, upload-and-verify without removing the originals:
# open the .prot vault in the 1Password app and confirm .env is there
The .prot file
Auto-created on first lock. dotprot owns everything above the sentinel and rewrites it freely; the file list below the sentinel is yours to edit:
# dotprot — managed below, do not edit
vault: abcd1234efgh5678
doc .env: 6yx...
doc config/secrets.json: q9z...
# ---- your files (edit below) ----
.env*
config/secrets.json
Tip: commit
.protto version control. It contains only 1Password vault/item IDs — no secrets — and lets teammatesdotprot unlockthe same files, given access to the vault.
.prot backups and dotprot restore
.prot is the map from your (deleted) files back to their 1Password documents,
so losing it is the one local mistake that hurts. Every time dotprot writes a
.prot, it also mirrors it to a per-project backup in your home directory:
~/.prot/backups/<absolute project path>/.prot
# e.g. /Users/you/code/myapp → ~/.prot/backups/Users/you/code/myapp/.prot
# on Windows: C:\Users\you\code\myapp → C:\Users\you\.prot\backups\C\Users\you\code\myapp\.prot
Deleted your .prot by accident? From the project directory:
restore is purely local (no 1Password sign-in needed) and cautious: if a
.prot already exists it never overwrites it — it tells you when the two
already match, and refuses when they differ. Like .prot itself, backups
contain no secrets, only vault/document IDs and your file patterns. A
backup that can't be written (say, an unwritable home directory) prints a
warning but never blocks a lock.
Safety guarantees
dotprot's whole reason to exist is to make secrets easier to manage, never to put them at risk. The design centers on one rule: a local file is deleted only after a verified, recoverable copy exists in 1Password.
- Verify-then-delete. A file is removed from disk only after its 1Password
copy is uploaded, read back, and confirmed byte-identical. The file is
also re-read immediately before deletion — if it changed while the upload was
in flight, it's left in place (the vault copy would be stale). Any failure in
that chain leaves the original untouched. Use
--keepto skip deletion entirely. - Scoped to the
.protvault only. Every 1Password operation is scoped with--vault .prot. dotprot never deletes 1Password items in normal operation — lock creates/updates documents, unlock only reads them. The vault ID recorded in.protis verified to still be the vault named.protbefore every run, so a stale or tampered ID can't point writes at another vault in your account. - Incremental persistence.
.protis updated after each file locks, so an interruption mid-batch leaves you in a consistent, recoverable state. Each update is written atomically (temp file + rename), so even a crash mid-write can't corrupt the recorded document IDs. - Backups are kept. Documents stay in 1Password after unlock, so a directory
stays re-lockable and you always have a copy. Re-locking overwrites the
existing document in place.
.protitself is mirrored to~/.prot/backups/…on every write, anddotprot restorebrings it back if it's ever lost. - Stable titles. Document titles are the file's absolute path, so they're easy to find in the 1Password UI and never collide across directories or machines.
- Restores stay inside the project.
unlockaccepts only plain relative.protentry paths (no absolute or rooted paths, no..), validates every recorded path before restoring anything, and never writes through a symlink (even a dangling one) — a tampered or malicious.protcan't redirect a restored secret elsewhere on disk. - No silent skips. A pattern match that can't be safely locked — a file
outside the working directory, or a filename that
.prot's format can't record faithfully — is skipped with a loud warning, never silently, so a secret is never left in plaintext while you believe it's protected. - Minimal on-disk exposure. Secrets are handed to
opvia a short-lived0600temp file that's deleted immediately afterward (the 1Password CLI does not reliably accept piped stdin). Restored files and the.protstate file are also written0600(newly created ones; an existing.prot's mode is left as you set it).
Platform note (Windows): the owner-only (
0600) file-permission hardening is currently enforced on macOS and Linux only. On Windows the temp and restored files are created with default ACLs. The verify-then-delete guarantee and vault scoping hold on all platforms; only the file-permission tightening is Unix-only for now. See CHANGELOG.md.
Development
See CHANGELOG.md for release history.