Use Emendant alongside the AI SDK codemod
Should I use the AI SDK codemod or Emendant to upgrade ai?
Section titled “Should I use the AI SDK codemod or Emendant to upgrade ai?”You can use both. Vercel’s @ai-sdk/codemod rewrites your files to follow an AI SDK upgrade, and the AI SDK 7.0 migration guide tells you to run it. Emendant reports which of your call sites a supported release changed, offers patches, and checks them in a copy of your repository. Each tool found a site on the file below that the other missed. Neither was complete.
Emendant covers the AI SDK releases in its feed, and other SDKs such as openai and langchain. The codemod covers the AI SDK only.
What each tool does
Section titled “What each tool does”@ai-sdk/codemod |
Emendant | |
|---|---|---|
| How it finds code | Each transform matches by syntax: a property or key with a given name, anywhere in the file. | Each entry matches a use of a named ai export, followed from its import. |
| What it changes | Edits your files in place. --dry previews without writing. |
Writes patches to .emendant/patches/. It does not edit your working tree. |
| Checks after the edit | None. Run your typecheck and tests yourself. | Runs discovered or configured typecheck and test commands against a patched copy, and grades each patch. |
| What it reports | The files it changed, and transform errors. | Each affected place, the release that changed it, its sources, and changes it found but cannot patch. |
| Coverage | Its own list of transforms for the 4.0, 5.0, 6.0 and 7.0 upgrades. | The changes in its feed for supported releases. |
npx @ai-sdk/codemod v7 runs the 7.0 transforms. npx @ai-sdk/codemod upgrade runs every transform in its bundle, from 4.0 through to 7.0. Each transform runs jscodeshift with the tsx parser over the path you give it. The transforms do not read TypeScript types.
One file, both tools
Section titled “One file, both tools”This file was written for ai@6.0.312. On 7 November 2026 we ran three of the codemod’s 7.0 transforms on it, from @ai-sdk/codemod@4.0.4. We also ran emendant scan --package ai from emendant@0.12.0.
import { generateText, streamText, tool } from 'ai';import { z } from 'zod';
const lookup = tool({ inputSchema: z.object({ id: z.string() }), execute: async ({ id }, { experimental_context }) => ({ id, ctx: experimental_context }),});
export async function run(model: any) { const result = await generateText({ model, prompt: 'hi', tools: { lookup }, experimental_context: { userId: '1' }, onFinish: () => {}, }); console.log(result.steps[0].experimental_context);
const s = streamText({ model, prompt: 'hi' }); for await (const part of s.fullStream) console.log(part);
const video = { fullStream: [] as string[] }; console.log(video.fullStream); const upload = { onFinish: () => console.log('unrelated library callback') }; return upload;}The transforms were v7/rename-experimental-context-to-context, v7/rename-full-stream-to-stream and v7/rename-on-finish-to-on-end. In ai@7.0.0, generateText and StepResult take runtimeContext, and a tool’s execute options take context.
| Line | Codemod | Emendant |
|---|---|---|
execute: async ({ id }, { experimental_context }) |
Renamed to context. Correct. |
Not reported. The feed has no entry for this option yet (#1008). |
generateText({ experimental_context: ... }) |
Not changed. | Reported, and patched to runtimeContext. |
onFinish in generateText |
Renamed to onEnd. onFinish still works in 7.0.0 and is deprecated. |
Not reported. |
result.steps[0].experimental_context |
Renamed to context, which StepResult does not declare. |
Not reported by 0.12.0. The release after 0.12.0 reports it and patches it to runtimeContext. |
s.fullStream, the streamText result |
Renamed to stream. |
Reported, and patched to stream. |
video.fullStream, a local object |
Renamed to stream. |
Not reported, as expected. |
upload.onFinish, an unrelated callback |
Renamed to onEnd. |
Not reported, as expected. |
Emendant’s two patches were structurally checked: the uses they remove are gone and no new one appeared. This file has no typecheck or test command, so neither tool could compile or run the result.
This is one file and three transforms, not a measure of either tool across a codebase.
Run both on an upgrade
Section titled “Run both on an upgrade”-
Commit or stash your work, so each tool’s changes show as their own diff.
-
Scan before you change anything. Run from the repository root with Node.js 20 or later:
Terminal window npx emendant scan --package ai -
Preview the codemod, then run it:
Terminal window npx @ai-sdk/codemod v7 --drynpx @ai-sdk/codemod v7 -
Read the codemod’s diff before you keep it. Look for renamed properties on objects that are not from
ai. -
Scan again with the new version adopted, and generate Emendant’s patches for what is left:
Terminal window npx emendant scan --package ai --adoptednpx emendant fix --package ai --adoptedRead
.emendant/report.mdand each patch. See Fix a finding for the grades. -
Run your typecheck and tests. Then read the AI SDK 7.0 migration guide for the steps neither tool covers.
The recorded AI SDK 6 to 7 migration of steel-dev/atlas shows the manual work that remained after Emendant’s patch. See Known limitations for what a clean scan does not establish.
Sources
Section titled “Sources”The AI SDK 7.0 migration guide gives the v7 command. Codemod behaviour checked against vercel/ai at bdc3f91 on 7 November 2026:
- README: the commands and transform list
upgrade.ts: the transformsupgraderunstransform.ts: thejscodeshiftcommand and its optionsrename-experimental-context-to-context.ts,rename-full-stream-to-stream.tsandrename-on-finish-to-on-end.ts: the three transforms run above
StepResult, generateText and tool execution options were read from the type declarations published in ai@7.0.0 and ai@7.0.164.
Emendant behaviour and coverage: AI SDK 7.0.0 changes, scan guide, fix guide and supported projects.