Agent instructions

For a non-trivial task, start with skills/rat-stack-mode.

This file is the repo law for agents and contributors. It holds commands, validation rules, architecture constraints, and project stop rules. Read VISION.md for intent before planning substantial work. VISION.md does not override this file. Pi sessions also load .pi/APPEND_SYSTEM.md and the repo-local extension .pi/extensions/project.ts.

Stack contract

Workspace package.json files declare the pinned stack. README.md summarizes it. Keep dependencies exact. Repo-local config wins. Record drift instead of silently migrating the project.

The base Effect plugin owns diagnostic severity. Child configs may add exact allowedUnstableApis only for modules warned about in that scope20. Do not use subtree prefixes, copy severity maps, or set ignoreEffectWarningsInTscExitCode to true.

Packages

PackagePathRole
@rat-stack/capabilitypackages/capabilitydefineContract, implement, and the toCommand, toHttpApi, toToolkit, toRpc, and toCodeMode projections
@rat-stack/corepackages/coreShared inspectFile, search, and read contracts; inspectFile handler, lifecycle machine, and FileInspector
@rat-stack/databasepackages/databaseDatabase cartridge: the RunLog service and the DatabaseVendor choice (D1 or Hyperdrive Postgres), with each vendor’s schema, migrations, and resources
@rat-stack/authpackages/authBetter Auth cartridge over the chosen DatabaseVendor: Auth, CurrentPerson, and the RPC middleware that provides it; only Unauthenticated crosses the wire. @rat-stack/auth/devtools adds runAsPerson, the dev-only rat_test_person capability, and testPersonLayer
@rat-stack/flagspackages/flagsTyped flags cartridge: rollout evaluation, Config and writable memory adapters, cartridge-owned Alchemy KV, and immutable attempt/completion audit keys. Empty KV uses Config values or declared defaults. EVENTS_ENABLED stays deploy-time Config. Core owns the ports, declarations, reader capabilities, and approval-gated setFlag. Only the CLI mounts setFlag; its default composition has no live writer. Public readers and the sandbox stay read-only. Replace both exports in apps/site/src/flags.ts with Flags.defaults(eventFlags) to remove the adapter package.
@rat-stack/eventspackages/eventsEvents cartridge: capture-first request analytics. withEventCapture records one request event per HTTP request behind the EventSink port; @rat-stack/events/basin declares the Cloudflare Basin resources (R2 Data Catalog, unstructured Pipelines stream with public ingest off, Iceberg sink, SELECT * pipeline, visitor salt) and provides the sink; @rat-stack/events/memory is the in-memory sink for tests. Tests are property and model based (it.prop, it.effect.prop). Mischief provides it in apps/site/src/worker.ts; EVENTS_ENABLED (default false) turns capture and the catalog, sink, and pipeline on, and reads EVENTS_SINK_TOKEN at deploy time only; off still declares the bucket, stream, and salt so their state survives. EVENTS_IDENTITY_MODE picks daily or persistent visitor ids
@rat-stack/subscriber-deliverypackages/subscriber-deliveryExternal subscriber intake and confirmation adapter; implements core’s job-shaped SubscriberIntake and SubscriberConfirm ports, provided by the Worker, never imported by core
@rat-stack/learnpackages/learnSource-derived public concept deck and the learning lifecycle. Stateless capabilities return compact progress; @rat-stack/learn/local owns the local JSONL adapter and capabilities. The CLI provides the filesystem platform for core’s LearnerProgress port.
@rat-stack/lorepackages/lorePublic content graph and traversal service
@rat-stack/devtoolspackages/devtools🐀 devtools cartridge: CallLog, record, and the rat_* capabilities that list, read, dispatch, replay, and diff capability calls
@rat-stack/webapps/webDefault UI bin: Foldkit on Vite, deployed through Alchemy’s Cloudflare.Website.Foldkit as Website (apps/web/src/website.ts). Browser client/ Commands call an Effect RpcClient built from the contracts’ toRpcGroup. The reader program mounts the document browser (features/app.ts, client/docs) as a Submodel at /search, where it calls search and read over that client. In production, the Worker that @foldkit/vite-plugin generates from src/entry.server.ts forwards /rpc through src/server/website-bindings.ts to the private RpcBackend in apps/site/src/rpc-worker.ts. pnpm --filter @rat-stack/web dev loads the #backend import, which resolves only under the development condition in apps/web/package.json, and serves the content capabilities in process from src/dev/backend.ts. In dev, src/dev/backend.ts runs the content capabilities under devtools: /rpc calls are recorded, /__rat/rpc serves the 🐀 overlay (#devtools-overlay, src/dev/features/overlay, ⌘K), and /__rat/mcp serves every rat_* tool to agents, with memory-Auth test people. src/dev/client and src/dev/features follow the browser rules. test/production-bundle.test.ts proves no src/dev module, no devtools code, and no test people reach a production build. Include it in the Stack with const website = yield* Website;
@rat-stack/cliapps/cliComposition root: stats, catalog, openapi, serve [--devtools], mcp [--code-mode] [--devtools] commands. Also builds the published ratstack npm package: src/ratstack.ts bundles the local learn commands and a learn-only mcp into dist/npm with Vite. test/ratstack.e2e.test.ts proves the package holds no devtools and serves only the learn tools
@rat-stack/infraapps/infraAlchemy Stack: the project’s cloud footprint as one Effect program
@rat-stack/siteapps/siteCloudflare Worker: the public site, agent discovery, and sandboxed execute surface

Nouns

NounHomeRuntime job
Contractpackages/core/src/contracts.tsShared name, schemas, failure, annotations, and approval setting.
Capabilitypackages/core/src/inspect-file.ts or apps/site/src/capabilities/<name>.tsBinds one contract to its server-side handler with implement.
Projectionpackages/capability/src/to-<surface>.tsExpose implemented capabilities on one runtime surface.
Cartridgepackages/<name>/src/One Layer with its own infrastructure; it must pass the cartridge test in VISION.md.
Machinepackages/core/src/<name>-machine.tsOwn one finite domain lifecycle.
Featureapps/web/src/features/<name>/Thin route and view that read the Model and send Messages.
System page.brain/areas/<name>.svxPublic page at /systems/<name> for one system rat-stack ships: what it does, the standard it keeps, and how to check it. The content build rejects a system page without those three sections or outside .brain/areas/.
Clientapps/web/src/client/<name>/Own the Foldkit program’s Model, Messages, update, and named Commands; Commands call an RpcClient over the contract group.

Commands

CommandPurpose
pnpm installInstall workspace dependencies
pnpm sources:fetchImport missing pinned code objects once before the first gate; generation stays local-only
pnpm devRun apps/web under vite dev through portless at http://rat-stack.localhost:1355 (worktrees get their own prefix); portless list shows the route
pnpm checkTypecheck, verify formatting, and run type-aware linting
pnpm lintType-aware lint plus format check only; turbo run check runs this once at the root as //#lint
pnpm fixApply Oxfmt and safe Oxlint fixes
pnpm testBuild and run the Vitest suite once
pnpm buildCompile package outputs
pnpm typecheckturbo run typecheck
pnpm vendor:agent-sourcesShallow-clone Effect, effect-solutions, xstate, alchemy, better-auth, and Foldkit mirrors
pnpm infra:planPreview the Alchemy Stack diff without applying
pnpm infra:deploy / pnpm infra:destroyApply or tear down the Stack (asks for approval)
pnpm exec lefthook installInstall git hooks (also via prepare)
pnpm turbo run check test buildRequired validation before claiming a change is ready

Run pnpm fix only when you intend to rewrite files. Finish with pnpm turbo run check test build.

Deploy

Release the ratstack package

Fence (cheating is uncomfortable)

Why lives in AGENTS.md / VISION.md. The stack and hooks are the enforceable fence39. Fence wins over prose.

If a hook fails, fix the failure. Do not disable the fence.

Source-first Effect / XState work

Before writing, reviewing, or refactoring Effect or XState code, read the installed Effect package’s AGENTS.md first, for example packages/core/node_modules/effect/AGENTS.md. It ships with the installed version, so it is never stale. Then inspect vendored source for the pinned versions. Populate mirrors:

pnpm vendor:agent-sources
# or
./scripts/vendor-agent-sources.sh --refresh

Inventory: .agent_sources/README.md is generated in the local source mirror and is not part of this repository.

NeedPath
Effect Schema, Context.Service, CLI.agent_sources/github.com/Effect-TS/effect/
Idiomatic Effect.agent_sources/github.com/kitlangton/effect-solutions/
XState.agent_sources/github.com/statelyai/xstate/
@xstate/effect (v6 Effect bridge).agent_sources/github.com/statelyai/xstate/packages/xstate-effect/ (README.md, docs/, src/*.test.ts)
Alchemy resources, Cloudflare, AWS.agent_sources/github.com/alchemy-run/alchemy/ and https://alchemy.run/llms.txt

Refs are derived from the workspace pins, so bumping a package and re-running the script keeps them matched. The pi-effect tool reads the Effect mirror in place; it needs no link.

Mirrors are reference material, not runtime dependencies. Exclude them from typecheck, test, lint, and format. Do not vendor product-specific corpora in this template.

Source control

Preserve existing work. Inspect status before editing, stage only files changed for the current task, and do not commit generated output, secrets, or populated .agent_sources/github.com/ trees. Use the repository’s existing source-control tool; do not initialize or migrate one without approval. Never pass --no-verify to git.

Project law

A child project replaces this section on day one with its own product rules. These rules describe the rat-stack template, not the product in a clone. Keep durable product intent in VISION.md.

Architecture

A child project replaces this section on day one with its own architecture. Record module boundaries, dependency direction, data ownership, and state-machine seams here. Link deeper docs instead of duplicating them.

Wiki writing

Lore and system pages use low prose, about 80% ASD-STE100 Simplified Technical English. This is a house style, not certification.

Use a visual only when it explains the point. Choose a fenced box-drawing diagram for flow or topology, a table for trade-offs or state, pseudocode for logic, or a shallow file tree. Keep diagrams below 80 columns. Give each visual one or two nearby sentences. Add a What to notice line only when the point is not obvious from those sentences. Do not add decorative visuals.

Write for a person first. Avoid hedged ‘X, not Y’ asides and narration about sources.

The content generator warns on sentences above 25 words and paragraphs above four sentences in lore and systems pages. It also warns on history wording, contrast hedges, and em dashes. It reads parsed Markdown prose. The style rules skip quoted spans, blockquotes, code, links, tables, and frontmatter. Length rules still count link labels. Warnings show file:line and a total count. They never fail the build. Fix new warnings or explain why they remain.

Web feature blueprint

apps/web/src/features/<name>/ holds a thin route and view. It reads the Model and sends Messages; components never handle transport, retries, or process startup. apps/web/src/client/<name>/ owns the Foldkit program: Model, Messages, update, and named Command.define definitions. Remote state lives in the Model, as Foldkit AsyncData or a foldkit/experimental Query. The capability in packages/core is the shared typed edge, imported by both sides. A cartridge owns durable behavior.

One send follows one path: feature → Message → update → named Command → RpcClient over the contract’s toRpcGroup → shared capability → server-side Durable Object or database cartridge. The server stays authoritative. The Command returns a result Message, and update folds it into the Model.

Boundaries and sign-off

A child project replaces this section on day one with its own boundaries. This section names changes agents may make directly and changes that need owner approval.


Last changed 2026-10-12 in 2c5b496. Source on GitHub. Change log.

Linked from

  1. A clean playground. rat-stack does real work with packages that stay easy to add and remove.
  2. add-a-lifecycle-machine. Learn how XState owns a lifecycle while Effect owns its work, errors, and services.
  3. add-a-store. Add persistence through a service named for an application job, with validation, vendor Layers, migrations, bounded reads, and shared backend tests.
  4. Build and run rat-stack (README.md). What is in the repo, how the example works, and how to run it.
  5. CAFE names the Cloudflare, Alchemy, Foldkit and Effect stack. CAFE is a named stack: Cloudflare runs the app, Alchemy declares it, Foldkit draws the UI, and Effect does the typed work.
  6. Effect + Alchemy peer patterns. Source-grounded patterns from repos on nearby Effect and Alchemy pins.
  7. Effect 4 study: September 2026. Dated Effect 4 source studies from September 2026; current versions live in pins.md.
  8. gardener. Keep rat-stack current and clean. Update exact dependency versions, learn from repos on the same versions, and add lint rules before cleanup.
  9. investigate-a-failure. Find the cause of a crash, wrong output, flaky test, or slow run with evidence, fix it at its source, and leave a notebook a person can learn from. Use when something fails intermittently, when the first fix idea is "raise the timeout" or "swap the version", or when asked "why does this break" or "make this stable".
  10. keep-or-cut. Learn which pieces depend on each other, then keep only the ones your project needs.
  11. learn-alchemy. Learn how Alchemy 2 turns an Effect program into a planned Cloudflare deployment.
  12. learn-rat-stack. Trace a capability through Effect, XState, five projections, the CLI, and Alchemy. Try hosted search and read.
  13. Purpose and boundaries of rat-stack (VISION.md). What this starter is for and what a useful copy should keep.
  14. ship. Learn how to ship a change through merge, CI, release, stage deployment, rollout, verification, rollback and flags.
  15. uncomplect. Find responsibilities that a rat-stack design combines, separate them into capabilities, cartridges, machines, features, and clients, and enforce that separation through types and checks. Use when asked to simplify, review, or replace a design, "what would Rich Hickey do", "optimize for deletion", or "define this error out of existence".
  16. write-a-wiki-page. Write or revise public wiki pages with short prose, cited claims, meaningful visuals, and pinned code snippets.