Search

Sign in to launch Copilot/Codex from the palette.

Back to prompts

Effect-First

Modular AI-agent reference for Effect-TS. 9 rules, token-budgeted modules, and a fetch strategy that gives agents exactly the context they need.

Engineering Updated Feb 23, 2026 ~1.1k tokens
0.6% of 200k
You write Effect-first TypeScript. Your reference is https://effect-first.coey.dev — a plain-text resource designed for AI coding agents.

## How to use effect-first.coey.dev

Fetch ONLY what you need. Each endpoint is a standalone module with a known token cost:

  /rules        ~1,000 tokens   The 9 rules (start here)
  /reference    ~800 tokens     Type signatures + primitives
  /examples     ~2,300 tokens   Copy-paste patterns
  /anti-patterns ~650 tokens    What NOT to do
  /http-server  ~1,700 tokens   @effect/platform HTTP APIs
  /http-client  ~1,100 tokens   Typed requests + resilience
  /sql          ~1,650 tokens   @effect/sql tagged queries + models
  /cli          ~900 tokens     Command execution + arg parsing
  /streams      ~1,200 tokens   Pull-based backpressured sequences
  /concurrency  ~1,000 tokens   Fibers, racing, structured parallelism
  /resources    ~900 tokens     Lifecycle, pools, scoped cleanup
  /full         ~7,000 tokens   All core sections combined

Custom bundles: /full?modules=rules,reference,examples

## Fetch strategy

Most tasks: fetch /rules + /reference (~1,800 tokens). That's enough for 80% of Effect work.
Building an API: add /http-server and/or /http-client.
Database work: add /sql.
Need examples: add /examples.
Debugging bad patterns: fetch /anti-patterns.
Full context: /full — still only 7k tokens, 3.5% of Claude's 200k window.

## The 9 Rules (summary)

1. Effect.fn — Wrap all effectful functions: Effect.fn("name")(function* (...) { })
2. Effect.gen — Sequence with generators: yield* to compose effects
3. Schema.TaggedError — All errors are tagged, recovered with catchTag
4. Context.Tag + Layer — Services are tags, implementations are layers, compose at entry point
5. Schema for data — Schema.Class for records, Schema.TaggedClass for unions, brand primitives
6. Schema.Config — Validated env vars, Config.redacted for secrets
7. Resilience via pipe — timeout, retry(exponential), tap, span — each ~1 line
8. @effect/vitest — it.effect() and it.layer() for testing
9. Service-driven dev — Sketch contracts first → orchestrate → implement layers → wire at entry

## Quick wins (1-liners)

Slow AI response?     → Stream it
Same request twice?   → Cache it
Request hanging?      → Effect.timeout("5 seconds")
Request failing?      → Effect.retry(Schedule.exponential("100 millis"))
Unknown issue?        → Effect.withSpan("operation") for observability

## Key type

Effect<A, E, R>
  A = success value
  E = typed error channel (tagged errors only)
  R = required services (provided via layers)

## Anti-patterns to internalize

✗ async/await          → use Effect.fn + Effect.gen + yield*
✗ try/catch            → use Effect.catchTag / Effect.catchAll
✗ throw new Error()    → use Schema.TaggedError
✗ Promise<T> returns   → use Effect<A, E, R>
✗ scattered .provide() → compose one appLayer, provide once at entry
✗ raw string IDs       → brand with Schema.brand()
✗ manual fetch()       → use HttpClient tag + schema decoding
✗ .then() / await      → always yield* inside Effect.gen

## When to reach for each module

Building HTTP endpoints?       → /http-server (HttpApiGroup + HttpApiEndpoint + schema validation)
Making HTTP requests?          → /http-client (HttpClient tag + schemaBodyJson + retry)
Database queries?              → /sql (tagged templates + Model.Class + SqlResolver batching)
Running external processes?    → /cli (Command.make + streamLines + piping)
Processing data sequences?     → /streams (Stream.make + map/filter/flatMap + Sink)
Parallel work?                 → /concurrency (Effect.all + fork/join + FiberSet)
Managing connections/files?    → /resources (acquireRelease + Layer.scoped + Pool)

## Service pattern (the core of everything)

// 1. Define the contract
class MyService extends Context.Tag("@app/MyService")<MyService, {
  readonly doThing: (input: string) => Effect.Effect<Output, MyError>
}>() {}

// 2. Implement as a Layer
const MyServiceLive = Layer.succeed(MyService, {
  doThing: Effect.fn("doThing")(function* (input) {
    // implementation
  })
})

// 3. Use anywhere via yield*
const program = Effect.gen(function* () {
  const svc = yield* MyService
  return yield* svc.doThing("hello")
})

// 4. Provide ONCE at entry point
const appLayer = Layer.provideMerge(MyServiceLive, OtherServiceLive)
program.pipe(Effect.provide(appLayer), Effect.runPromise)

When writing Effect code, always check effect-first.coey.dev for the correct pattern before guessing.

How to use this prompt

  1. Copy the prompt using the button above
  2. Paste it into your preferred AI coding assistant
  3. Adjust any placeholders or context as needed
  4. Let the agent implement the changes