monosecret 0.3.4

Declarative secrets, every environment, any provider
Documentation

Stop committing secrets to git and putting them to .env files.

Secrets end up in .env files that get accidentally committed, shared over Slack, or copy pasted between machines. Each developer has their own version, nobody knows which secrets are actually needed, and onboarding means asking around for values.

Monosecret fixes this by separating secret declaration from secret storage. You commit a monosecret.toml that declares what secrets your application needs, while the actual values live in a secure provider like your system keyring, 1Password, or any other backend. No secrets in git, no .env files to leak.

Documentation | Quick Start | Announcement Blog Post

Features

Quick Start

# 1. Initialize monosecret.toml (discovers secrets from .env)
$ monosecret init
✓ Created monosecret.toml with 0 secrets

Next steps:
  1. monosecret config global init    # Set up user defaults (0.17+)
  2. monosecret check          # Verify all secrets are set
  3. monosecret run -- your-command  # Run with secrets

# 2. Set up provider backend
$ monosecret config global init  # 0.17+
? Select your preferred provider backend:
> keyring: Uses system keychain (Recommended)
  kdbx: KeePass KDBX databases (0.17+)
  onepassword: 1Password password manager
  keeper: Keeper Secrets Manager (0.18+) via official Rust SDK
  dotenv: Traditional .env files
  file: Plaintext files, one per secret (0.19+)
  env: Read-only environment variables
  null: Use defaults, generation, or run prompts without storage (0.19+)
  systemd-credential: Read-only systemd service credentials (0.17+)
  pass: Unix password manager with GPG encryption
  gopass: Gopass CLI password manager with GPG encryption (0.15+)
  protonpass: Proton Pass via official pass-cli
  passbolt: Passbolt self-hosted password manager (0.19+) via go-passbolt-cli
  lastpass: LastPass password manager
  dashlane: Dashlane password manager, read-only (0.18+)
  gcsm: Google Cloud Secret Manager
  awssm: AWS Secrets Manager
  awsps: AWS Systems Manager Parameter Store (0.18+)
  scaleway: Scaleway Secret Manager (0.17+)
  vault: HashiCorp Vault secret management
  openbao: OpenBao secret management (0.17+)
  bw: Bitwarden Password Manager (0.18+)
  bws: Bitwarden Secrets Manager
  akv: Azure Key Vault
  infisical: Infisical secret management (0.16+)
  age: age-encrypted file (0.17+)
  sops: SOPS encrypted files (0.17+)
? Select your default profile:
> development
  default
  none
✓ Configuration saved to /home/user/.config/monosecret/config.toml

# 3. Check and configure secrets
$ monosecret check

# 4. Run your application with secrets
$ monosecret run -- npm start

# Or with a specific profile and provider
$ monosecret run --profile production --provider dotenv -- npm start

See the Quick Start Guide for detailed instructions.

Installation

$ npm install --global @monosecret/cli

See the installation guide for more options including Nix and Devenv.

Configuration

Each project has a monosecret.toml file that declares the required secrets:

[project]
name = "my-app"  # Inferred from current directory name when using `monosecret init`
revision = "1.0"
# Optional: extend other configuration files
extends = ["../shared/common", "../shared/auth"]

# Monosecret 0.21+: use one provider chain unless a profile or secret overrides it.
[defaults]
providers = ["developer"]

[profiles.default]
DATABASE_URL = { description = "PostgreSQL connection string" }
REDIS_URL = { description = "Redis connection string" }

# Profile-specific configurations
[profiles.development]
DATABASE_URL = { required = false, default = "sqlite://./dev.db" }
REDIS_URL = { required = false, default = "redis://localhost:6379" }

[profiles.production]
DATABASE_URL = { required = true }
REDIS_URL = { required = true }

# Monosecret 0.19+: a profile can use an independent secret set.
[profiles.deployment.defaults]
inherit = false

[profiles.deployment]
DEPLOY_TOKEN = { description = "Deployment credential", required = true }

Monosecret 0.19+ can map one logical secret to different native coordinates per provider alias, including independent import source and destination refs:

[providers]
remote = { uri = "onepassword://Production", ref = { item = "{project}-{profile}", field = "{key}" } }
local = "keyring://"

[profiles.production]
API_KEY = { description = "API key", providers = [
  "local",
], refs = { remote = { item = "legacy-api", field = "token" } } }

See the configuration reference for all available options.

Profiles

Profiles allow you to define different secret requirements for each environment (development, production, etc.):

$ monosecret run --profile development -- npm start
$ monosecret run --profile production -- npm start

# Set a user-global default profile (0.17+)
$ monosecret config global init

# Monosecret 0.17+: set provider and profile defaults without prompting
$ monosecret config global init --provider env --profile default

Learn more about profiles and profile selection.

Providers

Monosecret supports multiple storage backends for secrets:

$ monosecret run --provider keyring -- npm start
$ monosecret run --provider dotenv -- npm start

# Configure a user-global default provider (0.17+)
$ monosecret config global init

See provider concepts and provider reference for details.

Rust SDK

Generate strongly-typed Rust structs from your monosecret.toml:

monosecret_derive::declare_secrets!("monosecret.toml");

fn main() -> Result<(), Box<dyn std::error::Error>> {
	// Load secrets with type safety
	let secrets = Monosecret::load(Provider::Keyring)?;

	// Access secrets as struct fields
	println!("Database: {}", secrets.database_url);

	// Optional secrets are Option<String>
	if let Some(redis) = &secrets.redis_url {
		println!("Redis: {}", redis);
	}

	Ok(())
}

See the Rust SDK documentation for advanced usage including profile-specific types.

Language SDKs

Beyond Rust, Monosecret ships SDKs for other languages. Each is a thin client over the same native core, so every provider, chain, profile, and generator works identically with no per-language resolution logic:

The shared embedded ABI is named monosecret_ffi in Monosecret 0.20+; it was named monosecret-ffi through 0.19. Its exported monosecret_* symbols and the MONOSECRET_FFI_LIB override are unchanged.

  • Python (via a pyo3 extension)
  • Go (via purego, no cgo, over the monosecret_ffi C ABI)
  • Ruby (via a native C extension)
  • Node.js / TypeScript (napi-rs addon)
  • Haskell (build-time FFI link)
  • PHP (ext-php-rs extension, with an ext-ffi fallback)
  • C# (0.16+) (P/Invoke with native assets in the NuGet package)
  • Swift (0.18+) (SwiftPM XCFramework for macOS Intel and Apple silicon)
from monosecret import Monosecret

resolved = Monosecret.builder().with_provider("keyring://").with_reason("boot").load()
print(resolved.secrets["DATABASE_URL"].get)

For typed access, monosecret schema emits a JSON Schema you feed to quicktype to generate typed classes for any language, built from the SDK's fields() map.

CLI Reference

Common commands:

# Initialize and configure
monosecret init                    # Create monosecret.toml
monosecret config global init    # Set up user defaults (0.17+)

# Manage secrets
monosecret check                  # Verify all secrets are set
monosecret add KEY --description "Purpose" # Declare a secret (0.18+)
monosecret set KEY               # Set a secret interactively
monosecret get KEY               # Retrieve a secret
monosecret delete KEY            # Delete a stored provider value (0.18+)
monosecret import PROVIDER       # Import secrets from another provider
monosecret import PROVIDER --delete-source # Move verified values (0.18+)
monosecret cache clear [KEY]     # Clear cached provider values (0.17+)

# Run with secrets
monosecret run -- command        # Run command with secrets as env vars

# Inspect access
monosecret audit                 # Show the local audit log of secret access

See the full CLI reference for all commands and options.

Contributing

We welcome contributions! Areas where you can help:

  • New provider backends - See the provider implementation guide
  • Language SDKs - Help us support more languages beyond Rust
  • Package managers - Get Monosecret into your favorite package manager
  • Documentation - Improve guides and examples

See our GitHub repository to get started.

License

This project is licensed under the Apache License 2.0.