Skip to content

Research what a PostHog Wizard run needs to migrate a codebase from Resend #529

Closed

Description

@Silthus

Question

What does a PostHog Wizard run need so a team migrates a codebase from Resend to PostHog in one go?

Michael (2026-10-20): extend the Wizard with an easy run that moves a codebase from Resend to PostHog. Other email services may follow later; target Resend only for now. This is part of the full attack on Resend (map decision "Full attack on Resend").

Answer with links and file:line evidence:

  1. The Wizard today. The @posthog/wizard CLI (npx @posthog/wizard, repo PostHog/wizard; confirm the repo and entry point). How does it pick a flow (framework detection, flags, subcommands)? Which agent runs, and where do its prompts and skills come from (context-mill, ~/dev/context-mill)? How does it log in, create keys and write env files? How does it edit code and end the run (local diff, PR)? What events does it capture about a run?
  2. Flows beyond install. Does it run anything other than "install PostHog" today: other products (error tracking, LLM analytics, flags), MCP setup, migrations from another tool? What is the smallest change that adds a new flow, and who owns the repo?
  3. A Resend run, step by step. Detect resend and @react-email/*; list the send call sites; rewrite them to posthog.emails.send (posthog-node draft feat(node): send transactional email with the flat SDK contract PostHog/posthog-js#5312, gaps in the #522 report); move React Email templates (the render path is open in prototype #528); set up the sending domain (can the Wizard drive sender verification through the MCP tools of #466, and how does the email domain setup wizard on the fork, feat(workflows): add a read-only email domain status endpoint #324 to feat(workflows): open the email domain wizard from setup entry points #341, fit in?); keys per environment (#524); Resend webhooks and features with no PostHog equivalent yet. For each step: can the Wizard do it alone, or must it hand it to the person?
  4. One skill or two. How does this run relate to the context-mill skill send-transactional-email (feat(skills): add send-transactional-email skill PostHog/context-mill#433) and to the Resend migration skill Michael asked for? Can one context-mill skill serve the Wizard, coding agents and the MCP learn catalog?
  5. Proof. How would we prove a migration run end to end on a sample Resend app, and what does the run report to the person at the end?

Write the report on branch research/wizard-resend-migration. Resolve this ticket with the recommended shape of the run, the smallest first PR in each repo it touches, and what it waits on from grilling #525 and prototype #528.

How to work this ticket

  • Map: Map: send code-managed email templates with one PostHog call #461 (map tracker Silthus/posthog, pass -R Silthus/posthog to gh issue). Code repo: PostHog/posthog; this checkout's origin is the public fork Silthus/posthog, upstream is PostHog/posthog. Read PostHog/posthog master as upstream/master (fetch it first); the fork's origin/master is stale.
  • Claim the ticket first (assign yourself, comment the claim), per the wayfinder skill. Resolve it with the research skill. When the Skill tool refuses a prescribed skill, read its SKILL.md (under ~/.claude/skills/ or ~/.agents/skills/) and follow it directly.
  • Public repo: the fork, its issues, branches and commits are public. Never write usage or revenue numbers, customer names or data, internal metrics, Slack quotes, or security-sensitive reasoning there.
  • Read-only for product code: change nothing outside your report. Commit the report on the named research branch and push it to origin before you resolve or park.
  • Casting: you are the cast for this ticket. Any nested worker follows the user's model selection policy: Survey work on Sonnet 5.5 high, Deep research on GPT-6.1 Sol high; name model and effort on every dispatch.
  • Wall-time cap: 60 minutes. Before you go idle, leave a durable report: the resolution comment and closed ticket, or one park comment with the exact question for Michael and the wayfinder:awaiting-human label.
  • Leave nothing running: run every wait in the foreground; end with no background command, watcher, monitor, subagent, or child task live.
  • Run heavy jobs (broad test suites, typechecks, builds) through ~/dev/fleet/fleet heavy -- <command>. This ticket should need none.

Activity

  1. Silthus commented on Oct 20, 2026

    @Silthus
    OwnerAuthor

    Dispatched as a T3 child task of the conductor thread: Sonnet 5.5, high, worktree isolation, 60-minute cap.

  2. self-assigned this
    on Oct 20, 2026
  3. Silthus commented on Oct 20, 2026

    @Silthus
    OwnerAuthor

    Claimed by the research sub-agent (Sonnet 5.5). Report goes on branch research/wizard-resend-migration.

  4. Silthus commented on Oct 20, 2026

    @Silthus
    OwnerAuthor

    Resolution

    Report: research/wizard-resend-migration.md on branch research/wizard-resend-migration (commit c82bd7874d5). No PR, per the map's research convention.

    1. The Wizard today. PostHog/wizard (@posthog/wizard, 2.85.0), commands in src/cli/, agent runs as "programs" in src/programs/. A run downloads a context-mill skill from the latest release, runs an agent (Pi harness through PostHog's LLM gateway) with the PostHog MCP and in-process wizard-tools, and ends with an outro and a Markdown report. It never commits or opens a PR. Login is OAuth; the secret-prompt tool (wizard_ask sensitive, then set_env_values) keeps a typed key out of the agent's context.
    2. Flows beyond install. 16 programs, including audits, error tracking, flags, a generic wizard skill <id>, and wizard migrate (Statsig only, flat, analytics-shaped). Its own comment and context-mill's convention say to turn it into a family when the second vendor arrives. Resend is that vendor. A new skill alone adds a flow with no Wizard release; wizard migrate resend needs one release to make migrate a family. Default owner team-wizard-docs; migration code and skill team-fde.
    3. The run. Detect, inventory, classify, rewrite, templates, client setup, report: the agent alone. Sender creation and verify through MCP tools: the agent, but publishing DNS is the person's. The phs_ key: the person (the Wizard has no project:write; paste through the secret prompt). Webhooks and features with no equivalent (attachments, batch, cc/bcc, scheduling, outbound delivery webhooks): report rows, source left on Resend. The fork's UI domain wizard is the fallback the report links to, not something the Wizard drives. Step table with who does what is in the report.
    4. One skill or two. Two skills, one body of reference text. send-transactional-email (context-mill#433) keeps "how a PostHog send works"; a new migrate-email group with a resend variant owns "how to leave Resend" and links to the send skill's reference instead of copying it. One skill can serve the Wizard, coding agents and MCP learn if the procedure is plain text and the Wizard conventions sit in one optional section. The production learn catalog carries no context-mill skill yet.
    5. Proof and report. Three workbench fixtures (happy, hard, no Resend), a run against the local stack, judged on the working-tree diff, then the migrated app sending into the dev mail catcher. The closing report lists migrated sites, sites left on Resend with reasons, templates, sender and DNS state, keys per place RESEND_API_KEY appears, webhooks, and ordered next steps.

    Recommended shape: npx @posthog/wizard migrate resend, a skill-driven run on the generic skill program, two person hand-offs by design (DNS, phs_ key), destructive steps gated, no commit.

    Smallest first PRs

    • PostHog/context-mill: the migrate-email skill with a resend variant, role: skill, runnable today as wizard skill <id>. Covers detect, inventory, classify, rewrite of file/stored-template sites, report.
    • PostHog/wizard: turn wizard migrate into a family, add the run's OAuth scopes per family, release note for the breaking change.
    • PostHog/posthog: no code PR. Ops step: the Wizard OAuth app's scope ceiling must include the scopes the run needs, or the run falls back to the UI.
    • PostHog/posthog-js: none; waits on the Think through the Elements tab PostHog/posthog#5312 release.

    Waits on

    • Grilling #525: inline content on the send (decides whether html:/react: sites are one-line rewrites or template conversions), from, sender-scoped keys, idempotency, replyTo, array to.
    • Prototype #528: which React Email path ships. Its read (inline content plus an optional template key) is what the skill would target.

    For Michael

    • Family (breaks wizard migrate for Statsig scripts) or wizard skill only until the run proves itself?
    • New migrate-email group or a resend variant of migrate? I recommend the new group, which leaves the Statsig chain alone.

    Not verified: no Wizard code was run and context-mill was not built; the OAuth scope that gates the template-upload tool; Resend's exact DNS record names; the replacement for Resend delivery webhooks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions