CLI for making AAuth-authenticated HTTP requests. Handles HTTP Message Signatures, agent tokens, and the full AAuth authorization flow including R3 (Rich Resource Requests).
Part of aauth-dev/packages-js. Protocol spec: dickhardt/AAuth.
The agent must be bootstrapped before making authorized requests — it needs a signing key and a person server in config. Use @aauth/bootstrap:
# Register an agent provider: generate a key, bind it, and bind the default
# person server (person.hello.coop) — all in one command.
npx @aauth/bootstrap create <your-agent-provider-url>
# ...or point at a specific person server
npx @aauth/bootstrap create <your-agent-provider-url> --person-server https://person.example# Call an AAuth-protected API — handles 401 challenges and auth flow automatically
npx @aauth/fetch https://whoami.aauth.dev
# Request specific scopes
npx @aauth/fetch "https://whoami.aauth.dev?scope=email+profile"Fetch a resource's OpenAPI document and fetch reads its operation access
annotations (x-aauth-access-mode / x-aauth-budget, AAuth R3) out of the body,
grouping the operations by the credential each one needs — on stderr, so stdout is
still the raw spec for jq:
$ npx @aauth/fetch https://notes.aauth.dev/openapi.json > openapi.json
Operation access annotations (advisory — the resource may return any AAuth-Requirement at runtime):
agent-token — your agent token alone — no person involved
getHealth GET /health
auth-token — an auth token — costs one authorization round trip
listNotes GET /notes
exportNotes POST /notes/export [budget]
per-call — authorized per invocation — will stop and wait for a person
purchaseReport POST /reports/{id}/purchase [budget]
Annotations are advisory: a resource may return any AAuth-Requirement at runtime
regardless of what it published, so fetch prints them and enforces nothing. When
your agent has no person server, the groups it cannot complete say so.
Capture an auth token once, then reuse it for subsequent calls.
# 1. Authorize and capture tokens (writes JSON to stdout)
npx @aauth/fetch authorize "https://whoami.aauth.dev?scope=email"
# For R3 resources, POST to the authorize endpoint with operations:
npx @aauth/fetch authorize https://notes.aauth.dev/authorize \
--operations listNotes,createNote
# Bind the grant to one of your accounts at the resource:
npx @aauth/fetch authorize https://googleapis-com.proxy.aauth.dev/authorize \
--operations gmail.users.messages.send,calendar.events.list \
--account dick@example.comReturns the auth token and ephemeral signing key. Or capture the credential with
the call using --emit, then export it so later calls reuse it:
OUT=$(npx @aauth/fetch --emit https://notes.aauth.dev/notes)
export AAUTH_AUTH_TOKEN=$(jq -r .auth_token <<<"$OUT")
export AAUTH_SIGNING_KEY=$(jq -c .signingKey <<<"$OUT")
npx @aauth/fetch https://notes.aauth.dev/notes # signs with the saved auth tokenTokens are never written to disk — you decide how to reuse them (export to env,
pipe between commands). Only the public person-server metadata is cached, under
~/.aauth/cache/.
npx @aauth/fetch <resource> [flags] # authenticated fetch (full flow)
npx @aauth/fetch authorize <resource> [flags] # auth flow only; print tokens for reuse
npx @aauth/fetch skill # print the fetch guide (+ site & protocol URLs)
npx @aauth/fetch help # show help (--help also works)
Request:
-X, --method <method> HTTP method (default: GET)
-d, --data <body> Request body
-H, --header <header> Additional header (repeatable)
--json Read full request from stdin as JSON (input only)
AAuth:
--agent-provider <url> Agent provider to sign as (default: from config)
--local <name> Local part of agent identifier (default: from config)
--person-server <url> Override person server URL
--poll-timeout <seconds> Seconds to wait for the person to approve consent
(default: 900 — covers a human consent ceremony
including a chained upstream OAuth)
Modes:
--agent-only Sign with agent token only; don't handle 401
--auth-token <jwt> --signing-key <jwk> Use an existing auth token + signing key (three-party)
--session-token <token> Reuse a session token (two-party, carried in
AAuth-Access; no signing key)
--emit Emit the reusable credential(s) to stdout alongside the body.
Three-party: { auth_token, expires_in, signingKey, response }
Two-party: { session_token, response } (no signingKey)
`response` is the body (same as bare fetch)
Authorize (with the `authorize` command):
--operations <ops> R3 operation ids (comma-separated), as they
appear in the resource's vocabulary
--scope <scope> Requested scopes
--account <account> Upstream account at the resource to bind the
authorization to (e.g. a Google email)
Person server (passed during consent) / consent handling:
--login-hint / --domain-hint / --tenant / --justification
--prompt-login / --prompt-consent (force re-auth / force the consent prompt)
--browser / --non-interactive (consent URL + QR print by default; --browser auto-opens)
Output (response body → stdout; these add detail on stderr, clean for `… | jq`):
--explain Teaching view: per-step request/response with
summaries, descriptions, real RFC 9421 signed
headers, and bodies. Pretty + colorized at a TTY;
compact JSONL when piped/captured.
--explain-log <path> Write the --explain event stream (JSONL) to this
file (default: ~/.aauth/fetch/logs/<timestamp>.jsonl).
--debug, -v, --verbose Raw wire view: every HTTP hop as { request } /
{ response } objects (with bodies); no descriptions.
The CLI's full flag list is generated from one spec (
src/args.ts) — runnpx @aauth/fetch --helpfor the authoritative, always-current reference.
Run npx @aauth/fetch skill to print the agent usage guide (markdown), which also
links to https://www.aauth.dev, the llms.txt index, and the AAuth protocol spec.
@aauth/bootstrap— set up agent keys and configure a person server (run this first)@aauth/agent— programmatic agent-side AAuth for use inside applications
MIT