dotprot 0.3.0

Lock up .env files (and anything in .prot) inside a 1Password vault.
dotprot-0.3.0 is not a library.

🔒 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.

License: MIT Built with Rust Buy me a coffee

Support this project (Appreciated but not necessary)


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? 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.

Contents

Quickstart

  • Install dotprot
  • Change directory to any directory with a .env file.
    • If you don't use .env then type dotprot setup and add your file(s) to .prot
  • 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 .env is no longer there.
  • Check your brand new .prot vault in 1Password
  • 🎉 There it is!
  • Type dotprot again to bring your .env file back. (It stays in 1Password)

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

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

brew install jstilwell/tap/dotprot

Cargo

cargo install dotprot

Prebuilt binaries

Download the binary for your platform from the releases page and put it on your PATH.

From source

git clone https://github.com/jstilwell/dotprot
cd dotprot
cargo build --release      # binary at target/release/dotprot

Usage

dotprot           # smart toggle: lock if files present, unlock if absent
dotprot lock      # force lock:   upload → verify → delete from disk
dotprot unlock    # force unlock: restore files from 1Password
dotprot --keep    # lock, but keep the originals on disk (don't delete)
dotprot setup     # optional: pre-create the .prot vault in 1Password

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:

dotprot --keep    # .env is copied to 1Password and verified, but stays on disk
# open the .prot vault in the 1Password app and confirm .env is there
dotprot lock      # now remove the local copy

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 .prot to version control. It contains only 1Password vault/item IDs — no secrets — and lets teammates dotprot unlock the same files, given access to the vault.

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. Any failure in that chain leaves the original untouched. Use --keep to skip deletion entirely.
  • Scoped to the .prot vault 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.
  • Incremental persistence. .prot is updated after each file locks, so an interruption mid-batch leaves you in a consistent, recoverable state.
  • 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.
  • 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.
  • Minimal on-disk exposure. Secrets are handed to op via a short-lived 0600 temp file that's deleted immediately afterward (the 1Password CLI does not reliably accept piped stdin). Restored files and the .prot state file are also written 0600 (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

cargo build            # debug build
cargo test             # run unit tests
cargo clippy           # lint
cargo build --release  # optimized binary

See CHANGELOG.md for release history.

License

MIT