@weft-js/cli 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,67 +1,419 @@
1
- # @weft-js/cli
1
+ <p align="center">
2
+ <a href="https://github.com/Ravonus/weft">
3
+ <img src="https://raw.githubusercontent.com/Ravonus/weft/main/site/public/logo.svg" width="88" height="88" alt="Weft">
4
+ </a>
5
+ </p>
2
6
 
3
- > **Early release (0.1.x).** APIs can change between minor versions.
7
+ <h1 align="center">@weft-js/cli</h1>
4
8
 
5
- The `weft` command. It runs an app (`dev`, `build`, `start`), checks it (`check`, `tsc`, `fix`, `audit`), ships it
6
- (`deploy`), serves its docs to people and agents (`docs`, `agents-md`, `mcp`) and manages plugins (`add`, `plugins`). An app made with `npm create @weft-js`
7
- already has it.
9
+ <p align="center">
10
+ <strong>The <code>weft</code> command: run, check, build, audit and deploy a Weft app.</strong><br>
11
+ Every finding has a code, a reason and a fix, as text for you and as JSON or MCP tools for an agent.
12
+ </p>
13
+
14
+ <p align="center">
15
+ <a href="https://www.npmjs.com/package/@weft-js/cli"><img src="https://img.shields.io/npm/v/@weft-js/cli?color=145c3c&label=npm" alt="npm version"></a>
16
+ <a href="https://github.com/Ravonus/weft/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-145c3c" alt="MIT license"></a>
17
+ <a href="https://github.com/Ravonus/weft/actions"><img src="https://img.shields.io/github/actions/workflow/status/Ravonus/weft/quality.yml?branch=main&label=checks" alt="checks"></a>
18
+ <img src="https://img.shields.io/badge/node-%3E%3D24-145c3c" alt="Node 24 or later">
19
+ </p>
20
+
21
+ <p align="center">
22
+ <a href="#quick-start">Quick start</a> ·
23
+ <a href="https://github.com/Ravonus/weft/tree/main/packages/cli/docs">Docs</a> ·
24
+ <a href="https://github.com/Ravonus/weft/tree/main/examples">Examples</a> ·
25
+ <a href="https://github.com/Ravonus/weft/blob/main/CHANGELOG.md">Changelog</a> ·
26
+ <a href="https://github.com/Ravonus/weft">GitHub</a>
27
+ </p>
28
+
29
+ > [!IMPORTANT]
30
+ > **Early release (0.1.x).** The command works end to end, and commands, flags and output can still change between
31
+ > minor versions.
32
+
33
+ `weft` is the one command a Weft app needs. It runs the app (`dev`, `build`, `start`), checks it (`check`, `tsc`, `fix`,
34
+ `audit`, `test --gate`), ships it (`deploy`), serves its docs to people and agents (`docs`, `agents-md`, `map`, `mcp`)
35
+ and manages plugins (`add`, `plugins`). An app made with
36
+ [`npm create @weft-js`](https://github.com/Ravonus/weft/tree/main/packages/create) already has it.
37
+
38
+ It is built for two readers. A person gets short lines on stderr, and a tool gets the same result as JSON on stdout
39
+ with `--json`, or as MCP tools through `weft mcp`.
40
+
41
+ ## Highlights
42
+
43
+ - **Diagnostics with fixes.** `weft check` compiles every component in check mode. Each problem prints as
44
+ `file:line:col CODE severity why`, with a `fix:` line under it, and `weft fix` applies the safe ones.
45
+ - **Docs that match the install.** `weft docs W014` prints the page for a code, with whether the installed Weft reports
46
+ it. `weft agents-md` writes an `AGENTS.md` for the version you have.
47
+ - **A build that audits itself.** `weft build` opens the built pages in a clean Chrome at a phone's and a desktop's
48
+ width, runs axe-core's WCAG rules, and fails on an error.
49
+ - **The running app, driven from the terminal.** `weft browser snapshot`, `act` and `assert` work against any browser
50
+ connected to the dev server, and `record` turns a session into a test.
51
+ - **A test gate on the diff.** `weft test --gate` checks that new tests fail on the old code, kill mutants of the changed
52
+ lines, and that no existing test got weaker.
53
+ - **Deploys that say why not.** `weft deploy hosts` says which hosts can run this app before you have an account, and
54
+ `weft deploy` is a dry run until you pass `--yes`.
55
+ - **An MCP server.** `weft mcp` serves `docs`, `check`, `audit`, the style tools, the test gate and the `browser_*`
56
+ tools on stdio.
57
+
58
+ ## Contents
59
+
60
+ - [Install](#install)
61
+ - [Quick start](#quick-start)
62
+ - [Global flags, output and exit codes](#global-flags-output-and-exit-codes)
63
+ - [Commands](#commands)
64
+ - [Run the app](#run-the-app): `dev`, `build`, `start`
65
+ - [Check it](#check-it): `check`, `tsc`, `fix`, `doctor`, `audit`, `routes`, `surfaces`
66
+ - [Test and verify](#test-and-verify): `test --gate`, `browser`
67
+ - [Deploy](#deploy): `deploy`, `deploy hosts`, `deploy init`
68
+ - [Data](#data): `db generate`, `db live`, `db listen`
69
+ - [Add things](#add-things): `add`, `plugins`
70
+ - [Docs for people and agents](#docs-for-people-and-agents): `docs`, `agents-md`, `map`, `mcp`, `tasks`, `run`
71
+ - [Style and design](#style-and-design): `style`, `tokens`, `icons`
72
+ - [Editors](#editors): `lsp`
73
+ - [The diagnostic shape](#the-diagnostic-shape)
74
+ - [Diagnostic families](#diagnostic-families)
75
+ - [The package API](#the-package-api)
76
+ - [Troubleshooting](#troubleshooting)
77
+ - [Related packages](#related-packages)
78
+
79
+ ## Install
80
+
81
+ A new app already lists it in `devDependencies`. To add it to an existing one:
8
82
 
9
83
  ```bash
10
84
  npm install -D @weft-js/cli
85
+ ```
86
+
87
+ ```bash
88
+ pnpm add -D @weft-js/cli
89
+ ```
90
+
91
+ ```bash
92
+ bun add -d @weft-js/cli
93
+ ```
94
+
95
+ ```bash
96
+ deno add -D npm:@weft-js/cli
97
+ ```
98
+
99
+ It needs Node 24 or later, or Bun or Deno in its place. `@weft-js/core` is a peer dependency: the CLI uses the project's
100
+ own compiler, and falls back to its own copy only when the project has none.
101
+
102
+ ## Quick start
103
+
104
+ ```bash
105
+ # Compile every component, report diagnostics with fixes
11
106
  npx weft check
107
+ npx weft dev # the dev server, for an app with src/routes
108
+ # The production build into .output/, then the audit
109
+ npx weft build
110
+ npx weft start # run the build
12
111
  ```
13
112
 
14
- Each problem prints as `file:line:col CODE severity why`, with a `fix:` line under it, and the run ends with a count of
15
- files, errors and warnings.
113
+ When `check` finds something, it looks like this:
114
+
115
+ ```text
116
+ src/routes/counter.tsx:8:8 W015 error
117
+ `count` is a box; JSX needs its value.
118
+ fix: Read `count.value`. (autofix)
119
+ weft check: 12 files, 1 errors, 0 warnings (84 ms)
120
+ ```
121
+
122
+ Then:
123
+
124
+ ```bash
125
+ npx weft docs W015 # the page for that code
126
+ npx weft fix # apply the safe autofixes
127
+ npx weft check --json # the same result, for a tool
128
+ ```
129
+
130
+ `npx weft help` prints the full command list.
131
+
132
+ ## Global flags, output and exit codes
133
+
134
+ Every command takes these:
135
+
136
+ | Flag | Default | What it does |
137
+ |---|---|---|
138
+ | `--root <dir>` (or `--root=<dir>`) | the working directory | The app to work on |
139
+ | `--json` | off | Print the result as JSON on stdout. Text for people still goes to stderr |
140
+ | `--check` | off | Used by `agents-md`: report, don't write |
141
+ | `--stdout` | off | Used by `agents-md`, `map` and `style matrix`: print instead of writing a file |
142
+
143
+ A flag that takes a value accepts `--flag value` or `--flag=value`. An unknown flag is a usage error.
144
+
145
+ | Exit code | Meaning |
146
+ |---|---|
147
+ | `0` | OK |
148
+ | `1` | Errors found: diagnostics with `error` severity, a build refused on one, a failed assertion, or a stale `AGENTS.md` under `--check` |
149
+ | `2` | A usage error or an internal error. With `--json`, stdout gets `{ "ok": false, "error": { "code", "message" } }` |
16
150
 
17
151
  ## Commands
18
152
 
19
- `npx weft help` prints this list.
153
+ ### Run the app
154
+
155
+ | Command | Flags | What it does |
156
+ |---|---|---|
157
+ | `weft dev` | `--port <n>` | The dev server for an app with `src/routes` (Vite and Nitro). Loads `.env` under what's already set, writes `.weft/map.md`, and starts any Rust `remote()` sidecars before the server |
158
+ | `weft build` | `--runtime node\|bun\|deno`, `--preset <p>`, `--unsafe-allow <codes>` | The production build, into `.output/`, plus `.weft/contract.json`. Then the built pages are audited (L-codes), and an error fails the build |
159
+ | `weft start` | `--runtime <r>` | Runs `.output/server/index.mjs` on its runtime: `--runtime`, else the config's `runtime`, else the one running `weft`. Starts sidecars first |
160
+
161
+ `--runtime` picks Node, Bun or Deno. `--preset` picks a host preset instead, such as `netlify`, `vercel` or
162
+ `cloudflare_durable`; with `deploy.target` in the config, `weft build` builds for that host.
163
+
164
+ `--unsafe-allow` lets a build go past codes you have looked at: a code (`R002`), a family (`L`), several
165
+ (`L003,R002`) or `all`. Each one it lets through is listed as a warning, every build. To keep that in the config with a
166
+ reason, use `build.unsafeAllow`:
167
+
168
+ ```ts
169
+ // weft.config.ts
170
+ export default defineConfig({
171
+ build: {
172
+ unsafeAllow: { L003: 'the legacy page is replaced next sprint' },
173
+ },
174
+ })
175
+ ```
176
+
177
+ A build that fails still writes its output, and says so: fix the errors, or force it with `--unsafe-allow <code>`.
178
+
179
+ ### Check it
180
+
181
+ | Command | Flags | What it does |
182
+ |---|---|---|
183
+ | `weft check [files…]` | `--preset <p>`, `--verbose` | Compiles every component in check mode and reports W-, P-, D- and the other codes, with fixes. Files limit it to those. `--verbose` says which compiler ran (native addon or WASM). Ends with `files, errors, warnings (ms)` |
184
+ | `weft tsc` | | Type-checks the whole project with inferred props (tsc or tsgo). For CI |
185
+ | `weft fix [files…]` | | Applies the safe autofixes and lists each one as `file:line:col CODE` |
186
+ | `weft doctor` | `--preset <p>`, `--runtime <r>` | Which compiler this install uses, whether Rust is around (it's optional), and which hosts fit. For an app with `src/realtime.server.ts`, or with `--preset`, also what live data does on that target, what it requires and the options |
187
+ | `weft audit [routes…]` | `--url <u>`, `--indexing public\|private\|auto`, `--all`, `--max <n>` | The built pages, or a running site with `--url`, in a clean Chrome at a phone's and a desktop's width: axe-core's WCAG rules, console errors, deprecations, the head, sideways scroll and layout shift |
188
+ | `weft routes` | `--meta`, `--preset <p>` | The route table, path and file. `--meta` adds each route's merged metadata, tags, card mode and H-diagnostics |
189
+ | `weft surfaces` | | The canvas and WebGL surfaces this project already defines, with their kind, file and props |
190
+
191
+ `weft audit` samples up to 30 pages unless you pass `--all` or `--max <n>`. Without Chrome it skips, with an `L000`
192
+ warning. `--indexing public` makes a `noindex` an error (L024), for a site meant for search. Run it again with `--url`
193
+ after a deploy: a host or proxy can add a header a local build can't see.
194
+
195
+ ### Test and verify
196
+
197
+ #### `weft test --gate`
198
+
199
+ The test gate runs on the diff, in scratch copies. Your working tree is never touched.
200
+
201
+ | Flag | Default | What it does |
202
+ |---|---|---|
203
+ | `--gate` | required | Run the gate. `weft test` without it is a usage error: run the suite itself with vitest |
204
+ | `--base <ref>` | `HEAD` (the uncommitted change) | What the diff is against |
205
+ | `--budget <sec>` | `60`, or `test.gate.mutationBudgetSec` | Time for mutants |
206
+ | `--max-mutants <n>` | `40`, or `test.gate.maxMutants` | Mutants sampled |
207
+ | `--concurrency <n>` | up to 4, from the CPU count | Parallel runs |
208
+ | `--refactor` | off | Promise no behavior change: then no test may change |
209
+ | `--no-mutation` | off | Skip the mutants |
210
+
211
+ It reports **T010** (a new or changed test must fail on the code before the change), **T011** (each new test must kill
212
+ at least one mutant of the changed lines) and **T020** (deleting, skipping or loosening a test needs
213
+ `// weft-allow T020: <reason>`). `weft docs verify` has the details.
214
+
215
+ #### `weft browser <cmd>`
216
+
217
+ Drives the running app. The page is the app open in any browser connected to the dev server: yours, an agent's, or one
218
+ `launch` starts. In a browser that runs JS, the same commands are `await __weft__.agent.run('<command>', args)`.
219
+
220
+ Every `browser` command takes `--url <dev server>`, `--tab <id>` and `--json`.
221
+
222
+ | Command | Flags and arguments | What it does |
223
+ |---|---|---|
224
+ | `tabs` | | Tabs connected to the dev server |
225
+ | `launch [route]` | `--headed` | Starts a headless Chrome on the app, for when you have no browser |
226
+ | `open <route>` | | Navigates the tab and waits for the new page |
227
+ | `snapshot` | `--interactive`, `--delta`, `--scope role:name\|@ref`, `--graph-only`, `--no-graph`, `--full` | Roles, names and refs, plus the reactive graph (`Cart.total = 42.5 ← …`). Long output spills to a file unless `--full` |
228
+ | `act <target> <action> [value]` | | `click`, `dblclick`, `hover`, `focus`, `clear`, `fill`, `type`, `press`, `select`, `check`, `uncheck` (default `click`) |
229
+ | `assert <target> <expectation> [value]` | `--timeout <ms>` | `visible` (default), `absent`, `text`, `exactText`, `value`, `checked`, `unchecked`, `disabled`, `enabled`, `focused`, `count`. Retries until the timeout. Exits 1 on a failure |
230
+ | `graph [filter]` | `--full` | The named reactive graph |
231
+ | `set <Name.box> <json>` | | Writes state by its graph name (dev only) |
232
+ | `time pause\|advance <ms>\|resume\|status` | `--reload` | The page's clock |
233
+ | `net offline\|online\|latency <ms>\|drop\|reset\|status` | | The page's network |
234
+ | `record start\|stop\|note <text>\|code` | `--component`, `--from`, `--props '{…}'`, `--name`, `--out file.test.tsx` | Records actions and assertions; `code` writes them as a test |
235
+ | `logs` | | Console errors and warnings, and uncaught errors, since the last call |
236
+ | `overlay [on\|off]` | | The graph panel in the page (Alt+Shift+G) |
237
+ | `info` | | What the tab is showing, starting with its URL |
238
+ | `reload` | | Reloads the tab |
239
+ | `screenshot` | `--out file.png` | Launched Chrome only; use your own browser's screenshot otherwise |
240
+ | `close` | | Stops the launched Chrome |
241
+
242
+ A target is `<role> <name>` (`button "Add Banana"`), `label <text>`, `text <text>`, or a ref from a snapshot (`@e5`).
243
+
244
+ ```bash
245
+ npx weft browser launch /cart
246
+ npx weft browser act button "Add Banana" click
247
+ npx weft browser assert text Cart text "1 item"
248
+ npx weft browser record code --component Cart \
249
+ --from ./Cart --out src/Cart.test.tsx
250
+ ```
251
+
252
+ ### Deploy
253
+
254
+ | Command | Flags | What it does |
255
+ |---|---|---|
256
+ | `weft deploy hosts` | | Which hosts can run this app, why not, what each costs, and the one Weft suggests |
257
+ | `weft deploy init [target]` | `--target <t>`, `--dry-run`, `--force` | Writes the host's files (`netlify.toml`, `fly.toml` and a Dockerfile…), a GitHub workflow that checks and deploys on push, and `deploy` in the config. Then prints the one-time commands to run yourself |
258
+ | `weft deploy` | `--target <t>`, `--prod`, `--yes`, `--unsafe-allow <codes>` | Checks the fit, builds for the target, then runs the host's own CLI and prints the live URL. Without `--yes` it's a dry run that prints what would run and which environment variables it reads. Without `--prod` it's a preview |
259
+
260
+ | Target | Kind | Reads from the environment |
261
+ |---|---|---|
262
+ | `netlify` | functions | `NETLIFY_AUTH_TOKEN`, `NETLIFY_SITE_ID` |
263
+ | `vercel` | functions | `VERCEL_TOKEN`, `VERCEL_ORG_ID`, `VERCEL_PROJECT_ID` |
264
+ | `cloudflare` | Workers, with Durable Objects | `CLOUDFLARE_API_TOKEN`, `CLOUDFLARE_ACCOUNT_ID` |
265
+ | `fly` | a server that stays up | `FLY_API_TOKEN` |
266
+ | `render` | a server that stays up | `RENDER_DEPLOY_HOOK_URL` |
267
+
268
+ `weft deploy hosts` also rates AWS Lambda, which `weft deploy` doesn't ship to yet. Nothing in Weft creates a site, an
269
+ app, a volume or a DNS record, and a token written into the config, a host file or a workflow is **E008**.
270
+ `weft docs deploy` covers which app features each host can run (E001–E003), `deploy` in the config, and the CDN.
271
+
272
+ ```bash
273
+ npx weft deploy hosts # fit, cost and the suggestion
274
+ npx weft deploy init fly # host files and the GitHub workflow
275
+ npx weft deploy # dry run: what --yes would run
276
+ npx weft deploy --yes --prod # ship it
277
+ ```
278
+
279
+ ### Data
20
280
 
21
281
  | Command | What it does |
22
282
  |---|---|
23
- | `check [files…]` | Compiles every component in check mode and reports diagnostics with fixes. `--verbose` says which compiler ran |
24
- | `tsc` | Type-checks the whole project with inferred props, for CI |
25
- | `fix [files…]` | Applies the safe autofixes |
26
- | `doctor` | Which compiler this install uses, whether Rust is around (it's optional), and what live data does on the target |
27
- | `dev [--port <n>]` | The dev server, for an app with `src/routes` |
28
- | `build [--runtime node\|bun\|deno] [--preset <p>]` | The production build, into `.output/`. The built pages are then audited (L-codes), and an error fails the build |
29
- | `start [--runtime <r>]` | Runs the build |
30
- | `audit [routes…] [--url <u>]` | The built pages, or a running site, in a clean Chrome at phone and desktop widths: axe-core's WCAG rules, console errors, the head, sideways scroll and layout shift |
31
- | `deploy hosts` | Which hosts can run this app, why not, what each costs, and the one Weft suggests |
32
- | `deploy init [target]` | The host's files (`netlify.toml`, `fly.toml` and a Dockerfile…) and a GitHub workflow that checks and deploys on push |
33
- | `deploy [--prod] [--yes]` | Checks the fit, builds for the target and runs the host's own CLI: Netlify, Vercel, Cloudflare, Fly or Render. Without `--yes` it's a dry run |
34
- | `db generate [name]`, `db live`, `db listen` | A migration for schema changes; one with change triggers; the change feed as its own process |
35
- | `routes [--meta]` | The route table; `--meta` adds each route's metadata and H-diagnostics |
36
- | `surfaces` | The canvas and WebGL surfaces the project already defines |
37
- | `test --gate` | The test gate on the diff: fail-before, mutants on changed lines and no weakened tests |
38
- | `browser <cmd>` | Drives the running app: open, snapshot, act, assert and more (`weft browser help`) |
39
- | `docs [topic\|code]` | Prints a docs page or a diagnostic (`weft docs props`, `weft docs W014`) |
40
- | `agents-md [--check]` | Writes AGENTS.md from the installed Weft; `--check` exits 1 when it's stale |
41
- | `map [--stdout]` | Writes `.weft/map.md`: what to call in this app |
42
- | `icons publish <dir>` | Every icon and variant as static `.svg` files with a `manifest.json`, for a CDN |
43
- | `tasks`, `run <task>` | Lists commands and project tasks; runs a task from `weft.config.ts` |
44
- | `add <feature>` | Installs a plugin and wires it into the config; also `tailwind`, `auth`, `db` and `rust` |
45
- | `plugins [list\|explain\|sync\|audit\|approve]` | Plugins, their slots and permissions |
46
- | `style find\|explain\|matrix` | Style groups |
47
- | `tokens` | Warp's resolved tokens as DTCG, in `.weft/tokens/` |
48
- | `lsp` | A language server for editors, with inferred props |
49
- | `mcp` | An MCP server on stdio: `docs`, `check`, `audit`, `routes_meta`, `map`, `tasks`, `surfaces`, `style_find`, `style_explain`, `test_gate` and the `browser_*` tools |
50
-
51
- Every command takes `--root <dir>` (the working directory by default) and `--json`. JSON goes to stdout and text for
52
- people to stderr. Exit codes: 0 ok, 1 errors found (or a stale AGENTS.md under `--check`), 2 a usage or internal error.
53
-
54
- ## Docs
55
-
56
- - `weft docs config`: `weft.config.ts` and every key in it.
57
- - `weft docs diagnostics`: every code, and which ones the installed Weft reports.
58
- - `weft docs verify`: `weft browser` and the test gate.
59
- - `weft docs deploy`: hosts, `weft deploy` and the E-codes.
60
- - `weft docs plugins`: writing a plugin.
61
-
62
- The source of each page is in [docs/](docs). Adding a diagnostic is in [CONTRIBUTING.md](../../CONTRIBUTING.md).
63
-
64
- ## A diagnostic
283
+ | `weft db generate [name]` | A migration for the schema's changes, through the app's data layer (Drizzle, Prisma or native SQL). It applies on the next request |
284
+ | `weft db live` | A migration that adds change triggers to the tables in `changes` (`src/realtime.server.ts`), on Postgres, SQLite or MySQL. On Prisma or native SQL it prints the SQL for you to add |
285
+ | `weft db listen` | The change feed as its own process, for an app on functions |
286
+
287
+ An app with no database gets a usage error that points at `weft add db`.
288
+
289
+ ### Add things
290
+
291
+ #### `weft add <feature>`
292
+
293
+ Installs a package with the app's package manager (found from its lockfile: pnpm, bun, yarn, deno or npm) and wires it
294
+ into the config, whichever format it's in.
295
+
296
+ | Feature | What it does |
297
+ |---|---|
298
+ | `db [engine]` | A database on an app that has none: `sqlite` (default), `postgres` or `mysql`, with `--layer drizzle\|prisma\|native` (default `drizzle`). Writes the same wiring a new app gets, without the todo app. Refuses if the app has a database, or if a file it writes exists |
299
+ | `auth` | Better Auth on an app with a database: `src/auth.server.ts`, `src/server/session.ts`, a sign-in page and the auth tables. Refuses without a database or with an existing `src/auth.server.ts` |
300
+ | `tailwind` | Tailwind: the Vite plugin, a Tailwind entry in `src/app.css` (without its reset when Warp is there), and the layout's import of it |
301
+ | `rust [name]` | A Rust crate, its server module and one working function. `native()` by default (in process); `--remote` for a sidecar behind HTTP |
302
+ | `warp`, `icons`, `text` | `@weft-js/warp`, [`@weft-js/warp-icons`](https://www.npmjs.com/package/@weft-js/warp-icons), [`@weft-js/text`](https://www.npmjs.com/package/@weft-js/text) |
303
+ | `media`, `media-ffmpeg`, `surface-keel` | [`@weft-js/plugin-media`](https://www.npmjs.com/package/@weft-js/plugin-media), [`@weft-js/plugin-media-ffmpeg`](https://www.npmjs.com/package/@weft-js/plugin-media-ffmpeg), [`@weft-js/plugin-surface-keel`](https://www.npmjs.com/package/@weft-js/plugin-surface-keel) |
304
+ | `redis`, `nats` | [`@weft-js/realtime-redis`](https://www.npmjs.com/package/@weft-js/realtime-redis), [`@weft-js/realtime-nats`](https://www.npmjs.com/package/@weft-js/realtime-nats) |
305
+ | `pay`, `pay-stripe` | [`@weft-js/pay`](https://www.npmjs.com/package/@weft-js/pay), `@weft-js/pay/stripe` |
306
+ | any other name | Another `@weft-js/<name>` add-on, or a package name as given |
307
+
308
+ | Flag | What it does |
309
+ |---|---|
310
+ | `--dry-run` | Print what it would install and write, and change nothing |
311
+ | `--no-install` | Wire it in without installing |
312
+ | `--layer drizzle\|prisma\|native` | For `add db` |
313
+ | `--remote` | For `add rust` |
314
+
315
+ Some add-ons (`pay`, `text`, the media plugins and the realtime transports) aren't released on npm yet.
316
+
317
+ #### `weft plugins`
318
+
319
+ | Command | Flags | What it does |
320
+ |---|---|---|
321
+ | `weft plugins` (or `plugins list`) | | Each plugin, its version, the slots it provides and whether they're bound, its tokens, and diagnostics |
322
+ | `weft plugins explain <slot>` | | The binding chain: config, plugin, module, `.weft/slots/<id>.ts` |
323
+ | `weft plugins sync` | | Regenerates `.weft/slots/*`, `.weft/slots.d.ts` and `.weft/tokens/*` |
324
+ | `weft plugins audit` | | Each plugin's permissions and code against `.weft/plugins.lock.json`, and what it uses that it didn't declare |
325
+ | `weft plugins approve [name…]` | `--all` | Records plugins in the lock. With no names and no `--all`, shows what's waiting and writes nothing |
326
+
327
+ `weft docs plugins` walks through writing one.
328
+
329
+ ### Docs for people and agents
330
+
331
+ | Command | Flags | What it does |
332
+ |---|---|---|
333
+ | `weft docs [topic\|code]` | | Prints a docs page or a diagnostic (`weft docs props`, `weft docs W014`). With no topic, the index |
334
+ | `weft agents-md` | `--check`, `--stdout` | Writes `AGENTS.md` from the installed Weft. `--check` exits 1 when it's stale; `--stdout` prints it. Any run exits 1 when it's over the 9 KB limit |
335
+ | `weft map` | `--stdout` | Writes `.weft/map.md` and `.weft/map.json`: a matrix of what to call in this app |
336
+ | `weft mcp` | | An MCP server on stdio (below) |
337
+ | `weft tasks` | | The built-in commands and the project's tasks, with arguments, side effects and environments |
338
+ | `weft run <task>` | | Runs a project task from `tasks` in `weft.config.ts` |
339
+
340
+ `weft docs` topics:
341
+
342
+ | Topic | Covers |
343
+ |---|---|
344
+ | `rules` | The nine rules: boxes, derived, live JSX and props, run-once bodies. Start here |
345
+ | `state` | Every reactive function and `defineState` with persist, sync and history |
346
+ | `props` | How props stay live |
347
+ | `lists` | Keyed lists, conditionals and stable items |
348
+ | `async` | `resource`, `<Boundary>`, `@weft-js/core/ssr` and hydrate |
349
+ | `start` | The full stack: routes, `load`, `query`, `mutation`, the database, auth, realtime, runtimes |
350
+ | `rust` | Rust bodies: `native()` addons with a WASM fallback, `remote()` sidecars, `weft add rust` |
351
+ | `deploy` | Hosts, `weft deploy`, the push workflow, the CDN |
352
+ | `plugins` | Building a plugin: slots, server extensions, check hooks, docs, `weft add` |
353
+ | `theme` | `warp()` options, worked looks, button tone channels |
354
+ | `testing` | `@weft-js/core/test`: render, screen, user, flush, clock |
355
+ | `browser` | `@weft-js/core/browser`: online, visible, lifecycle, media, the fakes |
356
+ | `ui-state` | Hover, press and focus as state: `interaction()`, the `ui` prop |
357
+ | `surface` | `@weft-js/core/surface`: canvas and WebGL as layout children |
358
+ | `verify` | `weft browser`, `__weft__.agent` and the test gate |
359
+ | `icons` | `@weft-js/warp-icons`: per-icon exports, tiers, sizes |
360
+ | `fonts` | Fonts with `@weft-js/text` |
361
+ | `meta` | Page metadata and share cards, `weft routes --meta` |
362
+ | `config` | `weft.config.ts`: scope, tasks, environments, plugins |
363
+ | `design` | The design language: `Stack`, `Row`, `Heading`, `Text`, `Link`, `weft fix`, `weft tokens` |
364
+ | `style` | Style groups, `weft style find` and `explain` |
365
+ | `diagnostics` | Every code, and which ones the installed Weft reports |
366
+ | `commands` | This project's commands and tasks |
367
+ | `agents` | The generated `AGENTS.md` |
368
+
369
+ Installed plugins can add their own topics; `weft docs` with no topic lists them.
370
+
371
+ #### `weft mcp`
372
+
373
+ An MCP server on stdio, rooted at `--root`. Its tools:
374
+
375
+ | Tool | Same as |
376
+ |---|---|
377
+ | `docs` | `weft docs` |
378
+ | `check` | `weft check` |
379
+ | `audit` | `weft audit` |
380
+ | `routes_meta` | `weft routes --meta` |
381
+ | `map` | `weft map` |
382
+ | `tasks` | `weft tasks` |
383
+ | `surfaces` | `weft surfaces` |
384
+ | `style_find`, `style_explain` | `weft style find`, `weft style explain` |
385
+ | `test_gate` | `weft test --gate` |
386
+ | `browser_tabs`, `browser_launch`, `browser_open`, `browser_snapshot`, `browser_act`, `browser_assert`, `browser_state`, `browser_time`, `browser_net`, `browser_record`, `browser_logs`, `browser_screenshot` | `weft browser` |
387
+
388
+ To add it to an MCP client:
389
+
390
+ ```json
391
+ {
392
+ "mcpServers": {
393
+ "weft": { "command": "npx", "args": ["weft", "mcp"] }
394
+ }
395
+ }
396
+ ```
397
+
398
+ ### Style and design
399
+
400
+ | Command | Flags | What it does |
401
+ |---|---|---|
402
+ | `weft style find <query>` | | Style groups that fit what you're about to style (`card`, `status badge`). Reuse before you write |
403
+ | `weft style explain <group\|selector>` | `--<axis> <value>`, `--states a,b`, `--accent intent:token`, `--part <p>` | The resolved CSS for one variation, and where each value came from. The group's own axes are flags (`--status late`) |
404
+ | `weft style matrix` | `--stdout` | Writes `.weft/styles.json`: every group, with axes, parts, accents, resolved CSS and uses |
405
+ | `weft tokens` | | Warp's resolved tokens as DTCG, in `.weft/tokens/` |
406
+ | `weft icons publish <dir>` | | Every icon and variant as static `.svg` files with a `manifest.json`, for a CDN. Nothing is uploaded: host the folder, then set `icons({ source })` |
407
+
408
+ ### Editors
409
+
410
+ | Command | What it does |
411
+ |---|---|
412
+ | `weft lsp` | A language server for editors on TypeScript 7: `tsc --lsp` with inferred props |
413
+
414
+ A new app's `tsconfig.json` also loads `@weft-js/cli/ts-plugin`, which gives the editor the same inferred props.
415
+
416
+ ## The diagnostic shape
65
417
 
66
418
  `check`, `tasks` and the MCP tools report the same shape:
67
419
 
@@ -85,15 +437,119 @@ The source of each page is in [docs/](docs). Adding a diagnostic is in [CONTRIBU
85
437
  }
86
438
  ```
87
439
 
88
- - `span` is 1-based `[line, col, endLine, endCol]`, with columns in UTF-16 units. `offset` is UTF-16 indices into the
89
- file's text.
90
- - `fix.edits` (`{ file, span, offset, text }`) is there when there's a mechanical change, and `fix.safe` says whether
91
- `weft fix` applies it without asking.
92
- - `project: true` marks a result that needed more than one file to find.
440
+ | Field | What it is |
441
+ |---|---|
442
+ | `span` | 1-based `[line, col, endLine, endCol]`, with columns in UTF-16 units |
443
+ | `offset` | UTF-16 indices into the file's text |
444
+ | `fix.text` | The fix, in words |
445
+ | `fix.edits` | `{ file, span, offset, text }`, when there's a mechanical change |
446
+ | `fix.safe` | Whether `weft fix` applies it without asking |
447
+ | `project` | `true` for a result that needed more than one file to find |
448
+ | `related` | Other places that explain it |
449
+ | `docs` | The command that prints its page |
450
+
451
+ ## Diagnostic families
452
+
453
+ `weft docs diagnostics` lists every code and whether the installed Weft reports it.
454
+
455
+ | Prefix | Area |
456
+ |---|---|
457
+ | `W` | Reactivity, from the compiler |
458
+ | `S` | State and `defineState` |
459
+ | `P` | Plugins and config |
460
+ | `D` | Design language and style groups |
461
+ | `H` | Page metadata and hydration |
462
+ | `Q`, `A`, `C`, `F`, `R` | Server functions and the database, auth, the contract, forms, realtime and Rust |
463
+ | `E` | Deploys |
464
+ | `L` | Built pages, from `weft build` and `weft audit` |
465
+ | `T` | Tests and the test gate |
466
+ | `U` | UI state |
467
+ | `X` | Surfaces and text |
468
+ | `M`, `I` | Media and icons |
469
+
470
+ A test that needs a T-code on purpose keeps it with `// weft-allow <code>: <why>`, in the file header or on the line
471
+ above. Adding a diagnostic is in [CONTRIBUTING.md](https://github.com/Ravonus/weft/blob/main/CONTRIBUTING.md).
472
+
473
+ ## The package API
474
+
475
+ Most people only run the command. The package also exports what the command is built from:
476
+
477
+ | Import | Exports |
478
+ |---|---|
479
+ | `@weft-js/cli` | `check`, `docs`, `topics`, `agentsMd`, `writeAgentsMd`, `catalog`, `entry`, `probe`, `loadConfig`, `tasks`, `bindSlots`, `slotTable`, and the MCP server's `serve`, `handle` and `tools` |
480
+ | `@weft-js/cli/config` | `defineConfig`. Apps import it from `@weft-js/core/config`; this is the fallback when a project's Weft doesn't resolve |
481
+
482
+ ```js
483
+ import { check } from '@weft-js/cli'
484
+
485
+ const result = await check(process.cwd(), {
486
+ files: ['src/routes/index.tsx'],
487
+ })
488
+ console.log(result.summary) // { files, errors, warnings }
489
+ ```
490
+
491
+ ## Troubleshooting
492
+
493
+ <details>
494
+ <summary><code>weft is not installed</code> (E_NO_WEFT)</summary>
495
+
496
+ `@weft-js/core/compiler` resolves neither from the project nor from the CLI. Install `@weft-js/core` in the app.
497
+ </details>
498
+
499
+ <details>
500
+ <summary>Which compiler am I running?</summary>
501
+
502
+ `weft doctor`, or `weft check --verbose`. The WASM build gives the same output as the native addon; the addon only adds
503
+ speed. Rust is never needed to use Weft.
504
+ </details>
505
+
506
+ <details>
507
+ <summary><code>weft build</code> refused with a code</summary>
508
+
509
+ The build found an error in the built pages or the target. The message has the fix, and the way past it:
510
+ `--unsafe-allow <code>`, or `build.unsafeAllow` in `weft.config.ts` with a reason. It exits 1, not 2.
511
+ </details>
512
+
513
+ <details>
514
+ <summary><code>weft audit</code> skipped</summary>
515
+
516
+ It needs a Chrome or Chromium on the machine. Without one it reports `L000` as a warning and checks nothing.
517
+ </details>
518
+
519
+ <details>
520
+ <summary><code>weft test</code> says to use vitest</summary>
521
+
522
+ `weft test` only runs the gate, with `--gate`. Run your suite with vitest.
523
+ </details>
524
+
525
+ <details>
526
+ <summary><code>weft agents-md --check</code> fails in CI</summary>
527
+
528
+ `AGENTS.md` is stale for the installed Weft. Run `weft agents-md` and commit the file. A file over 9 KB fails every run.
529
+ </details>
530
+
531
+ ## Related packages
532
+
533
+ | Package | What it is |
534
+ |---|---|
535
+ | [`@weft-js/core`](https://www.npmjs.com/package/@weft-js/core) <sup>[source](https://github.com/Ravonus/weft/tree/main/packages/core)</sup> | The runtime, the compiler binding, the Vite plugin, SSR and test utilities |
536
+ | [`@weft-js/start`](https://www.npmjs.com/package/@weft-js/start) <sup>[source](https://github.com/Ravonus/weft/tree/main/packages/start)</sup> | The full stack: file routes, server functions, SSR, a database, auth and live data |
537
+ | [`@weft-js/create`](https://www.npmjs.com/package/@weft-js/create) <sup>[source](https://github.com/Ravonus/weft/tree/main/packages/create)</sup> | `npm create @weft-js`: a new app with this CLI in it |
538
+ | [`@weft-js/db`](https://www.npmjs.com/package/@weft-js/db) <sup>[source](https://github.com/Ravonus/weft/tree/main/packages/db)</sup> | Prisma and native SQL layers, and list sources |
539
+ | [`@weft-js/warp`](https://www.npmjs.com/package/@weft-js/warp) <sup>[source](https://github.com/Ravonus/weft/tree/main/packages/warp)</sup> | Warp's components, and the `warp()` theming plugin |
540
+
541
+ ## Contributing
542
+
543
+ [CONTRIBUTING.md](https://github.com/Ravonus/weft/blob/main/CONTRIBUTING.md) has the setup. To work on this package:
544
+
545
+ ```bash
546
+ pnpm --filter @weft-js/cli test
547
+ ```
548
+
549
+ The pages `weft docs` prints are in
550
+ [`packages/cli/docs`](https://github.com/Ravonus/weft/tree/main/packages/cli/docs). Report security problems privately,
551
+ as [SECURITY.md](https://github.com/Ravonus/weft/blob/main/.github/SECURITY.md) says.
93
552
 
94
- ## Links
553
+ ## License
95
554
 
96
- - [Source](https://github.com/Ravonus/weft/tree/main/packages/cli)
97
- - [Weft on GitHub](https://github.com/Ravonus/weft): the framework, the docs and every package
98
- - [Changelog](https://github.com/Ravonus/weft/blob/main/CHANGELOG.md)
99
- - [Issues](https://github.com/Ravonus/weft/issues)
555
+ [MIT](https://github.com/Ravonus/weft/blob/main/LICENSE).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weft-js/cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "The weft command: dev, build, check, the agent layer and the MCP server",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -21,17 +21,17 @@
21
21
  "./config": "./src/config.mjs"
22
22
  },
23
23
  "engines": {
24
- "node": ">=26"
24
+ "node": ">=24"
25
25
  },
26
26
  "dependencies": {
27
- "@weft-js/create": "0.1.2",
27
+ "@weft-js/create": "0.1.4",
28
28
  "axe-core": "4.14.0",
29
29
  "typescript": "6.0.3",
30
30
  "yaml": "2.9.1",
31
31
  "zod": "4.6.7"
32
32
  },
33
33
  "peerDependencies": {
34
- "@weft-js/core": "^0.1.2"
34
+ "@weft-js/core": "^0.1.4"
35
35
  },
36
36
  "publishConfig": {
37
37
  "access": "public"
@@ -60,6 +60,7 @@ function baseSchemas(z) {
60
60
  inlineCss: z.boolean().optional(),
61
61
  criticalCss: z.boolean().optional(),
62
62
  criticalKeep: z.array(z.string()).optional(),
63
+ csp: z.literal('strict').optional(),
63
64
  image: z.union([z.literal('auto'), z.literal(false), z.string().min(1), image]).optional(),
64
65
  card: card.optional(),
65
66
  head: z.string().optional(),
package/src/mcp.mjs CHANGED
@@ -191,7 +191,7 @@ export async function handle(root, msg) {
191
191
  return reply({
192
192
  protocolVersion: versions.includes(asked) ? asked : versions[0],
193
193
  capabilities: { tools: { listChanged: false } },
194
- serverInfo: { name: 'weft', version: '0.1.2' },
194
+ serverInfo: { name: 'weft', version: '0.1.4' },
195
195
  instructions:
196
196
  'weft is a fine-grained reactive TSX framework, not React. Read `docs` topic `rules` first, and run `check` after every edit. Every page sets `meta` from its own context as part of building it (`docs` topic `meta`). Chrome shared across route sections (a sidebar) goes in one layout above them that follows `currentPath()`, never a layout per section (`docs` topic `start`). Style with groups from @weft-js/core/style, not class lists: `style_find` before you write one. Verify behavior in the running app with the browser_* tools (or `__weft__.agent` in your own browser), and run `test_gate` before you call a change done.',
197
197
  })