С любовью ко всем разработчикам на свете ❤️
The point0 CLI ships in @point0/engine. Every command
finds your engine file, imports it, and calls the matching
engine method — point0 dev runs engine.dev(), point0 build runs
engine.build(), and so on. The CLI's own job is small: resolve the
environment, find the engine, parse flags.
// package.json — the scripts a scaffolded app ships with
{
"scripts": {
"dev": "point0 dev --hot",
"generate": "point0 generate",
"build": "point0 build",
// there is NO `point0 start` — production runs the built server directly:
"start": "cross-env NODE_ENV=production bun run ./dist/server/index.server.js",
},
}You rarely type these by hand — they live in package.json and you run them
with bun run dev / bun run build. The rest of this page is one section per
command, then a full flag reference.
Start the dev server and client dev servers. Thin wrapper over
engine.dev().
point0 dev # serve everything
point0 dev --hot # + bun-native server hot reload (the scaffold default)By default dev also generates the src/generated/point0 tree before
serving and watches for changes; pass --no-generate to skip it, --no-watch
to stop restarting on change.
Narrow what runs with --side and --scope:
point0 dev --side server # serve only the server
point0 dev --side client --scope web # one client scopeAnything after -- is forwarded to the spawned bun server process (bun-native
server only):
point0 dev -- --inspect # pass --inspect to the server runtime--hot hot-swaps edited points without restarting the server; cold files (the
@point0/core/cold subtree, the boot entry) still restart. It is
experimental and only affects the bun-native server — the Vite path ignores
it. See Dev for the full restart / hot-reload model.
There is no
point0 stopand no lock file — a running dev tree always sits in a terminal, and--no-orphans(below) tears the whole process tree down when that terminal dies. See Dev.
Build the server and every client for production. Thin wrapper over
engine.build().
point0 build # clean build of server + clients
point0 build --side client # build only the clientsBuild always generates first — there is no "build without generate". It also
forces LOG_MODE=pretty and defaults NODE_ENV to production; building with
any other mode warns and ships unminified, inline-sourcemapped client bundles.
--watch rebuilds on change. With no value it watches the import graph of
your build entries; a glob value adds to that:
point0 build --watch # watch the entries' import graph
point0 build --watch 'src/**/*.css' # + an extra glob--keep-alive holds the process open after a one-shot build, so a long-lived
build plugin (a bundle-analyzer server, say) keeps running until Ctrl-C:
point0 build --keep-aliveOther toggles: --no-clean (skip the pre-build clean), --no-publicdir (skip
copying public assets). Full build flow on Build.
Generate the src/generated/point0 tree — points.server / points.client,
routes, meta, assets.d.ts. Thin wrapper over engine.generate(). This
output is gitignored, so a fresh checkout must run it before typechecking.
point0 generate # generate once
point0 generate --watch # regenerate on changeIt runs as part of every app's setup script:
// package.json
{ "scripts": { "setup": "… && point0 generate && …" } }What each file contains is on Generator.
Print the point0-compiled output of one source file to stdout — useful to see exactly what the compiler strips (server-only code, babel-plugin rewrites).
point0 compile src/pages/home.tsx --side server
point0 compile src/pages/home.tsx -c # -c = --side client--side (or the -c / -s shorthands) picks which side to compile; --scope
is inferred from the side when there is only one. Mode shorthands -p / -d /
-t map to --mode production|development|test. --no-babel strips babel
plugins from the compiler options.
GOTCHA —
-his not help here.compilereassigns help to--helponly, so-his free for--hmr(force the HMR fix on). This is unique tocompile; every other command keeps-has help.
Trace the import chain from a source file to a target import, using the
engine's compiler. Prints each step on its own line.
point0 trace @prisma/client src/pages/home.tsx --side server--side / --scope work as in compile; --cwd overrides the trace root
(defaults to the engine file's directory). Throws Trace was not found when
there is no path from source to target.
Remove point0's temporary directories — the @point0 temp namespace
(node_modules/.cache/@point0) and the server hot-reload store
(node_modules/.cache/server-hot). No flags. Best-effort: errors are swallowed.
point0 pruneInspect the points your app declares, read from the generated meta.ts. Two
subcommands, both printing JSON. Every invocation needs at least one
--meta <path>.
# list points, with filters / pagination / field selection
point0 points list --meta ./src/generated/point0/meta.ts --type query --limit 20
# get the first point matching the filters
point0 points get --meta ./src/generated/point0/meta.ts --name ideaFilters include --ids / --id, --tags (every tag must match), --scope,
--type, --name, --route / --url, the --endpoint-* trio, --valid /
--ssr booleans, --file, --parent-id, --layout-id, and --fields to
select output keys. list adds --limit (default 100) and --offset (default
0). These are the CLI mirror of the project MCP's list_points /
get_point tools.
Search and read the Point0 documentation offline. Needs the @point0/docs
package installed (bun add -D @point0/docs); the docs and a search index ship
inside it.
point0 docs search "server only imports" # hybrid keyword + semantic search
point0 docs list # table of contents
point0 docs get cli # full markdown of one doc, by slugsearch and list take --limit / --offset; search defaults to 8 results.
This is the CLI mirror of the docs MCP.
@point0/engine and @point0/docs also ship MCP servers, and there's a
separate scaffolding CLI. Each has its own page.
An MCP server that exposes your app's points (and compile / trace) to an AI
agent. It reads the generated meta.ts and re-reads it on every call, so it
never serves stale points after a generate.
// package.json
{
"scripts": {
"mcp:project": "point0-project-mcp --meta ./src/generated/point0/meta.ts",
},
}Tools: list_points, get_point, compile, trace. Full setup on
MCP: project.
An MCP server (shipped in @point0/docs) that serves the Point0 docs to an
agent — list_docs, search_docs, get_doc. No --meta, no project setup; it
runs offline.
// .mcp.json — run the installed copy, matching your point0 version
{
"mcpServers": {
"point0-docs": { "command": "bunx", "args": ["point0-docs-mcp"] },
},
}Full setup, plus the "always latest" variant, on MCP: docs.
Scaffold a new app. Run it once; it asks for a directory name and a bundler
(Bun or Vite), scaffolds the template, installs deps, and runs
setup.
bun create point0-app@latest my-app # interactive
bun create point0-app@latest my-app --vite --no-interactivebun create point0-app resolves to the create-point0-app bin. Flags: --vite
/ --no-vite, --install / --no-install, -O, --override,
-I, --no-interactive. See Getting started.
Every command does the same three things before it touches your app, in order.
1. Resolve the env mode and load .env files. A command resolves its mode
from flags (--mode, or the -p / -d / -t shorthands where present) and
calls applyEnvMode before importing your engine — your engine reads
process.env at module scope, so the cascade must be loaded first. Precedence:
flag mode > --env NODE_ENV=… > a shell-exported NODE_ENV > the
command's default. The .env cascade (later overrides earlier) is .env,
.env.<mode>, .env.local (skipped in test), .env.<mode>.local; shell
exports always win over files. Defaults: dev / generate / compile /
trace → development, build → production.
point0 build --mode test # load the test cascade
point0 dev --env API_URL=http://localhost # define a var, overrides .env files2. Find the engine file. --engine <path> is explicit; otherwise the CLI
checks POINT0_ENGINE_FILE, then auto-finds a file named engine (.ts /
.js / .tsx / .jsx) in ., ./src, ./lib, and a few point0
subfolders. Not found:
Could not find engine.ts or engine.js file. Searched in: ./, ./src/.
Use --engine <path> to specify the engine file locationThe module must export engine (named) or default, an Engine instance.
3. The flag-free shebang. The bin starts with a plain interpreter line:
#!/usr/bin/env bunDeliberately flag-free: flags in a shebang need env -S, which Bun's Windows
bin shim mis-parses — a flagged shebang could never launch on Windows. What
flags used to do here is handled in code instead. Bun may auto-load a .env
cascade for the startup-derived NODE_ENV before any CLI code runs;
applyEnvMode (step 1 above) restores process.env from the native OS
environment and loads exactly the resolved mode's cascade before your engine
file is imported. And --no-orphans (bun ≥ 1.3.14, no-op on Windows) is passed
explicitly on every dev/build child spawn and inherited by nested bun processes
— a child dies when its parent dies, even by SIGKILL, and SIGKILLs every
descendant on exit. This is why @point0/engine carries an engines field, and
why each app's bunfig.toml sets [run] noOrphans = true to extend the
invariant to your bun run dev wrapper.
AGENT GOTCHA: because of
--no-orphans, a backgroundedbun run dev &dies the moment the shell that spawned it returns — run it in a real long-lived process, not a throwaway shell.
| Command | Wraps | Does |
|---|---|---|
dev | engine.dev() | dev server + client dev servers |
build | engine.build() | production build of server + clients |
generate | engine.generate() | write src/generated/point0 |
compile <file> | Compiler | print compiled output of one file |
trace <target> <source> | Compiler | print import chain source → target |
prune | engine.prune() | remove temp dirs + hot store |
points list / points get | analyzer meta.ts | inspect declared points (JSON) |
docs search / list / get | @point0/docs | search / read the docs offline |
Available across most commands (each command's full set is in its section above).
| Flag | On | Effect |
|---|---|---|
--engine <path> | dev, build, generate, compile, trace | engine file, absolute or relative to cwd |
--mode <mode> | dev, build, compile | production | development | test — picks the .env cascade |
-p / -d / -t | compile | shorthand for --mode production / development / test |
--env <name=value> | dev, build | define a var (repeatable); overrides .env files |
--side <side> | dev, build, compile, trace | server or client |
--scope <scope> | dev, build, compile, trace | one scope (inferred from side when single) |
| Flag | Effect |
|---|---|
-G, --no-generate | skip generation before serving |
-W, --no-watch | do not restart / regenerate on change |
-w, --watch [glob] | watch glob(s); no value = server config's devWatchGlob |
--side <side> / --scope <scope> | serve one side / one scope |
--entry <name|path> | server entry points (comma-separated or repeated) |
--hot | server hot reload (bun-native, experimental) |
--env / --mode / --engine | see shared flags |
-- <args> | forwarded to the spawned bun server process |
| Flag | Effect |
|---|---|
-w, --watch [glob] | watch the entries' import graph; a glob adds to it |
--side <side> / --scope <scope> | build one side / one scope |
-C, --no-clean | do not clean before building |
-P, --no-publicdir | do not copy the public dir |
-k, --keep-alive | hold open after the build (for long-lived plugins) |
--env / --mode / --engine | see shared flags |
| Flag | Effect |
|---|---|
--side <side> / -c / -s | compile side (-c = client, -s = server) |
--scope <scope> | compile scope (inferred from side when omitted) |
-b, --built | treat the engine as built (else POINT0_BUILT === 'true') |
-B, --no-babel | strip babel plugins from compiler options |
-h, --hmr / -H, --no-hmr | force the HMR fix on / off (else engine config) |
-p / -d / -t / --mode / --engine | see shared flags |
| Var | Effect |
|---|---|
POINT0_ENGINE_FILE | engine file fallback when no --engine |
POINT0_DEV_SERVER_HOT='true' | enables dev server hot reload when --hot is omitted |
POINT0_BUILT='true' | compile / trace treat the engine as built |
POINT0_MODULE_PRELOAD='false' (also 0/off) | kill switch: disables per-page modulepreload (manifest emission at build + link injection at serve); any other / unset value keeps it on |
NODE_ENV | mode resolution (after flags and --env) |
LOG_MODE | build forces pretty |