Skip to content

aridyckovsky/effect-migrate

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

effect-migrate

TypeScript migration toolkit for adopting Effect with Amp coding agents

TypeScript Effect License: MIT

Quick Start β€’ Documentation β€’ Packages β€’ Contributing


Co-authored by humans and Amp
This repo is developed collaboratively by the maintainers and Amp coding agents. We use shared threads and structured context to keep the agent aligned across sessions and contributors.

⚠️ Early Stage Development
All existing commands are functional and in dogfooding (APIs may change) except the docs command, which is planned. Pin to specific versions if using, though not recommended for production yet!


What is effect-migrate?

effect-migrate helps teams migrate TypeScript codebases to Effect (aka Effect-TS) by detecting legacy patterns, enforcing architectural boundaries, and generating persistent migration context for AI coding agents.

It's co-authored by maintainers and Amp: the tool surfaces what to change, and Amp (or other agents) performs refactors while carrying context forward across sessions and teammates.

Key Features

  • πŸ” Pattern Detection β€” Identify legacy async/await, Promise, and error handling patterns
  • πŸ—οΈ Boundary Enforcement β€” Maintain clean separation between Effect and legacy code
  • πŸ€– Amp Context Generation β€” Writes index.json, audit.json, threads.json for agent ingestion
  • πŸ“Š Time-Series Checkpoints β€” Track migration progress with automatic snapshots and delta computation
  • πŸ”— Thread Continuity β€” Track relevant Amp threads with thread add to resume work with read-thread
  • πŸ“Ž @-mentions First β€” Reference @.amp/effect-migrate/index.json to load the whole context
  • πŸ”§ TypeScript SDK Friendly β€” Drive programmatic workflows via Amp's TypeScript SDK
  • πŸ”Œ Extensible Rules β€” Create custom rules and share presets with your team
  • ⚑ Built with Effect β€” Dogfoods Effect patterns: Effect.gen, Layers, Services, and Schema validation

Why Use effect-migrate?

Effect migrations are iterative and cross-cutting. Without persistent context, coding agents start from scratch in every session:

Traditional workflow (without effect-migrate):

You: "We're migrating to Effect. Don't use async/await in migrated files."
Agent: [suggests async function]
You: "No, I said use Effect.gen instead"
Agent: [fixes it]
[Next session, next day...]
You: "Remember we're migrating to Effect..."

With effect-migrate:

$ effect-migrate audit --amp-out .amp/effect-migrate
You: Read @.amp/effect-migrate/index.json
Agent: [loads audit, metrics, threads via the index, proposes Effect-first refactors]

Continuity across sessions:

  • Start a new thread: Read @.amp/effect-migrate/index.json
  • Reference prior work: read-thread https://ampcode.com/threads/T-... and then load @.amp/effect-migrate/index.json

The context captures:

  • Which files have violations vs. are clean
  • Active rules/boundaries and their documentation
  • Related threads to resume work

Built with Amp, for Amp

We actively co-develop this tool with Amp and use it on this repo.

  • Source of truth: We run effect-migrate audit and commit .amp/effect-migrate/*.json. Amp reads @.amp/effect-migrate/index.json to align suggestions.
  • Shared threads: We document work in Amp threads and reference them in .amp/effect-migrate/threads.json. Anyone can read-thread a prior session to pick up where it left off.
  • Concrete guidance: AGENTS.md encodes Effect patterns. Amp auto-loads this guidance and applies it during refactors.
  • Integration details: See docs/agents/concepts/amp-integration.md

Honest note: effect-migrate's pattern rules are conservative and may surface false positives; Amp's suggestions still require review. We prefer CLI regeneration over manually editing context files to avoid drift.


Packages

This is a monorepo with three core packages:

Package Description Status
@effect-migrate/core Migration engine with services, rules, and schema validation πŸ§ͺ Dogfooding
@effect-migrate/cli Command-line interface built with @effect/cli πŸ§ͺ Dogfooding
@effect-migrate/preset-basic Default Effect migration rules πŸ§ͺ Dogfooding

Each package includes its own README and detailed development guidance in AGENTS.md.


Quick Start

Installation

pnpm add -D @effect-migrate/cli

Or globally:

pnpm add -g @effect-migrate/cli

Note: APIs are unstable and may change. Pin to specific versions in production.

1. Initialize Configuration

effect-migrate init

This creates effect-migrate.config.ts with type-safe configuration:

import { defineConfig } from "@effect-migrate/core"

export default defineConfig({
  version: 1,

  // Load default Effect migration rules
  presets: ["@effect-migrate/preset-basic"],

  paths: {
    include: ["src/**/*.{ts,tsx}"],
    exclude: ["**/{node_modules,dist,build}/**"]
  },

  // Optional: add custom rules that extend the preset
  patterns: [
    {
      id: "no-async-await",
      pattern: "\\basync\\s+function",
      files: "**/*.ts",
      message: "Replace async/await with Effect.gen",
      severity: "warning",
      docsUrl: "https://effect.website/docs/essentials/effect-type"
    }
  ],

  boundaries: [
    {
      id: "no-node-in-services",
      from: "src/services/**/*.ts",
      disallow: ["node:*"],
      message: "Use @effect/platform instead of Node.js APIs",
      severity: "error"
    }
  ]
})

