Skip to content
Skill

effect-services

by beep-effect

AI Summary

Every service needs a unique key from . Never use plain strings. Use . Note: type params FIRST, then key in second call. Use an explicit constructor effect and . Parameterized or reusable constructor functions should be named . Zero-arg constructor values may stay to avoid immediate IIFEs.

Install

Copy this and paste it into Claude Code, Cursor, or any AI assistant:

I want to install the "effect-services" skill in my project.

Please run this command in my terminal:
# Install skill into your project
mkdir -p .claude/skills/effect-services && curl --retry 3 --retry-delay 2 --retry-all-errors -o .claude/skills/effect-services/SKILL.md "https://raw.githubusercontent.com/beep-effect/beep-effect/main/.claude/skills/effect-services/SKILL.md"

Then restart Claude Code (or reload the window in Cursor) so the skill is picked up.

Description

Creating services with Context.Service, IdentityComposer keys, and Layer composition. Trigger on: new service, service definition, Layer wiring, dependency injection, Context.

Step 1: Create the Identity

Every service needs a unique key from @beep/identity/packages. Never use plain strings. `ts // WHY: IdentityComposer produces branded strings with compile-time path validation. // The tagged template literal validates segment characters at runtime. import { $PackageNameId } from "@beep/identity/packages" const $I = $PackageNameId.create("relative/path/to/file/from/package/src") // ↑ package composer ↑ file-local composer `

Step 2: Define the Service Class

Use Context.Service<Self, Shape>()(identityKey). Note: type params FIRST, then key in second call. `ts import { Effect, Context, Layer } from "effect" // WHY: Class syntax gives you a nominal type (Self) + the service shape in one declaration. // The $I template tag produces a branded IdentityString under the file-local path. class Notifications extends Context.Service<Notifications, { readonly notify: (msg: string) => Effect.Effect<void> }>()($INotifications) {} `

Step 3: Add the Constructor

Use an explicit constructor effect and Layer.effect(...). Parameterized or reusable constructor functions should be named Effect.fn("Service.make"). Zero-arg constructor values may stay Effect.gen(...).pipe(Effect.withSpan("Service.make")) to avoid immediate Effect.fn() IIFEs. `ts const makeNotifications = Effect.gen(function*() { const config = yield* AppConfig return { notify: Effect.fn("Notifications.notify")(function*(msg: string) { yield* Effect.annotateCurrentSpan({ message_length: msg.length }) yield* Effect.logInfo({ message: "notification emitted" }).pipe( Effect.annotateLogs({ service: "notifications" }) ) return yield* Effect.log([${config.prefix}] ${msg}) }) } }).pipe(Effect.withSpan("Notifications.make")) class Notifications extends Context.Service<Notifications, { readonly notify: (msg: string) => Effect.Effect<void> }>()($INotifications) { // WHY: Explicit layer construction. Wire deps with Layer.provide, not dependencies. static layer = Layer.effect(this, makeNotifications).pipe( Layer.provide(AppConfig.layer) ) } `

Step 4: Consume the Service

Prefer yield* over .use() — it makes dependencies visible at the call site. Exception: in callback-only APIs (for example SchemaTransformation.transform decode/encode callbacks) where yield is not available, use Context.Service.use(...) directly. `ts // WHY: yield* in Effect.fn makes the Notifications dependency appear in the R channel. const sendWelcome = Effect.fn("sendWelcome")(function*(userId: string) { const notifications = yield* Notifications yield* notifications.notify(Welcome ${userId}) }) const JsoncTextToUnknown = S.String.pipe( S.decodeTo( S.Unknown, SchemaTransformation.transformOrFail({ decode: (content) => JsoncCodecService.use((service) => service.parseUnknown(content)), encode: (value) => Effect.fail(unsupported encode: ${value}) }) ) ) `

Discussion

0/2000
Loading comments...

Health Signals

MaintenanceCommitted 22d ago
Active
AdoptionUnder 100 stars
68 ★ · Niche
DocsREADME + description
Well-documented

GitHub Signals

Stars68
Forks13
Issues11
Updated22d ago
View on GitHub
Apache-2.0 License

My Fox Den

Community Rating

Sign in to rate this booster

Works With

Claude Code