Skip to content

usemantle/dugout

dugout

CI Crates.io License

Git-native secrets manager for development teams, written in Rust.

Highlights

  • Git-native — secrets live in your repo as encrypted values, access control is git commits
  • No server required — no SaaS, no cloud dependency, no infrastructure to manage
  • Team-friendlyknock / admit workflow for access requests, all through git
  • Multi-vault — separate secrets for dev, staging, prod in the same repo
  • Encrypted at rest — age encryption by default, optional AWS KMS, GCP KMS
  • Hardware-backed security — automatic macOS Keychain integration with Secure Enclave & TouchID
  • Zero configdugout init and start adding secrets
  • Auto-detectdugout . detects your stack and runs with secrets injected
  • Fast — encrypts in ~100µs, single binary, no runtime dependencies
  • Vendor-agnostic — works with any git host, any infrastructure, any language

Comparison

dugout sops dotenvx Vault Doppler Infisical
Secrets in repo
No server
No config file
Team access via git
Auto-detect & run
Single binary
Encrypt speed ~100µs ~1ms N/A N/A N/A N/A
Free & open source ✅*
Written in Rust Go JS Go TS

*Vault BSL license

Installation

Install dugout with our standalone installers:

# On macOS and Linux.
curl -LsSf https://raw.githubusercontent.com/usemantle/dugout/main/scripts/install.sh | sh
# On Windows.
powershell -ExecutionPolicy ByPass -c "irm https://raw.githubusercontent.com/usemantle/dugout/main/scripts/install.ps1 | iex"

Or, with Homebrew:

brew install usemantle/tap/dugout

Or, from crates.io:

cargo install dugout

Or, from source:

git clone https://github.com/usemantle/dugout && cd dugout
cargo install --path .

Quick Start

# One-time identity setup
dugout setup

# Initialize in your project
cd my-app
dugout init

# Add secrets
dugout set DATABASE_URL postgres://localhost/db
dugout set STRIPE_KEY sk_live_xxx

# Run your app with secrets (auto-detect)
dugout .

# Or run any command with secrets injected
dugout run -- npm start
dugout run -- python manage.py runserver
dugout run -- cargo run

Team Workflow

# Alice creates the project
dugout init
dugout set API_KEY sk_live_xxx
git add .dugout.toml && git commit -m "init vault" && git push

# Bob clones and requests access
git clone ... && cd project
dugout knock
git add .dugout/requests/ && git commit -m "request access" && git push

# Alice approves
git pull
dugout admit bob
git commit -am "grant bob access" && git push

# Bob pulls and runs
git pull
dugout .

No Slack DMs. No shared password vaults. No .env files in git history. Access requests and approvals are git commits.

Commands

Command Description
dugout setup Generate global identity
dugout init Initialize vault in current directory
dugout set KEY VALUE Set a secret
dugout get KEY Get a secret value
dugout add KEY Add a secret interactively
dugout list List all secret keys
dugout rm KEY Remove a secret
dugout . Auto-detect project and run with secrets
dugout run -- CMD Run a command with secrets injected
dugout knock Request vault access
dugout admit NAME Approve an access request
dugout pending List pending requests
dugout team add/rm/list Manage team members
dugout secrets diff Compare vault and .env
dugout secrets rotate Rotate encryption keys
dugout secrets lock/unlock Lock or decrypt secrets
dugout secrets import/export Import or export .env files
dugout vault list List all vaults in repository
dugout check status Vault overview
dugout check audit Audit for leaked secrets
dugout migrate-keychain Migrate keys to macOS Keychain (macOS only)
dugout reset-keychain Remove identities from macOS Keychain (macOS only)

macOS Keychain Integration

Keychain integration is default on macOS:

If Keychain is unavailable or you're in a headless environment (CI, SSH, Docker), you must explicitly enable filesystem storage:

