Stop committing secrets by accident.
Inject secrets into any command — no cloud, no setup.
keynest exec -- docker compose upYour app receives secrets via environment variables.
| Instead of | You get |
|---|---|
.env files |
Encrypted local secrets |
| Vault | Zero setup |
| 1Password CLI | No account |
| Hardcoded secrets | Runtime injection |
keynest init
keynest set api_key test123
keynest exec -- printenv API_KEYOutput: test123
Use Keynest as a secure local secret store for AI agents.
keynest exec -- python agent.pyAccess secrets via environment variables (e.g. API_KEY):
import os
api_key = os.environ["API_KEY"]Keeps secrets out of:
- source code
- logs
- prompts
- LLM context
Works well with:
- LangChain
- AutoGPT
- custom agents
brew tap capydev42/keynest
brew install keynestDownload the latest release from GitHub: keynest/releases/latest
cargo install keynestcargo install --git https://github.com/capydev42/keynest.gitOr build locally:
cargo build --release
./target/release/keynest# Initialize a new keystore
keynest init
# Store a secret (three ways)
keynest set github_token "ghp_xxxx" # as argument
keynest set github_token --file secret.txt # from file
keynest set github_token --prompt # interactive prompt
# Retrieve a secret
keynest get github_token
keynest get github_token --clip # copy to clipboard (auto-clears after 15s)
keynest get github_token --clip --timeout 30 # copy with custom timeout
# List all keys
keynest list
# Update a secret
keynest update github_token "ghp_yyyy"
# Remove a secret
keynest remove github_token
# Run command with secrets as environment variables
keynest exec -- docker compose up
keynest exec --only API_KEY -- \
curl -H "Authorization: Bearer $API_KEY" https://api.example.com
keynest exec --prefix MY_ -- env
keynest exec --print
# Show keystore info (KDF params, creation date)
keynest info
# Change password (and optionally KDF parameters)
keynest rekey
keynest rekey --argon-mem 131072 # upgrade memory cost
# Import/Export secrets
keynest import .env
keynest import secrets.json
keynest import --overwrite .env
keynest export --format env
keynest export secrets.json| Command | Description |
|---|---|
init |
Initialize a new keystore |
set <key> [<value>] |
Store a secret (value, --file, or --prompt) |
get <key> |
Retrieve a secret (exits 1 if not found) |
get <key> --clip |
Copy secret to clipboard (auto-clears after 15s) |
update <key> <value> |
Update existing secret |
list [--all] |
List keys (--all shows values & timestamps) |
remove <key> |
Remove a secret |
exec -- <cmd> |
Run command with secrets as environment variables |
info |
Show keystore information (KDF params, creation date) |
rekey |
Change password and/or KDF parameters |
import <file> |
Import secrets from file (env or json) |
export [file] |
Export secrets to file or stdout |
All commands support --json for structured output (get, list, info).
- Key Derivation: Argon2id with configurable parameters
- Secure Memory: Keys and passwords are zeroized after use
- Encryption: XChaCha20-Poly1305 AEAD
- Uses well-established cryptographic primitives (Argon2id, XChaCha20-Poly1305)
- No network access
- No telemetry
- Zero-config — works out of the box
--store <path>- Specify custom keystore location
--argon-mem <kb>- Memory cost in KiB (default: 65536)--argon-time <n>- Time cost / iterations (default: 3)--argon-parallelism <n>- Parallelism (default: 1)
Keynest accepts passwords via:
- Environment variable:
KEYNEST_PASSWORD="secret" keynest get key - Stdin:
echo "secret" | keynest get key - Interactive prompt (default)
cargo add keynestuse keynest::{Keynest, Storage, KdfParams};
use zeroize::Zeroizing;
fn main() -> Result<()> {
let storage = Storage::new("/path/to/keystore.db");
let password = Zeroizing::new(String::from("my-password"));
// Create new keystore with custom KDF parameters
let kdf = KdfParams::default();
let mut kn = Keynest::init_with_storage_and_kdf(password, storage, kdf)?;
// Store secrets
kn.set("api_token", "secret123")?;
kn.save()?;
// Later: reopen
let kn = Keynest::open_with_storage(Zeroizing::new(String::from("my-password")), storage)?;
assert_eq!(kn.get("api_token"), Some("secret123"));
Ok(())
}Default keystore locations by OS:
- Linux:
~/.local/share/keynest/.keynest.db - macOS:
~/Library/Application Support/keynest/.keynest.db - Windows:
%APPDATA%\keynest\.keynest.db
Use --store <path> to override.
# Build
cargo build
# Test
cargo test
# Format
cargo fmt
# Lint
cargo clippy -- -D warningsIf you find Keynest useful, consider giving it a star ⭐
Licensed under either of:
- Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
