Local credential vault and lease broker for AI agents.
中文说明 · Quick Start · HTTP API · Development
Passka is a local credential broker for AI agents.
You store long-lived credentials once in macOS Keychain. Agents never receive those raw secrets. Instead, an agent authenticates to the local broker with an agent token, asks for a short-lived lease, and then uses that lease through Passka's HTTP proxy.
If an upstream key leaks, you rotate the credential inside Passka and keep the agent integration unchanged.
| Concept | Meaning |
|---|---|
| Credential Account | A stored credential such as an API key, OAuth app, OTP seed, or opaque secret bundle. |
| Agent | A local AI tool or automation that is allowed to use an account. |
| Agent Token | A local broker-issued token that authenticates one agent principal to the daemon. |
| Lease | A short-lived access ticket issued for one account and scoped to specific upstream targets. |
| Proxy | The broker sends the upstream request after checking the lease scope and can replace primary placeholders before forwarding. |
| Audit | A record of authorizations, token issuance/revocation, denials, proxy requests, and refreshes. |
Without a broker, AI tools often get raw API keys through environment variables or copied secrets. That is convenient, but fragile.
Passka keeps the safer parts local:
- You add a credential through the macOS app or CLI.
- The secret is stored in macOS Keychain under
passka-broker. - You authorize a local agent to use that account.
- You issue an agent token for that local agent principal.
- The agent uses that token to request a short-lived lease for the account.
- The agent uses the lease through Passka's proxy.
- Passka records what happened in the audit log.
- Long-lived secrets stay in macOS Keychain.
- Broker state lives in
~/.config/passka/broker/state.json. - CLI admin commands add, list, show metadata, authorize, issue/revoke agent tokens, and inspect audit history.
- CLI agent commands (
requestandproxy) go through the local daemon instead of talking to broker state directly. - There is no secret reveal surface in the CLI, app, or daemon.
- The default daemon is agent-only: it accepts authenticated agent requests, not general admin traffic.
- Leases are scoped to allowed hosts, methods, and path prefixes. If you do not specify host or path scope explicitly, Passka derives defaults from
account.base_urlwhen possible. - Agents receive leases and proxied results, not raw API keys or refresh tokens.
Passka now has one primary flow:
- Register an account.
- Allow an agent principal to use that account.
- Issue an agent token for that principal.
- Let the agent request a lease and proxy upstream requests with that lease.
Administrative work stays on the CLI. Agent traffic goes through the daemon.
flowchart TD
subgraph Human["Human / Admin"]
H1["1. Add account in app or CLI"]
H2["2. Allow agent principal to use account"]
H3["3. Issue agent token once"]
end
subgraph Passka["Passka Broker"]
P1["Store long-lived secret in macOS Keychain"]
P2["Store account, authorization, and audit state"]
P3["Check token + account authorization"]
P4["Issue short-lived lease"]
P5["Check lease scope (host / method / path)"]
P6["Inject real credential and proxy upstream request"]
P7["Write audit events"]
end
subgraph Agent["AI / Agent"]
A1["4. Call /access/request with agent token + account_id"]
A2["5. Receive lease_id"]
A3["6. Call /http/proxy with lease_id"]
A4["7. Receive proxied response"]
end
H1 --> P1
H1 --> P2
H2 --> P2
H3 --> P2
A1 --> P3
P3 --> P4
P4 --> A2
A2 --> A3
A3 --> P5
P5 --> P6
P6 --> A4
P3 --> P7
P6 --> P7
GitHub Releases publish architecture-specific macOS artifacts for both the CLI and the desktop app:
passka-cli-<version>-macos-x86_64.tar.gzpasska-cli-<version>-macos-arm64.tar.gzPasska-<version>-macos-x86_64.zipPasska-<version>-macos-arm64.zip
Choose the archive that matches your Mac.
Install the CLI:
tar -xzf passka-cli-<version>-macos-<arch>.tar.gz
mkdir -p "$HOME/.local/bin"
mv passka "$HOME/.local/bin/passka"
chmod +x "$HOME/.local/bin/passka"If ~/.local/bin is not already on your PATH, add this line to ~/.zshrc:
export PATH="$HOME/.local/bin:$PATH"Install the macOS app:
- Unzip
Passka-<version>-macos-<arch>.zip - Drag
Passka.appinto/Applications - Right-click
Passka.appand chooseOpenthe first time if macOS warns that the app is unsigned
Release artifacts are currently unsigned and not notarized, so the first launch needs an explicit Open confirmation.
Assume the default agent principal principal:local-agent.
- Start the daemon
cargo run -p passka-cli -- broker servePasska tries 127.0.0.1:8478 first. If that port is already busy, it automatically falls back to a free local port and prints the actual broker URL.
CLI agent commands auto-discover the last started daemon. If you need to override that, pass --broker-url <url> or set PASSKA_BROKER_URL.
- Register one account, allow that agent, and issue one agent token
cargo run -p passka-cli -- account add openai-prod \
--provider openai \
--auth api_key \
--base-url https://api.openai.com
cargo run -p passka-cli -- account allow <account_id> \
--agent principal:local-agent \
--allow-host api.openai.com \
--allow-method GET,POST \
--allow-path-prefix /v1 \
--lease-seconds 300
cargo run -p passka-cli -- principal token issue principal:local-agentThe token command prints JSON containing agent_token. Passka only returns the plaintext token at issuance time.
- Request a lease, then proxy through Passka
cargo run -p passka-cli -- request \
--account <account_id> \
--agent-token <agent_token>
cargo run -p passka-cli -- proxy \
--lease <lease_id> \
--agent-token <agent_token> \
--method GET \
--path https://api.openai.com/v1/modelsPasska stores several credential shapes under the same account model:
api_key: API key plus auth header metadataoauth: authorize locally, refresh locally, proxy without exposing refresh tokensotp: store a TOTP seed locallyopaque: arbitrary key-value secret bundles
These are storage types, not separate product concepts.
The agent sends the upstream request to Passka, and Passka injects the real credential locally.
Direct proxy request:
curl -s <broker_url>/http/proxy \
-H 'authorization: Bearer <agent_token>' \
-H 'content-type: application/json' \
-d '{
"lease_id": "<lease_id>",
"request": {
"method": "GET",
"path": "https://api.openai.com/v1/models"
}
}'Forward proxy request:
curl -x <broker_url> \
--proxy-header "X-Passka-Agent-Token: <agent_token>" \
--proxy-header "X-Passka-Lease: <lease_id>" \
https://api.openai.com/v1/modelsPasska can replace placeholders in forwarded headers and UTF-8 text bodies before sending the upstream request.
PASSKA_API_KEYfor API key accountsPASSKA_TOKENfor OAuth accounts
This replacement uses only the primary proxied account for the lease. It does not reintroduce multi-lease alias expansion.
Minimal example:
curl -s <broker_url>/http/proxy \
-H 'authorization: Bearer <agent_token>' \
-H 'content-type: application/json' \
-d '{
"lease_id": "<lease_id>",
"request": {
"method": "POST",
"path": "https://api.openai.com/v1/responses",
"headers": {
"x-debug-key": "PASSKA_API_KEY"
},
"body": "{\"api_key\":\"PASSKA_API_KEY\"}"
}
}'Passka now snapshots target constraints into each lease.
- Configure scope at authorization time with
account allow. --allow-hostaccepts hostnames orhost:portvalues.--allow-methodaccepts a comma-separated list such asGET,POST.--allow-path-prefixaccepts one or more path prefixes such as/v1/models.- If
--allow-hostis omitted and the account has abase_url, Passka derives the default host scope from thatbase_url. - If
--allow-path-prefixis omitted and the accountbase_urlcontains a path prefix such ashttps://api.example.com/v1, Passka derives/v1as the default path scope. - If neither explicit host scope nor
base_urlis available, the lease can still be issued, but proxy use will be denied because there is no target host boundary to enforce.
The macOS app is the human-facing credential manager:
- Browse stored credential accounts
- Add API key, OAuth, OTP, and opaque accounts
- Register agent principals
- Inspect recent audit activity for an account
Build it with:
cd app && swift buildThe local daemon exposed by passka broker serve is now the default agent plane for agents and MCP bridges.
GET /health
POST /access/request
POST /http/proxy
Notes:
- JSON API requests must include
Authorization: Bearer <agent_token>. - Forward proxy requests must include
X-Passka-Agent-Token: <agent_token>. /access/requesttakesaccount_idplus optionalcontext; the daemon derives the principal from the authenticated token.- Proxy execution enforces the scoped lease snapshot on every request.
- Administrative actions such as account registration, authorization, OAuth completion, and audit inspection stay on the CLI/admin side.
passka requestandpasska proxyauto-discover the last started daemon, so they keep working when the daemon moves off127.0.0.1:8478.- For raw HTTP tools such as
curl, use the broker URL printed bypasska broker serve.
Build the Rust workspace:
cargo buildRun the Rust tests:
cargo test --workspaceBuild the macOS app:
cd app && swift buildCreate a GitHub release by pushing a semver tag such as v0.1.0. The release workflow builds macOS Intel and Apple Silicon artifacts, packages the CLI and desktop app, and uploads them to the GitHub Release with a SHA256SUMS.txt file.