Start

It is a GitHub template. Create a repo from it:

gh repo create <name> --template JakubSzwajka/drunk-cat-stack

Then run corepack enable and pnpm install. The install patches tsc with the Effect diagnostics and puts the pre-commit hook in place.

Or paste this into your coding agent:

Read https://github.com/JakubSzwajka/drunk-cat-stack and use it as the
reference for how we set up TypeScript repos: exact pins, one
`pnpm check` that fails on structure rules, Effect 4 with typed
errors, and a fence that blocks `--no-verify`. Read its README,
AGENTS.md and skills before you write code. Follow its rules, and
tell me when my code breaks them.

Already have a pnpm workspace? The Adapt it section of the README lists which files to copy.

Why

Every new project started with the same setup. Exact pins, lint and type rules, import boundaries, a pre-commit hook. I set it up by hand each time, and each repo ended up configured a little differently.

That setup matters more once agents write the code. An agent learns from what fails. A check that runs on every change gives it the same clear answer every time. A rule in a style guide gives it nothing to hit.

Joel Hooks' rat-stack showed me how to put all of this in one repo. drunk-cat-stack is my version of it. I start new projects from it and move fast without giving up on code quality or architecture. I care about both a lot, and I don't want speed to cost me either one.

Agents take the shortest path. A rule that lives only in prose gets skipped the first time it is in the way. So every rule a tool can check lives in pnpm check, lefthook runs it before each commit, and a Pi extension blocks --no-verify. The fence does not make an agent good. It raises the floor, so the worst normal run still passes the checks.

What is in it

Maintained tools, used as they are, each pinned to an exact version.

pnpm and Turborepo
One workspace, one lockfile, install policy, and the order of typecheck and test.
Biome
Formatting, plus a few lint rules such as no export * and no non-null assertions.
ESLint with eslint-plugin-codebase-ai-rules ↗
Comments stay one line and sit inside a function or class body.

My opinion This one is pure opinion. It is how I like comments. Opus 5 wrote comments like prose, and I hate that. So I wrote a rule for it and keep it in its own repo.

TypeScript 7 with @effect/tsgo
Strict types, and Effect diagnostics that fail the typecheck.
Dependency Cruiser
Import rules between apps, packages, and the layers inside an app.
Vitest with @effect/vitest
Tests that run Effects only through it.effect and it.layer.
varlock
Every variable in .env.schema resolves and matches its type.
lefthook
Runs pnpm check and pnpm test before each commit.

The rules they check fall into a few groups.

Pins and supply chain
Every dependency is an exact version, a full commit SHA, or workspace:<exact>. pnpm refuses a version younger than one day and any install script nobody approved.
Typed Effect errors
No floating Effects. No global Error, unknown, or any in an error channel, and no try/catch inside Effect.gen. No async, fetch, Date, or console where Effect has its own.
Module boundaries
No import cycles. A package never imports an app, and callers reach a package only through its src/index.ts. Use-cases never import delivery or server code.
The fence
lefthook runs the checks before each commit. A Pi extension blocks git commit --no-verify and the other ways to skip that hook.

The README table lists every rule with its tool and config file.

What pnpm check runs

pnpm check ─> pins ─> env:check ─> biome ─> lint ─> turbo run typecheck ─> deps
                                                     ├─ @hosti/bookings typecheck
                                                     └─ @hosti/api typecheck (after bookings)

pnpm test  ─> node --test tests/ ─> turbo run test
                                     ├─ @hosti/bookings typecheck ─> test
                                     └─ @hosti/api typecheck ─> test
What to notice. Turborepo caching is off for typecheck and test, so a gate never passes from cache.

The fence

git commit ──> lefthook pre-commit ──> pnpm check ──> pnpm test

Pi bash tool call
  └─> .pi/extensions/git-interceptor.ts
        └─> scripts/vcs-command-policy.mjs
              ├─ bypass     ─> deny, with reason
              └─ git or jj  ─> allow
What to notice. The block runs inside Pi, before the shell sees the command. It does not stop an agent that writes the command into a script file and runs that.

Credit

drunk-cat-stack is heavily inspired by rat-stack by Joel Hooks. The fence, the Effect setup, and the pnpm and Turborepo setup are adapted from its repo under the MIT license. The NOTICE file lists each adapted file.