Last week we integrated WorkOS and PostHog into Oqoqo. Auth setup has always been a trap door. Every time I think I’ve solved it, I end up knee-deep in redirect URI mismatches and CORS errors that take three times longer to debug than the actual integration. And telemetry I always keep pushing to the end of the sprint because let's face it, it's boring, but ends up being rushed the night before release.
This time was different. The WorkOS CLI detected Next.js, confirmed the redirect URI and CORS origin in WorkOS, updated the app homepage URL, then patched the code. It wrote the middleware into middleware.ts exactly where we would have put it, set the env vars, and left us with a clean git diff to review. An hour later PostHog's wizard did something similar for analytics. We looked at two diffs, made one small fix, and merged them both.
What's happening here isn't a CLI improvement and definitely is not "we added AI." Personalized onboarding finally works in B2B software, and it requires a very specific way of thinking about the architecture.
Consumer products have been personalizing everything for a decade - your feed, recommendations, default settings. It's so baked in we don't even call it personalization anymore. In B2B it was always different. You either got a solutions engineer on a Zoom call walking you through setup (if you were paying six figures), or you were on your own. The promise of "we'll meet you where you are" was real if you were an enterprise customer and completely meaningless otherwise.
What's changed is that the solutions engineer now lives in an npx command. It reads your codebase, figures out what framework you're using and which version, writes the integration in the way your project already does things, and does all of it on a self-serve plan in a few minutes. There's a fork in how vendors are approaching this, two different paths that lead to completely different places.
What sounds good but doesn't work: skills as a product
A lot of vendors are basically doing this: we've built structured reference material about our SDK, and we're calling it a skill. The pitch is straightforward. You write the skill once, publish it, and whenever a developer runs an agent locally, that agent can grab the skill and integrate your product correctly. You've turned your docs into something an agent can read. You don't have to build anything. The user does the work of hooking it up.
The problem with this, at least so far, is that the user has to do all the work. Find the skill. Install it in whatever agent they use. Make sure it's loaded for the right project. Tell the agent what they want. Each step in that chain loses people. It's structured exactly like "go read our documentation and follow the tutorial," which fails for the same fundamental reason: you're asking the person who doesn't know your product to figure out what to do.
What's actually starting to shift is that some companies are realizing they need to own the experience instead of making it the user's problem to assemble. Publishing skills is still worth doing - agents with your skill loaded will do better work - but that's reference material with better delivery, not onboarding. Onboarding means the user doesn't have to assemble anything (not you, IKEA).
What actually works: you own the whole runtime
WorkOS and PostHog have both converged on roughly the same architecture. The vendor ships a CLI - @posthog/wizard, workos install - that you run in your project directory. This isn't an “AI installer”, it's a deterministic installer wrapped around an agent. The CLI owns the work that has to be reliable - argument parsing, terminal prompts, framework detection by reading package.json and project files, package manager detection, dashboard provisioning, auth, env writing, safety policy, validation, and retry loops. The agent only runs in the part where static recipes break down: finding the right files, composing with whatever middleware already exists, adapting to the conventions the project already uses. The CLI hands the agent a tight prompt, a constrained tool surface, and the right skills loaded into context. When the agent finishes, the CLI takes over again, runs validations, shows you the diff, and you decide via git diff whether to keep it.
The first thing that matters is what the vendor doesn't rely on. Both installers bundle the Claude Agent SDK as a dependency they control. PostHog pins @anthropic-ai/claude-agent-sdk to an exact version, WorkOS uses a constrained SDK dependency and loads it directly and they run that instead of whatever agent you have installed locally. PostHog's code is explicit about this: use the bundled Claude Code CLI, not the user's installed one. This decision cascades into everything else, and it's as much a support boundary as a technical one. When npx @posthog/wizard or npx workos@latest install fails, the vendor knows exactly what runtime was executing. They can reproduce it. Without that, every failure report is filtered through a stack of variables they can't see.
Your local agent could be any version, logged into any account, configured with various global settings, project overrides, custom MCP servers, custom skills that might conflict. None of that is visible from inside the installer. If the installer depends on your agent, the install behaves differently on everyone's machine for reasons that are basically impossible to debug. By pinning the runtime and shipping it in the npm package, they've converted something wildly variable into something fixed. Once you control the runtime, you can control everything that happens inside it.
Auth and billing follow from this. PostHog routes agent calls through their own gateway by setting ANTHROPIC_BASE_URL and a gateway token, and explicitly clears ANTHROPIC_API_KEY so the user's credentials don't take over mid-run. WorkOS does the same by default but exposes --direct, which switches the run onto the user's own Anthropic key. In gateway mode the install doesn't depend on whatever Claude account the user happens to have, whether they have credits that day, or whether their personal key has the right model access. The vendor controls the model choice and the failure modes that come from it.
Tools work the same way, but the two installers actually diverge in interesting ways here. WorkOS prewrites .env.local before the agent starts, so the agent doesn't need to invent or request env values. PostHog goes the other direction: it blocks direct .env reads and writes at the tool layer and forces all env mutation through its wizard-tools MCP server, which writes them safely.
Around that, the rest of the tool surface is similar. The agent runs with vendor-specific MCP servers attached - PostHog's product MCP plus the in-process wizard-tools server, WorkOS's @workos/mcp-docs-server plus its bundled skills loaded as a local plugin. Bash is allowlisted to package installs, builds, typechecks, lint, format. PostHog scans the agent's tool calls with YARA-style regex rules before letting them execute, and enforces an SDK sandboxed write area. WorkOS uses restricted tool permissions instead. The agent isn't free to do whatever; it's running inside a surface the vendor designed for one specific job.
The skills are the most interesting divergence, and the simple version of this story is "both inject curated skills into the prompt." But that’s not quite right. WorkOS does inject directly: it calls getReference(...) on the @workos/skills package and inserts the markdown straight into the prompt, and also loads the same package as a local plugin available to the Claude runtime. PostHog's default flow is two steps removed from that, it fetches a skill menu from Context Mill releases, the prompt instructs the agent to call load_skill_menu and then install_skill to pull the right one, and the installed SKILL.md lands in project-local .claude/skills/ for the agent to read. Same destination, very different delivery.
There's also a difference in what happens to those skills after the install ends. WorkOS treats the install as a chance to seed your machine: it copies bundled skills into whatever agent directories it detects - ~/.claude/skills, ~/.codex/skills, ~/.cursor/skills etc. so future sessions in any agent on that machine already have them. PostHog stays project-local; the skills land under .claude/skills in the project, and at the end it explicitly asks whether you want to keep them or have them removed.
What matters for the personalization argument is that in both cases the skills aren't something you hope the user pre-installed. They're baked into the installer and they show up in context automatically. Every user gets the right skills whether they know what a skill is or not. You don't need to have an agent already. You don't need to know what an MCP server is. You don't configure anything before you start. You run one command and the entire chain, runtime, auth, tools, skills, prompt, is correct because the vendor controls every link in it.
If you're building a dev tool and you want this to work
Publishing skills matter, but it's not enough on its own. Skills are reference material, and reference material has the same problem docs do. You have to get the user to load them at the right moment, which is the problem you started with.
What's actually working is the whole vertical stack: vendor-built CLI, vendor-bundled agent runtime, vendor-controlled auth and tools, vendor-curated skills automatically loaded, validation built in, git diff as the review layer. You can't really ship half of this and get most of the value. The value isn't in any individual piece, it's that a user runs one command and gets a correctly-configured stack without having to understand any of it exists.
There's a second-order effect worth flagging. Once your install runs through an agent the vendor controls, the install itself becomes instrumented. What they can see is the metadata: which lifecycle events happened, where the agent had to retry, how long runs took, which skills were loaded, which framework versions tripped up the schema, which bash commands the safety policy denied. Onboarding goes from being a one-way handoff to being a telemetry surface for failure modes, the kind of signal B2B companies used to only get when solutions engineers wrote up notes after customer calls.
What this means
For basically twenty years the developer onboarding playbook was: write good docs, make a tutorial video, run a Discord, hire DevRel, and accept that most self-serve users are going to disappear somewhere between your quickstart and their actual project. That gap felt inevitable because there's no document that can branch on every framework, every version, every codebase someone might show up with.
WorkOS and PostHog feel different because they didn't try to bridge that gap but rather they collapsed it. Not by writing better docs but by shipping a system that actually reads your project and writes the integration for it, in your codebase, in patterns you already use.
Vendors who frame this as "we shipped a CLI" are going to miss what's actually happening. So are the ones treating it as "AI-powered documentation." What's really changed is that the high-leverage play for onboarding used to be content, and now it's an installer that runs an agent the vendor controls completely. The teams that ship this are going to pull self-serve users through integrations that used to require a sales call. The teams that publish a skill and wait for people to discover it will keep running the same Discord, writing the same blog posts, getting the same conversion numbers, and will probably blame anything except the fact that they made it the user's problem instead of solving it themselves.
B2B personalized onboarding has been a promise for a long time. It's actually here now - WorkOS and PostHog ship it, Amplitude is doing something close. It just lives inside an npx command. But onboarding was just the first step.
Think about what happens six months in. The SDK ships a breaking change and someone has to migrate a codebase that's drifted from the patterns the installer wrote. A production auth bug surfaces and the developer's agent needs to understand how the middleware composes with custom logic the team added months ago. What happens to brownfield projects which have legacy code? Right now all of that is back on the user - their agent, their problem to figure out what's theirs and what's the vendor's.
The same architectural idea probably extends but none of this is solved yet.