CLI Overview
Every manic command, global flags, and what the binary actually runs.
CLI Overview
The manic binary ships with manicjs and is the entry point for dev, production builds, local production serves, deploy helpers, lint, and format.
bunx manic <command> [options]With a global install (bun add -g manicjs), you can run manic without bunx.
Commands at a glance
manic dev
Spawn Bun --watch on ~manic.ts, merged bunfig, config hot reload
manic build
Lint gate, bundles, minify, provider adapters
manic start
Run production server.js from outdir
manic deploy
Print or run provider deploy commands
manic lint / fmt
oxlint and oxfmt via bun x
Typical workflows
Command comparison
| Command | Primary output | Honors -p / --port | Honors --network | Spawns a child Bun process |
|---|---|---|---|---|
dev | Running dev server + writes bunfig.toml | Yes → PORT | Yes → HOST + NETWORK | Yes (bun --watch ~manic.ts) |
build | <outdir>/ bundles | Parsed globally; ignored inside build() | Parsed; ignored | No |
start | Foreground server.js logs | Yes → PORT env on child | Yes → NETWORK | Yes (bun server.js) |
deploy | stdout hints or vendor CLI runs | Ignored | Ignored | Sometimes (--run → Bun.spawn) |
lint | oxlint diagnostics | — | — | Yes (bun x oxlint subprocess) |
fmt | Rewrites sources via oxfmt | — | — | Yes (bun x oxfmt subprocess) |
Global behavior
| Flag | When it applies | What it does |
|---|---|---|
-h, --help | Always (no command or as an arg) | Prints full usage text and exits. |
-v, --version | Anywhere in argv | Prints a version string and exits (today: the literal latest from the CLI; for the precise package version use bun pm ls manicjs or package.json). |
-p, --port <n> | Parsed for dev, build, start, deploy | Currently only dev and start consumers use it: they set process.env.PORT on the spawned bun process. build accepts the parsed object today but does not change output or bind ports. deploy does not spawn your app server. createManicServer reads server.port from manic.config.ts (via loadConfig(), default 6070), not PORT—set server.port to match CLI expectations, or read process.env.PORT in custom ~manic.ts if you rely on the CLI flag. |
--network | Parsed for dev, build, start, deploy | Only dev / start set NETWORK on the child process (dev also toggles HOST). Other commands ignore it. |
Commands that do not spawn your ~manic server (build, lint, fmt, deploy) receive parsed port/network from argv but do not use them in their implementations today.
Command summary
| Command | Purpose |
|---|---|
manic dev | Development: generate bunfig.toml, spawn bun --watch on ~manic.ts with plugin preloads, watch manic.config.*. |
manic build | Production: lint, clean output dir, client + API + server bundles, minify, run provider.build hooks. |
manic start | Run ${outdir}/server.js with NODE_ENV=production. |
manic deploy | Ensure build output exists, print (or run) provider deploy commands. |
manic lint | Run oxlint with .oxlintrc.json. |
manic fmt | Run oxfmt with .oxfmt.json. |
argv routing (same binary, different handlers)
manic dev (in depth)
Handler: packages/manic/src/cli/commands/dev.ts
-
loadConfig()readsmanic.config.ts/.jsfrom the project root. -
writeBunfig()merges each plugin’sbunfigstring: collects[serve.static].pluginsentries from every plugin and writes a rootbunfig.tomlprefixed with# Auto-generated by manic dev — do not edit. Other non-static snippets are appended. -
Spawns:
bun --watch [--preload <plugin.preload> ...] ~manic.tswith
envincludingPORT,HOST(localhostvs0.0.0.0), andNETWORK. -
If
manic.config.tsormanic.config.jsexists,fs.watchdebounces (~100ms) and kills + respawns the child after re-importing config so plugin list and bunfig stay fresh.
Does not parse: --no-hmr, --no-view-transitions (those are not CLI flags today—use manic.config.ts server.hmr and router.viewTransitions).
manic build (in depth)
Handler: packages/manic/src/cli/commands/build.ts
Output directory: config.build.outdir (default .manic).
- Lint: Runs oxlint on
.(prefersnode_modules/.bin/oxlint, elseoxlint). Fails the build on non-zero exit (no separate--no-lintflag). - Prepare:
rm -rf <outdir>,mkdir -p <outdir>/client. - Plugin Bun plugins: For each
plugins[].preload, dynamicallyimportand registersdefaultorpluginexport viaBun.plugin()beforeBun.build. - Routes manifest:
writeRoutesManifest('app/~routes.generated.ts'). - Client bundle:
Bun.buildfrom resolved./app/main(app/main.tsx/.jsxrequired). Targetbrowser,oxcPlugin(),bun-plugin-tailwind, hashed entry/chunk/asset names. Copies top-levelassets/→<outdir>/client/assetsif present. Rewritesapp/index.html(or generates minimal HTML) somainscript and Tailwind CSS point at built filenames; writes<outdir>/client/index.html. - Plugin
buildhooks: Runs each plugin’sbuild()withemitClientFile,injectHtml, route lists,dist, etc.; reapplies HTML injections toindex.html. - API bundles: Skipped when
mode === 'frontend'. Otherwise globsapp/api/**/index.ts, bundles each withBun.build(target: 'bun', dependencies external), outputs under<outdir>/api. Writes RFC 9727/.well-known/api-catalogunder<outdir>/clientwhen any API exists. - Server bundle: Reads
~manic.ts, rewritesimport … from './app/index.html'toBun.file("<outdir>/client/index.html").text(), adjustscreateManicServer({ htmlinjection, writes temp<outdir>/_entry.ts,Bun.build→server.js, deletes temp entry. - Minify: oxc-minify over
<outdir>/client,<outdir>/api(if any), andserver.js(es2022, mangle). - Providers: For each
config.providerswith abuildfunction, callsprovider.build({ dist, config, apiEntries, clientDir, serverFile }).
manic start (in depth)
Handler: packages/manic/src/cli/commands/start.ts
- Requires
<outdir>/server.js(exit 1 with “Run build first” if missing). - Runs
bun <outdir>/server.jswithNODE_ENV=production,PORT,NETWORKset from CLI/config parsing.
See manic start for workflows.
manic deploy (in depth)
Handler: packages/manic/src/cli/commands/deploy.ts
- Requires
config.providersnon-empty; otherwise exits with a hint to add@manicjs/providers. - If
<outdir>missing, runsbuild()first. - For known providers (
vercel,cloudflare,netlify), prints a suggested command and optionally generatesvercel.json/netlify.tomlif missing. --runor-r:Bun.spawnthe suggested command (split on spaces—keep paths without spaces).
See manic deploy for commands per provider.
manic lint / manic fmt (in depth)
manic lint:bun x oxlint --config .oxlintrc.json .manic fmt:bun x oxfmt -c .oxfmt.json .
No extra argv is forwarded—you cannot pass oxfmt --check through manic fmt today; invoke bun x oxfmt … directly if needed.
Details: Lint & format.
Routing lives in packages/manic/src/cli/index.ts: lint / fmt ignore port & network; dev, build, start, deploy receive { port, network } (see argv routing diagram above).