Installation
The KeyZula command-line tool is a single-file program for macOS (Apple Silicon and Intel) and Linux (x64 and arm64); it doesn't need Node.js. The easiest way is Homebrew:
brew install keyzula/tap/keyzula
keyzula --versionOn Linux machines without Homebrew (for example servers and CI runners), download it and unpack it into /usr/local/bin:
# x64
curl -fsSL https://github.com/KeyZula/homebrew-tap/releases/download/v1.1.0/keyzula-1.1.0-linux-x64.tar.gz | sudo tar -xz -C /usr/local/bin keyzula
# arm64
curl -fsSL https://github.com/KeyZula/homebrew-tap/releases/download/v1.1.0/keyzula-1.1.0-linux-arm64.tar.gz | sudo tar -xz -C /usr/local/bin keyzulaTo update:
brew update && brew upgrade keyzulaThe archives and a SHA256SUMS file are published in the KeyZula/homebrew-tap releases.
Sign in and basics
keyzula login asks for your email address and master password, and for a code if two-step verification is on. The master password is hidden as you type and never written to disk.
keyzula login
keyzula status
keyzula list github
keyzula get password GitHub
keyzula get username GitHub
keyzula get totp GitHubget prints the password, username or totp field of an item by name or ID; 2FA codes are computed on your computer. list and status have --json output for scripts. If the SSH agent is running and unlocked, these commands don't ask for your password.
The default server is https://app.keyzula.com. For another server, use the --server flag or the KEYZULA_SERVER environment variable:
keyzula login --server https://vault.example.comAccounts that sign in with SSO or passwordless (trusted device) sign-in aren't supported in the command line yet.
Starting the SSH agent
The built-in SSH agent offers the SSH key items in your personal vault and in the collections you can access to ssh and git. Private keys live only in the agent process's memory; they never touch the disk and are wiped when the agent locks.
keyzula ssh-agent --daemon
keyzula ssh add-config--daemon runs the agent in the background (log: ~/.config/keyzula/ssh-agent.log; it only contains key names, fingerprints and times). The agent refreshes the vault every 5 minutes, so keys you add to the vault show up on their own.
- Supported keys: Ed25519, RSA (rsa-sha2-256/512) and ECDSA P-256/384/521; OpenSSH and PEM/PKCS#8 formats, including passphrase-protected keys (the item's passphrase field is used).
- Hardware keys (
sk-*) and DSA aren't supported. - Keys shared with the "can't see the password" permission aren't added to the agent.
- Add and remove requests from
ssh-addare refused; manage keys in the vault.
ssh configuration
keyzula ssh add-config prints the configuration snippet for your system. To use KeyZula keys for all hosts, add it to ~/.ssh/config:
# ~/.ssh/config
Host *
IdentityAgent "~/.config/keyzula/ssh-agent.sock"For the current terminal session only, use the SSH_AUTH_SOCK variable:
export SSH_AUTH_SOCK="$HOME/.config/keyzula/ssh-agent.sock"
ssh-add -L
ssh -T git@github.comThe socket is created with permissions only you can access (0600). If XDG_CONFIG_HOME is set, the path changes accordingly; keyzula ssh add-config always shows the right one.
Signature confirmation and auto-lock
keyzula ssh-agent --confirm
keyzula ssh-agent --daemon --lock-after 2h
keyzula lock
keyzula unlock--confirm: asks for confirmation (y/N) on the agent's terminal before every signature. Because it needs a terminal, it can't be combined with--daemon; run the agent in the foreground in a separate terminal tab.--lock-after: locks the agent after this much inactivity (default12h;0= never). Write durations like30mor2h.keyzula lockwipes the keys from memory;keyzula unlockasks for your master password and opens the agent again.
Git commit signing
You can sign git commits with an SSH key from your vault. With the agent running:
git config --global gpg.format ssh
git config --global user.signingkey "key::$(ssh-add -L | head -n1)"
git config --global commit.gpgsign truessh-add -L lists the public keys in the agent; if you have more than one, pick the right line instead of head -n1. Add the same public key to your GitHub or GitLab account as a signing key.
Secrets: read, run and inject
Instead of writing passwords into scripts and configuration files, write a reference that points to the value in your vault:
kz://<collection>/<item>/<field>- Collection and item: a name (case-insensitive) or an ID.
~is your personal vault (signed-in users only). - Field:
password,username,totp(the current code),notes,url,private_key,public_key,passphrase,number,codeor the label of a custom field. - Write a
/inside a name as%2F, and always quote references in the shell.
keyzula read "kz://Production/Postgres/password"
keyzula read -n "kz://~/GitHub/totp"keyzula run resolves the kz:// values in the environment and in the files given with --env-file, then starts the command with that environment. Resolved values are concealed in the command's output by default; use --no-masking for interactive programs.
# .env
DB_PASSWORD=kz://Production/Postgres/password
STRIPE_KEY="kz://Production/Stripe/API key"
keyzula run --env-file .env -- ./deploy.shkeyzula inject fills in the {{ kz://… }} placeholders in a template. The output file is written with permissions only you can read (0600), and an existing file is only replaced with --force.
# config.yml.tpl
database:
password: "{{ kz://Production/Postgres/password }}"
keyzula inject -i config.yml.tpl -o config.ymlAll references are resolved before anything runs; if a single one fails, nothing is started or written.
Service accounts: CI, servers and AI agents
A service account is a machine identity that lets servers, CI jobs and AI agents read the secrets in selected collections of an organization, read-only. An owner or admin creates one in the web vault under Organization → Service accounts, picks the collections and creates an access token. The token is shown only once.
export KEYZULA_SERVICE_TOKEN='kzsa_1_…'
keyzula read "kz://Production/Postgres/password"- Zero knowledge: the token and its keys are created in the admin's browser. The server never sees the token itself; the command-line tool decrypts items locally.
- Read-only: a service account can only read the collections it was given; it can't add or change items.
- Revocation: each token can be revoked on its own and can have an expiry date. Revoking a token deletes its keys from the server.
- Audit: every read is written to the organization's audit log with the time, IP address and collection.
Without KEYZULA_SERVICE_TOKEN, the same commands run as the signed-in user.
GitHub Actions example
Add the token to your repository's secrets as KEYZULA_SERVICE_TOKEN. In the workflow, download the Linux build and pass secrets to a step's environment as kz:// references:
jobs:
deploy:
runs-on: ubuntu-latest
env:
KEYZULA_SERVICE_TOKEN: ${{ secrets.KEYZULA_SERVICE_TOKEN }}
steps:
- uses: actions/checkout@v4
- name: Install KeyZula CLI
run: curl -fsSL https://github.com/KeyZula/homebrew-tap/releases/download/v1.1.0/keyzula-1.1.0-linux-x64.tar.gz | sudo tar -xz -C /usr/local/bin keyzula
- name: Deploy
env:
DB_PASSWORD: kz://Production/Postgres/password
run: keyzula run -- ./scripts/deploy.sh
- name: Render config
run: keyzula inject -i deploy/app.yml.tpl -o deploy/app.ymlkeyzula run removes KEYZULA_SERVICE_TOKEN from the child process's environment, forwards signals and passes the exit code through. Use one token per repository or environment, give it an expiry date and revoke it when it's no longer needed.
Give AI agents their own service account too, one that sees only the collection they need. API keys then reach only the process environment, never the prompt or the repository:
KEYZULA_SERVICE_TOKEN=kzsa_1_… \
OPENAI_API_KEY="kz://AI agents/OpenAI/API key" \
keyzula run -- python agent.pySecurity notes
- Only the server URL, email, session token and the encrypted keys returned by the server are written to
~/.config/keyzula(0700;config.json, 0600). - The master password, derived keys, the decrypted vault and private SSH keys never touch the disk; they live only in the agent process's memory and are wiped on lock.
- With a service token, the tool writes nothing to
~/.config/keyzula. No secret is written to disk except theinject -ooutput you explicitly ask for. - Reads with
getand keys the agent uses for signing are recorded in the access log like in the other apps (only the item ID, the action and the time; never the name or contents). - Never put the token in a repository, a Docker image or a prompt; keep it in your CI's secrets.
For architecture details, see the Security page.