A cross-platform secrets manager with CLI, TUI, API server, and MCP server. Secrets are stored in an age-encrypted vault with timed unlock sessions, policy-controlled injection, and audit logging.
Install the latest stable Rust toolchain (rustup default stable), then:
cargo install --path crates/kyz-cliOr build everything:
cargo build --release# Create config directories and default files
kyz init
# Create a new encrypted vault
kyz vault create
# Store a secret
kyz set my-api-key "sk-abc123" --service github
# Store a multi-field secret
kyz set db-creds --service postgres -f host=localhost -f user=admin -f password=secret
# Retrieve a secret
kyz get my-api-key --service github
# Retrieve a single field
kyz get db-creds --service postgres -f password
# List secrets in a namespace
kyz list --service github
# Tag secrets for group injection
kyz set deploy-key --service github -f token=ghp_xxx --tag deploy --tag ciWrap a command with secrets injected as environment variables:
# Using a config alias
kyz exec --alias deploy -- make deploy
# Explicit secret references
kyz exec --secret github/deploy-key --secret aws/prod -- ./deploy.sh
# Explicit env-var mapping
kyz exec --env GITHUB_TOKEN=github/deploy-key:token -- gh pr create
# Tag-based: inject all secrets tagged "dev"
kyz exec --tag dev -- cargo test
# Interactive fzf picker (multi-select with TAB)
kyz exec --pick -- ./my-appPipe a single secret into a command's stdin (never touches env or args):
kyz pipe github/deploy-key:token -- docker login --password-stdinWrap an agent or long-running process with pre-approved secret access and policy enforcement:
kyz wrap --allow github/deploy-key,aws/prod -- ./agent.sh
kyz wrap --allow '*' -- ./trusted-script.shDefine reusable secret sets in config.toml:
[aliases.deploy]
secrets = ["github/deploy-key", "aws/prod-creds"]
tags = ["deploy"]
env_map = { GITHUB_TOKEN = "github/deploy-key:token" }
[aliases.dev]
tags = ["dev"]Secrets are stored in an age-encrypted vault file. The vault uses timed unlock sessions so the passphrase is entered once, then cached for a configurable duration.
kyz vault create # Create a new vault
kyz vault unlock # Unlock (default: 30 minutes)
kyz vault unlock --timeout 3600 # Unlock for 1 hour
kyz vault lock # Lock immediately
kyz vault status # Show lock state and session infokyz enforces command policies when injecting secrets. Policies block obvious exfiltration vectors — commands like cat, echo, env, and printenv that trivially leak values.
This is a best-effort guardrail, not a security boundary. Any sufficiently creative command can exfiltrate environment variables (writing to a file, sending over the network, spawning a subshell, etc.). The policy engine raises the bar and catches accidental leaks, but it cannot cover every possible path. Treat it as defense-in-depth alongside access controls, audit logging, and limiting which secrets are injected in the first place.
Policy files are discovered from:
.kyz-policy.jsonin the current directory.kyz-policy.jsonin the workspace root$XDG_CONFIG_HOME/kyz/policy.json
{
"deny_commands": ["cat", "echo", "env", "printenv"],
"allow_commands": [],
"deny_args": ["-c", "eval"],
"secrets": {
"prod/db-password": {
"allow_commands": ["psql", "pg_dump"]
}
}
}Bypass with --no-policy (use with caution).
All secret access through exec, pipe, and wrap is logged to syslog with operation type, secret names, and target commands.
# Export secrets as JSON
kyz export --service github > secrets.json
# Import from file or stdin
kyz import secrets.json
cat secrets.json | kyz import -crates/
kyz-core/ # Shared library: config, paths, vault, store, policy, audit
kyz-cli/ # Command-line interface
kyz-tui/ # Terminal user interface (ratatui)
kyz-mcp/ # Model Context Protocol server
kyz-api/ # HTTP API server (axum)
Shared library providing:
- Age-encrypted vault backend with timed sessions
- OS keyring backend (desktop sessions)
SecretStoretrait abstracting both backends- Multi-field secret entries with tags
- XDG-compliant path resolution
- Configuration loading via
configcrate - Command policy engine
- Audit logging
- Auth request flow for headless/remote use
Command-line interface with subcommands: set, get, delete, list, export, import, vault, exec, pipe, wrap, init, config, completions.
Global flags: -q, -v, --debug, --trace, --json, --yaml, --no-color, --dry-run, --yes.
kyz --help
kyz completions bash > ~/.local/share/bash-completion/completions/kyzStub. The ratatui scaffolding is in place (three-pane layout, vim keybindings, help overlay) but it displays hardcoded placeholder items. No vault or secret browsing yet.
kyz-tuiMCP server stub. Currently exposes only template tools (get_profile, echo, get_runtime_config). Secret management tools are not yet implemented.
kyz-mcpHTTP API server (axum) with auth request workflow for headless agents:
| Endpoint | Method | Description |
|---|---|---|
/ |
GET | Service info |
/health |
GET | Health check |
/config |
GET | Current configuration |
/auth/request |
POST | Create an auth request |
/auth/request |
GET | List auth requests |
/auth/request/{id} |
GET | Get auth request status |
/auth/approve/{id} |
POST | Approve an auth request |
/auth/deny/{id} |
POST | Deny an auth request |
/auth/secrets/{id} |
GET | Pick up approved secrets |
/auth/wait/{id} |
GET | WebSocket wait for approval |
kyz-api --port 3000Set KYZ_API_TOKEN to require Authorization: Bearer <token> on all endpoints except /health.
Default config path: $XDG_CONFIG_HOME/kyz/config.toml (fallback: ~/.config/kyz/config.toml).
Override with --config <path> or environment variables using the KYZ__ prefix:
KYZ__LOGGING__LEVEL=debug kyz listManage configuration:
kyz config show # Print current config
kyz config path # Print config file path
kyz config paths # Print all resolved paths
kyz config schema # Print JSON schema
kyz config reset # Reset to defaultsSee examples/config.toml for all options.
cargo fmt # Format code
cargo clippy --all-targets --all-features # Lint
cargo test # Run tests
cargo build --release # Release buildMIT