# AI wizard - Handbook

Developers love the [wizard](/docs/ai-engineering/ai-wizard.md): 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.

Terminal

PostHog AI

```bash
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](https://platform.claude.com/docs/en/agent-sdk/overview) to perform the integration, reviewing project code and making edits as needed.

To direct the agent, the wizard uses the PostHog [context mill repository](https://github.com/PostHog/context-mill) 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`](https://github.com/PostHog/wizard/blob/main/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](https://github.com/PostHog/context-mill/pull/202)), the wizard command stub ([wizard#731](https://github.com/PostHog/wizard/pull/731)), the test fixtures ([wizard-workbench#2158](https://github.com/PostHog/wizard-workbench/pull/2158)), and the docs/`wizardSupport` label ([posthog.com#17939](https://github.com/PostHog/posthog.com/pull/17939)). Copy that shape rather than inferring from the `cli:` schema alone.

Cover **both test layers** when you add a command:

-   **Unit (wizard repo)** — a per-command test in [`programs-cli.test.ts`](https://github.com/PostHog/wizard/blob/main/src/__tests__/programs-cli.test.ts) asserting the command registers in the expected shape (flat vs. family) and dispatches the right `skillId`. Fast, runs in the wizard's CI.
-   **End-to-end (workbench)** — a PostHog-less fixture app under [`apps/<command>/`](https://github.com/PostHog/wizard-workbench/tree/main/apps) plus an entry in `apps/manifest.json`, so the workbench can drive the real agent run via `phrocs`. 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](https://github.com/PostHog/context-mill/blob/main/CONTRIBUTING.md); the wizard side (command registration, families, aliases) is documented in the wizard repo's [AGENTS.md](https://github.com/PostHog/wizard/blob/main/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](https://github.com/PostHog/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.

![Wizard workbench](https://res.cloudinary.com/dmukukwp6/image/upload/q_auto,f_auto/wizard_workbench_flow_38a895e0bb.png)

## Setting up the workbench

Clone these repos:

-   [https://github.com/PostHog/wizard-workbench](https://github.com/PostHog/wizard-workbench)
-   [https://github.com/PostHog/context-mill](https://github.com/PostHog/context-mill)
-   [https://github.com/PostHog/wizard](https://github.com/PostHog/wizard)
-   [https://github.com/PostHog/posthog](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](https://github.com/PostHog/wizard-workbench/) 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:

Terminal

PostHog AI

```bash
phrocs
```

## Using the MCP inspector

You'll want the link that looks like this from the `mcp-inspector` phrocs panel:

PostHog AI

```
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](https://mcp.posthog.com/mcp)**).

![MCP inspector](https://res.cloudinary.com/dmukukwp6/image/upload/q_auto,f_auto/mcp_inspector_auth_c3f67d4db9.png)

You'll need a PostHog API key to access the MCP server. Get one from the [user API keys settings page](https://app.posthog.com/settings/user-api-keys?preset=mcp_server). 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](https://github.com/PostHog/wizard-workbench/tree/main/apps) 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](https://github.com/PostHog/wizard/releases) 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](https://github.com/PostHog/wizard/pulls) that reverts the bad commits. The PR title must use a [conventional commit](https://www.conventionalcommits.org/) prefix (e.g. `revert: rollback to pre-X.Y.Z`). Once merged, [release-please](https://github.com/PostHog/wizard/blob/main/.github/workflows/release-please.yml) will auto-create a release PR with the version bump. Merge that release PR, and the [publish workflow](https://github.com/PostHog/wizard/blob/main/.github/workflows/publish.yml) 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](/handbook/engineering/operations/incidents.md), 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.

### Community questions

Ask a question

### Was this page useful?

HelpfulCould be better