Imported from 1gr14/point0 (
AGENTS.md). Install upstream withnpx skills add 1gr14/point0. Copyright stays with the author.
point0 — agent guide
Agent guide for the point0 monorepo. point0 is a fullstack TypeScript framework
on Bun; its point0 CLI (from @point0/engine) drives dev/build/generate for
apps built on it. This file gets you oriented — the real conventions live in the
code, its JSDoc, and docs/; trust those over priors.
First-time setup (fresh checkout or worktree)
A fresh tree has no node_modules and no dist/. Bootstrap once, in order:
bun install # deps (+ Bun's native binary on first run)
bun run build # every @point0/* dist + .d.ts, in dependency order
bun run setup # codegen across the workspace: prisma generate + point0 generate
buildis mandatory — every@point0/*imports its siblings from their builtdist/. Skip it and you get hundreds of phantomTS2307 Cannot find module '@point0/…'andpoint0: command not found.setupis codegen-only (no DB) — needed beforebun run types, because every app'ssrc/generated(Prisma client + point0 points/routes/assets) is gitignored. (examples/expois the exception: nogenerate, commits itspoints.server.ts.)installis safe in a fresh tree — the apps' migrate/seed lives in their ownsetup, notprepare. If it ever stops with "Bun's postinstall script was not run", finish withbun node_modules/bun/install.js.- On Windows, run
bun installa second time afterbuild(it takes ~5s and reports "no changes"), thensetup. Bun links bins only during an install, and on Windows a bin is a real.exeshim, sopoint0cannot be linked at install time —packages/engine/dist/cli.jsdoes not exist yet, andbuilddoes not link bins. Without that second install every app failssetupwithbun: command not found: point0. macOS and Linux are unaffected: a bin there is a symlink, which is created pointing at the not-yet-built file and starts working the moment the build produces it. (Verified on Windows 11 / bun 1.3.14, two fresh clones, deterministic; CI never hits it because the test jobs download the builtdistbefore installing.) - To run an example after building:
bun installonce more to relink thepoint0bin, thenbun run setupinside the example for its SQLite DB.
Golden rules
- Don't read giant files whole.
packages/core/src/point0.tsis ~11,300 lines; grep for the symbol, Read only that range (offset/limit). Same for any>1000-line file (types.ts, mountable.ts). Serena MCP (mcp__serena__*) is nicer if you've enabled it, but it's off by default and this repo configures no MCP — Read + grep is the baseline. - Don't rebuild manually in the main checkout.
bun run build:watchis usually running there, so a manualbun run buildjust races it — rebuild only if adist/is clearly stale or the user asks. In agit worktree(yours alone) rebuild freely. Either way, a fresh tree needs the bootstrap above. - Never run the full suite.
bun test/bun run testais slow (integration-heavy). Usebun run testf,bun test path/to/file.int.test.ts, orbun --filter '@point0/<pkg>' test— the narrowest run that proves the change. Every test file carries its class in the name —.unit(pure logic),.int(real processes/servers, no browser),.e2e(real browser) — andscripts/test.tsis the single runner/planner (--list/--plan). - Never commit, push, publish, tag, or release on your own — no
git commit/push,npm/bun publish,bun run release/publish:packages, unless asked in the current chat. Prior approval doesn't carry over. - Don't create README files — docs live in docs/, managed separately.
- Versions live in the root
workspaces.catalog(package.json) as a data table; each package carries the materialized version (nocatalog:/workspace:*). Change the catalog, thenbun run versions:write(CI/pre-commit runversions:check).bun run releasebumps internal@point0/*ranges + the version (see dev/docs/releasing.md).
Repo layout
packages/
core/ isomorphic kernel: Point0, points-manager, eventer, super-store, env, error, navigation, schema adapters. Pure logic, no server I/O.
engine/ server runtime + CLI + build orchestration. Owns the `point0` and `point0-project-mcp` bins; dev/build/generate, vite/bun integration.
compiler/ source transform: walker, point detection, virtual modules, babel/mdx plugins, bun/vite plugin entry points.
react-dom/ React/DOM bindings on top of core.
openapi/ OpenAPI generation from points.
basic-auth/ basic-auth helper points. cors/ CORS helper.
create-app/ scaffolding CLI (`create-point0-app`).
docs/ docs content + search/embeddings; owns the `point0-docs-mcp` bin.
examples/ basic (canonical: Prisma + tailwind + wouter), better-auth, capacitor, expo, socket (channels/spaces/handlers), vite.
docs/ user-facing docs (don't write here unless asked).
scripts/ repo tooling (publish, local-registry, test runner/planner, setup, release).
Fast navigation
| You want to… | Start here |
|---|---|
A Point0 API surface |
grep (or Serena find_symbol) in point0.ts — never read it whole |
| How an app is configured | examples/basic/src/engine.ts |
| How a page/component/mutation is authored | examples/basic/src/pages/home.tsx |
| Add/modify a CLI command | packages/engine/src/cli.ts |
| Engine config schema | packages/engine/src/config.ts |
| Compiler/transform | compiler.ts, walker.ts, file.ts |
| Bun/Vite/Babel plugin glue | packages/compiler/src/plugin/ |
| Schema adapters (zod/valibot/…) | packages/core/src/schema/ |
| Test patterns | packages/core/tests/, packages/compiler/tests/ |
| What's untested / what to test next | dev/docs/coverage.md, then bun run cov → coverage/coverage.md |
| Client bundle size + its client deps | scripts/size.ts — measures, audits, and rewrites the numbers in the docs |
Commands
From repo root unless noted.
bun run build # build all packages in dependency order
bun run build:watch # parallel watch (usually already running in main checkout)
bun run testf # fast: unit + int minus the solo heavies — default while iterating
bun run testa # everything incl. e2e (slow); `tests` = solo lane only (heavy int + e2e)
bun run test:unit # one class; also test:int, test:e2e; test:plan prints the CI plan
bun run cov # `testf` with line coverage → coverage/coverage.md (what to test next); `cov:all` adds the heavies
bun run size # measure Point0's client-bundle weight; `size:write` syncs the docs, `size:audit` gates in CI
bun run types # tsc --noEmit — `tsc` is TypeScript 7, via the `@typescript/native` alias
bun run types:6 # examples only: same check on TS 6, so the published types keep working for users still on 6
bun run check:toolchain # asserts which TypeScript is wired where (both ways of getting it wrong are silent)
bun run lint # eslint --fix; `format` = prettier --write
Two TypeScripts are installed on purpose. @typescript/native
(npm:typescript@7) owns the tsc bin and does every type-check. The plain
typescript dep stays on 6 because typescript-eslint's type-aware rules and
tsdown's .d.ts emit load it as a module, and 7 ships no compiler API until 7.1
— its own tsc bin is shadowed, so types:6 invokes it by path. Nothing point0
SHIPS depends on either: the compiler reads tsconfig paths itself, so a user's
project works on 6, 7, or with no TypeScript at all.
Inside an example: bun run dev | build | start | generate.
Conventions
- ESM-only (
"type": "module"); imports use the explicit.jsextension even from.tssources (tsdown expects it). - Build is tsdown. Adding a subpath export → update
exports+typesVersionsin the package'spackage.jsonand itstsdown.config.ts. - Workspace deps use
"workspace:*"; external deps use"catalog:", declared once in the root. - A package that imports a sibling maps it to source in its
tsconfig.jsonpaths("@point0/core": ["../core/src/index.ts"]) — Bun uses the tsconfig nearest the importing file, so without it the tests run against a stale builtdist.tsconfig.build.jsonstays path-less on purpose. - Added or removed something the browser downloads?
bun run size:write— it re-measures, rewrites the numbers in README + the two overviews, and fails if a third-party package reached the client bundle without being declared. - Tests live in each package's
tests/(bun test), fixtures undertests/fixtures/. Generated code (examples/*/src/generated/point0/) is never hand-edited. bunonly — not npm/pnpm/yarn.- After a change, run the touched package's
types+testbefore declaring done — type errors incorecascade everywhere. Touched public API? Update the matchingexports/typesVersionsand anyexamples/basicconsumer. - Touched public behavior? Update the docs in the same change. Before
declaring a task done (and before any commit), check whether the change
affected anything the user-facing docs cover — a method, an option, a CLI
command, an endpoint, observable behavior, the compiler's strip categories. If
so, update the matching
docs/<category>/<slug>.mdpage and its JSDoc (they must stay in sync), and re-check the<!-- TODO(...) -->markers. How the docs are structured and written: dev/docs/docs.md — it covers the<!-- TODO -->markers and the extractor that collects them into adev/backlog/docs-todo.mdon demand (no file in the tree when none are open).