Skip to main content

Quick access to your non-critical secrets from the terminal

Project description

mb-stash

Quick access to your non-critical secrets from the terminal.

mb-stash is not a password manager. Use a proper password manager (1Password, Bitwarden, KeePass) for critical secrets like passwords, bank credentials, and private keys.

mb-stash is for everything else — API tokens, service URLs, license keys, snippets you need 10 times a day but don't want to dig through a password manager every time.

How it works

mb-stash stores secrets encrypted on disk. On first access it starts a background daemon and asks for your master password. While the daemon is running and unlocked, you have instant access to your secrets. When you lock mb-stash (or walk away from your computer), the decryption key is wiped from memory — secrets are safe until you enter your password again.

mb-stash get my-token    # daemon starts automatically, asks password if locked
                             # → copied to clipboard

One command. Token in your clipboard.

Security model

Encryption

All secrets are stored as a single encrypted blob on disk. The encryption pipeline:

  1. Master password → key (scrypt): Your password is passed through scrypt — a memory-hard key derivation function. scrypt takes the password + a random 16-byte salt and produces a 32-byte AES key. This is deliberately slow (~0.5s) so that brute-force attacks are impractical. The salt is stored alongside the ciphertext — it's not a secret, its purpose is to ensure identical passwords produce different keys.

  2. Plaintext → ciphertext (AES-256-GCM): The secrets (a JSON dict of key-value pairs) are encrypted with AES-256-GCM — an authenticated encryption algorithm. "Authenticated" means it provides both confidentiality (data is unreadable) and integrity (any tampering is detected). A random 12-byte nonce is generated on every write. Wrong password → wrong key → GCM tag verification fails → we know the password is wrong without needing a separate password hash.

All crypto is handled by cryptography (PyCA) — Python's standard cryptography library backed by OpenSSL.

Storage

Data directory: ~/.mb-stash/

~/.mb-stash/
├── stash.json      # encrypted store
├── config.toml     # settings (timeouts, etc.)
├── daemon.sock     # Unix domain socket (while daemon is running)
└── daemon.pid      # daemon PID file (while daemon is running)

The encrypted store (stash.json):

{
  "version": 1,
  "kdf": {
    "algorithm": "scrypt",
    "salt": "<base64>",
    "n": 1048576,
    "r": 8,
    "p": 1
  },
  "encryption": {
    "algorithm": "aes-256-gcm",
    "nonce": "<base64>",
    "ciphertext": "<base64>"
  }
}

Everything except ciphertext is public metadata (salt, nonce, KDF parameters). This is by design — these values are useless without the password. The ciphertext, when decrypted, contains a flat JSON dict:

{
  "my-token": "xxxxxxxxxxxx",
  "work/api-key": "xxxxxxxxxxxx"
}

Every write (add, delete, change-password) generates a new random nonce and rewrites the file atomically (write to .tmp, then os.replace — no corruption even on crash).

Daemon and locking

The background daemon holds the derived key and decrypted secrets in memory:

  • Unlock: CLI prompts for password → sends it to daemon via Unix socket → daemon derives key with scrypt → decrypts ciphertext → stores key + secrets in memory
  • Lock: daemon wipes key and secrets from memory (None). The only way to recover them is to enter the password again
  • Get/add/delete: CLI sends command to daemon → daemon performs the operation using in-memory data → returns result. The derived key never leaves the daemon process

CLI ↔ daemon communication uses a Unix domain socket (~/.mb-stash/daemon.sock) with 0600 permissions (owner-only access). This is the same approach used by ssh-agent and gpg-agent.

Auto-lock

mb-stash automatically locks when:

  • Manually via mb-stash lock
  • Configurable inactivity timeout
  • System screen locks (macOS, Linux) — planned

Clipboard is automatically cleared after a configurable timeout (default: 30s). Repeated get resets the timer. mb-stash lock also clears the clipboard.

What mb-stash does NOT protect against

  • Compromised machine: if an attacker has access to your running system (malware, root access), they can read daemon memory or intercept socket communication. This is a fundamental limitation shared by ssh-agent, gpg-agent, and similar tools.
  • Memory forensics: Python cannot guarantee secure memory wiping (garbage collector, no mlock). After locking, key material may linger in process memory briefly. Acceptable for non-critical secrets.
  • Other processes running as your user: any process running under your UID can connect to the Unix socket. Same limitation as ssh-agent.

