acidnet
amenoacids’ working estate: the apps he runs, the records of what he runs and pays for, and the Effect + Alchemy stack under them. VISION.md says what belongs here. AGENTS.md is the law for agents.
acidnet grew out of rat-stack at b8df5c2. Sections from “Create a repository” down still describe that inherited template, and they stay accurate for the stack.
What acidnet adds
| Path | What it is |
|---|---|
apps/session-review | Private session review program: journaled batches, hash-bound human approval, cheap-mode reviews |
apps/steward | Operational work in Amp. Slice 1 is the thread janitor: it plans, and a person approves the plan’s hash |
packages/journal | Append-only JSONL journal and actor conventions shared by the apps |
packages/workspace | Worktree-backed Workspace port for eval trials |
packages/usage, apps/infra/alchemy.railway.ts | Railway usage service and its guarded deploy wrapper |
registers/ | Machines and subscriptions registers |
scripts/eval, results/ | Assay eval suite and its baseline results |
Checks run locally
Lefthook runs pnpm check and pnpm test before every commit. The agent hooks in .amp/plugins/hook-fence.ts, .claude/settings.json, .cursor/ and .pi/ call scripts/vcs-command-policy.js, which blocks --no-verify and every other way of skipping the hook. The CI workflows run only when started by hand (workflow_dispatch); ratstack-publish.yml still runs on ratstack-v* tags.
Apps that run in Amp orbs get their dependencies from .agents/setup. Private data belongs under the git-ignored .amp/in/ and never enters a commit.
Create a repository
gh repo create <name> --template joelhooks/rat-stack Clone the new repository, then install and verify it:
nvm use
pnpm install
pnpm vendor:agent-sources
pnpm sources:fetch
pnpm turbo run check test build Node 24.18.0 and pnpm 11.3.0 are required. The requirement is declared in .nvmrc, engines, devEngines, and packageManager.
Workspace layout
apps/cli:- Package:
@rat-stack/cli - Role: Composition root18:
stats,openapi,serve,mcp
- Package:
packages/capability:- Package:
@rat-stack/capability - Role:
defineContract,implement, and thetoCommand,toHttpApi,toToolkit,toRpc, andtoCodeModeprojections
- Package:
packages/core:- Package:
@rat-stack/core - Role: Domain example: the
inspectFilecontract, handler, and lifecycle machine27
- Package:
packages/flags:- Package:
@rat-stack/flags - Role: Typed flags, Config, memory and KV adapters, stable rollouts, audited writes, and removal dates
- Package:
packages/events:- Package:
@rat-stack/events - Role: Request analytics18: capture, visitor privacy rules, and Basin resources behind core’s
EventSinkport
- Package:
packages/crash:packages/motion:- Package:
@rat-stack/motion - Role: Easing7, tweens, springs and interpolation as dependency-free TypeScript, with an optional Foldkit27 adapter
- Package:
packages/lore:- Package:
@rat-stack/lore - Role: Public content graph and traversal service
- Package:
packages/subscriber-delivery:- Package:
@rat-stack/subscriber-delivery - Role: External subscriber intake and confirmation adapter behind core’s job-shaped ports
- Package:
apps/infra:- Package:
@rat-stack/infra - Role: Alchemy Stack (Cloudflare by default)
- Package:
apps/site:- Package:
@rat-stack/site - Role: Cloudflare Worker for the public site, agent discovery, and sandboxed execute
- Package:
.agent_sources/:- Package: —
- Role: Shallow upstream mirrors (gitignored clones; see README there)
Try the example CLI
The included stats command counts bytes, Unicode characters, words, and lines in a file:
pnpm cli stats README.md
pnpm cli stats README.md --json After pnpm build, you can run the built entrypoint directly:
node apps/cli/dist/cli.js stats README.md The same capability on the other surfaces:
pnpm cli openapi # OpenAPI 3.1 document for the REST projection
pnpm cli serve --port 3000 # POST /inspectFile, GET /openapi.json, GET /docs
pnpm cli mcp # MCP server over stdio, one tool per capability
pnpm cli mcp --code-mode # MCP server with two tools: search and execute
pnpm cli catalog --types # the `tools` declarations a code-mode program sees Code mode23 is another projection. The model gets search for ranked matches with TypeScript signatures and execute for JavaScript with tools in scope35. The program runs in a fresh Node subprocess under --permission. It cannot touch the file system or spawn processes. To call the host, it uses tools.<name>(input). The host validates the input schema and runs the same handler used by every other surface26. Node’s permission model allows network egress. Put a Worker or Deno runtime behind the same Sandbox service to isolate the network too.
packages/capability/src is where a capability becomes a Command, an HttpApiEndpoint, a Tool, and a catalog entry. packages/core/src/inspect-file.ts supplies the CLI’s example capability. Hosted content has its own registry in apps/site/src/capabilities/index.ts. Provider adapters stay outside core (rat-stack-boundaries/no-core-adapters); apps provide them to core’s job-shaped ports at composition. Add another to capabilities28, then verify every projection you keep; CLI command registration lives in apps/cli/src/command.ts.
What is in the stack?
- pnpm workspaces + Turborepo
2.11.10: cachedtypecheck/test/buildacross packages from day one. - Effect
4.1.2: typed runtime, errors, filesystem service, and the three surfaces the capabilities project onto:effect/cli,effect/http-api(withOpenApi.fromApi), andeffect/ai(Toolkit+McpServer). @effect/platform-node4.1.2: Node-backed services; keep adapter and core pins matched.- TypeScript
7.0.2: strict module and index-access checks. @yielded/effect-tsrs0.2.3: runs TypeScript and Effect diagnostics intypecheckandcheck.--type-checkincludes ordinary TypeScript diagnostics;--strictmakes Effect warnings fail. It bundles tsrs8f135f106a63, contained in plain tsrs0.20.0.- tsrs
0.23.0-ts7.1.0-beta: experimental compiler targeting TypeScript7.1.0-betafortypecheck:fast. It still has no Effect diagnostics; usetypecheckorcheckfor those. - XState
6.0.0-beta.1: real lifecycle states; do not replace those with boolean soup. @xstate/effect1.0.0-beta.0: the official XState v6 to Effect 4 bridge:createEffectActorruns a machine as a scoped Effect,createEffectLogicmakes Effects into actors with typed failures38 and requirements.packages/core/src/inspect-machine.tsis the example.- Alchemy
2.0.0-beta.85: Infrastructure as Effects:apps/infra/alchemy.run.tsis the Stack; cloud providers come from@alchemy.run/cloudflare,@alchemy.run/drizzle, and@alchemy.run/sql;pnpm infra:plan/infra:deploy/infra:destroy; auth viapnpm alchemy profile edit. - Foldkit
0.170.0+@foldkit/vite-plugin0.29.0: the web UI. Server rendering9 and prerendering are on by default. Onevite buildwrites the browser bundle, a serverfetchfunction, and an HTML file for every public page.Cloudflare.Website.Foldkitserves the files and sends every other request to that function. The browser hydrates the same view..brain/areas/web.svx9 is the system page. - Oxlint + Ultracite + Oxfmt: native lint and format.
- Vitest
5.1.0+@effect/vitest4.1.2:it.effectandit.layerfor every Effect test; running Effects by hand in a test file is a lint error. @effect/tsgo0.67.5: patches TypeScript 7 inpreparefortypecheck:tsc. Effect warnings fail becauseignoreEffectWarningsInTscExitCodestays false. Patchedtscruns at the switch and on checker bumps through parity, not on every CI run. Report any checker disagreement.- varlock
1.24.0:.env.schemadeclares every variable with@env-specdecorators;pnpm checkrunsvarlock load, secrets stay in gitignored.env.local. - Vendored agent sources: Effect, effect-solutions, XState, Alchemy, Better Auth, and Foldkit via
./scripts/vendor-agent-sources.sh, each at the ref its workspace pin names (not x-algorithm; that stays app-specific). - Agent fence50: lefthook pre-commit (
pnpm check+pnpm test, which builds too) is the CI; GitHub Actions run only on demand. Amp, Claude Code, Pi, and Cursor hooks refuse every hook bypass (--no-verify,commit -n,LEFTHOOK=0,core.hooksPath,.git/hookswrites) throughscripts/vcs-command-policy.js. Cheating should be uncomfortable and obvious.
Every dependency is pinned exactly. Review pin upgrades as stack changes.
Commands
pnpm typecheck: Check TypeScript and Effect diagnostics with strict effect-tsrspnpm typecheck:tsc: Run patched TypeScript7.0.2/@effect/tsgo0.67.5; runs at checker bumps, not in CIpnpm typecheck:fast: Fast feedback with tsrs; no Effect diagnostics;pnpm checkstays the gatepnpm typecheck:parity: Compare effect-tsrs and patchedtscerrors and exit verdicts, includingTS377xxx; also compare plain tsrs with Effect-only codes excludedpnpm bump:checkers: Bump both exact checker pins to npm latest, report bundled revision alignment, and run both parity pairspnpm check: Typecheck, check formatting, and run type-aware lintingpnpm fix: Apply Oxfmt and safe Oxlint fixespnpm test: Run the Vitest suite oncepnpm build: Compile package outputspnpm cli -- ...: Build and run the CLIpnpm vendor:agent-sources: Clone core lib mirrorspnpm turbo run check test build: Cached verification pipeline
Agentic surface
Every clone includes AGENTS.md for repo law and commands, CLAUDE.md as Claude Code’s pointer to that law, and VISION.md for project intent. Source mirrors live under .agent_sources/ after you run the vendor script. Repo-local Pi extensions belong in .pi/extensions/.
Make it yours
Start with the template:
gh repo create <name> --template joelhooks/rat-stack Clone the new repository, then install it:
pnpm install
pnpm sources:fetch pnpm sources:fetch imports missing pinned source commits from the configured repository remotes once, including in template children. Generation reads only local Git objects and never fetches. Re-run the command when adding a new pin that is not present locally.
Rename the workspace package names before you build on the example. These are examples, not the full package inventory:
package.json:rat-stackapps/cli/package.json:@rat-stack/cliapps/infra/package.json:@rat-stack/infraapps/site/package.json:@rat-stack/sitepackages/capability/package.json:@rat-stack/capabilitypackages/core/package.json:@rat-stack/core
Rename the bin entry in apps/cli/package.json, the root command in apps/cli/src/command.ts, and the version in apps/cli/src/version.ts. Then change every matching import and workspace manifest reference. Find the current @rat-stack/ names with:
rg -n '@rat-stack/' --glob '*.json' --glob '*.ts' -l A new scope changes line lengths, so run the formatter once after the rename:
pnpm fix Replace inspectFile in packages/core with one useful capability. Add it to capabilities28, then verify each surface you keep. Rewrite the Project law, Architecture, and Boundaries sections of AGENTS.md and the top of .pi/APPEND_SYSTEM.md; they describe rat-stack until you do. Keep expected failures typed and map them to deliberate exit codes.
apps/site is the public site and Worker. apps/infra is its Alchemy Stack. The browser reader and content build also depend on apps/site; deleting those directories alone is not a supported cut. Trace the dependencies in Keep or cut first. If you keep the site, change the Cloudflare Zone name and the DNS names and targets derived from it in apps/infra/alchemy.run.ts. Change the Worker domain and redirects in apps/site/src/worker.ts. Choose an Alchemy stage for each plan or deploy. The stage is a command-line choice, for example --stage <stage>. Configure credentials with:
pnpm alchemy profile edit --add Cloudflare Run the acceptance gate before the first push:
pnpm turbo run check test build What it promises and how to check
- One capability reaches every kept surface. Proof:
packages/capability/test/to-command.test.ts,packages/capability/test/to-http-api.test.ts,packages/capability/test/to-toolkit.test.ts,packages/capability/test/to-code-mode.test.ts, andapps/cli/test/cli.e2e.test.ts. - Schemas are the contract. Proof:
packages/capability/test/catalog.test.ts,packages/capability/test/to-http-api.test.ts, andpackages/capability/test/to-toolkit.test.tscheck derived JSON Schema and typed failures. - A fresh sandbox isolates model code. The Node sandbox has a 10-second wall-clock limit and a 1-second limit per synchronous evaluation. Both run inside the child. Scope close and interruption send SIGTERM, then SIGKILL after 250 milliseconds. Stdin EOF, a lost parent, or a failed protocol write ends the child. Child-process imports remain blocked. Proof:
packages/capability/test/sandbox.test.tschecks isolation and VM budgets;sandbox-lifetime.test.tsandsandbox-orphan.test.tscheck deadlines, parent death, and process-group cleanup. - Rate limits fail closed. Proof:
apps/site/test/worker.test.tschecks 429 responses before another execute worker starts and when the global limit denies. - Markdown is the default machine representation. Proof:
apps/site/test/worker.test.tschecks Markdown withoutAccept: text/htmland HTML only when requested.
Keep or cut
Choose a feature cut below. Combined package names mean the dependent features go together; the Keep entries name shared build dependencies, not independent removal recipes. After each cut, update the package list in AGENTS.md and run pnpm install, pnpm fix, pnpm git-snapshot, and pnpm turbo run check test build. For projection cuts, trim packages/capability/src/index.ts too. These are local-source cuts, not instructions to destroy deployed resources or data.
Only the CLI:
- Keep:
packages/capability/src/contract.ts,packages/capability/src/implement.ts,packages/capability/src/to-command.ts,call-watch.ts,actor-watch.ts, every dependency imported by retained code, and their tests; all ofpackages/core; thetoCommandcomposition inapps/cli/src/surfaces.ts - Delete: unused projections and their matching tests after tracing the retained imports; unused compositions in
apps/cli/src/surfaces.ts; thecatalog,openapi,serve, andmcpcommands inapps/cli/src/command.ts;apps/cli/test/serve.test.tsand the MCP and catalog cases inapps/cli/test/cli.e2e.test.ts
- Keep:
No code mode:
- Delete:
packages/capability/src/catalog.ts,packages/capability/src/code-mode.ts,packages/capability/src/sandbox-error.ts,packages/capability/src/sandbox-service.ts,packages/capability/src/sandbox-subprocess.ts, andpackages/capability/src/to-code-mode.ts;packages/capability/test/catalog.test.ts,packages/capability/test/sandbox.test.ts,packages/capability/test/sandbox-lifetime.test.ts,packages/capability/test/sandbox-orphan.test.ts,packages/capability/scripts/sandbox-lifetime-proof.mjs, andpackages/capability/test/to-code-mode.test.ts; the./sandboxand./code-modeexports inpackages/capability/package.json;codeModeandmcpServer.codeModeinapps/cli/src/surfaces.ts; thecatalogcommand and the--code-modeflag inapps/cli/src/command.ts; the code-mode and catalog cases inapps/cli/test/cli.e2e.test.ts
- Delete:
No HTTP:
- Delete:
packages/capability/src/to-http-api.ts,packages/capability/src/http-api.ts, and their tests; the./http-apiexport inpackages/capability/package.json;http,routes, andwebServerinapps/cli/src/surfaces.ts; theopenapiandservecommands;apps/cli/test/serve.test.ts; the OpenAPI case inapps/cli/test/cli.e2e.test.ts
- Delete:
No MCP:
- Delete:
packages/capability/src/to-toolkit.ts,packages/capability/src/toolkit.ts, their test, andpackages/capability/test/mcp-harness.ts; the./toolkitexport inpackages/capability/package.json;toolsandmcpServerinapps/cli/src/surfaces.ts; themcpcommand; the MCP cases inapps/cli/test/cli.e2e.test.ts. Code mode imports frompackages/capability/src/to-toolkit.ts, so cutting MCP cuts code mode too
- Delete:
Default flags only:
- Keep: Core’s
Flagsport and declarations - Delete: Replace
apps/site/src/flags.tswith core imports andexport const flagsLayer = Flags.defaults(eventFlags); export const liveFlagsLayer = flagsLayer;; removepackages/flagsand its dependency inapps/site/package.json. Readers use defaults; the CLI writer fails with a named read-only error
- Keep: Core’s
No analytics:
- Delete:
packages/events; the@rat-stack/eventsline inapps/site/package.json - Change: the one line in
apps/site/src/events.tsbecomesexport { events, memoryEvents } from "@rat-stack/core/events-off"; - Then:
pnpm install,pnpm git-snapshot, and the gate - Optional:
EVENTS_ENABLED,EVENTS_SINK_TOKEN, andEVENTS_IDENTITY_MODEinapps/site/.env.schemaandapps/site/src/config-fingerprint.ts, and the events flags inpackages/core/src/flags.ts. The Worker ignores them once capture is off. Details:packages/events/README.md
- Delete:
No account auth or database (
auth18 anddatabase11, with protected feedback and browser dev identity):- Delete:
packages/authandpackages/database; their dependencies inapps/site/package.json, and@rat-stack/authinapps/web/package.json;apps/site/src/auth/{binding-client,foundation,infrastructure,private-capabilities,private-tag,private-worker}.tsandapps/site/test/feedback-auth.test.ts - Delete:
apps/web/src/dev/{client,features,devtools},apps/web/test/overlay.test.ts, andapps/web/test/overlay.scene.test.ts; the recording case inapps/web/test/dev-server.test.tsand the development-build case inapps/web/test/production-bundle.test.ts. Keep its production no-leak check - Change: in
apps/site/src/worker.ts, remove thefeedbackInfrastructureimport and call, and passundefinedin the feedback argument tomakeMischief. Keep the unavailable feedback port inauth/feedback-access.ts; it cannot write feedback - Change: remove the
privateAuthimport andAUTH_ENABLEDprovider wrapper fromapps/infra/alchemy.run.ts; removeLearnFeedbackAuthfrom the budget, entry, temporary-raise, and measurement lists inapps/site/scripts/startup-budget.ts, and remove itsfeedbackAuthBuildimport - Change: replace
devtoolsRouteswithcontentRoutesfrom./content-routes.jsinapps/web/src/dev/backend.ts; point thedevelopmentcondition of#devtools-overlayat./src/client/no-devtools.ts; remove@rat-stack/devtoolsfromapps/web/package.json - Change: in
packages/core/test/boundaries-rule.test.ts, remove the auth-onlytestPeoplefixture; replaceauthDistributionwith adevtools8 import from@rat-stack/devtools/dist/index.js, andauthBarrelwith apackages/core/srcre-export from@rat-stack/devtools. Keep their refusal assertions. Remove auth test people from the allowed dev fixture - Change: in
apps/infra/test/provider-coverage.test.ts, keep both events modes and every provider-registration assertion; remove the auth-mode loop and the assertions requiringDrizzle.SchemaandBetterAuth.Migrate. Remove the two database excerpt fences from.brain/resources/lore/scopes-own-resources.svx35 and refer to its linked source instead - Then:
pnpm install,pnpm git-snapshot, andpnpm turbo run check test build - Keep: the unused
AUTH_ENABLEDschema/fingerprint input can stay.WEB_BOT_AUTH_ENABLEDandWEB_BOT_AUTH_PRIVATE_JWKprotect a different interface; do not remove them with account auth. Never replace protected feedback with an unauthenticated writer
- Delete:
No devtools (keep the CLI and browser reader):
- Delete:
packages/devtools; its dependencies inapps/cli/package.json,apps/web/package.json, andpackages/auth/package.json;apps/web/src/dev/{client,features,devtools};apps/web/test/overlay{,.scene}.test.ts;packages/auth/test/devtools.test.ts, which tests recorder/identity integration - Change: in
apps/cli/src/surfaces.ts, removeDEVTOOLS_MCP_PATH,withDevtools,toolkitServer,devtoolsRoutes,devtoolsWebServer, andmcpServer.{devtools,devtoolsCodeMode}; remove theirAnyCapability,Effect, and recorder imports. Inapps/cli/src/command.ts, removedevtoolsFlag, bothdevtools8 options and handler branches, the devtools URL log, and theSERVE_HOST/DEVTOOLS_MCP_PATH/devtoolsWebServerimports.servebecomes({ port }) => Layer.launch(webServer(port)); MCP still selectsmcpServer.codeModeormcpServer.toolsthrough an expression arrow - Change: replace
devtoolsRouteswithcontentRoutesfrom./content-routes.jsinapps/web/src/dev/backend.ts; point thedevelopmentcondition of#devtools-overlayat./src/client/no-devtools.ts - Change: remove only the recorder cases in
apps/cli/test/{serve,cli.e2e}.test.tsandapps/web/test/dev-server.test.ts, and the development-build positive control inapps/web/test/production-bundle.test.ts. Remove the unused recorder anddevtoolsRoutesimports and thedecodeDevtoolsCalldecoder; keep ordinary REST, MCP, RPC, and production no-leak checks - Change: in
packages/core/test/boundaries-rule.test.ts, replace removed recorder fixtures with retained@rat-stack/auth/devtoolstest-person fixtures (ratTestPerson as devtools, andtypeof import("@rat-stack/auth/devtools").runAsPersonfor the type import). Drop the recorder from the allowed dev wiring fixture. UseinspectFileContractfrom@rat-stack/core/contractsfor the browser-safe fixture andinspectFilefrom@rat-stack/corefor the rejected browser-handler fixture. Keep every boundary assertion - Then:
pnpm install,pnpm git-snapshot, andpnpm turbo run check test build - Optional: keep auth’s unmounted test-person helpers and capability’s no-op observer ports. Removing the recorder does not require deleting the ports used by handlers and machines
- Delete:
No live signup (
subscriber-deliveryandintake-live):- Delete: both packages and their dependencies in
apps/site/package.json;apps/site/src/interest/{applications,interest-durable-object,interest-index-durable-object}.ts;apps/cli/src/{join-interest,intake,intake-erase,intake-redeliver}.tsand the three matchingintake*CLI tests. Delete site testsintake-applications{,-concurrency},interest{,-capture}-runtime,join-interest,mcp-privacy, andpage-ticket, plusapps/site/test/fixtures/interest{,-capture}-worker.ts - Change: remove the
joinInterestimport and registration inpackages/core/src/inspect-file.tsandapps/site/src/capabilities/index.ts. RemoveintakeCommandfromapps/cli/src/command.ts; removeremoteJoinInterestLayerand its provision fromapps/cli/src/cli.ts. Inapps/cli/test/command.test.ts, change the extra-subcommand count from5to4 - Change: in
apps/site/src/worker.ts, remove the signup imports; theinterestDirectoryandagentSignupparameters and arguments ofmakeMischief; the signup Config reads andinterestServices,interest14,joinServices,applications,erasure, andredeliverydeclarations; andscheduleIntakeSweep. Remove theinterest14 andjoinTokensroute options and thejoinServicesprovision. Remove theInterest/InterestIndexresources,agentSignupconstruction, andCronEventSourceregistration/provision. Keep capture, auth, flags, rate limits, sandbox, and reader wiring - Change: replace
apps/site/src/interest/page-ticket.tswith the unavailable-page implementation below. Inworker-{runtime-init,events,error-pages}.test.ts, removeInterestDirectoryimports andInterestDirectory.memoryarguments. Remove thejoinInterestinventory expectations fromworker.test.ts; make both inventory assertions ininterest.test.tsexcludejoinInterest. Remove only that file’s two signup-UI cases, “offers the agent-only primary application control and no retired form or Shield” and “serves the approval card, five questions and ticket only to agents”, and their unusedcopyPrompts/htmlTokensimports. Instatic-assets.test.ts, remove theIntakeTicketimport andIntakeTicket.testLayerprovision; importSIGNUP_UNAVAILABLEfrom../src/interest/page-ticket.jsand replace the fresh-ticket inequality with equal bodies containing that message. Keep its HEAD, validator, cache, and routing assertions - Then:
pnpm install,pnpm git-snapshot, andpnpm turbo run check test build - Keep: the
INTEREST_*,DROVR_*,JOIN_DELIVERY_DEADLINE_SECONDS, andTYPESAFE_API_KEYschema/fingerprint inputs remain declared. Core’s ports and unmounted route/domain helpers also stay. This cut removes live resources and public signup capabilities, not every domain type; the workshop returns an unavailable signup message
import { Effect } from "effect"; export const SIGNUP_UNAVAILABLE = "Signup is temporarily unavailable; try again shortly."; const unavailableSignup = (body: string) => body .replace( /The page ticket is:[\s\S]*?Do not claim they joined or received a seat from the submission response\./u, SIGNUP_UNAVAILABLE ) .replaceAll("__INTAKE_PAGE_TICKET__", SIGNUP_UNAVAILABLE); export const withAvailablePageTicket = (body: string) => Effect.succeed(unavailableSignup(body));- Delete: both packages and their dependencies in
No deployment driver (
deployandcheck-harnesstogether):- Delete:
packages/deploy,packages/check-harness,scripts/deploy-build.ts, andscripts/deploy-preview.sh; the rootpackage.jsonscriptsdeploy:plan,deploy:prod,deploy:preview,deploy:preview:destroy,deploy:rollback, andstate:copy - Change: remove the three
packages/deployexcerpt fences from.brain/resources/lore/http-responses-need-validation.svx11; change “the in-memory fixture below” to “the in-memory fixture in the linked source”. Keep its historical source links - Then:
pnpm install,pnpm git-snapshot, andpnpm turbo run check test build - Keep:
check-harnesswhile retainingdeploy; deployment contracts, checks, receipts, and machines import its verdicts. This cut removes the deployment driver, rollback receipts, preview driver, and state-copy command; it does not removeapps/infraor run a deployment
- Delete:
No cloud stack (
infra, after the deployment-driver cut):- Delete:
apps/infra; the rootpackage.jsonscriptsalchemy,infra:deploy,infra:destroy,infra:dev, andinfra:plan; theapps/infra/alchemy.run.tsexcerpt fences inskills/learn-rat-stack/SKILL.mdandskills/learn-alchemy/SKILL.md - Change: replace
apps/infra/package.jsonwithapps/site/package.jsoninapps/site/scripts/generate-content.ts,apps/site/scripts/migration-inputs.ts,apps/site/test/component-registry.test.ts, and theALCHEMY_VERSIONread inscripts/vendor-agent-sources.sh. The site already pins the same Alchemy version. Change that script’s source-pin explanation fromapps/infratoapps/site - Change: in
packages/core/test/boundaries-rule.test.ts, replace the@rat-stack/infrabrowser-import fixture with../../../../infra/alchemy.run.ts. Keep its rejection assertion; the deleted package alias no longer resolves, but the reserved infra-path boundary still applies - Then:
pnpm install,pnpm git-snapshot, andpnpm turbo run check test build;bash -n scripts/vendor-agent-sources.shchecks the adapted source-fetch script. This combined cut removesinfra,deploy, andcheck-harness; it leaves the Worker declarations and content build available without a deployment Stack
- Delete:
No CLI (keep browser devtools and hosted interfaces):
- Delete:
apps/cli,.github/workflows/ratstack-publish.yml, and the rootpackage.jsonscriptcli. This also removes the publishedratstackbin - Change: in
scripts/acceptance-cold-clone.sh, wrap the CLI help, HTTP, MCP, and catalog smoke steps after the full gate inif [[ -f apps/cli/package.json ]]; then…fi. Keep cold install, workspace rename, capability registration, and the full gate; they still apply without the CLI - Change: remove all
apps/cliexcerpt fences fromskills/learn-rat-stack/SKILL.mdand.brain/resources/lore/{structure-effect-by-domain,one-schema-three-surfaces,layers-make-dependencies-explicit,error-model,effect-basics}.svx. Keep historical source links. Inapps/site/test/worker.test.ts, keeppackages/core/src/inspect-file.tsas the pinned-excerpt link fixture and remove onlyapps/cli/src/surfaces.tsfrom that path list - Then:
pnpm install,pnpm git-snapshot, andpnpm turbo run check test build;bash -n scripts/acceptance-cold-clone.shchecks the adapted shell script - Optional: keep
packages/devtoolsfor the browser overlay. Keeping HTTP, MCP, and code mode in Mischief does not require the local CLI
- Delete:
Keep
lorewith the hosted content graph:apps/site/src/content-store.tsbuilds its graph throughLoreGraph;apps/site/scripts/generate-content.tsconsumes its graph schemas. Cutting the package without replacing those callers loses graph-backed content queries and the content build. Remove the graph feature first; this is not an independent package cutKeep
code-snippets16 with the teaching-content build:apps/site/scripts/{code-pipeline,generate-content,git-snapshot,doc-fences}.tsuse its schemas, source adapters, and excerpt pipeline. Cutting it loses source-checked excerpts, snapshot generation, and documentation-fence checks. Replace that pipeline before deleting the packageKeep
web9 with the shared reader build:apps/site/scripts/reader-*-flags.tsandreader-body-document.tsimport reader models, document nodes, and templates fromapps/web;generate-content.tsimports its page copy.apps/infra/alchemy.run.tsalso composesWebsiteand theWEBSITEbinding. Cuttingapps/webloses the browser reader and breaks hosted-content generation, not just UI deployment. Separate those shared build inputs firstKeep
mischief(apps/site) with the hosted content product:apps/web/src/dev/backend.tsimports its content capabilities and Node layer;apps/web/src/website.tsimports its RPC workers.apps/web/scripts/reader-build.tsimports its reader-input generators, andapps/web/package.jsonruns its content generator before development. The infra Stack imports its workers. Cuttingapps/siteloses the hosted tools and the reader’s generated content/backend. Extract or replace those pieces before deleting the appNo XState (only after removing interest and every other lifecycle except file inspection):
- Keep: Keep XState and its bridge while any retained lifecycle imports them
- Delete:
packages/core/src/inspect-machine.tsand its test (callFileInspector.inspectdirectly frompackages/core/src/inspect-file.ts);xstateand@xstate/effectinpackages/core/package.jsonand theirminimumReleaseAgeExcludeentries inpnpm-workspace.yaml; the compiled@xstate/effect/oxlintplugin registration andxstate-effect/no-inline-effectrule inoxlint.config.ts
defineContract, implement, and toCommand are the minimum that keep stats working. The contract module has no dependency on the other projections.
License
MIT
Last changed 2026-11-11 in 08d6482. Source on GitHub. Change log.
Linked from
- Agent rules for rat-stack (AGENTS.md). What you may change, which commands to run, and which changes need approval.
- Effect + Alchemy peer patterns. Source-grounded patterns from repos on nearby Effect and Alchemy pins.
- gardener. Keep rat-stack current and clean. Update exact dependency versions, learn from repos on the same versions, and add lint rules before cleanup.
- Learn mode presents concepts at useful depths. An agent presents source-derived concepts during real work and keeps learning events in a private local log.
- model-a-protocol. Check a protocol with a small TLA+ model before you build or change it. Use when steps can interleave or die halfway, such as a crash between two writes, a retry after an unknown outcome, an alarm or sweep that redrives work, or two writers on one record. Also use when asked "can this race?", "what if it dies here?", or "model this", or before a durability design review.