effected
The unglamorous app plumbing that Effect leaves to you, done right.
A pnpm monorepo (npm org @effected) of Effect v4 libraries designed v4-first, not lifted from their v3 predecessors. The repo holds libraries only; the applications that consume them stay in their own repos.
Every CLI, dev tool, and service reaches for the same machinery: reading and writing config files, parsing package.json and tsconfig.json, resolving semver ranges and runtime versions, walking a monorepo's workspaces and lockfiles, shelling out to git, finding the right XDG directory, keeping a little durable state on disk. effected gives you each of those as a typed Effect schema or service — malformed input surfaces as a typed error instead of a thrown exception, IO sits behind layers you can swap in a test, and the whole set shares one design so the pieces fit together.
Reach for one library or a dozen. Each package declares exactly what it touches, so a pure schema library never pulls a filesystem or a subprocess into your app, and they all pin the same Effect version, so their peer ranges never fight.
Packages
Each package sits in one of four categories describing its runtime surface:
- Integrated — imports at least one runtime package outside
effectcore. - Boundary — the same
@effected/*-only dependency surface as a pure package, but does IO through Effect's coreFileSystemandPathservices. - Pure — peers on
effectand takes only@effected/*edges, with no IO. - Companion — not a library and exposes no API; published and installable, it ships pnpm catalogs and a pnpmfile that pin your
effectversions, your@effected/*versions and both sets of peer floors to the ones the kit was built against.
Every package is unstable; see release strategy.
Integrated
Boundary
Pure
Companion
Release strategy
Every package here is published to npm. Releases are changeset-driven: a change that affects a published package carries a changeset, and CI releases the packages those changesets name. That release is sometimes the whole kit and sometimes a single package — both are ordinary, and package versions move independently as a result. Each package's own npm page and package.json are the source of truth for where it stands.
What does not move independently is the Effect line. Every package is built and tested against the one Effect v4 release the workspace lockfile resolves, and every package peers effect at the same ^4.0.0, so their peer ranges agree with each other by construction rather than by luck. Publishing runs ahead of the applications that consume the kit rather than behind them, which surfaces integration problems against real published packages instead of a stand-in.
Pre-1.0.0
Effect v4 is stable, and the kit builds on it, but every package is still 0.x. Stable Effect makes a kit 1.0.0 possible, not automatic: packages graduate when their APIs settle, not on Effect's schedule. Until then, a breaking change can ride an ordinary minor release, so read the changeset before you advance.
Version and stability
Two independent dimensions describe where a package stands:
- Version — pre-
1.0.0, built on stable Effect v4. Each package carries its own version and advances when a release names it. - Stability —
stableorunstable, whether a package's API shape is considered complete. This is tracked per package.
Every package is unstable today. Treat the two as separate: even a package marked stable before 1.0.0 can break by accident, so pin each package to a minor (a caret on 0.x does exactly that) and read the changeset before advancing. A pinned minor turns an unexpected change into a type-check error at your own boundary instead of a runtime surprise in production.
Version alignment
@effected/pnpm-plugin-effect keeps a consumer's versions aligned with the kit's. It is a pnpm config dependency, installed ahead of the rest of the tree, that ships four pnpm catalogs: two for Effect and two for the kit itself.
The effect catalog carries effect and its @effect/* satellites at ^4.0.0 (@effect/tsgo is the exception: it versions independently on its own line). Effect releases all of them together at one version, so once the plugin is installed everything in your workspace resolves to one 4.x, and your lockfile holds the exact version. effect:peers carries the same package set at the peer range a library should advertise.
The effected catalog does the same job for the kit's own packages — every one except @effected/pnpm-plugin-effect itself, which is the package the catalog ships inside. Write "@effected/workspaces": "catalog:effected" in dependencies, or catalog:effected:peers in peerDependencies, instead of a hand-maintained range. That matters more than it sounds on 0.x, where a caret does not cross a minor: a range written by hand stops resolving anything current as soon as the package it names cuts a minor, and it does so silently across every manifest that repeats it. The catalog is rebuilt as packages release, so upgrading the config dependency advances the whole kit surface in one step.
{
"dependencies": {
"effect": "catalog:effect",
"@effected/workspaces": "catalog:effected"
}
}
A note on peers
Upstream Effect manifests occasionally introduce peer-dependency wrinkles that need an override rule to keep resolution clean. @effected/pnpm-plugin-effect ships the ones the kit knows about: today, scoped pins that keep tools still built on an Effect release candidate on their own @effect/platform-node-shared.
Contributing
Setup, the build pipeline, testing, code quality and the commit and pull-request flow live in CONTRIBUTING.md.
Requirements
- Node.js >=24.11.0
- pnpm 11.x