effect-ts

SKILL.md

Effect TypeScript

Effect is a powerful TypeScript library for building type-safe, composable applications with excellent error handling, dependency injection, and concurrency support.

Quick Start

Create new project

npx create-effect-app@latest    # npm
pnpm create effect-app@latest   # pnpm
yarn create effect-app@latest   # yarn
bunx create-effect-app@latest   # bun

Add to existing project

npm install effect    # npm
pnpm add effect       # pnpm
yarn add effect       # yarn
bun add effect        # bun
deno add npm:effect   # deno

Core Concepts

Effect<A, E, R>

The core type representing a computation that:

  • Succeeds with value A
  • Fails with error E
  • Requires dependencies R
import { Effect } from "effect"

// Succeed with a value
const success = Effect.succeed(42)

// Fail with an error
const failure = Effect.fail(new Error("Something went wrong"))

// Wrap a Promise
const fromPromise = Effect.tryPromise(() => fetch("/api/data"))

Running Effects

// Sync (throws on error)
Effect.runSync(effect)

// Promise
Effect.runPromise(effect)

// With exit status
Effect.runPromiseExit(effect)

// Fire and forget
Effect.runFork(effect)

Generator Pattern (Effect.gen)

The recommended way to compose Effects using generators:

import { Effect } from "effect"

const program = Effect.gen(function* () {
  const a = yield* Effect.succeed(1)
  const b = yield* Effect.succeed(2)
  return a + b
})

With error handling:

const program = Effect.gen(function* () {
  const config = yield* loadConfig()
  const db = yield* connectDatabase(config)
  const users = yield* db.query("SELECT * FROM users")
  return users
})

Pipe Pattern

Compose operations using pipe:

import { Effect, pipe } from "effect"

const result = pipe(
  Effect.succeed(5),
  Effect.map((n) => n * 2),
  Effect.flatMap((n) => Effect.succeed(n + 1))
)

Error Handling

// Catch all errors
Effect.catchAll(effect, (error) => Effect.succeed("fallback"))

// Catch specific errors
Effect.catchTag(effect, "NotFound", () => Effect.succeed(null))

// Map errors
Effect.mapError(effect, (e) => new CustomError(e))

// Provide fallback
Effect.orElse(effect, () => fallbackEffect)

Dependency Injection with Layer

Define a Service

import { Effect, Context, Layer } from "effect"

class Database extends Context.Tag("Database")<
  Database,
  { query: (sql: string) => Effect.Effect<unknown[]> }
>() {}

Create a Layer

const DatabaseLive = Layer.succeed(Database, {
  query: (sql) => Effect.succeed([{ id: 1 }])
})

Use the Service

const program = Effect.gen(function* () {
  const db = yield* Database
  return yield* db.query("SELECT * FROM users")
})

// Provide the layer
Effect.runPromise(Effect.provide(program, DatabaseLive))

Effect.Service (simplified pattern)

class Cache extends Effect.Service<Cache>()("app/Cache", {
  effect: Effect.gen(function* () {
    const fs = yield* FileSystem.FileSystem
    return {
      lookup: (key: string) => fs.readFileString(`cache/${key}`)
    }
  }),
  dependencies: [NodeFileSystem.layer]
}) {}

Configuration

import { Effect, Config } from "effect"

const program = Effect.gen(function* () {
  const host = yield* Config.string("HOST")
  const port = yield* Config.number("PORT")
  const apiKey = yield* Config.redacted("API_KEY") // Sensitive
  return { host, port, apiKey }
})

// With defaults
const port = Config.number("PORT").pipe(Config.withDefault(8080))

Packages Reference

Package Use Case
effect Core library
@effect/platform Cross-platform abstractions (HTTP, FileSystem, Terminal)
@effect/platform-node Node.js implementations
@effect/platform-bun Bun implementations
@effect/schema Data validation and transformation
@effect/ai AI/LLM abstractions
@effect/ai-openai OpenAI provider
@effect/ai-anthropic Anthropic provider
@effect/opentelemetry Tracing and metrics

Platform: FileSystem

import { FileSystem } from "@effect/platform"
import { NodeContext, NodeRuntime } from "@effect/platform-node"
import { Effect } from "effect"

const program = Effect.gen(function* () {
  const fs = yield* FileSystem.FileSystem
  const content = yield* fs.readFileString("./file.txt", "utf8")
  yield* fs.writeFileString("./output.txt", content.toUpperCase())
})

NodeRuntime.runMain(program.pipe(Effect.provide(NodeContext.layer)))

Platform: HTTP Client

import { HttpClient } from "@effect/platform"
import { NodeRuntime } from "@effect/platform-node"
import { Effect } from "effect"

const program = Effect.gen(function* () {
  const client = yield* HttpClient.HttpClient
  const response = yield* client.get("https://api.example.com/data")
  return yield* response.json
})

Platform: Command

import { Command } from "@effect/platform"
import { NodeContext, NodeRuntime } from "@effect/platform-node"
import { Effect } from "effect"

const program = Effect.gen(function* () {
  const output = yield* Command.string(Command.make("ls", "-la"))
  console.log(output)
})