2. Run Migration Audit

effect-migrate audit

Output:

πŸ” Running migration audit...

Pattern Violations
══════════════════
❌ src/api/fetchUser.ts:23
   Replace async/await with Effect.gen (no-async-await)

Boundary Violations
═══════════════════
❌ src/services/FileService.ts:5
   Use @effect/platform instead of Node.js APIs (no-node-in-services)
   Import: node:fs/promises

Summary
═══════
Errors: 1
Warnings: 1

3. Generate Amp Context

# Write context files to .amp/effect-migrate/
effect-migrate audit --amp-out .amp/effect-migrate

Generated files:

  • index.json β€” Entry point referencing all context files
  • audit.json β€” Latest audit snapshot (symlink to checkpoint)
  • checkpoints/ β€” Time-series audit history with deltas
  • threads.json β€” Tracked Amp threads for migration history
  • metrics.json β€” Metrics for the migration process

4. Track Migration Threads

# Add a thread where migration work happened
effect-migrate thread add \
  --url https://ampcode.com/threads/T-abc12345-6789-abcd-ef01-234567890abc \
  --tags "migration,services" \
  --scope "src/services/**"

# List tracked threads
effect-migrate thread list

5. View Checkpoint History

# List audit checkpoints with deltas
effect-migrate checkpoints list

# Show latest checkpoint
effect-migrate checkpoints latest

# Compare two checkpoints
effect-migrate checkpoints diff 2025-11-08T10-00-00Z 2025-11-08T11-30-00Z

6. Use Context in Amp

In your Amp thread:

Read @.amp/effect-migrate/index.json

I'm migrating src/api/fetchUser.ts to Effect.

Amp will:

  • Load the index which references all context files
  • Read audit.json with current violations and rules
  • Know which files have issues vs. are clean
  • Suggest Effect patterns based on active rules
  • Cross-reference prior migration threads from threads.json

Configuration with Presets

Presets provide ready-to-use rule collections. The @effect-migrate/preset-basic preset includes:

  • Pattern rules: Detect async/await, Promise constructors, try/catch, barrel imports
  • Boundary rules: Enforce @effect/platform usage, prevent Node.js built-in imports
  • Default excludes: Automatically excludes node_modules, dist, build artifacts

Preset behavior:

  • Preset rules combine with your custom patterns and boundaries
  • Preset config defaults (like paths.exclude) are merged with your config
  • Your config always wins β€” you can override any preset defaults
  • If a preset fails to load, the CLI logs a warning and continues

See @effect-migrate/preset-basic for the complete list of rules.


Commands

Command Description Status
effect-migrate init Create config file πŸ§ͺ Dogfooding
effect-migrate audit Detect migration issues πŸ§ͺ Dogfooding
effect-migrate thread add --url <url> Track Amp thread πŸ§ͺ Dogfooding
effect-migrate thread list Show migration threads πŸ§ͺ Dogfooding
effect-migrate metrics Show migration progress πŸ§ͺ Dogfooding
effect-migrate docs Validate documentation πŸ“… Not Started
effect-migrate --help Show help βœ… Complete

For detailed command usage, options, and troubleshooting, see the CLI package documentation.


Output Artifacts

When you run audit --amp-out .amp/effect-migrate, the following files are generated:

index.json

Entry point for Amp and other agents. References all context files:

{
  "schemaVersion": "0.2.0",
  "toolVersion": "0.3.0",
  "projectRoot": ".",
  "timestamp": "2025-11-08T00:12:58.610Z",
  "files": {
    "audit": "audit.json",
    "metrics": "metrics.json",
    "badges": "badges.md",
    "threads": "threads.json"
  }
}

audit.json

Detailed findings with file paths, line numbers, and documentation (uses indices for efficiency and smaller memory footprint):

