Keep Your Secrets Secret
A Git filter tool that keeps sensitive code local while committing safe alternatives to your repository.
Features β’ Installation β’ Quick Start β’ Usage β’ How It Works β’ Contributing
Ever accidentally committed an API key? Hardcoded a password for testing? Left debug code in production?
Whiteout solves this by letting you maintain local-only code that never reaches your Git repository, while preserving safe alternatives in commits.
// What you see locally:
const apiKey = "process.env.API_KEY"; // @whiteout: "sk-proj-SUPER-SECRET-KEY-123"
// What gets committed:
const apiKey = "process.env.API_KEY";
- π Secure by Design - Secrets never touch Git history
- π¨ Flexible Decorations - Multiple ways to mark sensitive code
- β‘ Fast - Written in Rust for optimal performance
- π Seamless Integration - Works transparently with Git workflows
- π Language Agnostic - Works with any text file or programming language
- π¬ Multi-Comment Support - Works with
//
,#
,--
comment styles - π‘οΈ Safe Defaults - Requires explicit marking to prevent accidents
- Git (version 2.0 or higher)
brew tap bytware/tap
brew install whiteout
cargo install whiteout-cli
# Clone the repository
git clone https://github.com/bytware/whiteout.git
cd whiteout
# Build and install
cargo build --release
sudo cp target/release/whiteout /usr/local/bin/
# Verify installation
whiteout --version
cd your-project
whiteout init
This automatically:
- Creates
.whiteout/
directory for local storage - Configures Git filters in your repository
- Adds necessary
.gitattributes
entries
Choose from multiple decoration styles that work with any comment format:
Works with any comment style (//
, #
, --
):
// JavaScript
const apiKey = "sk-12345"; // @whiteout: "process.env.API_KEY"
# Python
api_key = "sk-12345" # @whiteout: "os.environ['API_KEY']"
-- SQL
SELECT * FROM users WHERE key = 'sk-12345'; -- @whiteout: 'REDACTED'
Hide entire code blocks between markers:
// @whiteout-start
const DEBUG = true;
const SECRET_ENDPOINT = "http://localhost:3000";
console.log("Debug mode active");
// @whiteout-end
const DEBUG = false; // This line stays in commits
For markdown or documentation, hide content after a marker:
# Public Documentation
This content is committed.
\@whiteout
This content stays local only.
It won't appear in commits.
Back to public content.
For configuration values within strings:
const url = "https://[[localhost:3000||api.example.com]]/v1";
// Locally: uses localhost:3000
// Committed: uses api.example.com
# Edit your files with secrets
vim config.js
# Commit as usual - secrets are automatically removed
git add .
git commit -m "Add configuration"
# Your local files keep the secrets
cat config.js # Still shows your secret values
Syntax: <code> // @whiteout: <replacement>
Note: When documenting examples, escape the @ with backslash: \@whiteout
# Local version:
password = "getpass.getpass()" # @whiteout: "admin123"
# Committed version:
password = "getpass.getpass()"
Syntax: @whiteout-start
... @whiteout-end
# @whiteout-start
debug_mode: true
verbose_logging: true
test_endpoints:
- localhost:8080
# @whiteout-end
production_mode: true # This stays in commits
Syntax: @whiteout
(hides everything until blank line)
Normal content here.
\@whiteout
Secret information.
More secrets.
Public content resumes.
Syntax: [[local||committed]]
[database]
host = "[[localhost||db.production.com]]"
port = [[5432||3306]]
When writing documentation about Whiteout (like this README), use backslash to escape decorators:
# To show the literal text in docs:
\@whiteout # Shows as @whiteout
\@whiteout-start # Shows as @whiteout-start
\@whiteout-end # Shows as @whiteout-end
# These are treated as actual decorators:
@whiteout # Would hide content (without backslash)
whiteout init [--path <dir>]
# Apply clean filter (remove secrets)
whiteout clean < file.txt
# Apply smudge filter (restore secrets)
whiteout smudge < file.txt
Whiteout uses Git's clean/smudge filter mechanism:
- Clean Filter (Working β Repository): Removes decorated local values before commit
- Smudge Filter (Repository β Working): Restores local values after checkout
graph LR
A[Working Directory<br/>with secrets] -->|git add<br/>clean filter| B[Staging Area<br/>secrets removed]
B -->|git commit| C[Repository<br/>safe version]
C -->|git checkout<br/>smudge filter| A
Local values are stored in .whiteout/local.toml
(gitignored) and restored automatically.
Both Whiteout and .env files solve secret management, but with different approaches:
Aspect | Whiteout | .env Files |
---|---|---|
Where secrets live | Inline with code | Separate file |
What you can hide | Values, code blocks, files | Environment variables |
Git safety | Automatic via filters | Manual via .gitignore |
Use case | Development & debugging | Configuration management |
- Inline secrets - See actual values where they're used
- Debug code - Hide entire blocks that shouldn't reach production
- Mixed visibility - Public and private code in the same file
- Production config - Standard for deployment platforms
- Team workflows - Everyone knows how they work
- Docker/CI - Built-in support everywhere
Use each tool for what it does best:
// Production config from .env
const dbHost = process.env.DB_HOST;
// Development secrets inline with Whiteout
const apiKey = "process.env.API_KEY"; // @whiteout: "sk-dev-12345"
// Debug code that stays local
// @whiteout-start
console.log("Debug mode: connecting to local services");
const DEBUG = true;
// @whiteout-end
- Never commit
.whiteout/
directory (ensure it's in.gitignore
) - Local values are stored in
.whiteout/local.toml
- Backup your local values separately
- Use environment variables for production secrets
- Review commits before pushing to ensure secrets are removed
- Test filters work correctly before committing sensitive data
# Run all tests
cargo test
# Run specific test
cargo test test_inline_parser
# Run with output
cargo test -- --nocapture
# Run integration tests
./tests/git_integration_test.sh
- Smudge operation after marker removal: When
@whiteout
markers are removed during the clean operation, the smudge filter cannot currently restore the hidden content when checking out files. This is a planned feature for a future release.
Contributions are welcome!
# Build
cargo build
# Test
cargo test
# Format code
cargo fmt
# Lint
cargo clippy
MIT License - see LICENSE for details.