NodeRuntime.runMain(program.pipe(Effect.provide(NodeContext.layer)))

AI Integration

import { OpenAiClient, OpenAiLanguageModel } from "@effect/ai-openai"
import { LanguageModel } from "@effect/ai"
import { NodeHttpClient } from "@effect/platform-node"
import { Config, Effect, Layer } from "effect"

const generateText = Effect.gen(function* () {
  const response = yield* LanguageModel.generateText({
    prompt: "Generate a greeting"
  })
  return response.text
})

const Gpt4o = OpenAiLanguageModel.model("gpt-4o")

const OpenAi = OpenAiClient.layerConfig({
  apiKey: Config.redacted("OPENAI_API_KEY")
}).pipe(Layer.provide(NodeHttpClient.layerUndici))

const main = generateText.pipe(
  Effect.provide(Gpt4o),
  Effect.provide(OpenAi)
)

Observability: Logging

import { Effect } from "effect"

Effect.gen(function* () {
  yield* Effect.log("Info message")
  yield* Effect.logDebug("Debug message")
  yield* Effect.logWarning("Warning message")
  yield* Effect.logError("Error message")
})

// With annotations
Effect.log("Processing").pipe(
  Effect.annotateLogs({ userId: "123", action: "login" })
)

// With spans (timing)
Effect.gen(function* () {
  yield* Effect.sleep("1 second")
  yield* Effect.log("Done")
}).pipe(Effect.withLogSpan("operation"))

Concurrency: Fibers

import { Effect, Fiber } from "effect"

const program = Effect.gen(function* () {
  // Fork a fiber (runs concurrently)
  const fiber = yield* Effect.fork(longRunningTask)
  
  // Do other work...
  yield* otherWork
  
  // Wait for fiber result
  const result = yield* Fiber.join(fiber)
  return result
})

Concurrency: Parallel Execution

import { Effect } from "effect"

// Run effects in parallel
const results = yield* Effect.all([task1, task2, task3], {
  concurrency: "unbounded"
})

// With limited concurrency
const results = yield* Effect.all(tasks, { concurrency: 5 })

Concurrency: Streams

import { Stream, Effect } from "effect"

const stream = Stream.make(1, 2, 3).pipe(
  Stream.map((n) => n * 2),
  Stream.filter((n) => n > 2)
)

const result = yield* Stream.runCollect(stream)

Schema (Validation)

import { Schema } from "effect"

const User = Schema.Struct({
  id: Schema.Number,
  name: Schema.String.pipe(Schema.minLength(1)),
  email: Schema.String
})

type User = Schema.Schema.Type<typeof User>

// Decode unknown data
const user = Schema.decodeUnknownSync(User)({
  id: 1,
  name: "Alice",
  email: "alice@example.com"
})

Reference Documentation

Detailed examples and API documentation are split into focused files under references/. Use grep "^### " on the relevant file to list all section headings and their line numbers, then read_file with start_line/end_line to fetch a complete section.

Core

Topic File
Effect creation, generators, pipe, Ref, timeouts, concurrency references/core/effects.md
Error handling (catchAll, catchTag, Cause, Either) references/core/error-handling.md
Layers, services, Context.Tag, Effect.Service, DI references/core/dependency-injection.md
Config, ConfigProvider, environment variables references/core/configuration.md
Scope, finalizers, acquireUseRelease, Effect.scoped references/core/resource-management.md

Concurrency

Topic File
Fibers, forking, racing, Deferred, Latch, Supervisor references/concurrency/fibers.md
Queue, PubSub, SubscriptionRef, Semaphore references/concurrency/queues-pubsub.md
Stream creation, transformation, sinks references/concurrency/streams.md
Schedule, retry, repeat, cron, jitter references/concurrency/scheduling.md

Platform (@effect/platform)

Topic File
FileSystem, Path references/platform/filesystem.md
HttpClient, HTTP server, RequestResolver references/platform/http.md
Command execution, stdin/stdout, exit codes references/platform/command.md
KeyValueStore references/platform/keyvaluestore.md

Observability

Topic File
Log levels, structured loggers, spans, annotations references/observability/logging.md
Counters, gauges, frequency, summaries references/observability/metrics.md
OpenTelemetry, spans, OTLP export, tracing references/observability/tracing.md

Schema, AI & Data

Topic File
Validation, encoding, branded types, JSON Schema, arbitrary references/schema.md
OpenAI, Anthropic, LanguageModel, @effect/ai references/ai.md
HashSet, HashMap, Chunk, Order, Data, BigDecimal references/data/collections.md
DateTime, Duration, Clock, Cron references/data/datetime.md

Other

Topic File
Installation, scaffolding, tooling, running programs references/getting-started.md
Cache, TTL, Layer.memoize references/caching.md
Mocking services, config, file system; test DI references/testing.md
Micro lightweight runtime references/micro.md
Weekly Installs
6
First Seen
Feb 21, 2026
Installed on
opencode6
gemini-cli6
claude-code6
github-copilot6
codex6
kimi-cli6