Secure .env file management for developers who hate complexity.
A fast, simple CLI built on Bitwarden Secrets Manager SDK. Sync your environment variables across teams without the enterprise overhead.
- π 5-minute setup (vs 30min - 4 hours for competitors)
- π Free tier that works (full features, forever)
- π Drift detection (see exactly what's out of sync)
- π― 6 commands (vs 15-20 for enterprise tools)
- π Zero-knowledge encryption (via Bitwarden)
- Push local
.envto Bitwarden - Pull secrets from Bitwarden to
.env - Status command shows drift (local vs remote)
- Validate .env format before pushing
- Uses official Rust SDK (not CLI wrapper)
- Leverages Bitwarden's battle-tested security
- Works with Bitwarden Cloud or self-hosted
- End-to-end encryption (zero-knowledge)
- Single 3.3MB binary (no dependencies)
- Works offline (after initial pull)
- Git-friendly (never commit secrets)
- Drift detection (know what changed)
- 72 unit tests + 20 E2E tests
- Share secrets via Bitwarden projects
- Onboard teammates with one command
- Organization support (via Bitwarden orgs)
- RBAC through Bitwarden (if self-hosted)
- Bitwarden Account - Sign up free
- Secrets Manager Access - Enable free tier
- Access Token - Generate from Bitwarden Settings β Security
No Bitwarden CLI needed! bwenv uses the official Rust SDK directly.
cargo install bwenvbrew install bwenvgit clone https://github.com/yourusername/bwenv.git
cd bwenv
cargo build --release
sudo cp target/release/bwenv /usr/local/bin/Download from GitHub Releases
# Go to: https://vault.bitwarden.com
# Settings β Security β Access Tokens β New Access Token
# Name: "bwenv-dev"
# Permissions: β Secrets Manager
# Copy the token (shown only once!)export BITWARDEN_ACCESS_TOKEN="0.48b4774c-xxxx-xxxx-xxxx.your_token_data_here"
# Add to shell profile for persistence
echo 'export BITWARDEN_ACCESS_TOKEN="your_token"' >> ~/.bashrc # or ~/.zshrc- Go to Bitwarden Secrets Manager
- Click "New Project"
- Name it (e.g., "MyApp")
- Save
# Upload your .env to Bitwarden
bwenv push --project MyApp
# Output:
# β Successfully pushed 12 secrets to project 'MyApp'# New teammate pulls secrets
bwenv pull --project MyApp
# Done! They have the .env file with all secretsPull secrets from Bitwarden to local .env file:
# Basic usage
bwenv pull --project MyApp
# Custom output file
bwenv pull --project MyApp --output .env.production
# Overwrite existing file (skip confirmation)
bwenv pull --project MyApp --forceOptions:
-p, --project <PROJECT>- Project name or ID (required)-o, --output <OUTPUT>- Output file path (default:.env)--force- Overwrite existing file without prompting
Push local .env file to Bitwarden:
# Basic usage
bwenv push --project MyApp
# Custom input file
bwenv push --project MyApp --input .env.staging
# Overwrite existing secrets in Bitwarden
bwenv push --project MyApp --overwriteOptions:
-p, --project <PROJECT>- Project name or ID (required)-i, --input <INPUT>- Input .env file (default:.env)--overwrite- Overwrite existing secrets (default: creates new)
See exactly what's different between local and remote:
# Check sync status
bwenv status --project MyApp
# Example output:
# π Checking sync status...
# π¦ Project: MyApp (a1b2c3d4-...)
#
# β οΈ Out of sync detected:
#
# π₯ Only in Bitwarden (2):
# - NEW_API_KEY
# - FEATURE_FLAG_X
# β Run 'bwenv pull' to download these
#
# π€ Only in local .env (1):
# - LOCAL_DEBUG_MODE
# β Run 'bwenv push' to upload these
#
# π Different values (1):
# - DATABASE_URL
# β Run 'bwenv pull --force' to overwrite local
# β Run 'bwenv push --overwrite' to overwrite remoteOptions:
-p, --project <PROJECT>- Project name or ID (required)-e, --env-file <FILE>- Custom .env file to compare (default:.env)
List all projects and secrets:
# List all projects
bwenv list
# Output:
# Projects:
# MyApp (a1b2c3d4-5678-...)
# StagingEnv (b2c3d4e5-6789-...)
#
# Use 'bwenv list --project <name>' to see secrets
# List secrets in a specific project
bwenv list --project MyApp
# Output:
# Project: MyApp (a1b2c3d4-...)
#
# Secrets:
# DATABASE_URL = <hidden>
# API_KEY = <hidden>
# REDIS_URL = <hidden>Options:
-p, --project <PROJECT>- Show secrets in specific project (optional)
Create .bwenv.toml configuration file:
bwenv init
# Output:
# β Created .bwenv.toml configuration file
#
# Next steps:
# 1. Edit .bwenv.toml and set your default project
# 2. Run 'bwenv push' to upload your .env to Bitwarden
# 3. Add .bwenv.toml to git (safe to commit)
# 4. Add .env to .gitignore (contains secrets)Generated .bwenv.toml:
# bwenv Configuration
default_project = "MyProject"
env_file = ".env"
auto_sync = false
show_secrets = falseValidate .env file syntax:
# Validate default .env
bwenv validate
# Output:
# β .env is valid
# Validate specific file
bwenv validate --input .env.production
# Invalid file output:
# β Validation failed: Line 5: Missing '=' separatorOptions:
-i, --input <INPUT>- File to validate (default:.env)
bwenv uses Bitwarden Secrets Manager access tokens:
- Go to Bitwarden Settings
- Click "New Access Token"
- Name:
bwenv(or any name) - Permissions: β Secrets Manager
- Copy token (shown once)
# Temporary (current shell session)
export BITWARDEN_ACCESS_TOKEN="your_token_here"
# Permanent (add to shell profile)
echo 'export BITWARDEN_ACCESS_TOKEN="your_token"' >> ~/.bashrc
# Or for zsh
echo 'export BITWARDEN_ACCESS_TOKEN="your_token"' >> ~/.zshrc- β Access tokens are scoped to Secrets Manager only
- β Tokens can be revoked anytime in Bitwarden settings
- β Zero-knowledge encryption (Bitwarden can't see secrets)
β οΈ Never commit tokens to git (add.env.testto.gitignore)
| Feature | Infisical | Doppler | Vault | bwenv |
|---|---|---|---|---|
| Setup Time | 30+ min | 15 min | 4 hours | 5 min β‘ |
| Complexity | High | Medium | Very High | Very Low |
| Free Tier | Limited | 5 users | β | Full features π |
| Drift Detection | β | β | β | β π |
| Self-Hosting | β | β | β | β (via BW) |
| Commands to Learn | 20+ | 15+ | 30+ | 6 π― |
| Local Development | Requires server | Cloud-only | Complex | Works offline |
| SDK Language | Node/Python | Node | Go | Rust π¦ |
Perfect for:
- π¨βπ» Individual developers
- π₯ Small teams (2-10 people)
- π Startups & indie hackers
- π Side projects & learning
Not ideal for:
- π’ Large enterprises (50+ devs) β Use Vault or Infisical
- βοΈ AWS-only shops β Use AWS Secrets Manager
- π Teams needing dynamic secrets β Use Vault
See COMPETITIVE_ANALYSIS.md for detailed comparison.
bwenv has comprehensive test coverage across multiple layers:
- β Unit Tests (72 tests) - Core functionality (parser, provider, errors)
- β Integration Tests (29 tests) - CLI command parsing
- β E2E Tests (20 scenarios) - Real Bitwarden integration
- β Property Tests (5 tests) - Edge case discovery with random inputs
- β Security Tests (13 tests) - Secrets leakage prevention
- β Benchmarks (11 tests) - Performance tracking
# Unit tests (fast, < 1 second)
cargo test --lib
# All tests
cargo test
# E2E tests (requires Bitwarden token)
./scripts/run-e2e-tests.shEnd-to-end tests verify bwenv works correctly with real Bitwarden Secrets Manager:
# Setup (one-time, 5 minutes)
cp .env.test.example .env.test
# Edit .env.test with your Bitwarden access token
# Run E2E tests
./scripts/run-e2e-tests.sh
# Output:
# === bwenv E2E Test Runner ===
# Mode: docker
# Project: E2E-Test
#
# running 20 tests
# test test_push_basic_secrets ... ok
# test test_pull_basic_secrets ... ok
# test test_roundtrip_push_pull_integrity ... ok
# ...
# β All E2E tests passed!E2E Test Coverage:
- Push command (5 scenarios)
- Pull command (4 scenarios)
- Roundtrip integrity (2 tests)
- List command (2 scenarios)
- Validate command (3 scenarios)
- Error handling (4 scenarios)
- TESTING.md - Comprehensive testing guide (500+ lines)
- E2E_QUICKSTART.md - E2E test setup (5-minute guide)
tests/e2e/README.md- Developer guide for writing E2E tests
Cause: Environment variable not exported
Fix:
# Check if token is set
echo $BITWARDEN_ACCESS_TOKEN
# Export token
export BITWARDEN_ACCESS_TOKEN="your_token_here"
# Or add to shell profile for persistence
echo 'export BITWARDEN_ACCESS_TOKEN="your_token"' >> ~/.bashrc
source ~/.bashrcCause: Project doesn't exist or name is incorrect
Fix:
# List all projects to see correct name
bwenv list
# Projects are case-sensitive
bwenv pull --project MyApp # β Correct
bwenv pull --project myapp # β Wrong caseCause: Invalid or expired access token
Fix:
- Generate new access token in Bitwarden
- Go to Settings β Security β Access Tokens
- Click "New Access Token"
- Ensure "Secrets Manager" permission is checked
- Export new token:
export BITWARDEN_ACCESS_TOKEN="new_token"
Cause: .env file might not exist or be in wrong location
Fix:
# Check .env file exists
ls -la .env
# Specify custom env file location
bwenv status --project MyApp --env-file /path/to/.env
# Pull to create .env if missing
bwenv pull --project MyAppCause: Malformed .env file or permission issues
Fix:
# Validate .env format
bwenv validate
# Check file permissions
ls -l .env
# Fix permissions if needed
chmod 600 .envFor more troubleshooting, see:
- TESTING.md - Troubleshooting section
- E2E_QUICKSTART.md - E2E test troubleshooting
- GitHub Issues
We welcome contributions! π
# Clone repository
git clone https://github.com/yourusername/bwenv.git
cd bwenv
# Build
cargo build
# Run tests
cargo test
# Run E2E tests (requires Bitwarden token)
./scripts/run-e2e-tests.sh --local- Write tests first (TDD approach)
- Run full test suite before submitting PR
cargo test # Unit + integration tests cargo clippy # Linting cargo fmt # Formatting ./scripts/run-e2e-tests.sh # E2E tests
- Add E2E tests for new commands (see E2E_QUICKSTART.md)
- Update documentation (README, TESTING.md, command help text)
- Follow Rust conventions (rustfmt, clippy clean)
- Fork the repository
- Create feature branch
git checkout -b feature/amazing-feature
- Write tests for your changes
cargo test - Run E2E tests (if adding commands)
./scripts/run-e2e-tests.sh
- Commit changes
git commit -m 'Add amazing feature' - Push to branch
git push origin feature/amazing-feature
- Open Pull Request
Good First Issues:
- π Improve documentation
- π Fix bugs
- β Add more tests
- π Add examples
Medium Issues:
- π Performance improvements
- π§ New command options
- π¦ Package managers (Homebrew, apt)
Advanced Issues:
- π― New commands
- π CI/CD integrations
- ποΈ Architectural improvements
See TESTING.md for comprehensive testing documentation.
- β Core CLI commands (pull, push, list, status, validate, init)
- β Real Bitwarden SDK integration
- β Drift detection
- β E2E testing infrastructure (20 tests)
- β Comprehensive documentation
- Git hooks integration (auto-sync on pull)
- CI/CD examples (GitHub Actions, GitLab CI)
- Config file support (.bwenv.toml reading)
- Better error messages (actionable suggestions)
- Homebrew formula (easy macOS install)
- Team templates (shared .env.example generation)
- Secret rotation helpers (detect stale secrets)
- Import/export (migrate from Doppler/Infisical)
- Desktop notifications (drift alerts)
- Policy enforcement (required keys validation)
- Change approvals (via Bitwarden workflows)
- Cost tracking (secret usage analytics)
- SSO integration (via Bitwarden Enterprise)
- π Zero-knowledge encryption - Bitwarden uses end-to-end encryption
- π Access tokens are scoped to Secrets Manager only
- π« No master password storage - bwenv never sees your master password
- β Secrets never leave Bitwarden except when explicitly pulled
- π Open source - Audit the code yourself
- π‘οΈ Battle-tested SDK - Uses official Bitwarden Rust SDK
- Never commit
.envfiles - Add to.gitignore - Rotate tokens regularly - Generate new access tokens monthly
- Use separate projects - Different projects for dev/staging/prod
- Limit token permissions - Only grant Secrets Manager access
- Review team access - Check who has access to projects in Bitwarden
This project is licensed under the MIT License - see the LICENSE file for details.
- Bitwarden - For the excellent Secrets Manager SDK
- Rust Community - For amazing libraries and tooling
- Contributors - Thank you for improving bwenv! π
- π Documentation: TESTING.md, E2E_QUICKSTART.md
- π Bug Reports: GitHub Issues
- π¬ Discussions: GitHub Discussions
- π§ Email: your.email@example.com
Built with β€οΈ by developers, for developers.