jscodeshift
jscodeshift is a powerful toolkit for automating code transformations (codemods) across JavaScript and TypeScript projects. It operates by parsing source code into an Abstract Syntax Tree (AST), allowing programmatic manipulation, and then printing the modified AST back into code. The current stable version is 17.3.0, released in early 2026. While lacking a fixed release cadence, the project is actively maintained, with frequent minor and patch updates primarily driven by `recast` dependency bumps to support new language features (e.g., recent TypeScript syntax) and address parsing quirks. A significant version jump from `v0.x` to `v17.0.0` occurred in August 2024, signaling its maturity rather than a traditional `1.0` release. Its core strength lies in its tight integration with `recast`, which excels at preserving original code formatting, comments, and whitespace, minimizing disruption to a codebase's aesthetics during large-scale refactors. It offers a robust CLI runner for applying transforms to files and an intuitive API for writing complex, style-preserving codemods.
Common errors
-
Error: SyntaxError: Unknown word (1:0) (or similar parser error like Unexpected token)
cause The jscodeshift runner failed to parse the source file, typically due to an incorrect or missing parser setting for the file's language features (e.g., TypeScript, JSX).fixSpecify the correct parser via the CLI, for example: `jscodeshift -t transform.js my-file.ts --parser=ts` or `--parser=tsx` for JSX/TSX. Use `--parser-config` for custom Babel/Flow configurations. -
Error: The transform function must return a string or null.
cause The default exported transform function in your codemod file did not return either the modified source code (as a string) or `null` (if no changes were made).fixEnsure your `export default function transformer(...)` always returns `root.toSource()` after modifications, or `null` if the file should not be changed. -
Error: Cannot find module 'jscodeshift/testUtils'
cause An attempt was made to import utilities from `jscodeshift/testUtils` (or other subpaths) with an incorrect path or when the module is not accessible.fixVerify the exact import path. Ensure `jscodeshift` is installed and the subpath `jscodeshift/testUtils` is correctly resolved by your module resolver. This typically occurs in test files. -
ReferenceError: j is not defined
cause The `j` object, which provides the jscodeshift AST API, was used outside the scope of the transform function where it is passed as `api.j`.fixAccess the jscodeshift API through the `api` object provided to your transform function: `export default function transformer(fileInfo, api) { const j = api.j; /* ... */ }`.
Warnings
- breaking jscodeshift v17.0.0 and above explicitly require Node.js version 16 or higher. Earlier versions of Node.js are no longer supported.
- breaking The package underwent a significant major version bump from `0.x.x` to `17.0.0`. This jump was a deliberate choice to reflect the project's maturity after nine years, similar to how React transitioned from v0.14 to v15.0, rather than a traditional v1.0.0 release. While the core API largely remained stable, this indicates a new major release branch.
- breaking Versions of `jscodeshift` up to `0.13.0` depended on the `colors` package, which was subject to a critical security vulnerability (supply chain attack) in version `1.4.1`.
- gotcha Incorrect or missing parser configuration is a common source of errors when running codemods, especially with TypeScript or JSX files.
- gotcha jscodeshift, via `recast`, prioritizes preserving the original code's style, including formatting, comments, and whitespace. While beneficial, this means it will not automatically reformat your code to a new style guide or apply a linter's autofixes.
Install
-
npm install jscodeshift -
yarn add jscodeshift -
pnpm add jscodeshift
Imports
- transformer
export default function transformer(fileInfo: FileInfo, api: API, options: Options): string | null { /* ... */ } - j (jscodeshift API)
import j from 'jscodeshift';
const j = api.j;
- runTransform
import { runTransform } from 'jscodeshift';import { runTransform } from 'jscodeshift/testUtils'; - FileInfo, API, Options (types)
import { API, FileInfo, Options } from 'jscodeshift';import type { API, FileInfo, Options } from 'jscodeshift';
Quickstart
// transform.ts
import type { API, FileInfo, Options } from 'jscodeshift';
/**
* A simple codemod that transforms `var` declarations to `let` or `const`.
* It will use `const` if all declarators are simple literals, otherwise `let`.
*/
export default function transformer(file: FileInfo, api: API, options: Options): string | null {
const j = api.j;
const root = j(file.source);
let changed = false;
root
.find(j.VariableDeclaration, { kind: 'var' })
.forEach((path) => {
const declarations = path.node.declarations;
// A simplistic check to determine if all declarations are immutable literals
const allAreConstants = declarations.every(decl =>
j.match(decl, { id: j.Identifier, init: j.Literal }) && decl.init !== null
);
if (allAreConstants) {
path.node.kind = 'const';
} else {
path.node.kind = 'let';
}
changed = true;
});
// Only return the source if changes were made, otherwise return null
return changed ? root.toSource() : null;
}
// To run this codemod on a file named `my-code.js`:
// 1. Save the above code as `transform.ts`.
// 2. Ensure `jscodeshift` is installed globally or locally.
// `npm install -g jscodeshift`
// 3. Execute the codemod:
// `jscodeshift -t ./transform.ts ./my-code.js --parser=ts`