> ## Documentation Index
> Fetch the complete documentation index at: https://docs.codemod.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

This guide walks you through setting up Codemod in your agent, building a JSSG codemod, and testing and publishing it to the registry. It assumes you are familiar with codemods. If not, check out this [intro to codemods](https://codemod.com/blog/what-are-codemods#what-is-a-codemod).

## 1. Set up Codemod in your coding agent

Start by installing Codemod Master Skill and Codemod MCP for your preferred coding agent:

```bash theme={null}
npx codemod ai
```

This is the main setup path for Codemod's AI-native CLI. It installs Codemod Master Skill and Codemod MCP so your agent can use Codemod CLI with built-in best practices for building, running, testing, and publishing codemods.

## 2. Scaffold and build your codemod

Create a dedicated folder or repo for your codemod work, then scaffold a starter package:

```bash theme={null}
npx codemod init
```

The starter package gives your agent a concrete structure to refine or replace while keeping the workflow, tests, and publishing flow in place.

Once the package is scaffolded, you can ask your AI agent to help you build codemods for things like framework upgrades, design system migrations, i18n work, code-mining tasks, and more.

For example:

<Prompt description="Extract React components from inside other components to module scope to prevent re-creation on render." icon="react" iconType="solid" actions={["copy", "cursor"]}>
  Build a codemod to move React components defined inside other components
  to module scope to fix re-creation on every render.
</Prompt>

<Card title="Prompting best practices" icon="lightbulb" href="/model-context-protocol#best-practices">
  Tips for writing effective prompts and getting the most out of building codemods with AI.
</Card>

You will end up with a [Codemod package](/package-structure):

<Tree>
  <Tree.Folder name="my-codemod" defaultOpen>
    <Tree.File name="codemod.yaml" />

    <Tree.File name="workflow.yaml" />

    <Tree.Folder name="scripts" defaultOpen>
      <Tree.File name="codemod.ts" />
    </Tree.Folder>

    <Tree.Folder name="tests" defaultOpen>
      <Tree.Folder name="fixtures" defaultOpen>
        <Tree.File name="input.tsx" />

        <Tree.File name="expected.tsx" />
      </Tree.Folder>
    </Tree.Folder>
  </Tree.Folder>
</Tree>

<CodeGroup>
  ```yaml codemod.yaml expandable theme={null}
  schema_version: "1.0"

  name: "extract-inner-components"
  version: "0.1.0"
  description: "Move React components defined inside other components to module scope"
  author: "Your Name <you@example.com>"
  license: "MIT"
  workflow: "workflow.yaml"

  targets:
    languages: ["tsx"]

  keywords: ["react", "performance", "components"]

  registry:
    access: "public"
    visibility: "public"

  capabilities: []
  ```

  ```yaml workflow.yaml expandable theme={null}
  # yaml-language-server: $schema=https://raw.githubusercontent.com/codemod/codemod/refs/heads/main/schemas/workflow.json

  version: "1"

  params:
    schema:
      run_ai_step:
        name: "Run AI step"
        description: "Enable AI-powered fixups for edge cases"
        type: string
        default: "false"

  nodes:
    - id: extract-inner-components
      name: Extract inner React components to module scope
      type: automatic
      steps:
        - name: "Move inner components to module scope"
          js-ast-grep:
            js_file: scripts/codemod.ts
            language: "tsx"

        - name: "AI fixups for complex cases"
          if: params.run_ai_step == "true"
          ai:
            prompt: |
              The previous AST step extracted inner React components to module scope.
              Some cases could not be handled deterministically. Scan for remaining
              components defined inside other components and fix them:

              1. If the inner component closes over parent state or props, convert those
                 to explicit props on the extracted component and update the call site.
              2. If the inner component uses generics from the parent, lift the type
                 parameters to the extracted component's signature.
              3. Add a TODO comment for any case you cannot safely transform.

              Only modify files that still contain inner component definitions.
  ```

  ```ts scripts/codemod.ts expandable theme={null}
  import type { Codemod, Edit } from "codemod:ast-grep";
  import type { SgNode } from "codemod:ast-grep";
  import type TSX from "codemod:ast-grep/langs/tsx";

  const codemod: Codemod<TSX> = async (root) => {
    const rootNode = root.root();
    const edits: Edit[] = [];

    // Find function components defined inside other function components.
    // A component is a function_declaration whose name starts with uppercase,
    // nested inside another function_declaration's statement_block.
    const innerFuncComponents = rootNode.findAll({
      rule: {
        kind: "function_declaration",
        has: {
          field: "name",
          kind: "identifier",
          regex: "^[A-Z]",
        },
        inside: {
          kind: "statement_block",
          inside: {
            kind: "function_declaration",
            has: {
              field: "name",
              kind: "identifier",
              regex: "^[A-Z]",
            },
          },
        },
      },
    });

    // Find arrow function components: `const Foo = (...) => { ... }`
    const innerArrowComponents = rootNode.findAll({
      rule: {
        kind: "lexical_declaration",
        has: {
          kind: "variable_declarator",
          has: {
            field: "name",
            kind: "identifier",
            regex: "^[A-Z]",
          },
        },
        inside: {
          kind: "statement_block",
          inside: {
            kind: "function_declaration",
            has: {
              field: "name",
              kind: "identifier",
              regex: "^[A-Z]",
            },
          },
        },
      },
    });

    if (innerFuncComponents.length === 0 && innerArrowComponents.length === 0) {
      return null;
    }

    const allInner = [...innerFuncComponents, ...innerArrowComponents];

    // Group by parent component
    const parentMap = new Map<
      number,
      { parent: SgNode<TSX>; children: SgNode<TSX>[] }
    >();

    for (const inner of allInner) {
      const ancestors = inner.ancestors();
      const parentComponent = ancestors.find(
        (a) =>
          a.kind() === "function_declaration" &&
          a.field("name")?.matches({ rule: { regex: "^[A-Z]" } }),
      );
      if (!parentComponent) continue;

      const parentId = parentComponent.id();
      if (!parentMap.has(parentId)) {
        parentMap.set(parentId, { parent: parentComponent, children: [] });
      }
      parentMap.get(parentId)!.children.push(inner);
    }

    for (const { parent, children } of parentMap.values()) {
      const extractedParts: string[] = [];

      for (const child of children) {
        extractedParts.push(child.text());

        // Remove the inner component from its original location
        edits.push({
          startPos: child.range().start.index,
          endPos: child.range().end.index,
          insertedText: "",
        });
      }

      // Insert extracted components before the parent function.
      // If the parent is wrapped in an export_statement, insert before that instead.
      const parentParent = parent.parent();
      const insertTarget =
        parentParent && parentParent.kind() === "export_statement"
          ? parentParent
          : parent;

      const insertText = extractedParts.join("\n\n") + "\n\n";
      edits.push({
        startPos: insertTarget.range().start.index,
        endPos: insertTarget.range().start.index,
        insertedText: insertText,
      });
    }

    return rootNode.commitEdits(edits);
  };

  export default codemod;
  ```
</CodeGroup>

## 3. Validate and test

From your scaffolded codemod package directory, validate the workflow and run the generated tests.

Validate the workflow schema:

```bash theme={null}
npx codemod workflow validate -w workflow.yaml
```

Run tests against your input/expected fixtures:

```bash theme={null}
npx codemod jssg test -l tsx ./scripts/codemod.ts
```

Tests use fixtures in the `tests/` directory. You can use simple `input.*`/`expected.*` file pairs or `input/` + `expected/` directory snapshots when your codemod creates or deletes files. If MCP generated test fixtures, they will run automatically.

For test structure, CI integration, and debugging strategies, see [Testing](/jssg/testing).

## 4. Run your codemod

From the same package directory, run your codemod on a target codebase:

```bash theme={null}
npx codemod workflow run -w . -t /path/to/your/project
```

<Tip>
  **AI-powered steps**: If your workflow includes an AI step gated by a parameter, enable it at runtime:

  ```bash theme={null}
  LLM_API_KEY=your-key npx codemod workflow run -w . -t /path/to/project --param run_ai_step=true
  ```

  Set `LLM_API_KEY` as an environment variable for your chosen provider. With an API key, the built-in AI step runs normally. Without one, Codemod prints `[AI INSTRUCTIONS]`, which parent agents such as Codex- or Claude-style tooling can pick up. See [Workflow Reference — AI steps](/workflows/reference#ai-step) for provider configuration.
</Tip>

For all CLI options, see [CLI reference](/cli#codemod-workflow).

## 5. Publish

When you're happy with the result, publish from the package directory:

Share your codemod with your team or the community:

```bash theme={null}
npx codemod login
npx codemod publish
```

Your codemod is now in the [Codemod Registry](https://go.codemod.com/registry) and runnable by anyone via `npx codemod @your-scope/codemod-name`.

For CI/CD automation, trusted publishers, and API keys, see the [Publishing guide](/publishing).

## Next steps

### Scale your migrations

Your migration experience does not stop here. When you're managing migrations across large codebases or multiple teams, the same codemod package can power [Campaigns](/platform/campaigns) for automated multi-repo rollouts and [Insights](/platform/insights) for tracking adoption progress.

See the [Platform quickstart](/platform/quickstart) for the full enterprise workflow.

### Getting help

<CardGroup cols={2}>
  <Card title="Join the community" icon="slack" href="https://go.codemod.com/community">
    Ask questions, get help, and connect with other codemod users on Slack.
  </Card>

  <Card title="Book a call" icon="calendar" href="https://cal.com/alexbit">
    Schedule a demo or get hands-on help from the Codemod team.
  </Card>
</CardGroup>

### Learn more

<CardGroup cols={2}>
  <Card title="CLI reference" icon="terminal" href="/cli">
    Full CLI command reference.
  </Card>

  <Card title="Workflow reference" icon="diagram-project" href="/workflows/reference">
    Complete workflow\.yaml specification.
  </Card>

  <Card title="JSSG" icon="js" href="/jssg/intro">
    Learn the transformation engine in depth.
  </Card>

  <Card title="Publishing" icon="upload" href="/publishing">
    Authentication methods and CI/CD setup.
  </Card>
</CardGroup>