{
  "schemaVersion": "0.2.0",
  "revision": 7,
  "toolVersion": "0.3.0",
  "projectRoot": ".",
  "timestamp": "2025-11-08T00:12:58.610Z",
  "findings": {
    "rules": [
      {
        "id": "no-async-await",
        "kind": "pattern",
        "severity": "error",
        "message": "Replace async/await with Effect.gen",
        "tags": ["async", "migration"]
      },
      {
        "id": "no-console-log",
        "kind": "pattern",
        "severity": "warning",
        "message": "Use Effect Console service instead of console.*",
        "tags": ["effect", "logging"]
      }
    ],
    "files": ["src/api/fetchUser.ts", "src/services/UserService.ts"],
    "results": [
      {
        "rule": 0,
        "file": 0,
        "range": [23, 1, 23, 30]
      },
      {
        "rule": 1,
        "file": 1,
        "range": [45, 5, 45, 20]
      }
    ]
  }
}

metrics.json

Migration progress metrics:

{
  "schemaVersion": "0.2.0",
  "revision": 7,
  "toolVersion": "0.3.0",
  "projectRoot": ".",
  "timestamp": "2025-11-08T00:12:58.651Z",
  "summary": {
    "totalViolations": 17,
    "errors": 0,
    "warnings": 17,
    "info": 0,
    "filesAffected": 13,
    "progressPercentage": 6
  },
  "ruleBreakdown": [
    {
      "id": "no-effect-catchall-success",
      "violations": 12,
      "severity": "warning",
      "filesAffected": 9
    }
  ]
}

threads.json

Tracked Amp threads for context continuity:

{
  "schemaVersion": "0.2.0",
  "toolVersion": "0.3.0",
  "threads": [
    {
      "id": "t-abc12345-6789-abcd-ef01-234567890abc",
      "url": "https://ampcode.com/threads/T-abc12345-6789-abcd-ef01-234567890abc",
      "createdAt": "2025-11-08T00:12:58.625Z",
      "auditRevision": 7,
      "tags": ["migration", "services"],
      "description": "Migrated user services to Effect patterns"
    }
  ]
}

Programmatic Use (Amp TypeScript SDK)

import { execute } from "@sourcegraph/amp-sdk"

async function proposeNextSteps(cwd: string) {
  const prompt = [
    "Load @.amp/effect-migrate/index.json",
    "The index references audit.json and threads.json",
    "Propose the 3 highest-impact files to migrate next."
  ].join("\n")

  for await (const msg of execute({ prompt, options: { cwd, continue: false } })) {
    if (msg.type === "result") {
      console.log(msg.result)
      break
    }
  }
}

See Amp TypeScript SDK documentation for more examples.


Status and Roadmap

Current Status

πŸ§ͺ Dogfooding (functional but APIs may change):

  • Config file creation with TypeScript validation
  • Pattern-based rule detection (regex matching)
  • Boundary rule enforcement (import checking)
  • Audit command with console and JSON output
  • Amp context generation (index.json, audit.json, threads.json)
  • Thread tracking (thread add, thread list)
  • Checkpoint system with time-series audit history
  • Delta computation between consecutive audits
  • Preset loading and rule merging
  • Metrics command for migration progress tracking

πŸ“… Not Started:

  • Documentation rule validation (docs command)

Roadmap

Near-term:

  • Migration context checkpoints with time-series history and delta computation
  • Documentation validation (docs command)
  • Expanded preset coverage (more pattern and boundary rules)
  • Simple metrics monitoring/analytics for migration progress

Medium-term:

  • SQLite persistence layer for checkpoint queryability and analytics
  • Performance instrumentation with OpenTelemetry (audit runtime, memory usage)

Wishlist:

  • Trend analysis and progress tracking (rolling windows, hot spots, burn-down charts)
  • MCP server for programmatic query API
  • Workflow orchestration for distributed audits
  • VS Code extension for inline rule feedback
  • Team dashboards and integration endpoints

See comprehensive data architecture plan for detailed technical roadmap.

We welcome contributions! See Contributing below.


Rule System

Rules detect migration issues and can be shared as presets. See @effect-migrate/preset-basic for examples.

import { Effect } from "effect"
import type { Rule, RuleResult } from "@effect-migrate/core"