# Use filesystem storage instead of Keychain
DUGOUT_NO_KEYCHAIN=1 dugout setup
DUGOUT_NO_KEYCHAIN=1 dugout init

Migrating Existing Keys

If you have existing file-based keys, migrate them to Keychain:

# Migrate all identities (global + project keys)
dugout migrate-keychain

# Migrate and delete files after successful migration
dugout migrate-keychain --delete

# Skip confirmation prompts
dugout migrate-keychain --delete --force

Verifying Keychain Storage

Check if your identity is stored in Keychain:

# Open Keychain Access app
open /System/Applications/Utilities/Keychain\ Access.app

# Search for "dugout" in the search box
# Look for items with:
#   - Service: "com.usemantle.dugout"
#   - Account: "global" or your project ID

Or use the command line:

# Check for global identity in Keychain
security find-generic-password -s "com.usemantle.dugout" -a "global"

# Check for project-specific identity
security find-generic-password -s "com.usemantle.dugout" -a "<project-id>"

If the key exists in Keychain, you'll see output like:

keychain: "/Users/you/Library/Keychains/login.keychain-db"
class: "genp"
attributes:
    "acct"<blob>="global"
    "svce"<blob>="com.usemantle.dugout"
    ...

Multi-Vault

Manage separate secret sets for different environments (dev, staging, prod) in the same repository.

# Create vaults for different environments
dugout init                         # Creates .dugout.toml (default)
dugout init --vault dev             # Creates .dugout.dev.toml
dugout init --vault prod            # Creates .dugout.prod.toml

# Set secrets in specific vaults
dugout --vault dev set API_KEY sk_test_xxx
dugout --vault prod set API_KEY sk_live_xxx

# List all vaults
dugout vault list

# Run with specific vault
dugout --vault dev .
dugout --vault prod run -- ./deploy.sh

# Or use environment variable
export DUGOUT_VAULT=dev
dugout .

When only one vault exists, no flag is needed. With multiple vaults, use --vault or DUGOUT_VAULT to select one.

Cipher Backends

Backend Flag Use Case
age (default) Local development, small teams
AWS KMS --features aws AWS infrastructure, compliance requirements
GCP KMS --features gcp Google Cloud infrastructure
# Initialize with hybrid encryption (age + KMS)
dugout init --kms arn:aws:kms:us-east-1:...

# Install with AWS KMS support
cargo install dugout --features aws

See the full KMS Integration Guide for AWS, GCP, IAM setup, and multi-region.

CI/CD

GitHub Actions

- uses: usemantle/setup-dugout@v1
  with:
    identity: ${{ secrets.DUGOUT_IDENTITY }}
  env:
    DUGOUT_NO_KEYCHAIN: "1"  # Required on macOS runners

- run: dugout run -- npm test
  env:
    DUGOUT_NO_KEYCHAIN: "1"  # Required on macOS runners

See usemantle/setup-dugout for version pinning, KMS-only mode, and more examples.

Other environments

# Any CI — set both DUGOUT_IDENTITY and DUGOUT_NO_KEYCHAIN
export DUGOUT_IDENTITY="AGE-SECRET-KEY-1..."
export DUGOUT_NO_KEYCHAIN=1  # Disable Keychain in CI
dugout run -- ./deploy.sh

# Docker (macOS host)
docker run \
  -e DUGOUT_IDENTITY="$KEY" \
  -e DUGOUT_NO_KEYCHAIN=1 \
  myapp

See the full Deployment Guide for GitLab, Kubernetes, and more.

Benchmarks

Measured with Criterion. See BENCHMARKS.md for methodology.

Operation 32B 4KB 16KB
Encrypt 105µs 113µs 138µs
Decrypt 135µs 154µs 195µs
Roundtrip 258µs 271µs 355µs

Contributing

See CONTRIBUTING.md for setup and guidelines.

License

Licensed under either of:

at your option.

About

A Git-native secrets manager for development teams, written in Rust

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors