@aauth/fetch
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.
Prerequisites
The agent must be bootstrapped before making authorized requests — it needs a signing key and a person server in config. Use @aauth/bootstrap:
npx @aauth/bootstrap create <your-agent-provider-url>
npx @aauth/bootstrap create <your-agent-provider-url> --person-server https://person.example
Quick Start
npx @aauth/fetch https://whoami.aauth.dev
npx @aauth/fetch "https://whoami.aauth.dev?scope=email+profile"
Seeing what each operation needs
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.
Authorize-then-call (recommended for multi-call workflows)
Capture an auth token once, then reuse it for subsequent calls.
npx @aauth/fetch authorize "https://whoami.aauth.dev?scope=email"
npx @aauth/fetch authorize https://notes.aauth.dev/authorize \
--operations listNotes,createNote
npx @aauth/fetch authorize https://googleapis-com.proxy.aauth.dev/authorize \
--operations gmail.users.messages.send,calendar.events.list \
--account dick@example.com
Returns 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
Tokens 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/.
Usage
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) — run
npx @aauth/fetch --help for the authoritative, always-current reference.
For AI Agents
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.
Related Packages
@aauth/bootstrap — set up agent keys and configure a person server (run this first)
@aauth/agent — programmatic agent-side AAuth for use inside applications
License
MIT