Skip to main content
The wizard is the fastest way to integrate. It’s an AI agent that implements the whole integration, the “Connect with Agentcard” OAuth flow plus per-user card issuance via the MCP server, directly in your repository, then proves it by issuing a real card in sandbox. You don’t bring a key for the agent: the wizard runs on Agentcard’s own tokens through a hosted gateway.

Run it

npm install -g agent-cards-admin
cd /path/to/your/app
agent-cards-admin wizard
The wizard:
  1. Forces sandbox mode for the run. No real money can move.
  2. Detects your stack (framework, package manager, any existing OAuth or MCP code) and asks for consent before provisioning anything or touching files.
  3. Signs you in if needed (magic link), then provisions your organization and a confidential OAuth client with sandbox credentials. The secrets go straight into your app’s env file (.env.local or .env, chmod 600) and are never shown to the AI.
  4. Makes minimal, idiomatic edits following the Agentcard integration playbook.
  5. Verifies the integration by issuing a sandbox card, then prints a summary of every file it changed.
All edits are left uncommitted. Review the diff and commit; that’s the whole integration.

Options

FlagWhat it does
--path <dir>Target a repo other than the current directory
-y, --yesSkip the consent prompt. Required in agent mode: it is the explicit consent to modify files
--agentForce non-interactive agent mode (usually auto-detected, see below)
--email <email>Email for sign-in when no session exists. Interactive runs prefill the sign-in prompt with it (and offer to switch accounts if you’re signed in as someone else)
--code <code>Agent mode: finish a code sign-in after a code_required exit. Interactive runs prompt for the code directly
--org <id-or-name>Organization to provision under. Agent mode: only needed when your account has several. Interactive runs skip the org picker when it matches
--app-url <url>Your app’s base URL for the OAuth callback (default http://localhost:3000)
--app-name <name>Name for the org (when created) and OAuth client (default: the repo directory name)
--verboseInclude tool inputs and outputs in the stream

Agent mode

The wizard is built to be driven by another AI agent (Claude Code, Cursor, a CI job). In agent mode it never prompts: every input is a flag, progress streams as plain lines, and the run always ends with a single machine-readable result line. Agent mode turns on automatically when any of these is true:
  • --agent is passed
  • AGENT_CARDS_WIZARD_MODE=agent is set
  • CLAUDECODE or CLAUDE_CODE is set (Claude Code exports these)
  • CI is set
  • stdin or stdout is not a TTY
Set AGENT_CARDS_WIZARD_MODE=interactive to force the interactive UI back on (for example, a human piping output through tee). The copy-paste invocation:
npx agent-cards-admin wizard --agent --yes --email you@company.com --app-url http://localhost:3000
Driving the wizard from a coding agent. Runs take 5 to 20 minutes end to end, so use a generous timeout (20+ minutes) or run it in the background. Re-running is safe and resumable: a pending sign-in resumes instead of re-emailing, and every exit-2 result carries a hint naming the missing flag — and, when the value isn’t derivable, what to ask your user (the emailed sign-in code, which organization, the app’s base URL). Resolve it in your own conversation, then re-run with that flag. Add --verbose to stream tool inputs and outputs. If the stream prints a connect link that needs a user tap, open it so the run can continue.

Sign-in

With no existing session, the wizard emails a magic link to --email and polls for up to 15 minutes while someone clicks it (override the window with AGENT_CARDS_WIZARD_LOGIN_TIMEOUT_MS, in milliseconds). Transient backend errors during the wait are retried with backoff instead of failing the run. Re-runs resume a pending sign-in: if a driving agent times out and runs the wizard again, it keeps polling the same session instead of sending a fresh, superseding email. If more than one email did get sent, click the newest one. Backends that use code sign-in can’t be polled; the wizard exits 2 with code_required after emailing you a code. Finish with:
npx agent-cards-admin wizard --agent --yes --email you@company.com --code 123456
An existing session (agent-cards-admin login) or an exported AGENT_CARDS_ADMIN_JWT skips sign-in entirely.

Progress and the result line

While it works, the wizard streams plain progress lines, and during any silent stretch (in every phase, sign-in wait included) it prints a heartbeat so a driver can tell a pause from a hang:
… still working (3:42 elapsed; thinking)
The last stdout line is always machine-readable, on success and on every failure path, even a crash:
AGENTCARD_WIZARD_RESULT {"ok":true,...}
Grep for the AGENTCARD_WIZARD_RESULT prefix; the rest of the line is one JSON object. A success payload (pretty-printed here, the real thing is a single line):
{
  "ok": true,
  "runId": "3f8f9c9e-3f4b-4b7e-9a6d-2b1a7c5d9e10",
  "orgId": "cmcqi8dxr0001la047r8o5ykj",
  "orgName": "acme-shop",
  "clientId": "9b2f6a3e-8c1d-4f5a-b6e7-0d9c8b7a6f5e",
  "redirectUri": "http://localhost:3000/api/agentcard/callback",
  "appBaseUrl": "http://localhost:3000",
  "envFile": ".env.local",
  "connectUrl": "http://localhost:3000/api/agentcard/connect?user=<id>",
  "credentialsReused": false,
  "numTurns": 41,
  "elapsedSeconds": 612
}
The sample shows the fields to build against; the result line can carry additional diagnostic fields — ignore any you don’t recognize. credentialsReused is true when the wizard found valid Agentcard credentials already in your env (from a previous run) and reused them instead of minting new ones. Re-runs are therefore idempotent: they do not pile up orphaned clients, and a multi-org account only needs --org on the first run (the saved credentials pin the org). A warnings array appears when there is something worth flagging, for example ["not_a_git_repo"] (the wizard still runs, you just lose the review-the-diff safety net). Failures look like {"ok":false,"error":"<code>","runId":"…"} plus what a driver needs to recover without scraping the stream. Every exit-2 (missing/bad input) failure carries a message saying what is wrong and a hint saying how to fix it — including what to ask your user when the value can’t be derived (the sign-in code from their inbox, which organization the app belongs to, the app’s base URL). Relay that question, then re-run with the flag the hint names. Org errors additionally carry the orgs list ([{id, name}]) so the user can pick from real options. Exit-1 failures carry a bounded message and, when the cause is recognizable, a probableCause (gateway_disabled, daily_limit_exceeded, gateway_unconfigured, or auth_expired_mid_run). Secrets never appear in the stream or the result line. The OAuth client credentials are written only to your app’s env file.

Exit and error codes

Both modes let the user complete these cases instead of dead-ending — they just do it through different surfaces. The interactive wizard prompts in place: a bad --path asks for the right directory, an over-long app name asks for a shorter one, an unknown --org falls back to the organization picker, an invalid --app-url or --email falls back to the corresponding prompt, and a mistyped sign-in code re-prompts instead of failing the run. In agent mode the same resolution happens through the driving agent: the exit-2 result line carries message + hint (+ orgs on org errors) telling the driver exactly what to ask its user and which flag to re-run with, so the case gets solved in the driver’s own conversation.
ExitMeaning
0Success: the integration ran and verified
1Integration or unexpected error; re-run with the same flags to retry
2Missing input or consent; the result line names the flag to add. Nothing was provisioned
Error codeExitWhat to do
consent_required2Ask the user to approve file modifications, then re-run with --yes
login_required2Ask the user for their account email, then re-run with --email <address> (or export AGENT_CARDS_ADMIN_JWT)
code_required2A sign-in code was emailed; ask the user for the code from the newest email, then re-run with --email <address> --code <code>
invalid_email2Ask the user for their email address and fix the --email value
invalid_path2--path must be an existing, writable directory (checked before any network call); ask the user for the repo path if unknown
invalid_app_url2--app-url must be a URL like http://localhost:3000; ask the user for their app’s base URL
org_ambiguous2The account has several organizations; ask the user which one (the result carries the orgs list), then re-run with --org
org_not_found2--org matched none of the account’s organizations; ask the user to pick from the orgs list in the result
invalid_app_name2--app-name must be 89 characters or fewer
root_unsupported2Run as a non-root user, or inside a container (where the wizard sandboxes itself)
integration_agent_error1The integration agent stopped; the result carries message and, when known, probableCause
unexpected_error1Something else broke; the result carries message

Good to know

  • Re-running is safe. The wizard detects an existing integration and continues or fixes it; it never duplicates the integration.
  • You review everything. Edits happen locally and are left uncommitted; nothing ships until you commit.
  • It ends in sandbox. Production credentials come with an org subscription (agent-cards-admin subscribe) when you’re ready to go live.
  • Telemetry. The CLI reports lifecycle events (run started, phases, completion, with run id, error codes, and durations; never repo contents, paths, or secrets). Opt out with DO_NOT_TRACK=1 or AGENT_CARDS_TELEMETRY=0.
Prefer to wire things up yourself? Head to Manual Implementation.