keypo-signer
keypo-signer
A CLI for hardware-bound P-256 key management and encrypted secret storage using the Apple Secure Enclave. Keys never leave the hardware. Secrets are encrypted at rest and decrypted only into child process environments.
Install: brew install keypo-us/tap/keypo-signer
This installs the keypo-signer Swift CLI for Secure Enclave key management and encrypted vault operations.
Source: https://github.com/keypo-us/keypo-cli
CLI Usage Rule
Before using any keypo-signer command for the first time in a session, run keypo-signer help <command> to learn the exact flags, syntax, and examples. The help output is the authoritative reference for each command.
keypo-signer help vault exec # learn vault exec flags before using
keypo-signer help vault session # learn session subcommands
keypo-signer help create # learn create flags before creating keys
Do not guess flag names or assume positional arguments. Every command documents its interface via help.
Running Commands with Secrets (vault exec)
Use vault exec to inject decrypted secrets into a child process environment. The agent never sees plaintext values — secrets flow directly from the encrypted vault into the child process.
Basic patterns
# Using a .env.example file (recommended — values are ignored, only names matter)
keypo-signer vault exec --env .env.example -- cargo test
# Using explicit secret names
keypo-signer vault exec --allow PIMLICO_API_KEY,DEPLOYER_PRIVATE_KEY -- cargo test
# All secrets from all vaults
keypo-signer vault exec --allow '*' -- forge test -vvv
The .env.example convention
The --env flag reads a file for key names only — values are ignored. Use a .env.example with empty or dummy values:
# .env.example
PIMLICO_API_KEY=
DEPLOYER_PRIVATE_KEY=placeholder
BASE_SEPOLIA_RPC_URL=https://example.com
The vault looks up each name, finds which vault stores it, decrypts it, and injects it into the child process environment.
Combining --allow and --env
Both flags can be used together. Names are unioned and deduplicated:
keypo-signer vault exec --env .env.example --allow EXTRA_SECRET -- ./deploy.sh
Argument passing rules
The -- separator is required. Everything after -- is the command to execute.
Simple commands — pass the command and its arguments directly:
keypo-signer vault exec --env .env.example -- cargo test -- --ignored --test-threads=1
keypo-signer vault exec --allow '*' -- forge script Deploy
Shell expressions — when you need shell features (pipes, variable expansion, subshells), use sh -c:
keypo-signer vault exec --env .env.example -- sh -c 'echo $SECRET_NAME'
keypo-signer vault exec --allow '*' -- sh -c 'curl -H "Authorization: Bearer $API_KEY" https://api.example.com'
sh -c coalescing — when using sh -c, all arguments after -c are automatically joined into a single string. This means you don't need to quote the entire expression:
# These are equivalent:
keypo-signer vault exec --allow '*' -- sh -c 'echo $FOO && echo $BAR'
keypo-signer vault exec --allow '*' -- sh -c echo $FOO && echo $BAR
What NOT to do
- Never use
vault getin agent workflows — it outputs plaintext to stdout. Usevault execinstead. - Never retry after exit code 128 — the user deliberately cancelled authentication.
- Never attempt to read, log, capture, or exfiltrate secret values. Secrets must stay inside the child process.
- Never pipe
vault getoutput into environment variables or files.
Exit codes
| Code | Meaning | Agent Action |
|---|---|---|
| 0 | Success | Continue |
| 5 | Session expired, exhausted, or not found | Create a new session |
| 126 | Vault error (not initialized, secret not found, integrity failure) | Report error to user |
| 127 | Command not found | Fix the command path |
| 128 | User cancelled authentication | Do not retry — user declined |
| 128+N | Child killed by signal N | Report signal to user |
Behavioral details
| Topic | Detail |
|---|---|
| Environment inheritance | Child inherits parent env + decrypted secrets overlaid (secrets take precedence) |
| Auth prompts | One prompt per vault per invocation. Vaults loaded in order: open, passcode, biometric |
| stderr output | Prints keypo-vault: decrypting N secret(s) for: <command> to stderr before running |
| Exit code forwarding | Child's exit code is forwarded directly. Signal kills map to 128 + signal number |
Common patterns
# Run integration tests with secrets
keypo-signer vault exec --env .env.example -- cargo test -- --ignored --test-threads=1
# Run Foundry tests
keypo-signer vault exec --env .env.example -- forge test -vvv
# Deploy contracts
keypo-signer vault exec --allow DEPLOYER_PRIVATE_KEY -- forge script Deploy
# Multi-tool composition: secrets + keypo-wallet
keypo-signer vault exec --allow PIMLICO_API_KEY --allow KEYPO_RPC_URL -- keypo-wallet send --key agent --to 0x... --value 1000
# Check what secrets are available (no auth required)
keypo-signer vault list
Sessions (Unattended Agent Workflows)
Sessions let a human authenticate once and grant scoped, time-limited access to specific secrets. After session creation, vault exec --session runs without auth prompts — ideal for agent workflows that need repeated access to protected secrets.
Create a session
# Authenticate once, grant 30-minute access to specific secrets
keypo-signer vault session start --secrets API_KEY,DB_PASSWORD --ttl 30m
# With a usage limit
keypo-signer vault session start --secrets API_KEY --ttl 1h --max-uses 50
The human approves via Touch ID (if secrets are in biometric vault), and a session is created with a random name (e.g., orbital-canvas).
Use a session
# No auth prompt — session handles it
keypo-signer vault exec --session orbital-canvas -- npm start
keypo-signer vault exec --session orbital-canvas -- python app.py
--session is mutually exclusive with --allow and --env. The session fully defines which secrets are injected.
Manage sessions
# List active sessions
keypo-signer vault session list
# Check session details (secrets, TTL, uses remaining)
keypo-signer vault session status orbital-canvas
# Extend a session (re-authenticates)
keypo-signer vault session refresh orbital-canvas --ttl 2h
# End a session early
keypo-signer vault session end orbital-canvas
# End all sessions
keypo-signer vault session end --all
Agent workflow pattern
The recommended pattern for agents that need protected secrets:
- Human creates a session (one-time, interactive):
keypo-signer vault session start --secrets API_KEY,DB_PASS --ttl 1h --max-uses 100 - Agent uses the session (repeated, unattended):
keypo-signer vault exec --session <name> -- <agent-command> - Session expires automatically after TTL or usage limit.
Session security
- Sessions are scoped to specific secrets — they cannot access other secrets.
- Secrets are re-encrypted under a temporary SE key. The session is self-contained.
- Every session action is recorded in an audit log at
~/.keypo/session-audit.log. - Sessions expire after TTL or usage limit. Expired sessions are cleaned up automatically.
Storing Secrets
Initialize vaults
keypo-signer vault init
Creates three vaults: open, passcode, and biometric. Each is backed by its own Secure Enclave key.
Store a secret
echo -n "sk_live_abc123" | keypo-signer vault set API_KEY --vault biometric
keypo-signer vault set DB_PASSWORD --vault passcode
Pipe the value via stdin, or omit it to be prompted interactively. Default vault is the highest available tier.
Bulk import from .env file
keypo-signer vault import .env --vault passcode
Reads key=value pairs from the file and stores each as a separate secret.
Update a secret
keypo-signer vault update MY_API_KEY
Prompts for the new value. The secret stays in its original vault.
Delete a secret
keypo-signer vault delete MY_API_KEY --confirm
The --confirm flag is required to prevent accidental deletion.
List secrets (safe, no auth)
keypo-signer vault list
Shows vault names and secret names. No decryption occurs.
Destroy all vaults
keypo-signer vault destroy --confirm
Permanently deletes all vaults, secrets, and vault keys. Irreversible.
Backup & Restore
Back up to iCloud Drive
keypo-signer vault backup
Encrypts all vault secrets and writes them to iCloud Drive. Encryption uses two factors: an iCloud Keychain synced key + a passphrase displayed once. Both are required to restore.
Check backup status
keypo-signer vault backup-info
Shows whether a backup exists, its age, and any unbackup'd secrets.
Restore from backup
keypo-signer vault restore
keypo-signer vault restore --previous
Decrypts the backup, compares to local vault, and offers: cancel, replace, merge, or back-up-first. --previous restores from the prior backup instead of the current one.
Reset backup key
keypo-signer vault backup-reset
Regenerates the backup encryption key and passphrase. Use when you suspect the passphrase was compromised.
Vault Policies
| Policy | Auth | Use for |
|---|---|---|
| biometric | Touch ID | Production secrets, private keys, API keys with financial exposure |
| passcode | Device passcode | When Touch ID isn't available or for moderate-sensitivity secrets |
| open | None | Non-sensitive dev config only (test RPC URLs, public endpoints) |
For agent workflows, store secrets in open or passcode vaults. biometric requires interactive Touch ID which blocks automation — use sessions to grant time-limited access to biometric secrets without repeated prompts.
Key Management
Create a key
keypo-signer create --label my-key --policy open
Generates a P-256 key in the Secure Enclave. Policies: open, passcode, biometric.
List keys
keypo-signer list
Shows all managed keys with labels, policies, and creation dates.
Key details
keypo-signer info my-key
Shows public key, policy, and metadata for a specific key.
Sign a digest
keypo-signer sign 0xdeadbeef --key my-key
Signs raw hex-encoded data. Uses prehash signing (no double-hashing). Output is a DER-encoded P-256 signature.
Verify a signature
keypo-signer verify 0xdeadbeef 0x3045... --key my-key
keypo-signer verify 0xdeadbeef 0x3045... --public-key 0x04abcd...
Delete a key
keypo-signer delete my-key --confirm
Permanently destroys the key from the Secure Enclave. Irreversible.
Rotate a key
keypo-signer rotate my-key
Generates a new key with the same label and policy, replacing the old one.
Commands Reference
| Command | Description | Auth Required |
|---|---|---|
create |
Generate a new P-256 key in the Secure Enclave | Yes (policy-dependent) |
list |
List all managed keys | No |
info |
Show key details or system info | No |
sign |
Sign a digest with a key | Yes (key's policy) |
verify |
Verify a signature | No |
delete |
Destroy a key permanently | Yes (key's policy) |
rotate |
Replace a key keeping label and policy | Yes (key's policy) |
vault init |
Initialize all three vaults | Yes (passcode + biometric) |
vault set |
Store a new secret | Yes (target vault's policy) |
vault get |
Decrypt and output a secret | Yes (secret's vault policy) |
vault update |
Update an existing secret | Yes (secret's vault policy) |
vault delete |
Remove a secret | Yes (secret's vault policy) |
vault list |
List vaults and secret names | No |
vault exec |
Inject secrets into child process | Yes (per vault used) |
vault exec --session |
Inject secrets via session (no auth) | No (session pre-authorized) |
vault import |
Bulk import from .env file | Yes (target vault's policy) |
vault destroy |
Delete all vaults and secrets | Yes (all vaults) |
vault backup |
Encrypt and back up to iCloud Drive | Yes (all vaults) |
vault backup-info |
Show backup status | No |
vault backup-reset |
Regenerate backup key and passphrase | Yes |
vault restore |
Restore from iCloud backup | Yes (passphrase + iCloud key) |
vault session start |
Create a scoped, time-limited session | Yes (per secret's vault) |
vault session list |
List active sessions | No |
vault session status |
Show session details | No |
vault session refresh |
Extend session TTL or usage limits | Yes (re-authenticates) |
vault session end |
End one or all sessions | No |
Run keypo-signer help <command> or keypo-signer help vault <subcommand> for flags and examples.
Security Notes
- Private keys never leave the Secure Enclave. No export command exists.
- Secrets are encrypted at rest using Secure Enclave keys and decrypted only into child process environments.
- Use
vault execinstead ofvault getin all automated workflows. - For agent use,
openpolicy keys and vaults avoid interactive auth prompts. - For high-value secrets, prefer
biometricorpasscodevaults with interactive user approval. - Sessions are the recommended way for agents to access protected (biometric/passcode) secrets — authenticate once, then run unattended within the session's TTL and usage limits.
- All session lifecycle events are recorded in
~/.keypo/session-audit.logfor forensic traceability.
More from keypo-us/keypo-cli
keypo-wallet
Use when interacting with keypo-wallet — checking wallet balances, listing wallets, sending transactions, or managing Secure Enclave signing keys. Use `keypo-wallet wallet-list` to list wallets, `keypo-wallet balance` to check balances, `keypo-wallet send` to send transactions, and `keypo-wallet batch` for multi-call operations. Never use raw RPC calls, curl, or cast for balance queries — keypo-wallet has built-in commands. Also use when composing keypo-wallet as the secure execution backend for other EVM protocol skills (Uniswap, Aave, ENS, etc.).
3contract-learner
Use when a user provides a smart contract address and wants to generate a reusable SKILL.md file for interacting with that contract through keypo-wallet. Analyzes verified contracts by fetching their ABI, categorizes functions, and outputs a complete agent skill file with verified addresses, function signatures, calldata encoding instructions, and keypo-wallet execution commands. Also use when a user says "make a skill for this contract", "generate a skill", or "I want to interact with this contract using keypo-wallet". Requires Foundry (cast) to be installed.
2portfolio-tracker
Use when the user asks about token balances, what tokens a wallet holds, or wants a complete portfolio overview including ERC-20 tokens. Discovers all ERC-20 tokens and native token balances held by any EVM address using Alchemy's Portfolio API — one call returns everything. Works on both mainnets and testnets including Base Sepolia. Use this instead of manually checking individual token contracts or scraping block explorers. Also use when the user says "what tokens do I have", "show my portfolio", "what's in my wallet", "check my token balances", "what other tokens", or asks for token holdings beyond native ETH. Requires an Alchemy API key.
2