Amplitude Wizard — Agent Setup
You are driving @amplitude/wizard (the npm CLI) to set up Amplitude analytics
in the user's codebase. Follow this protocol exactly. The wizard's NDJSON
contract emits structured events on stdout — your job is to read them, surface
the user-relevant ones, and stop for explicit user confirmation before any
file or Amplitude project is modified.
Protocol — non-negotiables
- Never run
npx @amplitude/wizard(the bare interactive entrypoint). It assumes a TTY and a human at the keyboard. Always use the subcommands below. - Never run
applyin the background. Run it in the foreground so its NDJSON streams through your tool output in real time. Backgrounding it forces you to poll a tail file withsleep && tail, which adds minutes of latency between each progress update. - NEVER spawn a second
applywhile one is already running. If a previousapplyinvocation is still streaming events on stdout, do NOT start another. Each apply spawns an inner Claude SDK agent that writes files; two of them stomp each other's edits and produce contradictorysetup_completepayloads. Wait for the current run'srun_completedevent before any retry. - Always pass
--confirm-appwhen runningplanorapply. This forces the wizard to ask which Amplitude app to write into instead of silently picking the first one it finds. - Always pass
--install-dir <abs-path>and confirm it's a real project. If the user invokes the wizard from their home directory, a multi-project parent (~/dev/,~/code/, etc.), or any directory without a clear project marker (package.json,pyproject.toml,Cargo.toml,go.mod,Gemfile,pom.xml,build.gradle), STOP and ask the user which project to set up. Do not guess. - Never auto-approve the event plan. When you see
type: needs_inputwithcode: event_plan, STOP. Show the proposed events to the user. Re-invokeapplywith--approve-events,--skip-events, or--revise-events "<feedback>"based on their answer. - Always render
type: diagnosticevents as user-visible status. Transient retries should look like⚠ retrying (2/6)..., not silent gaps. - After
setup_complete, lock your project context toamplitude.appId. Use only that app id for follow-up Amplitude MCP queries (charts, dashboards, events). Do not reuse any project context cached earlier in the session. - Wizard-managed artifacts are owned by the wizard. Do NOT use
Write/Editon.amplitude/events.json,.amplitude/dashboard.json,.amplitude-events.json, or.amplitude-dashboard.json. The wizard'sconfirm_event_planMCP tool persists the events file in the canonical shape; the dashboard watcher mirrors the dashboard JSON. Direct writes are denied by the inner-agent permission hook with a clear error message — if you see that deny, switch to the MCP tool.
Step 1 — preflight (cheap, no writes)
Run all three in parallel; they're fast and read-only:
npx @amplitude/wizard whoami --json
npx @amplitude/wizard detect --json
npx @amplitude/wizard status --json
Tell the user, in one sentence, what you found:
Auth:
<email>(Org:<orgName>, Region:<region>) Framework:<frameworkName>detected at<install-dir>
If whoami.loggedIn === false: stop and ask the user to run
npx @amplitude/wizard login in their terminal (browser OAuth — agents
cannot drive it). After they confirm "logged in", re-run whoami --json to
verify.
Step 2 — plan (no writes; read-only)
npx @amplitude/wizard plan --confirm-app --json --install-dir <abs-path>
The output stream contains, in order:
type: lifecycle, data.event: setup_context, phase: plan— the resolved Amplitude scope (region, org, project). Show this to the user.type: plan, data.event: plan— theplanId, framework, SDK package, and proposed events.
Render the proposed events as a short bulleted list with one line each. Ask the user:
"I'll instrument these N events. Approve, revise, or skip? Reply 'approve', 'revise: ', or 'skip'."
Capture the planId — you need it for apply.
Step 3 — apply (foreground, NDJSON streamed)
Pick exactly one of these based on the user's reply:
npx @amplitude/wizard apply --plan-id <planId> --confirm-app --approve-events --yes --json
npx @amplitude/wizard apply --plan-id <planId> --confirm-app --skip-events --yes --json
npx @amplitude/wizard apply --plan-id <planId> --confirm-app --revise-events "<feedback>" --yes --json
Do NOT background this. Stream the NDJSON live and surface events to the user as they arrive. Translate each event type into one short status line:
| Event | Render |
|---|---|
lifecycle / setup_context (apply_started) |
"Setting up app <orgName> / <appName>..." |
lifecycle / inner_agent_started |
"Agent online." |
progress / tool_call |
(Skip — too noisy. Show only in verbose.) |
progress / file_change_planned |
"✏️ Planning change: <path>" |
result / file_change_applied |
"✓ Wrote <path>" |
status / spinner / kind: heartbeat |
(Skip; render the latest status line only.) |
diagnostic / kind: retry |
"⚠ Retrying (<attempt>/<max>)..." |
diagnostic / kind: retry_cleared |
"✓ Recovered." |
result / event_plan (decision: …) |
"✓ Event plan: <decision>" |
result / dashboard_created |
"✓ Dashboard: <dashboardUrl>" |
needs_input / code: app_selection |
STOP — see "Handling needs_input" below. |
needs_input / code: event_plan |
STOP — see "Handling needs_input" below. |
Step 4 — capture setup_complete
When you see type: result, data.event: setup_complete, this is the
authoritative artifact list. Pin these values for the rest of the session:
amplitude.appId— the ONLY project handle to use for follow-up Amplitude MCP queries. Disregard any earlier project context.amplitude.dashboardUrl— show this as a clickable link to the user.files.written / files.modified— summarize so the user knows what changed.events— final approved list of analytics events the wizard wired up.
The wizard also persists this scope to ampli.json in the install dir
(AppId, OrgId, ProjectId, EnvName, DashboardUrl, DashboardId) so
future agent sessions can recover it without re-running setup.
After setup_complete, you should see exactly one
type: lifecycle, data.event: run_completed with outcome: success and
exitCode: 0. Absence of run_completed before stream EOF means the wizard
crashed — surface a generic failure and ask the user to share
~/.amplitude/wizard/runs/<run_id>/log.txt.
Handling needs_input
When type: needs_input arrives, the wizard has exited with code 12
(INPUT_REQUIRED) and is waiting for you to re-invoke. Do NOT pick the
recommended value silently. Show the user the question + choices, get an
answer, then re-invoke apply with the appropriate resumeFlags from the
event payload (or compose them yourself):
| code | Re-invoke flags |
|---|---|
event_plan |
--approve-events / --skip-events / --revise-events "<text>" |
environment_selection |
--app-id <id> (use the appId field from the chosen choices[] entry) |
app_selection |
--app-id <id> |
confirm |
re-run with --yes (writes) or --auto-approve (no writes), per the choice |
| destructive overwrite | --force (only after the user confirms they're OK overwriting) |
For any other code you don't recognize, surface the message and choices
verbatim and let the user pick. Each choice carries resumeFlags for its
own re-invocation — use those rather than composing your own.
Recovery
| Exit code | Meaning | Action |
|---|---|---|
0 |
Success | Use setup_complete payload. |
3 |
AUTH_REQUIRED |
Tell the user to run npx @amplitude/wizard login. Re-run whoami --json to confirm before retry. |
12 |
INPUT_REQUIRED |
Surface the last needs_input. Re-invoke with resumeFlags. |
13 |
WRITE_REFUSED |
Confirm with the user, then re-invoke with --yes (or --force for overwriting existing files). |
| anything else | failure | Show the last error event's message. Don't retry blindly. |
What to NEVER do
- Do not background
apply. Run it in foreground so events stream live. - Do not spawn a second
applywhile one is running. Wait forrun_completed. - Do not auto-pick an Amplitude app, even when there's only one match. Always
pass
--confirm-appand surface thesetup_contextto the user. - Do not silently approve the event plan. The user's analytics taxonomy is their decision, not yours.
- Do not assume an existing project context. After
setup_complete, the authoritativeappIdis the one in that event — replace any earlier value. - Do not log raw NDJSON lines to the user. Translate each event into a one-line status using the table above.
- Do not run the wizard from the user's home directory or a multi-project
parent dir without explicit
--install-dir. Confirm the project first. - Do not
WriteorEdit.amplitude/events.json,.amplitude/dashboard.json,.amplitude-events.json, or.amplitude-dashboard.json. They are owned by the wizard's MCP tools.
Starting fresh — wizard reset
If a previous wizard run left artifacts that no longer match the user's intent (stale event plan, wrong dashboard, instrumented for the wrong Amplitude app), run:
npx @amplitude/wizard reset --install-dir <abs-path> --json
This deletes .amplitude/, the legacy .amplitude-*.json dotfiles, and
amplitude-setup-report.md from the project, and strips auth-scoped
fields (OrgId, AppId, AppName, EnvName, DashboardUrl,
DashboardId) from ampli.json. It does NOT log the user out and does
NOT remove any track() calls already wired into source code — the
user has to revert those manually if they want a true blank slate
(git checkout is the safe path; wizard reset won't touch your code).
When to suggest reset:
- Previous run targeted the wrong Amplitude app.
- User wants to switch from one Amplitude org to another.
- The proposed event plan no longer fits the codebase (UI changed, new flows added).
When NOT to suggest reset:
- The wizard is mid-run. Wait for
run_completed. - The user just wants to add more events. Re-running
plan+applyis enough; the wizard supplements the existing plan rather than replacing it.
Quick reference (full command shape)
# Probe + plan, in parallel
npx @amplitude/wizard whoami --json
npx @amplitude/wizard detect --json --install-dir <dir>
npx @amplitude/wizard plan --confirm-app --json --install-dir <dir>
# Apply (pick exactly one event-plan flag)
npx @amplitude/wizard apply \
--plan-id <id> \
--confirm-app \
--approve-events \
--yes --json \
--install-dir <dir>
# Resumes after needs_input
npx @amplitude/wizard apply --plan-id <id> --app-id <id> --approve-events --yes --json
See references/agent-protocol.md (in this skill) for the full NDJSON event
catalog and references/example-session.jsonl for a worked happy-path
session.