Skip to content
Agentmart
Submit a tool

effect-v3-to-v4

Effect v3 to v4 migration.

Skill by andabove

IndexedMIT
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/andabove-effect-v3-to-v4

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Effect v3 to v4 migration. Use when you upgrade `effect` or any `@effect/*` package from 3.x to 4.x, when you fix code or docs that use Effect 3 API names, or when you review a v4 migration.

Use cases: backend

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/effect-v3-to-v4

What's inside

Skill name
effect-v3-to-v4
Description
Effect v3 to v4 migration. Use when you upgrade `effect` or any `@effect/*` package from 3.x to 4.x, when you fix code or docs that use Effect 3 API names, or when you review a v4 migration.
License
MIT
Instructions
194 lines in SKILL.md · view on GitHub

Files (4)

  • SKILL.md
  • effect-v3-to-v4-errata.md · references/
  • effect-v3-to-v4-removed.md · references/
  • effect-v3-to-v4-renames.md · references/

SKILL.md (first lines)

# Effect v3 to v4 Migration

Checked against `effect` 4.0.0 (git tag `effect@4.0.0`, commit `67ba4e46a11c`). When the project targets a newer 4.x, use that version's tag in every command below.

Drive an Effect v3 to v4 migration from the generated migration reference that ships in the Effect repo, and confirm each answer in the v4 source. Every rename, removal, and signature change is answered by upstream data and the source - do not guess replacements.

## Workflow

Work through these steps in order; each one is detailed in the section named.

1. **Set up and validate the local checkouts** - two shallow clones pinned to release tags; verify any pre-existing `.repos/effect` before trusting it. See **Setup: Local Checkouts**.
2. **Read `MIGRATION.md`** and `ls .repos/effect/migration/` for the background and guide index. See **Reading Order**.
3. **Migrate `package.json`** - remove consolidated packages, align every remaining Effect package on one v4 version. Do this before type-checking, or the first run drowns in unresolved-import noise from packages that no longer exist. See **Repo-Level Changes**.
4. **Run the project's type-check** (e.g. `tsc --noEmit`) to get the initial error inventory.
5. **Iterate until the type-check is clean.** For each error, resolve the API through the lookup discipline - check **The renames you meet most** first, then search `migration/v3-to-v4.md` for the symbol, escalate per **Reading Order** - then fix the call site, delegating per-file fixes to sub-agents per **Delegating to Sub-Agents**. Never silence an error instead of resolving it; see **Hard Prohibitions**.
6. **Fix the runtime changes the type-check cannot see.** See **Changes that still compile**.
7. **Finish** - type-check clean; run tests and report their outcome honestly (not a gate); write the final summary. See **Done Condition**.

## Setup: Local Checkouts

The migration is driven from two shallow, single-branch clones of the canonical Effect repo, each pinned to a release tag:

```sh
git clone --depth 1 --single-branch --branch effect@4.0.0 https://github.com/Effect-TS/effect .repos/effect
git clone --depth 1 --single-branch --branch effect@3.22.2 https://github.com/Effect-TS/effect .repos/effect-v3
```

- `.repos/effect` - v4 at the version you migrate to. Contains `MIGRATION.md`, the `migration/` guides, and the v4 source.
- `.repos/effect-v3` - v3 at the version the project uses now (read it from the lockfile; `3.22.2` is the last v3 release on 2026-10-01). Escalation-only reference for old semantics.
- Add `.repos/` to `.gitignore`.

Each clone is independently re-runnable and separately deletable. Do not use `git worktree` to share one clone between branches. Do not clone `main`: it moves past the release you install, and its source and guides can describe APIs that your version does not have.

### Validate an existing checkout before trusting it

`./.repos/effect` may already exist, cloned from the archived `Effect-TS/effect-smol` repo by older setup instructions. That checkout is dead: it is stale and does not contain `migration/v3-to-v4.md`. A clone of `main` from the same instructions is not pinned to your version. Verify before using:

```sh
git -C .repos/effect remote get-url origin   # must be the canonical Effect-TS/effect repo
git -C .repos/effect describe --tags          # must be the effect@4.x tag you install
test -f .repos/effect/migration/v3-to-v4.md   # must exist
```

If the origin points at `effect-smol`, the tag is not the version in the lockfile, or the reference file is missing, delete the directory and re-clone as above.

## Reading Order

1. **Front-load `MIGRATION.md` once** (`.repos/effect/MIGRATION.md`).
2. **The renames table below**, for the names that most v3 code uses. Each entry was checked against the 4.0.0 source.
3. **`migration/v3-to-v4.md` - the first stop for every other API.** The generated reference covers every removed or changed API. Search it (see below); never read it whole.
4. **A per-topic guide** (`.repos/effect/migration/*.md`) when the mapping implies a rewrite rather than a rename - e.g. `Context.Tag` to `Context.Service` is a structural change, not a symbol swap. Reach these on demand from the `MIGRATION.md` index, not front-loaded.
5. **v4 source** (`.repos/effect/packages/*/src/`) to confirm a replacement's real signature before writing code against it. The source wins over the reference and the guides: see **Where the docs disagree with 4.0.0**.
6. **v3 source** (`.repos/effect-v3`) as escalation only - for when unsure about the old v3 semantics.

## Never Read the Reference Doc Whole

**This is the single most important rule in this skill.** `migration/v3-to-v4.md` is about 16,800 lines at `effect@4.0.0`. Reading it in one pass blows the context window and takes the migration with it.

