Skip to content
Playground

Contributing

Last updated today · 55e6c0c

Updated today

"docs: add next-step navigation to 51 pages, fix 2 real coverage/rendering gaps" · 55e6c0c · 2026-09-06

  • ## Release Workflow
  • ### What a contributor does: add a changeset
  • ### What a maintainer does: cut the release
  • ### Bump types
  • ## What's Next
Terminal window
git clone https://github.com/tylerjrbuell/reactive-agents-ts.git
cd reactive-agents-ts
bun install
bun test # 9,000+ tests — all must pass
bun run build # ESM + DTS for all 34 packages

Terminal window
bun test # Run full suite
bun test --watch # Watch mode during development
bun run typecheck # Workspace-wide type checking
bun run build # Build all packages and apps
bun run rax -- <args> # Run the local rax CLI
bun run docs:dev # Docs site dev server
  • bun test — 100% green
  • bun run build — no errors
  • Documentation updated (see below)
  • Changeset added (see Release Workflow below)

Releases are tag-driven lockstep: one version number stamps every public package at once. .changeset/*.md files are notes, not the driver — there is no auto-generated “Version Packages” PR. Never manually bump package.json versions or edit CHANGELOG.md.

Every PR that changes user-facing behaviour needs a changeset:

Terminal window
bun run changeset

The interactive prompt asks:

  • Which packages changed? — select the package(s) your change touches
  • Bump type?patch for fixes, minor for new features, major for breaking changes (this bump type informs the release note; every package still ships at the same lockstep version regardless)
  • Summary? — this text becomes the public CHANGELOG entry verbatim, so write it for a reader of the changelog, not as a commit message

This creates .changeset/<random-name>.md. Commit it alongside your code and open the PR as usual.

At release time, a maintainer aggregates all pending changesets into CHANGELOG.md, picks an explicit version number, and pushes a vX.Y.Z git tag. That tag push is the entire trigger — scripts/release.ts, run by CI, stamps every package to that version, builds, and publishes to npm in dependency order, then consumes (deletes) the changeset files it aggregated. See .claude/skills/prepare-release/SKILL.md for the full maintainer flow.

TypeWhen
patchBug fixes, test fixes, internal refactors
minorNew features, new builder methods, new exports
majorBreaking API changes, removed exports

All public packages ship at the same lockstep version — the bump type shapes the changelog note, it does not produce independent per-package versions.


ChangeUpdate
New packageAGENTS.md package map/status, README.md packages table, docs sidebar
New builder methodREADME.md, apps/docs/src/content/docs/reference/builder-api.md, AGENTS.md
New CLI commandREADME.md, apps/docs/src/content/docs/reference/cli.md
New featureapps/docs/src/content/docs/features/<name>.md
API signature changeSearch docs: grep -r "oldMethod" apps/docs/
Terminal window
bun run docs:dev # http://localhost:4321
bun run docs:build # Production build
bun run docs:preview # Preview built output

Docs are deployed to docs.reactiveagents.dev on every push to main.


New packages follow this layout:

packages/<name>/
src/
types.ts # Schema.Struct types, tagged errors
errors.ts # Data.TaggedError definitions
services/ # Effect-TS Context.Tag services
runtime.ts # Layer factories (createXxxLayer)
index.ts # All public exports
tests/
package.json # "version" matches workspace, "private": true if internal
tsconfig.json # extends ../../tsconfig.json

Internal packages that should never be published must have "private": true in package.json.

Adding a new package to the publish pipeline

Section titled “Adding a new package to the publish pipeline”
  1. Create the package following the structure above
  2. Add it to the fixed group in .changeset/config.json
  3. Add its build step to the build:packages script in root package.json
  4. Add it to the workspace in root package.json workspaces

This project uses Effect-TS throughout. Load the effect-ts-patterns skill before writing any service code.

import { Effect } from "effect";
// Often also: Layer, Context, Schema, Data, Ref — import only what you use
  • No throw — use Effect.fail with tagged errors (or Effect.die for defects)
  • No raw await inside Effect programs — use Effect.promise, Effect.tryPromise, or yield* inside Effect.gen
  • Prefer Effect.succeed / Effect.sync for pure or trivial sync work
  • No any — use precise types, generics, and tagged unions
  • All public APIs need JSDoc comments
  • New services need tests in tests/
  • FAQ — production readiness, honest caveats, what’s not done yet
  • Architecture — layer system and package boundaries before you dig into a package
  • Troubleshooting — symptom-to-fix reference for common failures