Effect v4
The CLI, @composio/cli-keyring, and @composio/json-schema-to-effect-schema run on
Effect v4 (release candidate). Every claim below is grounded in the migrated source, not memory of v3.
Exact version matrix
effect, @effect/platform-bun, and @effect/vitest
are pinned to the same exact 4.0.0-rc.112 — never ^, @next, or a mismatched
prerelease across packages. @effect/cli and @effect/platform no longer exist as
dependencies; their surfaces are consolidated into effect and effect/unstable/*.
See versions.json for the full matrix (also typescript, vitest).
Read next
- references/core-patterns.md — services, layers, typed
errors, Schema, choosing between
Effect.gen and Effect.fn, and the v3→v4 rename table
(labeled historical, for recognizing stale patterns).
- references/cli-surface.md —
effect/unstable/cli:
Command, Flag, Argument, GlobalFlag, CliConfig, the custom
CliOutput.Formatter, and the runner's double-print rule.
- references/upgrade-workflow.md — procedure for
bumping to a newer prerelease.
Code excerpts in those references are short quotes from real, currently-compiling repo
files (path cited at each excerpt) — not standalone examples. The compile-checked
source of truth is always the cited file itself; when it and a reference disagree,
trust the file and fix the reference.
Non-negotiables
Effect.gen(function* () {...}) for effect values — the dominant form, including named
module consts — and (params) => Effect.gen(...) for parameterized helpers.
Effect.fn(...) is the function form whose effects carry stack-frame annotations (its
optional name string adds a per-call tracing span), worth it for service members and
combinator callbacks that should be attributable in error reports. All forms re-run
their body per execution. See "Effect.gen vs Effect.fn" in core-patterns.
- Define services with
Context.Service and an explicit static readonly Default/layer
layer built with Layer.succeed/Layer.effect/Layer.provide. V4 does not generate a
layer for you.
- Model expected failures with
Schema.TaggedError (or a plain Data.TaggedError
when no Schema fields are needed) and recover with Effect.catchTag/catchTags/Match,
never manual _tag string comparisons.
- Wrap fallible Promises with
Effect.tryPromise({ try, catch }); Effect.promise turns
rejection into a defect. No async/await or try/catch inside Effect workflows —
ESLint bans them in ts/packages/cli/src.
- Treat every remembered v3 package name and API as wrong until verified against
ts/vendor/effect (read-only source oracle — never edit or import from it) and the
installed effect@4.0.0-rc.112 typings. Source may be ahead of the published package;
the compiler is the compatibility gate.
Verification
pnpm typecheck
pnpm --filter @composio/cli test
Run pnpm validate:agent-skills and pnpm validate:skill-routing after editing this
skill or its descriptions, and compile the TypeScript blocks in this skill and in
typescript-testing/references/effect-v4-cli.md against the pinned packages with:
node .agents/skills/effect-v4/scripts/check-examples.mjs
Blocks that quote repo files with unresolvable imports carry a no-check fence info string.
1---2name: effect-v43description: Write, review, or upgrade Effect v4 code in the Composio CLI, cli-keyring, and json-schema-to-effect-schema packages, all pinned exactly to effect@4.0.0-rc.112 — Context.Service and explicit layers, Schema.TaggedError and typed recovery, the effect/unstable/cli command surface, and the vendored effect source oracle. Use when writing or reviewing Effect v4 code, answering a v4 API question, working in effect/unstable/cli, defining a Context.Service service, modeling an error with Schema.TaggedError, bumping the Effect prerelease pins, or verifying an unfamiliar API against ts/vendor/effect. Do not use for CLI command UX/wiring design (use cli-command) or CLI E2E tests (use cli-e2e).4---56# Effect v478The CLI, `@composio/cli-keyring`, and `@composio/json-schema-to-effect-schema` run on9Effect v4 (release candidate). Every claim below is grounded in the migrated source, not memory of v3.1011## Exact version matrix1213`effect`, `@effect/platform-bun`, and `@effect/vitest`14are pinned to the **same exact** `4.0.0-rc.112` — never `^`, `@next`, or a mismatched15prerelease across packages. `@effect/cli` and `@effect/platform` no longer exist as16dependencies; their surfaces are consolidated into `effect` and `effect/unstable/*`.17See [versions.json](versions.json) for the full matrix (also `typescript`, `vitest`).1819## Read next2021- [references/core-patterns.md](references/core-patterns.md) — services, layers, typed22 errors, Schema, choosing between `Effect.gen` and `Effect.fn`, and the v3→v4 rename table23 (labeled historical, for recognizing stale patterns).24- [references/cli-surface.md](references/cli-surface.md) — `effect/unstable/cli`:25 `Command`, `Flag`, `Argument`, `GlobalFlag`, `CliConfig`, the custom26 `CliOutput.Formatter`, and the runner's double-print rule.27- [references/upgrade-workflow.md](references/upgrade-workflow.md) — procedure for28 bumping to a newer prerelease.2930Code excerpts in those references are short quotes from real, currently-compiling repo31files (path cited at each excerpt) — not standalone examples. The compile-checked32source of truth is always the cited file itself; when it and a reference disagree,33trust the file and fix the reference.3435## Non-negotiables3637- `Effect.gen(function* () {...})` for effect values — the dominant form, including named38 module consts — and `(params) => Effect.gen(...)` for parameterized helpers.39 `Effect.fn(...)` is the function form whose effects carry stack-frame annotations (its40 optional name string adds a per-call tracing span), worth it for service members and41 combinator callbacks that should be attributable in error reports. All forms re-run42 their body per execution. See "`Effect.gen` vs `Effect.fn`" in core-patterns.43- Define services with `Context.Service` and an explicit `static readonly Default`/`layer`44 layer built with `Layer.succeed`/`Layer.effect`/`Layer.provide`. V4 does not generate a45 layer for you.46- Model expected failures with `Schema.TaggedError` (or a plain `Data.TaggedError`47 when no Schema fields are needed) and recover with `Effect.catchTag`/`catchTags`/`Match`,48 never manual `_tag` string comparisons.49- Wrap fallible Promises with `Effect.tryPromise({ try, catch })`; `Effect.promise` turns50 rejection into a defect. No `async`/`await` or `try`/`catch` inside Effect workflows —51 ESLint bans them in `ts/packages/cli/src`.52- Treat every remembered v3 package name and API as wrong until verified against53 `ts/vendor/effect` (read-only source oracle — never edit or import from it) and the54 installed `effect@4.0.0-rc.112` typings. Source may be ahead of the published package;55 the compiler is the compatibility gate.5657## Verification5859```bash60pnpm typecheck61pnpm --filter @composio/cli test62```6364Run `pnpm validate:agent-skills` and `pnpm validate:skill-routing` after editing this65skill or its descriptions, and compile the TypeScript blocks in this skill and in66`typescript-testing/references/effect-v4-cli.md` against the pinned packages with:6768```bash69node .agents/skills/effect-v4/scripts/check-examples.mjs70```7172Blocks that quote repo files with unresolvable imports carry a `no-check` fence info string.