Per-project secrets in local KeePassXC vaults, injected into commands without ever printing them. Agent-safe: PreToolUse guard hook + read-only MCP server. Single Go binary.
claude mcp add kdbx -- docker run -i --rm ghcr.io/yarrasys/kdbx{
"mcpServers": {
"kdbx": {
"command": "docker",
"args": ["run", "-i", "--rm", "ghcr.io/yarrasys/kdbx"]
}
}
}MCP Servers overview
# kdbx — per-project secrets in KeePassXC vaults, safe to hand an AI agent
[](https://github.com/yarrasys/kdbx/actions/workflows/ci.yml)
[](https://github.com/yarrasys/kdbx/actions/workflows/govulncheck.yml)
[](https://github.com/yarrasys/kdbx/releases/latest)
[](https://scorecard.dev/viewer/?uri=github.com/yarrasys/kdbx)
[](go.mod)
[](LICENSE)
`kdbx` keeps a project's secrets in a **per-project, per-environment KeePassXC vault**
(KDBX4, unlocked by a key file only — no master password) and gets them into the tools that
need them **without kdbx ever printing them into a transcript, a log file, or your shell
history**.
Discovery is automatic: kdbx walks up from your current directory to a committed
`.keepassxc.json` pointer file, works out which environment is active, and takes it from
there. The headline command is `kdbx run -- <cmd>`, which resolves that environment's
variable mappings and injects them into a child process' environment. It replaces `.env`
files as the source of truth; the vault stays outside the repo, so there is nothing secret
to accidentally commit.
> Every install method below is live — the curl installer, Homebrew, `go install`, the
> `ghcr.io` container image, and the signed release archives (`SHA256SUMS` + cosign, with
> reproducible builds). The badge above tracks the current version.
## Install
```sh
# curl installer — downloads the release archive, verifies its SHA-256, installs to
# ~/.local/bin (override with KDBX_INSTALL_DIR; pin with KDBX_VERSION=v0.2.1)
curl -LsSf https://raw.githubusercontent.com/yarrasys/kdbx/main/install.sh | sh
```
```sh
brew install yarrasys/tap/kdbx # Homebrew
go install github.com/yarrasys/kdbx@latest # from source, needs Go 1.25+
docker run --rm ghcr.io/yarrasys/kdbx:latest --version # container (FROM scratch)
```
Windows: download the `_windows_` archive from the
[releases page](https://github.com/yarrasys/kdbx/releases) and put `kdbx.exe` on your PATH.
Building from source needs **Go 1.25 or newer** (the KDBX engine and `golang.org/x/term`
both declare a 1.25 floor). Release binaries are static and impose no toolchain
requirement on users.
Shell completions:
```sh
kdbx completion zsh > "${fpath[1]}/_kdbx"
kdbx completion bash > /etc/bash_completion.d/kdbx
kdbx completion fish > ~/.config/fish/completions/kdbx.fish
kdbx completion powershell | Out-String | Invoke-Expression
```
## Quick start
**1. Commit a pointer file** at the repo root. It names the project and its environments;
it contains no secrets, so it is safe to check in.
```json
{
"project": "demo",
"defaultEnv": "dev",
"envs": {
"dev": {},
"prod": {}
}
}
```
An empty env object is fine — kdbx derives the artifact paths from the project and
environment name: `<keepassxc-dir>/demo/dev.kdbx` and `<keepassxc-dir>/demo/dev.keyx`,
where `<keepassxc-dir>` is `$KEEPASSXC_DIR` if set, else `%LOCALAPPDATA%\keepassxc` on
Windows, else `$XDG_CONFIG_HOME/keepassxc` or `~/.config/keepassxc`. Set `vault` and
`keyFile` explicitly if you want them somewhere else; both accept a `${KEEPASSXC_DIR}`
token and a leading `~`.
**2. Create the vault and its key file.**
```console
$ kdbx init
ACTIVE ENV: dev vault=/home/you/.config/keepassxc/demo/dev.kdbx (source: pointer)
created /home/you/.config/keepassxc/demo/dev.kdbx
KEYFILE: /home/you/.config/keepassxc/demo/dev.keyx — back this up; losing it makes the vault unrecoverable.
```
**3. Store a secret and map it to an environment variable.** The value never appears on
the command line — it arrives on stdin, from `--from-env`, or from an interactive prompt.
```console
$ kdbx set api/openai --var OPENAI_API_KEY < secret.txt
ACTIVE ENV: dev vault=/home/you/.config/keepassxc/demo/dev.kdbx (source: pointer)
modified tracked file .keepassxc.json — review and commit
```
`--var` records the mapping in the pointer file, preserving existing key order so the diff
stays reviewable:
```json
"dev": {
"vars": {
"OPENAI_API_KEY": "api/openai"
}
}
```
**4. Run something with the secrets injected.**
```sh
kdbx run -- claude # the author's actual daily use
kdbx run -- npm test
kdbx --env prod run -- ./deploy.sh
```
The child inherits your environment plus the mapped variables. Its exit code is passed
straight back out. Nothing is written to disk, and the value never appears in your shell
history.
Reading is deliberately boring:
```console
$ kdbx list
api/openai
$ kdbx get api/openai
(set, hidden)
$ kdbx check # every mapping still resolves → exit 0, no output
$ kdbx envs
* dev
prod
```
## Operations
Every operation accepts `--env NAME`. Read operations additionally accept `--json`.
Operations marked ✦ print the banner `ACTIVE ENV: <env> vault=<path> (source: <src>)` to
**stderr**; pure display operations do not.
| Op | Flags | Behavior (stdout / stderr / exit) |
|----|-------|------------------------------------|
| `init` ✦ | `--mode standard\|strict` | create vault + key file; stderr `created <vault>` plus a KEYFILE backup warning; refuses to overwrite an existing vault or key file; `--mode` records the env's policy in the pointer, and `strict` anchors it into the new vault |
| `policy bless` ✦ | | anchor the pointer's current policy (its `policy` and `run.allow` sections) into the vault; interactive-only, like `rekey`, and denied to agents by the guard; strict `run` refuses until the anchor matches |
| `set PATH` ✦ | `--var NAME`, `--from-env VAR`, `--raw` | value from `--from-env`, else an interactive prompt with confirmation on a TTY, else stdin (empty → error; one trailing newline stripped unless `--raw`); an empty or whitespace-only value is refused; `--var` adds the mapping to the pointer file |
| `get PATH` | `--reveal` \| `--clip` | default: prints `(set, hidden)` — no length or prefix leak; `--reveal` prints the value with a stderr warning; `--clip` copies it and auto-clears after ~15 s; missing entry or field → exit 2 |
| `list [GROUP]` | | sorted `group/…/title` lines, filtered by the `GROUP` prefix, Recycle Bin excluded; never prints values |
| `delete PATH` ✦ | `--purge` | soft-deletes to the Recycle Bin by default; `--purge` prompts `y/N` (TTY only — a non-TTY refuses with exit 4) then removes permanently |
| `mv SRC DST` ✦ | | moves or retitles an entry, creating destination groups; re-points the active environment's var mappings that referenced `SRC`, keeping any `:field` suffix; stderr `re-pointed N var mapping(s) …` |
| `run` ✦ | `--allow-missing`, `--no-mask`, `--any`, `-- CMD…` | if the pointer has a `run.allow` list, refuses an unlisted command before the vault is even opened (exit 7, `NotAllowed`) unless `--any`; resolves the active environment's `vars` map, injects it into the child's environment, resolves `argv[0]` through PATH (PATHEXT on Windows), forwards signals, and passes the child's exit code through; when a child stream is captured (not a TTY), injected values ≥ 8 bytes in it become `***` (`--no-mask` disables; the guard denies it for agents); no command → exit 2; an unresolved var → exit 5 unless `--allow-missing` |
| `export` ✦ | `--out FILE`, `--allow-missing` | renders the mappings as dotenv (always double-quoted; `\`, `"` and newlines escaped); `--out` writes atomically at 0600 with a gitignore reminder, otherwise stdout |
| `import FILE` ✦ | | parses a dotenv file (no `$VAR` interpolation), stores each `KEY` at `imported/KEY` and registers the mapping; stderr reminds you to delete or rotate the source file |
| `check` | | prints `MISSING VAR -> path` per broken mapping; exit 0 when clean, 5 on drift |
| `envs` | | one line per environment, the active one marked `* `; stderr `active: <env> (source: <src>)`; no pointer file → exit 2 |
| `rekey` ✦ | | prompts `y/N` (TTY only, else exit 4), mints a new key file, re-keys the vault, replaces the old key file atomically; stderr reminds you to redistribute it |
Integration surfaces:
| Command | Purpose |
|---------|---------|
| `kdbx mcp` | read-only MCP server over stdio (five tools: `kdbx_list`, `kdbx_envs`, `kdbx_check`, `kdbx_get`, `kdbx_run`) |
| `kdbx guard --hook pretooluse` | evaluates a `PreToolUse` hook payload on stdin and denies agent-issued human-only operations |
| `kdbx completion <shell>` | emits a completion script for bash, zsh, fish, or powershell |
| `kdbx --version` | prints `kdbx <version>` |
### `--json`
`--json` gives read operations a machine-readable stdout. Secret values are never included.
```console
$ kdbx --json list
{"entries":["api/openai"]}
$ kdbx --json envs
{"envs":[{"name":"dev","active":true}],"source":"pointer"}
$ kdbx --json check
{"missing":[],"ok":true}
$ kdbx --json get api/openai
{"path":"api/openai","set":true}
```
`--json` with `--reveal` is rejected (exit 7). On failure, stdout carries
`{"error":{"op":"check","exit":5,"kind":"Drift"}}` alongside the usual stderr line and exit
code.
### Entry paths
An entry path is `group/sub/Title[:field]`. The field defaults to `password`. The reserved
field names — `title`, `username`, `password`, `url`, `notes`, matched case-insensitively —
map to the KeePass entry's native attributes; anything else becomes a **protected custom
property**. More than one `:`, an empty field after `:`, or an empty `/` segment is
rejected. Variable names passed to `--var` must match `^[A-Z_][A-Z0-9_]*$`.
### Environment selection
`--env` beats `$KDBX_ENV`, which beats the pointer's `defaultEnv`, which defaults to `dev`.
`kdbx envs` and the banner report which of thWhat people ask about kdbx
What is yarrasys/kdbx?
+
yarrasys/kdbx is mcp servers for the Claude AI ecosystem. Per-project secrets in local KeePassXC vaults, injected into commands without ever printing them. Agent-safe: PreToolUse guard hook + read-only MCP server. Single Go binary. It has 1 GitHub stars and was last updated today.
How do I install kdbx?
+
You can install kdbx by cloning the repository (https://github.com/yarrasys/kdbx) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.
Is yarrasys/kdbx safe to use?
+
yarrasys/kdbx has not been audited yet by our security agent. Review the original repository on GitHub before using it in production.
Who maintains yarrasys/kdbx?
+
yarrasys/kdbx is maintained by yarrasys. The last recorded GitHub activity is from today, with 0 open issues.
Are there alternatives to kdbx?
+
Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.
Deploy kdbx to your cloud
Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.
Maintain this repo? Add a badge to your README
Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.
[](https://claudewave.com/repo/yarrasys-kdbx)<a href="https://claudewave.com/repo/yarrasys-kdbx"><img src="https://claudewave.com/api/badge/yarrasys-kdbx" alt="Featured on ClaudeWave: yarrasys/kdbx" width="320" height="64" /></a>More MCP Servers
Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.
User-friendly AI Interface (Supports Ollama, OpenAI API, ...)
An open-source AI agent that brings the power of Gemini directly into your terminal.
The fastest path to AI-powered full stack observability, even for lean teams.
Real-time global intelligence dashboard. AI-powered news aggregation, geopolitical monitoring, and infrastructure tracking in a unified situational awareness interface
🕷️ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl!