mcpField
E
effect-v4

effect-v4

github.com/klausborgesDevelopment039 installsUpdated 3d ago
Repository

About effect-v4

effect-v4 is a coding skill for projects using Effect v4. It directs developers to verify APIs against installed types and version-matched sources, and provides conventions, references, and a read-only checker.

Key features

  1. 01Source authority order for API checks
  2. 02Effect v4 coding conventions
  3. 03Task-based reference guide
  4. 04Read-only diagnostics checker
  5. 05Guidance on compiler patching

Use cases

  1. 01Checking an Effect API before coding
  2. 02Implementing services, errors, or schemas
  3. 03Reviewing code with the supplied diagnostics preset

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/klausborges/skilltree --skill effect-v4

After installing, type/effect-v4in Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

agents/
openai.yaml
assets/
oxlintrc.json
sgconfig.yml
assets/.ast-grep/rules/
no-effect-in-pure-core.yml
no-effectful-ternary.yml
no-layer-memory.yml
no-live-suffix.yml
no-manual-runtime-in-tests.yml
no-v3-effect-either.yml
no-v3-schema-refinements.yml
no-v3-service-tag.yml
no-v3-servicemap.yml
assets/.ast-grep/tests/
no-effect-in-pure-core-test.yml
no-effectful-ternary-test.yml
no-layer-memory-test.yml
no-live-suffix-test.yml
no-manual-runtime-in-tests-test.yml
no-v3-effect-either-test.yml
no-v3-schema-refinements-test.yml
no-v3-service-tag-test.yml
no-v3-servicemap-test.yml
assets/.ast-grep/tests/__snapshots__/
no-effect-in-pure-core-snapshot.yml
no-effectful-ternary-snapshot.yml
no-layer-memory-snapshot.yml
no-live-suffix-snapshot.yml
no-manual-runtime-in-tests-snapshot.yml
no-v3-effect-either-snapshot.yml
no-v3-schema-refinements-snapshot.yml
no-v3-service-tag-snapshot.yml
no-v3-servicemap-snapshot.yml

Details

From the project README

Effect v4

Effect v4 is barely present in model training data, and effect.website documents v3 — recalled APIs look right and are wrong. Betas are not monotonic: a pattern from another beta is evidence to verify, not a fact, and even the first-party docs lag the shipped code (migration/yieldable.md still documents an .asEffect() that does not exist). When any of these disagree with the source, the source wins.

Established project conventions take precedence unless the task is explicitly changing them.

Source rule

Check these before guessing, highest authority first:

  1. The project's installed types in node_modules/effect — the final word.
  2. A pinned checkout of the Effect source, if the repo vendors one, at the tag matching the project's version.
  3. First-party docs in that checkout: LLMS.md, ai-docs/src/**, migration/**, packages/effect/SCHEMA.md.
  4. These reference files.

State the project's pinned version before writing Effect code.

Which reference to read

Read only what the task needs.

TaskRead
What earns a service or seam, coordinator/store splits, contracts-first, design reviewreferences/architecture.md
Services, layers, DI, where to provide, Effect.fnreferences/services-layers.md
Typed errors, catching, recovery, defectsreferences/errors.md
Retry/repeat policies, polling, TTL cachesreferences/schedule-cache.md
Schema, parsing untrusted input, domain modellingreferences/schema-boundaries.md
Tests, fakes, TestClock, property testsreferences/testing.md
Entrypoints, runtimes, Config, CLI, observabilityreferences/runtime-config.md
Porting v3 code, or an API that "should" existreferences/v3-to-v4.md
Which package or import path a module lives inreferences/module-paths.md

If a task spans several, read all the matching files before editing.

Core defaults

SituationUse
Define a serviceclass X extends Context.Service<X, Shape>()("pkg/dir/X") {}
Attach an implementationstatic readonly layer = Layer.effect(X, ...) returning X.of({...})
Name a function returning an EffectEffect.fn("X.method")(function* () {...})
Add combinators to an Effect.fntrailing arguments — not .pipe
Define an errorclass E extends Schema.TaggedErrorClass<E>()("E", {...}) {}
Raise an errorreturn yield* E.make({...}) — the return is required
CatchEffect.catchTag / catchTags; Effect.catch for the whole channel
Wrap a foreign causecause: Schema.Defect()
Decode untrusted inputSchema.decodeUnknownEffect(S)(input)
Refine a schema.check(Schema.isMinLength(1))
Model a domain valueSchema.Class; Schema.Struct for structural shapes
Read configConfig.*, never process.env
Current time / randomnessClock, DateTime, Random — never Date.now, Math.random
Files, paths, terminalFileSystem, Path from core effect — not node:fs
Run the programNodeRuntime.runMain / BunRuntime.runMain
Write a testit.effect with assert from @effect/vitest
provide layersinside a layer closing its own dependencies, and once at the process root — nowhere else

Layer naming

layer (production) · layerNoDeps (dependencies left in RIn) · layerFake · layerTest · layerInProcess · layerInMemoryStore · layerFromEnv

Never Live suffixes. Never the generic layerMemory.

Enforcement preset

The skill ships a read-only checker for these rules. Run it against a project before review or after substantial edits:

nu <path-to-this-skill>/scripts/check-effect.nu <project-dir> [source-paths...]

It runs effect-tsgo diagnostics, oxlint, and ast-grep using the preset in assets/, never writes to the target, and reports gates whose tools the target lacks as skipped. Wiring the diagnostics permanently into a project's tsconfig/editor is first-party territory: npx @effect/tsgo setup.

assets/tsconfig-compiler-options.json is the strictness baseline the diagnostics assume; extend it alongside tsconfig-language-service.json. Without strict there is no noImplicitAny, and effectFnImplicitAny silently no-ops.

effect-tsgo patch is not idempotent — it patches the installed tsc binary in place. Guard it: tsc --version reports a +effect-tsgo.<version> suffix once patched, so patch only when that suffix is absent or does not equal the installed @effect/tsgo version. A bare "prepare": "effect-tsgo patch" re-patches an already-patched compiler.

Adapter carve-outs

Adapter files are where vendor reality lands, and a few diagnostics have to yield there. Silence the narrowest thing that works:

  • // @effect-diagnostics <rule>:off at the top of the file — the preferred form. A project-local plugin overrides entry is discarded by any runner that injects config with --lspconfig (it replaces project plugin config); the pragma survives both paths. See references/runtime-config.md.
  • For leakingRequirements specifically, the language service has two JSDoc escapes: @effect-leakable-service on the interface declaration of a dependency that is meant to be passed through, or @effect-expect-leaking <Type> on the service that leaks it.

Every carve-out is a claim that the vendor boundary is genuinely here. If a file needs several, the boundary is drawn in the wrong place.

Do nots

  • Do not use try/catch inside Effect.gen — it cannot see an Effect failure. Use Effect.result and branch.
  • Do not use async/await or bare Promises; cross the boundary with Effect.tryPromise.
  • Do not call Effect.runPromise / runSync / runFork in library code.
  • Do not write a plain function whose only body is a returned Effect.gen — use Effect.fn.
  • Do not use as any, as unknown as, non-null !, or unchecked casts to silence Effect typing. Branch, parse, or refine instead.
  • Do not JSON.parse(x) as T — decode through a schema.
  • Do not hand-roll isString-style guards; use Predicate.
  • Do not hand-roll retry/poll loops or TTL caches; use Schedule and Cache.
  • Do not Effect.orDie on config, state, reconciliation, or recovery paths.
  • Do not import v3 packages: @effect/platform, @effect/schema, @effect/cli, @effect/rpc, @effect/cluster, @effect/experimental.
  • Do not use Context.Tag, Context.GenericTag, Effect.Tag, or anything named ServiceMap — all are pre-v4 or intermediate-beta names.
  • Do not use Layer.mergeAll or provideMerge as make-it-compile tools.

Comments

Markdown supported