From effect-ts
This skill should be used when the user asks about "Effect concurrency", "fibers", "Fiber", "forking", "Effect.fork", "Effect.forkDaemon", "parallel execution", "Effect.all concurrency", "Deferred", "Queue", "PubSub", "Semaphore", "Latch", "fiber interruption", "Effect.race", "Effect.raceAll", "concurrent effects", or needs to understand how Effect handles parallel and concurrent execution.
npx claudepluginhub andrueandersoncs/claude-skill-effect-ts --plugin effect-tsThis skill uses the workspace's default tool permissions.
Effect provides lightweight fiber-based concurrency:
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Checks Next.js compilation errors using a running Turbopack dev server after code edits. Fixes actionable issues before reporting complete. Replaces `next build`.
Effect provides lightweight fiber-based concurrency:
import { Effect } from "effect";
const results = yield * Effect.all([fetchUser(1), fetchUser(2), fetchUser(3)], { concurrency: "unbounded" });
const results = yield * Effect.all(tasks, { concurrency: 5 });
const results = yield * Effect.all(tasks);
const users = yield * Effect.forEach(userIds, (id) => fetchUser(id), { concurrency: 10 });
const program = Effect.gen(function* () {
const fiber = yield* Effect.fork(longRunningTask);
yield* doOtherWork();
const result = yield* Fiber.join(fiber);
});
const fiber = yield * Effect.fork(task);
const fiber = yield * Effect.forkDaemon(task);
const fiber = yield * Effect.forkIn(scope)(task);
const fiber = yield * Effect.forkWithErrorHandler(task, onError);
import { Fiber } from "effect";
const result = yield * Fiber.join(fiber);
const exit = yield * Fiber.await(fiber);
yield * Fiber.interrupt(fiber);
const maybeResult = yield * Fiber.poll(fiber);
const fastest = yield * Effect.race(fetchFromServer1(), fetchFromServer2());
const fastest = yield * Effect.raceAll([fetchFromCDN1(), fetchFromCDN2(), fetchFromCDN3()]);
const first = yield * Effect.raceFirst(task1, task2);
import { Deferred } from "effect";
const program = Effect.gen(function* () {
const deferred = yield* Deferred.make<string, never>();
const fiber = yield* Effect.fork(
Effect.gen(function* () {
const value = yield* Deferred.await(deferred);
yield* Effect.log(`Got: ${value}`);
}),
);
yield* Deferred.succeed(deferred, "Hello!");
yield* Fiber.join(fiber);
});
import { Queue } from "effect";
const program = Effect.gen(function* () {
const queue = yield* Queue.bounded<number>(100);
yield* Effect.fork(Effect.forEach([1, 2, 3, 4, 5], (n) => Queue.offer(queue, n)));
const items = yield* Effect.forEach(Array.from({ length: 5 }), () => Queue.take(queue));
});
const bounded = yield * Queue.bounded<number>(100);
const unbounded = yield * Queue.unbounded<number>();
const dropping = yield * Queue.dropping<number>(100);
const sliding = yield * Queue.sliding<number>(100);
import { PubSub } from "effect";
const program = Effect.gen(function* () {
const pubsub = yield* PubSub.bounded<string>(100);
const sub1 = yield* PubSub.subscribe(pubsub);
const sub2 = yield* PubSub.subscribe(pubsub);
yield* PubSub.publish(pubsub, "Hello!");
const msg1 = yield* Queue.take(sub1);
const msg2 = yield* Queue.take(sub2);
});
import { Effect } from "effect";
const program = Effect.gen(function* () {
const semaphore = yield* Effect.makeSemaphore(3);
yield* Effect.forEach(tasks, (task) => semaphore.withPermits(1)(task), { concurrency: "unbounded" });
});
import { Latch } from "effect";
const program = Effect.gen(function* () {
const latch = yield* Latch.make(false);
yield* Effect.fork(
Effect.forEach(
workers,
(worker) =>
Effect.gen(function* () {
yield* Latch.await(latch);
yield* worker.start();
}),
{ concurrency: "unbounded" },
),
);
yield* Latch.open(latch);
});
const fiber = yield * Effect.fork(longTask);
yield * Fiber.interrupt(fiber);
const critical = Effect.uninterruptible(
Effect.gen(function* () {
yield* beginTransaction();
yield* performOperations();
yield* commitTransaction();
}),
);
const program = Effect.uninterruptible(
Effect.gen(function* () {
yield* criticalSetup();
// This part can be interrupted
yield* Effect.interruptible(longOperation);
yield* criticalTeardown();
}),
);
Structured concurrency ensures child fibers are managed:
const parent = Effect.gen(function* () {
const child1 = yield* Effect.fork(task1);
const child2 = yield* Effect.fork(task2);
// If parent fails/interrupts, children are interrupted
yield* failingOperation();
});
// child1 and child2 automatically interrupted
Escape supervision with daemon:
const daemon = yield * Effect.forkDaemon(backgroundTask);
const withTimeout = task.pipe(Effect.timeout("5 seconds"), Effect.map(Option.getOrElse(() => defaultValue)));
const workerPool = Effect.gen(function* () {
const semaphore = yield* Effect.makeSemaphore(numWorkers);
return (task: Effect.Effect<A>) => semaphore.withPermits(1)(task);
});
const results =
yield *
Effect.all(tasks, {
concurrency: "unbounded",
mode: "either", // Collect all results
});
For comprehensive concurrency documentation, consult ${CLAUDE_PLUGIN_ROOT}/references/llms-full.txt.
Search for these sections: