Thanks for helping users adopt the latest features with your codemods!
Using an AI coding agent (Codex, Cursor, Claude Code, Aider, etc.)? See AGENTS.md for codemod authoring guidance and common mistakes to avoid.
This repository uses pnpm (see packageManager in the root package.json), Changesets for releases, and oxfmt + oxlint (not Prettier/ESLint) for formatting and linting.
# Install dependencies (also wires the Husky pre-commit hook)
pnpm install
# Format all files
pnpm run format
# Check formatting without writing
pnpm run format:check
# Lint all files
pnpm run lint
# Lint and auto-fix
pnpm run lint:fix
# Run all codemod package tests
pnpm run test
# Typecheck all codemod scripts (root tsconfig)
pnpm run check-types
# Same checks as CI (tests + typecheck)
pnpm run ci
# Verify URLs in tracked Markdown
pnpm run docs:linksRun one workspace package (the pnpm --filter value is the name field in that package's package.json):
pnpm --filter <package-name> testFor example:
pnpm --filter sample-codemod testTypechecking runs once from the repository root via pnpm run check-types (see root tsconfig.json).
Use Node 22 locally (see .nvmrc) to match CI.
After pnpm install, Husky runs lint-staged before each commit: oxfmt and oxlint on staged files, plus targeted pnpm test when you touch codemods/**/scripts/**/*.ts. If something fails, fix or stage the updates and try again.
The hook only inspects staged files. CI runs full-repo format, lint, and typecheck on every pull request, so unchanged files can still fail there even if the hook passed.
Three workflows support quality and releases:
ci.yaml— Pull request checks: runs on Ubuntu for PRs tomain. Format, lint, and typecheck run across the full repo. Tests run only for codemod packages changed in the PR, or the full test suite when root tooling files change (for examplepackage.json,pnpm-lock.yaml, or the workflow itself).release.yml+publish.yml— Release automation: see Release workflow below.
Match the local checks (pnpm run format, pnpm run lint, pnpm run ci) before you push.
- Issue: Check for an existing issue, or open one first.
- Safety: Codemods must be safe, predictable, and idempotent (running twice should not change code again). Avoid mixing patterns with different safety levels.
- Naming: In
codemod.yaml, the codemod name must start with@<scope>, where<scope>is this repo's GitHub org. - Tests: Add multiple fixtures (positive and negative).
- Docs: Update the README for your codemod.
- Create a branch from
main. - Make your changes and add or update fixtures under
tests/<case>/. - Run
pnpm run format,pnpm run lint, andpnpm run cito verify everything passes. - Add a changeset for every codemod package you touched (see below).
- Open a pull request.
This repo uses Changesets for versioning and releases. Every PR that changes a codemod package under codemods/ should include a changeset, unless you use the skip-changeset label (see CI). Details live in .changeset/README.md.
pnpm changesetFollow the prompts:
- Select the affected codemod(s).
- Choose the semver bump — patch for fixes, minor for new features, major for breaking changes.
- Write a short summary.
Commit the new Markdown file under .changeset/ with your PR.
pnpm run version-packages (run by automation on main, not usually by hand) runs changeset version, which bumps version in each affected package.json. Do not edit version in package.json by hand — automation owns that field.
Releases are fully automated via .github/workflows/release.yml and .github/workflows/publish.yml on every push to main:
- Merge a PR that includes one or more changesets into
main. - The
releasejob detects the pending changesets and runspnpm run version-packages(changeset version), which bumpsversionin each affectedpackage.json. - The bot opens (or updates) a Version Packages pull request on branch
changeset-release/version-packages— it does not push directly tomain. - Merge that PR (required checks apply like any other PR).
- On the next push to
main,scripts/tag-and-publish.shcreates a<name>@v<version>git tag for every bumped package and pushes the tags. - The
publishjob fans out a parallel matrix over the changed directories and publishes each codemod viacodemod/publish-action.
For emergencies (re-publish a specific codemod without a full release cycle), use the Publish Codemod (Manual) workflow (.github/workflows/publish.yml) and supply the codemod slug.
Do not hand-edit version in package.json to simulate a release — automation owns bumps.
Scaffold a new codemod with the CLI:
npx codemod initNew packages live under codemods/, for example:
codemods/<slug>/
scripts/codemod.ts # JSSG transform
tests/ # input / expected fixtures
codemod.yaml # manifest
workflow.yaml
package.json
README.md
SKILL.md
Conventions:
- The codemod name in
codemod.yamlandpackage.jsonmust start with@<scope>(e.g.@myorg/my-codemod). - Keep rewrites conservative. If a step requires a human decision, prefer a detector or recipe parameter over an unsafe transform.
- Use an existing sibling codemod as a template. See docs/CODEMOD-TEMPLATE.md for the full package spec.
Test your codemod locally against a sample project:
cd /path/to/sample/project
npx codemod workflow run -w /path/to/my-codemod/workflow.yamlEach codemod package should include:
package.jsonwith at least atestscript.codemod.yaml,workflow.yaml,README.md,SKILL.mdscripts/codemod.tstests/<case>/input.*andtests/<case>/expected.*
Keep transformations atomic and verifiable with fixtures.
| Command | What it does |
|---|---|
pnpm run format |
Auto-format with oxfmt |
pnpm run format:check |
Check formatting (no writes) |
pnpm run lint |
Lint with oxlint (type-aware) |
pnpm run lint:fix |
Lint and auto-fix with oxlint |
pnpm run test |
Run all codemod tests |
pnpm run check-types |
Typecheck all codemod scripts (root tsconfig.json) |
pnpm run ci |
Full check (test + typecheck) |
pnpm run docs:links |
Verify Markdown links |
- Describe the codemod and its migration use case.
- Follow Conventional Commits:
| Type | Usage |
|---|---|
feat |
New codemod or capability |
fix |
Bugfix in a transform or test |
docs |
Documentation-only changes |
refactor |
Non-feature, non-bugfix code changes |
test |
Add or update fixtures/tests |
chore |
Tooling, CI, formatting, repo hygiene |
By contributing, you agree that your work will be licensed under the MIT License.