> ## 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.

# Workflow Reference

This reference documents the complete `workflow.yaml` specification for Codemod Workflows.

## Complete Example

This example demonstrates all five step types working together in a migration workflow:

```yaml workflow.yaml theme={null}
version: "1"

params:
  schema:
    library:
      name: "Library"
      description: "Target library for migration"
      type: string
      default: "analytics-v2"

state:
  schema:
    - name: shards
      type: array
      items:
        type: object
        properties:
          team: { type: string }
          shardId: { type: string }

nodes:
  - id: migrate-analytics
    name: Migrate legacy analytics to analytics.track({ event, properties })
    type: automatic
    steps:
      # 1) Codemod Registry: run well-defined baseline migration first
      - name: "Run registry codemod: legacy analytics -> analytics.track"
        codemod:
          source: "@codemod/migrate-analytics-v2"
          args:
            - "legacy-analytics"
            - "analytics-v2"

      # 2) JSSG: handle project-specific patterns with programmatic logic
      - name: "Project-specific TS codemod (wrappers + key normalization)"
        js-ast-grep:
          js_file: "scripts/codemods/migrate-analytics-wrappers.ts"
          language: "typescript"
          include:
            - "src/**/*.{ts,tsx}"
          exclude:
            - "**/*.test.ts"

      # 3) AI: transform hard cases the rules miss
      - name: "AI fixups: dynamic calls + edge cases -> analytics.track object form"
        ai:
          prompt: |
            You are performing a code migration. Modify files directly.

            Goal:
            Convert any remaining legacy analytics calls into:
              analytics.track({ event: <string>, properties: <object> })

            Handle these hard cases:
            1) Dynamic event names: trackEvent(getName(), props)
              - Preserve semantics. event should become getName().
            2) Non-object props: trackEvent("X", foo)
              - Convert to properties: foo if foo is object-like, otherwise { value: foo }.

            Constraints:
            - Keep formatting roughly intact (prettier will run later).
            - If unsure about a transformation, add a TODO comment explaining why.

      # 4) YAML ast-grep: clean up simple leftovers (fast + deterministic)
      - name: "Apply cleanup rules (YAML ast-grep)"
        ast-grep:
          config_file: "rules/analytics_cleanup.yml"
          include:
            - "src/**/*.{ts,tsx,js,jsx}"
          exclude:
            - "**/*.test.*"

      # 5) Shell: format after all transformations
      - name: "Format code"
        run: npx prettier --write "src/**/*.{ts,tsx,js,jsx}"
```

***

## Workflow Structure

A workflow has four top-level keys:

```yaml workflow.yaml theme={null}
version: "1"
state:
  schema: []
params:
  schema: {}
templates: []
nodes: []
```