export const noConsoleLog: Rule = {
  id: "no-console-log",
  kind: "pattern",
  run: (ctx) =>
    Effect.gen(function* () {
      const files = yield* ctx.listFiles(["**/*.ts", "**/*.tsx"])
      const results: RuleResult[] = []

      for (const file of files) {
        const content = yield* ctx.readFile(file)
        const pattern = /\bconsole\.(log|error|warn|info|debug)/g

        let match: RegExpExecArray | null
        while ((match = pattern.exec(content)) !== null) {
          const index = match.index
          const beforeMatch = content.substring(0, index)
          const line = beforeMatch.split("\n").length
          const column = index - beforeMatch.lastIndexOf("\n")

          results.push({
            id: "no-console-log",
            ruleKind: "pattern",
            message: "Use Effect Console service instead of console.*",
            severity: "warning",
            file,
            range: {
              start: { line, column },
              end: { line, column: column + match[0].length }
            }
          })
        }
      }

      return results
    })
}

Rule Types

Type Purpose Example
pattern Detect code patterns via regex async/await, Promise constructors, try/catch
boundary Enforce architectural constraints No node:* imports in migrated code
docs Validate documentation (planned) Required spec files, no leaked secrets
metrics Track migration completion (planned) Files with @migration-status markers

For detailed rule creation, see the core package documentation.


Real-World Example

For a complete walkthrough, see this Amp thread demonstrating effect-migrate on a realistic project.

The example shows:

  • Setting up a partially migrated codebase with mixed legacy and Effect code
  • Running audit to find violations across files
  • Generating Amp context for persistent migration state
  • Using thread tracking to maintain continuity

Documentation

  • AGENTS.md β€” Comprehensive guide for AI coding agents (Effect patterns, service design, testing)
  • Amp Integration Guide β€” How @ references, thread sharing, read-thread, and SDK flows work
  • Core Package β€” Migration engine architecture and services
  • CLI Package β€” Command-line interface, options, and troubleshooting
  • Preset Package β€” Default migration rules

Local Development

Want to try effect-migrate before it's published? Clone and build locally:

git clone https://github.com/aridyckovsky/effect-migrate.git
cd effect-migrate
pnpm install
pnpm build

Running CLI Locally

During development (no build needed):

# Run directly from source using tsx
pnpm cli --help
pnpm cli audit
pnpm cli thread list
pnpm cli --version

Using built version:

node packages/cli/build/esm/index.js --help
node packages/cli/build/esm/index.js audit

Development Commands

# Install dependencies
pnpm install

# Build all packages
pnpm build

# Run CLI from source (recommended for dev)
pnpm cli <command>

# Run tests
pnpm test

# Type check
pnpm typecheck

# Format
pnpm format

# Lint
pnpm lint

See AGENTS.md for detailed development guidelines, Effect best practices, and anti-patterns to avoid.


Contributing

We welcome contributions! This project is in early stages, so now is a great time to:

  • πŸš€ Implement planned features (metrics, docs commands)
  • πŸ“‹ Add migration rules to @effect-migrate/preset-basic
  • πŸ“ Improve documentation and examples
  • πŸ§ͺ Test on real Effect migration projects
  • πŸ’‘ Provide feedback on the rule API

How to contribute:

  1. Read AGENTS.md for development guidelines and Effect patterns
  2. Check open issues for tasks
  3. Submit PRs following our contributing guidelines

We use Changesets for version management. After making changes, run pnpm changeset to create a changeset describing your changes.


Not Just a Linter

effect-migrate is a stateful migration orchestrator, not a generic linter:

What makes it different:

  • Stateful migration tracking β€” Tracks progress, findings, and decisions over time in .amp/effect-migrate
  • Boundary- and plan-aware β€” Rules express architectural boundaries; context files drive prioritization
  • Agent-native β€” index.json/audit.json/threads.json designed for @ ingestion and read-thread continuity
  • Multi-agent compatible β€” The context format is MCP-style JSON; any agent can consume it

Complementary tools:

  • ESLint β€” Keep your ESLint rules for code quality
  • @effect/language-service β€” Excellent for inline IDE feedback on Effect code patterns; effect-migrate adds migration-specific rules, progress tracking, and agent context
  • effect-migrate β€” Coordinates refactors and keeps Amp coding agents aligned across weeks

Inspiration:

  • ESLint β€” Pluggable rule system and severity levels
  • ts-migrate β€” TypeScript migration automation
  • Production Experience β€” Our own refactoring scripts from real Effect migrations

License

MIT Β© 2025 Ari Dyckovsky


Links


Built with Effect

@effect/cli β€’ @effect/platform β€’ @effect/schema

About

TypeScript migration toolkit for adopting Effect with Amp coding agents

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages