1,243 words. Estimated reading time: 6 min.
AI wizard
Auto TL;DR
At a Glance
This long page covers these main areas. The list is generated from the article headings, so it updates with every handbook rebuild.
Developers love the wizard: it's the fastest way to get a deep, correct integration of PostHog, with none of the hallucinations that come from naive agent-based attempts.
For users, it is a one-line CLI command which runs an AI agent that automatically instruments PostHog into their codebases.
npx -y @posthog/wizard@latest
The wizard's architecture
The wizard is a CLI tool that runs locally against developers' projects.
It wraps the Claude Agent SDK to perform the integration, reviewing project code and making edits as needed.
To direct the agent, the wizard uses the PostHog context mill repository as a context provider. The context mill provides the agent with skills packages for great integrations, which include workflow prompts, documentation, and example code to maximize correctness and completeness.
The context mill repo generates a zip file and manifest that determines the structure of the skills packages.
Commands and skills
The wizard's command surface comes from context mill, not hardcoded in the wizard. A skill becomes a command when its config.yaml declares a cli: block with role: command – so wizard audit events is the audit-events skill, promoted to a command. A skill without that block stays reachable only via wizard skill <name>. Same machinery, two surfaces — which is why wizard audit <subcommand> chooses an audit area rather than taking a skill name (the [skill] label in wizard audit --help is an internal positional name, not a prompt for a skill).
Because these entries are read from the published manifest at runtime, adding a subcommand under a command that already exists is a context mill release – no wizard release required. A new audit leaf (e.g. wizard audit feature-flags) is just a skill with cli: { role: command, parentCommand: audit }; the audit parent is already registered in the wizard, so the subcommand resolves from the manifest at runtime.
A brand-new top-level command word is the exception – it also needs a wizard PR. yargs only routes top-level commands that are statically registered in the wizard's bin.ts, so nothing in a context mill release can conjure a new top-level word on its own. To add one you ship both: the skill (with cli: { role: command }) in context mill, and a thin native command in the wizard — a ProgramConfig (usually via createSkillProgram) plus a nativeCommandFactory stub registered in bin.ts, exactly like migrate and revenue-analytics. Ship the context mill PR first so the manifest is published before the wizard tries to resolve the skill.
Worked example — adding
wizard mcp-analytics. This flat top-level command was added across four PRs and is the canonical reference for the pattern: the skill (context-mill#202), the wizard command stub (wizard#731), the test fixtures (wizard-workbench#2158), and the docs/wizardSupportlabel (posthog.com#17939). Copy that shape rather than inferring from thecli:schema alone.
Cover both test layers when you add a command:
- Unit (wizard repo) — a per-command test in
programs-cli.test.tsasserting the command registers in the expected shape (flat vs. family) and dispatches the rightskillId. Fast, runs in the wizard's CI. - End-to-end (workbench) — a PostHog-less fixture app under
apps/<command>/plus an entry inapps/manifest.json, so the workbench can drive the real agent run viaphrocs. Add a fixture per distinct path the skill handles (mcp-analytics ships one for the SDK-wrap path and one for the custom-dispatcher path).
The full cli: block schema (roles, parentCommand, the default leaf, naming rules) lives in context mill's CONTRIBUTING.md; the wizard side (command registration, families, aliases) is documented in the wizard repo's AGENTS.md. The command surface is curated, not inclusive — new role: command promotions want a wizard-maintainer sign-off, since a public command name is hard to deprecate.
Developing the wizard
Use the wizard workbench for local, end-to-end development of the wizard. The workbench can run the full wizard stack in local development mode, with hot reload where supported.
The workbench is also responsible for CI and testing the wizard across a matrix of test applications.
<ProductScreenshot imageLight="https://res.cloudinary.com/dmukukwp6/image/upload/q_auto,f_auto/wizard_workbench_flow_38a895e0bb.png" alt="Wizard workbench" />
Setting up the workbench
Clone these repos:
- https://github.com/PostHog/wizard-workbench
- https://github.com/PostHog/context-mill
- https://github.com/PostHog/wizard
- https://github.com/PostHog/posthog (contains the MCP server)
Next, configure the workbench to run the wizard and its local dependencies. Read the README.md file in the wizard-workbench repository to get started and create a .env file with the paths to the dependent repos.
Open a terminal at the workbench root and run:
phrocs
Using the MCP inspector
You'll want the link that looks like this from the mcp-inspector phrocs panel:
http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=97e0ba...
Access the link in your browser, set the transport type to Streamable HTTP, and set the URL to http://localhost:8787/mcp for local development. (Alternatively, you can also inspect the production MCP by setting the URL to https://mcp.posthog.com/mcp).
<ProductScreenshot imageLight="https://res.cloudinary.com/dmukukwp6/image/upload/q_auto,f_auto/mcp_inspector_auth_c3f67d4db9.png" alt="MCP inspector" />
You'll need a PostHog API key to access the MCP server. Get one from the user API keys settings page. Open the Authentication tab and paste the key into the Bearer token field.
Hit connect and you'll see the MCP server's contents.
Handling wizard drama
First, identify cause of failure: run npx -y @posthog/wizard@latest. You can find target projects known to work in the wizard-workbench repository.
Review the logs at /tmp/posthog-wizard.log. This log can be quite verbose, so agent-driven analysis may be helpful to quickly pinpoint where things are going wrong. Include the below details to help the agent diagnose the issue.
Potential points of upstream failure:
- Without OAuth from PostHog, the wizard cannot access the AI gateway. This will prevent all wizard runs. But if OAuth is not possible, we've probably got bigger problems than just the wizard itself.
- If GitHub's release artifacts are not available, the wizard will be guessing blindly at how to integrate PostHog, producing incorrect and incomplete integrations.
- If wizard's agent harness cannot connect to the AI gateway, the wizard run will fail.
- If Anthropic's API is down, the wizard run will fail.
The wizard has the above upstream dependencies. It is also a bundle of client code, subject to various bugs and distribution mishaps. If upstream services are healthy but the wizard is still failing, it's likely a bug in the wizard itself.
Find a previous release version number and run npx @posthog/wizard@<version> against your example project. If the wizard runs successfully, you can compare the logs to the current release to see what changed. This will also confirm a safe rollback path.
To roll back, submit a PR that reverts the bad commits. The PR title must use a conventional commit prefix (e.g. revert: rollback to pre-X.Y.Z). Once merged, release-please will auto-create a release PR with the version bump. Merge that release PR, and the publish workflow will publish the reverted code to npm.
Remember to do a quick sanity check after release with npm @posthog/wizard@latest to see if your fix actually worked.
Declare an incident
If an upstream dependent PostHog service like OAuth or the AI gateway is down, an incident may already in progress. Check the #incidents channel for any related alerts. If not, declare an incident, describing the highest-level issue that's causing the wizard to fail.
If the wizard client code itself is failing, that's an incident as well.