| Key                       | Required | Purpose                                      |
| ------------------------- | -------- | -------------------------------------------- |
| `version`                 | Yes      | Workflow schema version (currently `"1"`)    |
| [`nodes`](#nodes)         | Yes      | Executable DAG of transformation nodes       |
| [`state`](#shared-state)  | No       | Declares shared-state schema for persistence |
| [`params`](#parameters)   | No       | Configurable parameters with schema          |
| [`templates`](#templates) | No       | Reusable step blocks                         |

***

## Nodes

Nodes are execution units in your workflow. They can be automatic or manual, depend on other nodes, and may define strategy (matrix), trigger, runtime, env, and an ordered list of steps.

```yaml theme={null}
version: "1"
nodes:
  - id: build
    name: Build
    type: automatic
    steps:
      - name: npm install
        run: npm ci
```

<ParamField path="id" type="string" required>
  Unique identifier within the workflow.
</ParamField>

<ParamField path="name" type="string" required>
  Display name shown in logs and UI.
</ParamField>

<ParamField path="type" type="string" default="automatic">
  `automatic` or `manual`.
</ParamField>

<ParamField path="depends_on" type="string[]">
  Upstream node IDs that must complete before this node runs. See [Cyclic Dependencies](#cyclic-dependencies).
</ParamField>

<ParamField path="trigger" type="object">
  `{ type: manual }` creates an approval gate. See [Manual Triggers](#manual-triggers).
</ParamField>

<ParamField path="strategy" type="object">
  Matrix configuration for parallel fan-out. See [Matrix Strategy](#matrix-strategy).
</ParamField>

<ParamField path="steps" type="array" required>
  Ordered list of [steps](#steps) to execute.
</ParamField>

<ParamField path="env" type="object">
  Environment variables for all steps in this node.
</ParamField>

### Git Automation (Campaign/Cloud Runs)

In Campaign/cloud runs, each task executes on its own git branch. Codemod creates that branch before the node's steps run, can create commits after successful steps, and pushes the branch plus opens a pull request when the node ends with commits.

<Info>
  These git automation fields are only used in Campaign/cloud runs. Local `codemod workflow run` execution does not create branches, commits, or pull requests automatically.
</Info>

```yaml theme={null}
nodes:
  - id: migrate
    name: Migrate API usage
    branch_name: "codemod-${{ matrix.team }}-${{ task.signature }}"
    pull_request:
      title: "refactor: migrate ${{ matrix.team }}"
      body: "Generated from task ${{ task.id }}"
      draft: true
    steps:
      - name: Run transform
        js-ast-grep:
          js_file: "scripts/codemod.ts"
          language: "tsx"
```

<ParamField path="branch_name" type="string">
  Branch name template for Campaign/cloud runs. The branch is created before the node's steps run. If omitted, Codemod uses `codemod-<task.signature>`.
</ParamField>

<ParamField path="pull_request" type="object">
  Pull request customization for Campaign/cloud runs. If the node ends with commits, Codemod pushes the task branch and attempts to create a pull request. This field customizes the PR metadata; omitting it does not disable PR creation.
</ParamField>

<ParamField path="pull_request.title" type="string" required>
  Pull request title template.
</ParamField>

<ParamField path="pull_request.body" type="string">
  Optional pull request body template.
</ParamField>

<ParamField path="pull_request.draft" type="boolean" default="false">
  Create the pull request as a draft.
</ParamField>

<ParamField path="pull_request.base" type="string">
  Base branch to merge into. If omitted, Codemod auto-detects the remote default branch.
</ParamField>

<Info>
  **Default Campaign/cloud behavior:**

  If the node ends with commits and `pull_request` is omitted, Codemod attempts to open a pull request using the node name as the default title. If no explicit commit checkpoint was created and changes remain at the end of the node, Codemod attempts a fallback commit using the node name before pushing and opening the pull request.
</Info>

***

## Steps

Steps are atomic actions inside a node. They run sequentially and each step performs one transformation or action.

### Common Step Fields

All step types support `name`, `if`, `env`, and `commit`.

<ParamField path="name" type="string" required>
  Step label.
</ParamField>

<ParamField path="if" type="string">
  Conditional expression to gate step execution. Current runtime support for generic step conditions includes `params.x`, `state.x`, and `matrix.x`. See [Variable Resolution](#variable-resolution).
</ParamField>

<ParamField path="env" type="object">
  Step-level environment variables applied to the process environment.
</ParamField>

<ParamField path="commit" type="object">
  Optional commit checkpoint for Campaign/cloud runs. After a successful step, Codemod stages the configured paths and creates a git commit. If no step creates a commit but changes remain at the end of the node, Codemod attempts to create a fallback commit using the node name before pushing and opening the pull request.
</ParamField>

<ParamField path="commit.message" type="string" required>
  Commit message template.
</ParamField>

<ParamField path="commit.add" type="string[]">
  Paths to stage before committing. If omitted, Codemod stages the entire working tree for that task branch.
</ParamField>

<ParamField path="commit.allow_empty" type="boolean" default="true">
  If `true`, skip the checkpoint when nothing is staged. If `false`, the step fails when there are no staged changes to commit.
</ParamField>

<Info>
  Commit checkpoints are Campaign/cloud-only. They run after successful steps on the task branch created for the node.
</Info>

### JSSG Step

Executes a JavaScript/TypeScript codemod using ast-grep for pattern matching and AST manipulation.

```yaml theme={null}
steps:
  - name: Replace console.log with logger
    js-ast-grep:
      js_file: "scripts/codemod.ts"
      language: "tsx"
      include:
        - "**/*.ts"
        - "**/*.tsx"
      exclude:
        - "**/*.test.ts"
```

**JSSG Step Parameters**:

<ParamField path="name" type="string" required>
  Step label.
</ParamField>

<ParamField path="if" type="string">
  Conditional expression to gate step execution. Supports `params.x`, `state.x`, and matrix value keys. Operators: `==`, `!=`, `>`, `<`, `&&`, `||`. See [Variable Resolution](#variable-resolution).
</ParamField>

<ParamField path="js-ast-grep.js_file" type="string" required>
  Path to the JS/TS file that implements the codemod.
</ParamField>

<ParamField path="js-ast-grep.language" type="string">
  Target language (e.g., `typescript`, `tsx`, `javascript`, `jsx`).
</ParamField>

<ParamField path="js-ast-grep.include" type="string[]">
  Include glob patterns.
</ParamField>

<ParamField path="js-ast-grep.exclude" type="string[]">
  Exclude glob patterns.
</ParamField>

<ParamField path="js-ast-grep.base_path" type="string">
  Base path for resolving globs.
</ParamField>

<ParamField path="js-ast-grep.max_threads" type="number">
  Maximum concurrent threads.
</ParamField>

<ParamField path="js-ast-grep.dry_run" type="boolean" default="false">
  Perform a dry run without applying changes.
</ParamField>

<Card title="JSSG Documentation" icon="code" href="/jssg/intro">
  Learn how to write JavaScript/TypeScript codemods.
</Card>

### AI Step

Calls an AI agent with a prompt for LLM-powered transformations.

```yaml theme={null}
steps:
  - name: Review diffs with AI
    ai:
      prompt: |
        Summarize risky changes and suggest tests.
      model: "gpt-4o"
```

**AI Step Parameters**:

<ParamField path="name" type="string" required>
  Step label.
</ParamField>

<ParamField path="if" type="string">
  Conditional expression to gate step execution. See [Variable Resolution](#variable-resolution).
</ParamField>

<ParamField path="ai.prompt" type="string" required>
  Prompt to send to the AI agent.
</ParamField>

<ParamField path="ai.model" type="string" default="gpt-4o">
  Model identifier. Overrides `LLM_MODEL` if set.
</ParamField>

<ParamField path="ai.system_prompt" type="string">
  System prompt to scope the AI agent's behavior.
</ParamField>

<ParamField path="ai.max_steps" type="number" default="30">
  Maximum number of agent steps before stopping.
</ParamField>

<ParamField path="ai.llm_protocol" type="string" default="openai">
  LLM provider/protocol. Supported: `openai`, `anthropic`, `google_ai`, `azure_openai`.
</ParamField>

<ParamField path="ai.endpoint" type="string">
  LLM base URL. Defaults to the provider's standard endpoint.
</ParamField>

<ParamField path="ai.api_key" type="string">
  API key for LLM access.

  ```bash Environment variables for AI steps theme={null}
  LLM_API_KEY=YOUR_KEY
  LLM_PROVIDER=openai  # or anthropic, google_ai, azure_openai
  LLM_MODEL=gpt-4o
  LLM_BASE_URL=https://api.openai.com/v1  # optional
  ```
</ParamField>

### Install Skill Step

Installs package skill behavior into a supported harness via the Codemod CLI. Use this in skill-only or workflow + skill packages when you want authored skill files from the package to be installable for coding-agent workflows.

```yaml theme={null}
steps:
  - name: Install package skill
    install-skill:
      package: "@your-scope/my-codemod"
```

In dry-run mode, this step is skipped. In non-interactive runs, it is also skipped by default unless the workflow is run with `--install-skill`. See [CLI reference](/cli#codemod-workflow).

The target package must expose an authored `SKILL.md` with valid frontmatter and the authored-package markers:

```md theme={null}
---
name: "my-skill"
description: "Project-specific migration guidance"
allowed-tools:
  - Bash(codemod *)
---
codemod-compatibility: skill-package-v1
codemod-skill-version: 0.1.0
```

If you see `mcs-v1`, that is the marker for the built-in Codemod core skill profile, not for authored package skills installed by this workflow step.

**Install Skill Step Parameters**:

<ParamField path="name" type="string" required>
  Step label.
</ParamField>

<ParamField path="if" type="string">
  Conditional expression to gate step execution. See [Variable Resolution](#variable-resolution).
</ParamField>

<ParamField path="install-skill.package" type="string" required>
  Package identifier to install, for example `@codemod/jest-to-vitest`.
</ParamField>

<ParamField path="install-skill.path" type="string">
  Optional authored skill source path inside the package. Defaults to the conventional `agents/skill/<skill-name>/SKILL.md` layout.
</ParamField>

<ParamField path="install-skill.harness" type="string" default="auto">
  Target harness adapter: `auto`, `claude`, `goose`, `opencode`, `cursor`, or `codex`.
</ParamField>

<ParamField path="install-skill.scope" type="string" default="project">
  Install scope: `project` or `user`.
</ParamField>

<ParamField path="install-skill.force" type="boolean" default="false">
  Overwrite existing skill files if needed.
</ParamField>

### YAML ast-grep Step

Executes ast-grep using declarative YAML rules for simple, fast pattern matching.

```yaml theme={null}
steps:
  - name: "Apply cleanup rules"
    ast-grep:
      config_file: "rules/config.yml"
      include:
        - "**/*.js"
      exclude:
        - "**/*.test.js"
```

<Tip>
  When to use YAML ast-grep vs JSSG

  * **YAML ast-grep**: Simple find/replace, no conditional logic, fastest to write
  * **JSSG**: Conditional logic, complex AST manipulations, cross-file coordination
</Tip>

**YAML ast-grep Step Parameters**:

<ParamField path="name" type="string" required>
  Step label.
</ParamField>

<ParamField path="if" type="string">
  Conditional expression to gate step execution. See [Variable Resolution](#variable-resolution).
</ParamField>

<ParamField path="ast-grep.config_file" type="string" required>
  Path to the ast-grep configuration file (.yaml).
</ParamField>

<ParamField path="ast-grep.include" type="string[]">
  Include glob patterns.
</ParamField>

<ParamField path="ast-grep.exclude" type="string[]">
  Exclude glob patterns.
</ParamField>

<ParamField path="ast-grep.base_path" type="string">
  Base path for resolving globs.
</ParamField>

<ParamField path="ast-grep.max_threads" type="number">
  Maximum concurrent threads.
</ParamField>

### Codemod Registry Step

Runs another codemod by package name or local path.

```yaml theme={null}
steps:
  - name: Run registry codemod
    codemod:
      source: "@scope/package"
      args: ["--flag", "value"]
```

**Codemod Registry Step Parameters**:

<ParamField path="name" type="string" required>
  Step label.
</ParamField>

<ParamField path="if" type="string">
  Conditional expression to gate step execution. See [Variable Resolution](#variable-resolution).
</ParamField>

<ParamField path="codemod.source" type="string" required>
  Codemod source (registry package or local path). Supports version pinning: `@scope/pkg@1.2.3`.
</ParamField>

<ParamField path="codemod.args" type="string[]">
  CLI arguments passed to the codemod.
</ParamField>

<ParamField path="codemod.env" type="object">
  Environment variables used during execution.
</ParamField>

<ParamField path="codemod.working_dir" type="string">
  Working directory for execution.
</ParamField>

<Info>
  You can aggregate multiple codemods by adding multiple `codemod` steps in the same node. Steps run sequentially from top to bottom.
</Info>

### Shell Command Step

Runs shell commands on the host for setup, cleanup, or external tools.

```yaml theme={null}
steps:
  - name: Install dependencies
    run: |
      npm install
      npm run build
```

**Shell Command Step Parameters**:

<ParamField path="name" type="string" required>
  Step label.
</ParamField>

<ParamField path="if" type="string">
  Conditional expression to gate step execution. See [Variable Resolution](#variable-resolution).
</ParamField>

<ParamField path="run" type="string" required>
  Inline shell command to execute.
</ParamField>

<ParamField path="env" type="object">
  Step-level environment variables applied to the process environment.
</ParamField>

### Shard Step

Evaluates file shards and writes results to workflow state for use with [matrix strategies](#matrix-strategy). Supports built-in grouping algorithms (directory, codeowner) and custom shard functions.

```yaml theme={null}
steps:
  - name: Build shards
    shard:
      method:
        type: directory
        max_files_per_shard: 20
      target: "./src"
      output_state: shards
      js-ast-grep:
        js_file: scripts/codemod.ts
        language: tsx
        include: ["**/*.{ts,tsx}"]
```

**Shard Step Parameters**:

<ParamField path="name" type="string" required>
  Step label.
</ParamField>

<ParamField path="shard.method" type="object" required>
  Sharding method. Either `{ type: "directory" | "codeowner", max_files_per_shard: N }` for built-in methods, or `{ function: "path/to/shard.ts" }` for custom logic.
</ParamField>

<ParamField path="shard.target" type="string" default=".">
  Root directory to scan for files. Defaults to the workflow run target.
</ParamField>

<ParamField path="shard.output_state" type="string" required>
  State key to write shard results to.
</ParamField>

<ParamField path="shard.js-ast-grep" type="object">
  JSSG codemod configuration for pre-filtering. Dry-runs the codemod and only shards files where the transform produces changes.
</ParamField>

<ParamField path="shard.file_pattern" type="string">
  Glob pattern for eligible files (used when `js-ast-grep` is not set).
</ParamField>

<Card title="Sharding Guide" icon="layer-group" href="/workflows/sharding">
  Full guide covering built-in methods, custom functions, re-evaluation, and examples.
</Card>

***

## Matrix Strategy

Matrix strategies fan out a node into multiple parallel tasks. Use them to shard work by team, directory, or configuration.

```yaml theme={null}
nodes:
  - id: matrix-codemod
    name: Matrix Codemod
    strategy:
      type: matrix
      from_state: shards
    steps:
      - name: Codemod
        run: node codemod.js --team=$team --shard=$shardId
```

The `from_state` field references an array in your workflow's [state schema](#shared-state). Each array item spawns a parallel task.

**Accessing Matrix Values**:

In JSSG transforms via `options.matrixValues`:

```ts theme={null}
const codemod: Codemod<TSX> = async (root, options) => {
  const team = options.matrixValues?.team;
  const shardId = options.matrixValues?.shardId;
};
```

In shell steps as environment variables:

```yaml theme={null}
- name: Process shard
  run: |
    echo "Team: $team"
    echo "Shard: $shardId"
```

**Dynamic Matrix Task Recompilation**:

When the array referenced by `from_state` changes:

1. New tasks are created for new items
2. Tasks are marked `WontDo` if their item is removed
3. Existing tasks remain untouched if their item persists

Matrix nodes have a **master task** that tracks all generated tasks.

***

## Manual Triggers

Add approval gates to pause execution until manual intervention:

```yaml theme={null}
nodes:
  - id: manual-approval
    name: Manual Approval
    trigger:
      type: manual
    steps:
      - name: Deploy
        run: ./deploy.sh
```

Resume paused tasks:

```bash theme={null}
# Resume all paused tasks
npx codemod workflow resume -i <run-id> --trigger-all

# Resume a specific task
npx codemod workflow resume -i <run-id> -t <task-uuid>
```

***

## Shared State

State enables workflows to persist data across runs and coordinate work:

```yaml theme={null}
version: "1"
state:
  schema:
    - name: shards
      type: array
      items:
        type: object
        properties:
          team: { type: string }
          shardId: { type: string }
nodes: []
```

You can also use object map syntax:

```yaml theme={null}
state:
  schema:
    shards:
      type: array
      items:
        type: object
        properties:
          team: { type: string }
          shardId: { type: string }
```

### State Updates

| Syntax       | Meaning                | Example                                 |
| ------------ | ---------------------- | --------------------------------------- |
| `KEY=VAL`    | Set state key to value | `count=10`                              |
| `KEY@=VAL`   | Append value to array  | `shards@={"team":"core","shardId":"1"}` |
| Dot notation | Set nested fields      | `config.retries=5`                      |
| JSON values  | Use valid JSON         | `user={"name":"Alice","id":123}`        |

<Info>
  State updates must be valid JSON if not primitive. Updates are applied only if the task exits successfully.
</Info>

***

## Parameters

Parameters make workflows configurable and reusable:

```yaml theme={null}
version: "1"
params:
  schema:
    library:
      name: "Library"
      description: "Internationalization library to use"
      type: string
      default: "next-intl"
    prSize:
      name: "PR Size"
      type: string
      default: "50"
nodes: []
```

### Accessing Parameters

**In JSSG transforms** via `options.params`:

```ts theme={null}
export default function transform(root, options) {
  const library = options.params?.library || "next-intl";
}
```

**In shell steps** as `PARAM_` prefixed environment variables:

```yaml theme={null}
- name: Run script
  run: echo "Library: $PARAM_LIBRARY"
```

**In codemod steps** forwarded with `env_` prefix:

```yaml theme={null}
- name: Run nested codemod
  codemod:
    source: "@org/package"
  env:
    LIBRARY: ${{ params.library }}
```

<Card title="Advanced Parameter Usage" icon="gear" href="/jssg/advanced#accessing-parameters">
  Complete parameter patterns and examples in JSSG.
</Card>

***

## Variable Resolution

Workflow expressions are evaluated in a few different runtime contexts today. The available variables are not identical across all of them.

### Template interpolation

`${{ ... }}` interpolation is used in:

* `run`
* `ai.prompt`
* `branch_name`
* `commit.message`
* `pull_request.title`
* `pull_request.body`

Current variable availability:

| Syntax                  | Available today                                                                                                |
| ----------------------- | -------------------------------------------------------------------------------------------------------------- |
| `${{ params.x }}`       | Available in all of the interpolation sites above                                                              |
| `${{ state.x }}`        | Available in `run`, `ai.prompt`, and `commit.message`, but not in `branch_name` or `pull_request.title`/`body` |
| `${{ matrix.x }}`       | Available in all of the interpolation sites above                                                              |
| `${{ task.id }}`        | Available only in `branch_name`, `commit.message`, and `pull_request.title`/`body` during Campaign/cloud runs  |
| `${{ task.signature }}` | Available only in the same Campaign/cloud git automation fields; default branch names use this value           |

<Tip>
  In matrix tasks, each object key becomes an environment variable (e.g., `$team`, `$shardId`). Inside steps, matrix variables are unprefixed.
</Tip>

<Info>
  `${{ env.x }}` and generic `steps.<id>.outputs.*` interpolation are not wired into workflow runtime expression resolution.
</Info>

### `if` Conditions

Current generic workflow `if` evaluation receives:

* `params.*`
* `state.*`
* `matrix.*`

Current generic workflow `if` evaluation does not receive:

* `task.*`
* `env.*`
* `steps.<id>.outputs.*`

Operators supported in `if` conditions: `==`, `!=`, `>`, `<`, `>=`, `<=`, `&&`, `||`

```yaml theme={null}
- name: Run only for TypeScript
  if: params.language == "typescript"
  js-ast-grep:
    js_file: "scripts/codemod.ts"
```

***

## Task Statuses

| Status            | Description                            |
| ----------------- | -------------------------------------- |
| `Pending`         | Queued; waiting for runner             |
| `Running`         | Currently executing                    |
| `Completed`       | Succeeded; diff applied                |
| `Failed`          | Script exited non-zero; diff discarded |
| `AwaitingTrigger` | Waiting for manual approval            |
| `Blocked`         | Dependencies not finished              |
| `WontDo`          | Matrix item removed; task skipped      |

***

## Cyclic Dependencies

Workflows cannot have circular dependencies:

```yaml theme={null}
nodes:
  - id: a
    depends_on: [b]
    steps:
      - run: echo "A"
  - id: b
    depends_on: [a]
    steps:
      - run: echo "B"
```

This produces an error:

```
Error: Cyclic dependency detected: a → b → a
```

***

## Templates

Templates define reusable step blocks (planned feature):

```yaml theme={null}
templates:
  - id: format
    steps:
      - name: Format
        run: npx prettier --write .
```

***

## Roadmap

<Steps>
  <Step title="Container runtime support" icon="flag-pennant">
    Support for `runtime: docker` and other container runtimes.
  </Step>

  <Step title="Nested matrix strategies" icon="flag-pennant">
    Matrix strategies within matrix strategies for complex fan-out.
  </Step>
</Steps>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Package Structure" icon="folder-tree" href="/package-structure">
    Directory layout and codemod.yaml reference.
  </Card>

  <Card title="CLI Reference" icon="terminal" href="/cli#codemod-workflow">
    Validate and run workflows from the command line.
  </Card>

  <Card title="JSSG Intro" icon="code" href="/jssg/intro">
    Write JavaScript/TypeScript codemods.
  </Card>

  <Card title="Publishing" icon="upload" href="/publishing">
    Share your codemod via the Registry.
  </Card>
</CardGroup>
