Local credential gateway for agents and automations.
Usher lets tools call remote APIs without carrying API credentials themselves. It stores OAuth2 refresh tokens and bearer tokens locally, restricts who may call it, resolves the right credential from the target URL, and forwards approved requests through a single /call endpoint.
Agents get the API response they asked for. Credentials stay where they belong: outside prompts, logs, scripts, and model context.
Modern agents are excellent at deciding what to call next. They are much less ideal places to keep long-lived secrets.
Without a broker, credentials tend to leak into places that are hard to audit: shell history, environment dumps, prompt traces, generated code, tool logs, and copied examples. Usher creates a narrow boundary between an agent and the services it needs. The agent asks Usher to call a URL. Usher decides whether the caller is allowed, finds exactly one matching credential, applies authorization, and returns the upstream response.
Usher is headless, self-hosted, and intentionally small. It does not try to understand every provider API. It gives you a secure local path for authenticated HTTP.
- Install and run the
usherdaemon locally. - Configure credentials through the interactive CLI.
- Give each credential an allowed origin and path prefix.
- Send HTTP requests to
/call?url=<remote-url>. - Usher matches the target URL, injects the credential, proxies the request, and returns the upstream response.
Credential IDs are for administration. API callers do not pass credential IDs to /call; the target URL determines which credential is used.
Usher is published as @akoenig/usher and exposes the usher binary.
Paste this prompt into your AI agent to install Usher:
Install Usher locally for me.
Before installing anything, check whether Node.js is available by running `node --version`. If Node.js is missing, stop and tell me to install the current LTS release from https://nodejs.org/ before continuing.
Prefer `pnpm` for the installation. If `pnpm --version` works, use `pnpm add --global @akoenig/usher`. If pnpm is missing but Corepack is available, run `corepack enable`, then try `pnpm --version` again and use pnpm. If pnpm still is not available, use an npm-compatible global install command that is available on this machine, such as `npm install --global @akoenig/usher`.
After installation, verify the binary by running `usher --help` and report the installed command path if the shell can resolve it.
Install Usher directly with pnpm:
pnpm add --global @akoenig/usherAny npm-compatible package manager can install the package globally. The examples in this README use pnpm.
Create Usher's local configuration file:
usher initThe init command writes ~/.config/usher/config.json with 0600 permissions and an inline generated encryption key. It refuses to overwrite an existing non-empty config file.
port is optional and defaults to 3000.
The config file contains the encryption key and must be owned by the process user with 0400 or 0600 permissions. Generate the key once and keep it with the database. Stored credential secrets are encrypted with this key; replacing or deleting it makes existing encrypted credential material unreadable.
Environment variables are optional overrides, not required setup. Available overrides are USHER_DATABASE_PATH, USHER_ENCRYPTION_KEY, USHER_BASE_URL, USHER_ALLOWED_CALLER_IPS, and USHER_PORT. USHER_ALLOWED_CALLER_IPS is comma-separated when set as an environment variable, for example 127.0.0.1,::1.
Start Usher in the foreground:
usher daemon startusher daemon is also valid and starts the same daemon flow.
On Linux systems with user-level systemd, install and start Usher as a durable user service:
usher daemon installThe install command writes a user service named usher.service, reloads the user systemd daemon, enables lingering for the current user, and starts the service.
Credential administration is intentionally local. Start the daemon first, then use the usher credentials commands from the same machine.
Create a bearer token credential interactively:
usher credentials create-bearer-tokenCreate an OAuth2 credential interactively:
usher credentials create-oauth2The create commands prompt for the credential label, allowed request matcher, and secret material. Secrets are collected interactively instead of being passed as normal command-line arguments.
Inspect and manage credentials:
usher credentials list
usher credentials get cred_0123456789abcdef
usher credentials delete cred_0123456789abcdefBearer tokens are the fastest path to a working credential.
Run:
usher credentials create-bearer-tokenWhen prompted, provide:
- A human-readable label, such as
Internal API. - The allowed origin, such as
https://api.example.com. - The allowed path prefix, such as
/v1/. - The bearer token.
After creation, Usher can apply that token to matching /call requests.
Run:
usher credentials create-oauth2The CLI prompts for provider details, client credentials, scopes, and the allowed request matcher. For OAuth2 credentials, Usher returns a login URL. Open that URL in a browser to complete authorization before using the credential for /call.
When using the Google OAuth2 preset, choose the API host and path prefix that match the API you want to call:
Calendar: allowed origin https://www.googleapis.com, path prefix /calendar/
Drive: allowed origin https://www.googleapis.com, path prefix /drive/
Gmail: allowed origin https://gmail.googleapis.com, path prefix /gmail/
OAuth refresh tokens are stored encrypted. Access tokens are obtained as needed and are not exposed through CLI output.
Send approved requests through /call with the remote URL encoded in the url query parameter:
curl -sS 'http://localhost:3000/call?url=https%3A%2F%2Fapi.example.com%2Fv1%2Fresource'Usher resolves the target URL to one credential, applies authorization, forwards the request, and returns the upstream response. A credential with origin https://api.example.com and path prefix /v1/ can authorize calls under that path.
Usher forwards the HTTP method, body, and non-reserved headers, then returns the upstream status, headers, and body as directly as possible.
Example POST request:
curl -sS \
-X POST \
-H 'content-type: application/json' \
--data '{"name":"Ada"}' \
'http://localhost:3000/call?url=https%3A%2F%2Fapi.example.com%2Fv1%2Fusers'Usher records audit events for local inspection. Read the latest 10 events:
usher eventsRequest a larger tail or follow new events as they arrive:
usher events -n 50
usher events -f
usher events -n 50 -fEach line starts with the event name, such as OutboundCallCompleted, followed by the request outcome and metadata.
Usher is designed to make the secure path the simple path.
- Credential administration is local to the daemon.
- Admin credential endpoints are local administration paths.
/callis restricted byallowedCallerIpsfrom the config file orUSHER_ALLOWED_CALLER_IPS.- Stored credential secrets are encrypted with the configured key.
- Credential secrets are redacted from list, get, and create output.
- Overlapping allowed request matchers are rejected so a target URL resolves to at most one credential.
- Callers do not need to know credential IDs to call remote APIs.
Common CLI commands:
usher init
usher daemon start
usher daemon install
usher credentials create-bearer-token
usher credentials create-oauth2
usher credentials list
usher credentials get cred_0123456789abcdef
usher credentials delete cred_0123456789abcdef
usher events
usher events -n 50 -fEndpoint quick reference:
GET /credentials
POST /credentials
GET /credentials/{credentialId}
DELETE /credentials/{credentialId}
GET /credentials/{credentialId}/oauth2/login
GET /oauth2/callback
GET /events
<any> /call?url=<absolute-https-target-url>Configuration file:
~/.config/usher/config.json
Required JSON fields:
databasePath
encryptionKey
baseUrl
allowedCallerIps
Optional JSON fields:
port=3000
Example:
{
"databasePath": "/home/alice/.config/usher/usher.sqlite",
"encryptionKey": "base64url:<32-byte random key encoded as base64url>",
"baseUrl": "http://localhost:3000",
"allowedCallerIps": ["127.0.0.1", "::1"],
"port": 3000
}Replace /home/alice with your home directory.
Optional environment overrides:
USHER_DATABASE_PATH
USHER_ENCRYPTION_KEY
USHER_BASE_URL
USHER_ALLOWED_CALLER_IPS
USHER_PORT
Install dependencies from a source checkout:
vp installRun the daemon from source:
vp run dev daemonBuild and run the compiled daemon:
vp run build
node dist/Main.mjs daemon start