mb-stash is NOT a replacement for a password manager. It is NOT suitable for team/shared secret management.

Commands

Setup

Command Description
mb-stash init First-time setup: create master password
mb-stash change-password Change master password

Daemon

Command Description
mb-stash stop Stop the daemon
mb-stash lock Lock the stash and clear clipboard
mb-stash unlock Unlock with master password
mb-stash health Show daemon status (running, locked/unlocked)

Secrets

Command Description
mb-stash get <key>, g Copy secret to clipboard (or --stdout for stdout)
mb-stash list [filter], l List stored keys, optionally filter by substring
mb-stash add <key> Add a new secret (value entered interactively)
mb-stash delete <key> Delete a secret

Usage examples

# First run
mb-stash init
# Create master password: ****
# Confirm: ****

# Add some secrets
mb-stash add my-token
# Enter value: ****

mb-stash add work/api-key
# Enter value: ****

# Daily usage — daemon starts and unlocks automatically on first access
mb-stash get my-token      # copied to clipboard ✓
mb-stash g work/api-key     # short alias works too

# Use in scripts
curl -H "Authorization: Bearer $(mb-stash get my-token --stdout)"

# See what's stored
mb-stash list
# my-token
# work/api-key

# Filter
mb-stash list work
# work/api-key

# Going away? Lock it (or just lock your screen — mb-stash locks with it)
mb-stash lock

# Back? Just get what you need — it will ask for password
mb-stash get my-token
# Enter master password: ****
# copied to clipboard ✓

Auto-lock

mb-stash locks on inactivity timeout and manual mb-stash lock. Screen lock detection (macOS, Linux) is planned.

Raycast extension

Search and copy secrets without touching the terminal. The extension communicates directly with the mb-stash daemon over Unix socket — no CLI spawning, instant responses.

Installation

cd raycast
npm install
npm run dev    # opens in Raycast automatically

Requires Raycast and Node.js 22+.

Commands

Command Description
Search Secrets List all keys, filter by typing, copy to clipboard
Lock Stash Lock the stash immediately (no UI, good for a keyboard shortcut)

If the stash is locked, Search Secrets prompts for the master password before showing the list. The daemon starts automatically if not running.

Keyboard shortcuts (in Search Secrets)

Shortcut Action
Enter Copy secret to clipboard
Cmd+L Lock stash

Configuration

In Raycast extension preferences:

Setting Default Description
Data Directory ~/.local/mb-stash Path to mb-stash data directory
mb-stash CLI Path mb-stash Path to CLI binary (used only for daemon startup)

Tech stack

  • Python 3.14
  • Typer (CLI framework)
  • cryptography (AES-256-GCM, scrypt — PyCA/OpenSSL)

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mb_stash-0.0.5.tar.gz (17.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mb_stash-0.0.5-py3-none-any.whl (26.3 kB view details)

Uploaded Python 3

File details

Details for the file mb_stash-0.0.5.tar.gz.

File metadata

  • Download URL: mb_stash-0.0.5.tar.gz
  • Upload date:
  • Size: 17.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for mb_stash-0.0.5.tar.gz
Algorithm Hash digest
SHA256 e8565790f7d693ff88306729396246ead503273841939c738a3a89dd7ec253c4
MD5 0dacc5f11a844c3f8d2d706a478c314d
BLAKE2b-256 680e0211bc3dbe995787719160406ca804a861e17202aba20708f34aa80f3690

See more details on using hashes here.

File details

Details for the file mb_stash-0.0.5-py3-none-any.whl.

File metadata

  • Download URL: mb_stash-0.0.5-py3-none-any.whl
  • Upload date:
  • Size: 26.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for mb_stash-0.0.5-py3-none-any.whl
Algorithm Hash digest
SHA256 493779699427236dd292a9914103539b705017a91c0d5035710e2d553bccb5a5
MD5 c6d0233d222e8060486924efcec61e4e
BLAKE2b-256 2036a63976922803937c96789e90ebd85c32ddade130588dc11bd8831c76c393

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page