Always search it and read only matched lines plus surrounding context. The file has four sections - **Import Map**, **No Counterpart Imports**, **Removed Modules**, and **API Reference** (one `` ### `<v3 module path>` `` heading per module). Entries are grep-able one-liners of the form `` - `Old.symbol` -> `New.symbol`: <rationale> ``, and removals are explicit `` -> `none` `` entries with a stated alternative.

Concrete recipes:

```sh
# Look up a specific v3 symbol
rg -n 'Effect\.catchSomeDefect' .repos/effect/migration/v3-to-v4.md

# Read a whole module's section via its heading
rg -n -A 40 '^### `@effect/platform/FileSystem`' .repos/effect/migration/v3-to-v4.md

# Resolve a v3 import path in the Import Map
rg -n '^@effect/platform/FileSystem ' .repos/effect/migration/v3-to-v4.md

# List every module section for a package
rg -n '^### `@effect/cluster/' .repos/effect/migration/v3-to-v4.md

# Confirm the target exists in the v4 source before you use it
rg -n '^export (const|function|type|interface|class) catchFilter\b' .repos/effect/packages/effect/src/Effect.ts
```

Read the rationale after each target, not only the name: for entries such as `Logger.replace`, `Effect.timeoutTo`, `ConfigProvider.fromMap` and `Queue.takeUpTo` it holds the part of the rewrite that the target name alone loses. Look up APIs as you encounter them, one search at a time. A miss in the Import Map is not a dead end - check the **Removed Modules** and **No Counterpart Imports** sections before concluding anything. The reference was generated from a commit before the release tag (its header names commit `072cdc42`, which is not in the published history), so confirm each target in the v4 source.

## The renames you meet most

Each v4 name below was checked in the 4.0.0 source and type checked in use. The full map, grouped by module, with the v3 names that the reference misses: [references/effect-v3-to-v4-renames.md](references/effect-v3-to-v4-renames.md).

| v3 | v4 |
| --- | --- |
| `Effect.catchAll`, `catchAllCause`, `catchAllDefect` | `Effect.catch`, `catchCause`, `catchDefect` |
| `Effect.catchSome`, `catchSomeCause` | `Effect.catchFilter`, `catchCauseFilter` (take a `Filter`, not an `Option`-returning function) |
| `Effect.catchSomeDefect` | removed: `Effect.catchDefect`, and `Effect.die` again for defects you do not handle |
| `Effect.catch(discriminator, { failure, onFailure })` | `Effect.catchTag` for `_tag`, `Effect.catchIf` for another field; v4 `Effect.catch` takes only a handler |
| `Effect.either` | `Effect.result` |
| `Effect.fork`, `forkDaemon` | `Effect.forkChild`, `forkDetach` |
| `Effect.zipRight`, `zipLeft` | `Effect.andThen`, `Effect.tap` |
| `Effect.tapErrorCause` | `Effect.tapCause` |
| `Effect.async` | `Effect.callback` (an effect returned from the callback is still the interrupt cleanup) |
| `Effect.asyncEffect` | not a rename: v3 ran the returned effect as the registration, v4 runs it only on interruption. Register with `Effect.acquireRelease` in a scope and hand the result over through a `Deferred` (recipe in the renames reference) |
| `Effect.fromNullable` | `Effect.fromNullishOr` |
| `Effect.optionFromOptional` | `Effect.catchNoSuchElement` |
| `Effect.orElse(() => fallback)` | `Effect.catch(() => fallback)` |
| `Effect.orElseFail(() => e)` | `Effect.mapError(() => e)` |
| `Effect.timeoutFail({ duration, onTimeout })` | `Effect.timeoutOrElse({ duration, orElse: () => Effect.fail(onTimeout()) })` |
| `Effect.timeoutTo({ duration, onSuccess, onTimeout })` | `Effect.map(onSuccess)` first, then `Effect.timeoutOrElse({ duration, orElse: () => Effect.succeed(onTimeout()) })`; without the `map`, the success value loses its transformation |
| `Effect.dieMessage(m)` | `Effect.die(new Error(m))` |
| `Effect.ignoreLogged` | `Effect.ignoreCause({ log: "Debug" })` (the reference's `Effect.ignore({ log: true })` lets defects through) |
| `Effect.makeSemaphore`, `makeLatch` | `Semaphore.make`, `Latch.make` |
| `Effect.withConcurrency` | removed: pass `{ concurrency }` to each `all`, `forEach` or stream operator |
| `Effect.gen(this, function*() {})` | `Effect.gen({ self: this }, function*() {})` |
| `Context.Tag`, `Context.GenericTag`, `Effect.Tag` | `Context.Service<Self, Shape>()("id")`, or `Context.Service<Shape>("id")` |
| `Effect.Service` with `effect` and `dependencies` | `Context.Service<Self>()("id", { make })` plus your own `static layer = Layer.effect(this, this.make).pipe(Layer.provide(...))` |
| `MyService.method(...)` (a `Tag` accessor) | `MyService.use((s) => s.method(...))`, or `yield* MyService` |
| `FiberRef.currentLogLevel` and the other built-in `FiberRef`s | `References.CurrentLogLevel` and the rest of `References` |
| `FiberRef.set`, `reset`, `delete`, `update` | not a rename: v4 references cannot be mutated. Wrap the work that must see the value in `Effect.provideService(work, Reference, value)`; model shared mutable state, or state a parent reads after joining a child, with a `Ref` |
| `Effect.locally(effect, ref, value)` | `Effect.provideService(effect, Reference, value)` |
| `Runtime<R>`, `Effect.runtime<R>()`, `Runtime.runFork(rt)` | `Context<R>`, `Effect.context<R>()`, `Effect.runForkWith(context)` |
| `Layer.scoped`, `scopedDiscard` | `Layer.effect`, `effectDiscard` |
| `Layer.fail(e)` | `Layer.effectDiscard(Effect.fail(e))` (the reference's `Layer.unwrap(Effect.fail(e))` types `E` and `R` as `unknown`) |
| `Logger.replace(Logger.defaultLogger, l)` | `Logger.layer([l, Logger.tracerLogger])`: `Logger.layer` replaces the whole set, and v3 `replace` kept `tracerLogger`; list any other logger the app adds too |
| `Either.right`, `left`, `Right`, `Left`, `isRight`, `isLeft` | `Result.succeed`, `fail`, `Success`, `Failure`, `isSuccess`, `isFailure` |

From andabove/skills, MIT.

More from andabove/skills

Signals

Stars
0
Forks
0
Open issues
0
Last commit (this folder)
Oct 3, 2026 (26 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from andabove

Cite this page

effect-v3-to-v4 skill. Agent Mart. https://agentmart.dev/skills/andabove-effect-v3-to-v4 (last updated 2026-10-24)