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.
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.
| Package | Stability | Description |
|---|---|---|
| @effected/store | unstable | Durable local state on SQLite: a schema-versioned migrated store and a TTL cache with eviction, over one shared migration ledger |
| @effected/workspaces | unstable | Monorepo tooling as Effect services: root discovery, the dependency graph, package-manager detection, pnpm catalogs, lockfile IO and git change detection |
| @effected/app | unstable | The application control plane: one layer wiring XDG-namespaced directories, a migrated SQLite store, a TTL cache and a config file to the same place |
| @effected/github | unstable | Typed GitHub REST and GraphQL services over the octokit core request surface, with app auth and resource helpers |
| @effected/github-actions | unstable | The GitHub Actions runtime: env, inputs, outputs, state, logging, cache, artifacts, blob storage, OIDC and the token bridge |
| @effected/sbom | unstable | CycloneDX 1.6 SBOM construction, SLSA provenance, NTIA validation and Sigstore signing as typed services |
| @effected/schemastore | unstable | Build, validate, version and publish SchemaStore-shaped Draft-07 JSON Schema documents from Effect Schema sources, with ajv strict-mode validation and a content-comparing emit pipeline |
| Package | Stability | Description |
|---|---|---|
| @effected/config-file | unstable | Composable config file loading for Effect: JSON, JSONC, YAML and TOML codecs, resolution strategies and merge behaviors |
| @effected/walker | unstable | Upward path traversal as Effect primitives: ascend a directory chain and return the first candidate satisfying a predicate |
| @effected/xdg | unstable | XDG Base Directory resolution: environment paths, app-namespaced directories, native OS conventions and config-file resolvers |
| @effected/runtimes | unstable | Resolve semver-compatible Node.js, Bun and Deno runtime versions from live feeds, with an offline snapshot fallback |
| @effected/package-json | unstable | package.json parsing, editing, validation and file IO as Effect schemas |
| @effected/tsconfig-json | unstable | tsconfig.json handling as Effect schemas: JSONC document and compiler-option schemas, tsc-parity extends-chain resolution, nearest-config discovery and a portable subset for virtual TypeScript environments |
| @effected/git | unstable | Typed git introspection over Effect core's ChildProcessSpawner: file content and trees at any ref, typed diffs and status, branch, commit and config probes — plus a clearly-marked mutating tier (checkout, fetch, submodules, sparse checkout, config, add) |
| @effected/npm | unstable | Effect service contracts for resolving pnpm catalog: and workspace: dependency specifiers, plus the kit's shared dependency vocabulary, a tolerant Manifest model, and the registry and publish services |
| @effected/commands | unstable | Structured command running and CLI tool discovery over Effect's core ChildProcessSpawner contract |
| @effected/templates | unstable | Managed-section blocks in user-editable files: parse, reconcile, sync and check delimited regions |
| @effected/jsonl | unstable | Append-only, schema-validated JSONL journals as a definable Effect service |
| @effected/cli | unstable | The presentation boundary of an effect/unstable/cli program: audience-aware output, a document IR and renderers, editor links, failure reports and logging, plus opt-in Ink screens, widgets and a live view |
| @effected/env | unstable | Environment detection read through Config: agent, CI, terminal colour level, hyperlinks, columns and audience, swapped in tests with layerTest |
| @effected/mcp | unstable | The boundary layer of an effect/ai MCP server: stdio wiring that keeps stdout the wire, tool-failure shaping, strict-input walkers and test clients |
| Package | Stability | Description |
|---|---|---|
| @effected/semver | unstable | Strict SemVer 2.0.0 versions, ranges and comparators as Effect schemas |
| @effected/jsonc | unstable | Zero-dependency JSONC parsing, editing and formatting as Effect schemas |
| @effected/yaml | unstable | Zero-dependency YAML parsing, editing, formatting and linting as Effect schemas, with per-node comment fidelity and a public token stream |
| @effected/toml | unstable | TOML 1.1.0 parsing, editing and formatting as Effect schemas: typed diagnostics, a lossless CST and first-class date-time values |
| @effected/glob | unstable | Full-fidelity glob matching as Effect schemas: the complete minimatch dialect compiled to pure string predicates |
| @effected/lockfiles | unstable | Pure lockfile parsing for bun, npm, pnpm and yarn Berry into one unified Effect schema model, with pure integrity checking against workspace manifests |
| @effected/spdx | unstable | SPDX license identifiers, exceptions and license expressions as Effect Schema classes |
| @effected/schema-org | unstable | schema.org vocabulary as Effect Schema classes: a JSON-LD graph assembler, a script-safe serializer and offline conformance checking against a vendored vocabulary |
| @effected/markdown | unstable | CommonMark 0.31.2 and GFM as pure schemas: parse to mdast-shaped nodes with byte offsets, edit, format and project to and from mdast |
| @effected/memfs | unstable | An isolated virtual POSIX volume behind Effect's core FileSystem service: the kit's filesystem test double, for tests and dry-run programs |
| @effected/github-references | unstable | GitHub's issue-reference grammar as pure functions: inline-in-prose harvesting with offsets, bare-line parsing and the closing-list dialect |
| @effected/github-commands | unstable | The GitHub Actions workflow-command grammar as pure functions: render a command, and neutralize text so the runner cannot read it as one |
| @effected/engine | unstable | Platform-free primitives shared by every front end of an Effect v4 tool: distribution identity, remediation and launch context |
| Package | Stability | Description |
|---|---|---|
| @effected/pnpm-plugin-effect | unstable | pnpm config dependency shipping the catalogs that pin Effect and the @effected/* kit, for dependencies and peer ranges alike |
| @effected/schemastore-cli | unstable | The schemastore command: build and check SchemaStore-shaped JSON Schema documents from a schemastore.config.ts, with a per-schema published flag and a drift policy |
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.
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.
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.
@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"
}
}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.
Setup, the build pipeline, testing, code quality and the commit and pull-request flow live in CONTRIBUTING.md.
- Node.js >=24.11.0
- pnpm 11.x