Effect.ts monorepo template with agent-friendly tooling for code quality, documentation, and work tracking.
Explicit control flow. Every branch handled, every error typed. TaggedError gives errors identity, catchTag forces handling by name. No silent catches, no untyped throws, no bare new Error.
Code shape enforcement. ast-grep rules enforce architecture, not just style. Errors live in errors.ts. External SDK wrappers live in adapter files. runPromise only appears at entry points. The rules define the shape of the codebase — read them to understand the architecture.
Runtime observability. Structured logging with span context, traces at every boundary. Run with EFFECT_TRACE=1 to see the full call tree on stdout. The first two pillars enforce the preconditions that make this work.
apps/— Deployable applications (CLIs, APIs, workers)packages/— Internal shared packages consumed by apps- Each app and package has its own
package.jsonandtsconfig.jsonextending the root - Boundary convention: Adapter files (
*.adapter.tsoradapters/) wrap external SDKs and services that don't have Effect abstractions. Effect platform services (FileSystem,HttpClient, etc.) are already traced and injectable — use them freely in interior code. Seedocs/patterns/boundaries.md. - Schema-first at boundaries: All external data (HTTP bodies, JSON files, messages) must be validated through
Schema.decodeUnknownbefore use. Noascasts or typed assignments on parsed data, no bareJSON.parse. Seedocs/patterns/data-validation.md. - App templates: To build new apps (CLI, API, worker), see
docs/templates/.
| App | Runtime | Purpose |
|---|---|---|
apps/symphony-orchestrator |
Bun / Effect | Switchyard orchestrator implementation |
playgrounds/symphony-daytona-playground |
Bun | Daytona/Codex smoke evidence and experiments |
| Package | Purpose |
|---|---|
packages/qa |
Remote Daytona E2E scenarios, helpers, fixtures, and evidence |
The following tools must be installed on the host machine:
| Tool | Purpose | Install |
|---|---|---|
| bun | Package manager and runtime | bun.sh |
| fp | Issue tracking and work sessions | fp.dev |
| drift | Spec-to-code binding and staleness detection | github.com/fiberplane/drift |
ast-grep (sg) |
Custom lint rules | ast-grep.github.io |
bun install # Install all deps
bun run lint # oxlint
bun run lint:ast # ast-grep scan (custom rules)
bun run lint:drift # drift lint (stale spec check)
bun run format # oxfmt
bun run format:check # Check formatting without writing
bun run typecheck # tsgo --noEmit
bun run check # lint + ast-grep + drift + typecheck
bun run test # Tests (all workspaces, fan-out via --filter '*')
EFFECT_TRACE=1 bun run <command> # Enable trace + structured log output
bun testfrom the repo root walks the cwd, includingreferences/(gitignored upstream mirrors likereferences/effect/).bunfig.tomlprunes that path viapathIgnorePatterns, which requires Bun >= 1.3.13 — older Bun silently ignores the key and tries to load ~1000 upstream test files. Preferbun run test(fans out via--filter '*') or scope by workspace, e.g.bun run --filter @switchyard/symphony-orchestrator test.
bun run check does not run tests or format:check. Before closing code tasks, run all three:
bun run test
bun run format:check
bun run checkFor issue-backed implementation work, use the repo skill at
.agents/skills/fp-task/SKILL.md.
Minimum workflow:
- Load context with
fp context <id>andfp issue get <id>. - Claim work with
fp issue update <id> --status in-progress. - Log meaningful milestones with
fp comment <id> "...". - Commit with the fp issue id in the message.
- Mark done only after auditing acceptance criteria against real evidence.
Code review is mandatory by default for implementation work: use a review subagent unless the user explicitly opts out or the current agent environment does not provide subagents. If a review skill or plugin is available, instruct the subagent to use it. Address findings before final verification. If subagents are unavailable, state that exception clearly, perform a structured self-review, and ask for human or subagent-capable review before marking the issue done unless the user tells you to continue.
| Topic | Location |
|---|---|
| Effect conventions | docs/patterns/effect.md |
| Boundary conventions | docs/patterns/boundaries.md |
| Data validation at boundaries | docs/patterns/data-validation.md |
| Coding style | docs/patterns/coding-style.md |
| Observability setup | docs/patterns/observability.md |
| App templates (CLI, API, worker) | docs/templates/ |
| Architecture notes | docs/architecture/ |
| Proposals (active/completed) | docs/proposals/ |
| Experiments and demo evidence | docs/experiments/ |
| Testing patterns | docs/testing/ |
| Retired docs | docs/graveyard/ |
| Docs convention guide | docs/README.md |
| fp task workflow | .agents/skills/fp-task/SKILL.md |
| ast-grep rules | rules/shared/, rules/effect/ |
| ast-grep rule tests | rule-tests/shared/, rule-tests/effect/ |
- oxlint — Config in
.oxlintrc.json. Handles standard TypeScript lint rules. - oxfmt — Config in
.oxfmtrc.json. 2-space indent, 100-char lines, double quotes, import sorting. - tsgo — TypeScript native compiler (preview). Uses root
tsconfig.json. - ast-grep — Custom rules in
rules/. These enforce the architectural patterns described above — seedocs/patterns/effect.mdfor the full rule table. - drift — Binds specs in
docs/to source files.drift lintflags stale specs,drift link <spec>re-stamps.
After writing any code, run bun run test, bun run format:check, and bun run check.
Clone upstream repos into references/ when docs are insufficient. This directory is gitignored and excluded from linting.
git clone --depth 1 https://github.com/Effect-TS/effect.git references/effect@FP_AGENTS.md