pnpm scripts#
PacketBench ships no command-line binary. The scripts block in
package.json is the closest thing it has to a CLI surface: 48 entries
covering the dev loop, five quality gates, thirteen sidecar smoke tests, the
Node-runtime fetch, the release gate and two macOS build workarounds. There is
no CI, so every one of them runs on a developer's machine or it does not run
at all.
This page lists every script in package.json, what each one actually
executes, and when to reach for it. It also owns the "match the gate to the
change" table, which decides how far up the ladder a given change has to
climb.
Ordering. The table below is in source order — the order the scripts
are declared in package.json — not alphabetical, so it reads the way the
file reads. Composites are unpacked in the sections that follow.
Every script#
| Script | What it runs | When to use it |
|---|---|---|
dev |
vite — the frontend dev server on port 1420, strictPort (vite.config.ts:76-77) |
Rarely on its own. pnpm tauri dev invokes it as beforeDevCommand (src-tauri/tauri.conf.json:7); run it bare only to work on the UI in a plain browser |
build |
tsc && vite build |
The type-check and production bundle. Also the build half of Tauri's beforeBuildCommand |
preview |
vite preview |
Serve an already-built dist/ to check the production bundle without Tauri |
tauri |
tauri |
Passthrough to the Tauri CLI. This is the front door for pnpm tauri dev and pnpm tauri build |
lint |
pnpm run lint:src |
An alias. Type pnpm lint; it is the same run as lint:src |
lint:src |
eslint src e2e |
The lint gate preflight executes. Warnings are permitted |
lint:strict |
eslint src e2e --max-warnings=0 |
Checking whether the warning count has grown. No gate runs this — preflight uses lint:src, so warnings never fail a build |
format |
prettier --write "src/**/*.{ts,tsx,css}" |
Formatting frontend source. Note the file set: it does not overlap format:check — see below |
format:check |
prettier --check package.json eslint.config.js dev/local-quality-gates.md "e2e/**/*.{ts,tsx}" |
The first rung of preflight. Four targets only: the manifest, the ESLint config, the gate ladder document, and the e2e tests |
test |
vitest run |
The unit gate. Covers src/**/*.{test,spec}.{ts,tsx} and scripts/**/*.{test,spec}.{mjs,ts} (vitest.config.ts:15) |
test:watch |
vitest |
Watch mode while writing tests. Not a gate |
e2e |
playwright test |
Playwright against the Vite dev server in web mode, Chromium only, Tauri IPC mocked (playwright.config.ts:9-12). Run after anything user-facing in the browser |
generate:tauri-schema |
cd src-tauri && cargo test --test api_schema export_api_bindings -- --ignored --nocapture |
Regenerate src/generated/tauri-schema.ts after changing a shared DTO. Run this when check:tauri-schema fails |
check:tauri-schema |
node scripts/check-tauri-schema.mjs |
The gate that asserts the committed bindings match what the Rust exporter produces right now |
fetch-node |
node scripts/fetch-node.js |
Stage the pinned Node runtime for the host target into src-tauri/binaries/. Idempotent; prebundle calls it for you |
fetch-node:all |
node scripts/fetch-node.js --all-targets |
Stage the runtime for all five supported Rust triples at once (scripts/fetch-node.js:10-14). Cross-target packaging work only |
sidecar:install |
node scripts/run-pnpm-no-deprecation.mjs -C agent-sidecar install |
Install the sidecar's own dependencies. Run this after any production build — sidecar:prune deletes them |
sidecar:build |
pnpm -C agent-sidecar build |
Compile the sidecar to agent-sidecar/dist/ |
sidecar:dev |
pnpm -C agent-sidecar dev |
tsc --watch for the sidecar. Run it in a second terminal while working on sidecar code |
sidecar:check |
sidecar:install → sidecar:build → the thirteen smokes, chained with && |
The sidecar gate. Required for anything touching agent-sidecar/, provider routing, protocol types or the supervisor |
sidecar:prune |
node scripts/prune-sidecar.js |
Strip devDependencies from agent-sidecar/node_modules so the Tauri bundler picks up a production-only tree. Destructive; prebundle calls it |
sidecar:smoke |
node agent-sidecar/test/echo-smoke.mjs |
Baseline: the sidecar starts and echoes |
sidecar:remote-project-smoke |
node agent-sidecar/test/remote-project-path-smoke.mjs |
Remote project-path resolution |
sidecar:registry-smoke |
node agent-sidecar/test/registry-smoke.mjs |
The provider registry |
sidecar:protocol-smoke |
node agent-sidecar/test/protocol-v9-smoke.mjs |
Protocol v9 conformance |
sidecar:session-ordering-smoke |
node agent-sidecar/test/session-ordering-smoke.mjs |
Session event ordering |
sidecar:gating-smoke |
node agent-sidecar/test/openai-agents-gating-smoke.mjs |
OpenAI Agents tool gating |
sidecar:anthropic-edit-correlation-smoke |
node agent-sidecar/test/anthropic-edit-correlation-smoke.mjs |
Correlating Anthropic edit events to their tool calls |
sidecar:anthropic-multi-turn-smoke |
node agent-sidecar/test/anthropic-multi-turn-smoke.mjs |
Multi-turn Anthropic conversations |
sidecar:mcp-config-smoke |
node agent-sidecar/test/mcp-config-merge-smoke.mjs |
MCP config merging |
sidecar:mcp-trust-smoke |
node agent-sidecar/test/mcp-trust-smoke.mjs |
MCP trust state |
sidecar:mcp-trust-enforcement-smoke |
node agent-sidecar/test/mcp-trust-enforcement-smoke.mjs |
MCP trust actually being enforced, not merely recorded |
sidecar:remote-mcp-fromfs-smoke |
node agent-sidecar/test/remote-mcp-fromfs-smoke.mjs |
Remote MCP servers loaded from the filesystem |
sidecar:anthropic-apikey-smoke |
node agent-sidecar/test/anthropic-apikey-smoke.mjs |
Anthropic API-key handling |
clean:dmg-scratch |
node scripts/clean-dmg-scratch.mjs |
Detach leftover attached DMG scratch images and delete stray rw.*.dmg files. macOS-only; a no-op elsewhere (scripts/clean-dmg-scratch.mjs:21-23) |
build:macos |
node scripts/build-macos.mjs |
The macOS build. Use this instead of pnpm tauri build on macOS — it retries the flaky DMG step |
prebundle |
clean:dmg-scratch → fetch-node → sidecar:install → sidecar:build → sidecar:prune → release:gate |
Not a script you normally type. Tauri runs it as the first half of beforeBuildCommand (src-tauri/tauri.conf.json:9) |
preflight |
format:check → lint:src → test → build |
The everyday pre-commit pass. Run it before you push anything |
release:gate |
node scripts/release-gate.mjs |
Pre-bundle assertions about version, icons, the staged Node binary and the sidecar tree. Runs inside every pnpm tauri build |
release:gate:strict |
node scripts/release-gate.mjs --require-clean --require-signing --require-updater |
The same gate with three extra requirements turned on: a clean tree, signing configured, updater keys present (scripts/release-gate.mjs:15-21) |
postinstall |
node scripts/run-pnpm-no-deprecation.mjs -C agent-sidecar install |
Automatic. Every pnpm install installs the sidecar's dependencies too |
build:all |
pnpm sidecar:build && pnpm build |
Build the sidecar and the frontend in one step, without the full bundle chain |
rust:check |
cd src-tauri && cargo check |
Fast backend type-check |
rust:test |
cd src-tauri && cargo test |
The backend test gate. Required for changes to commands, providers, state or orchestration |
release:readiness |
node scripts/release-readiness.mjs |
Executes the nine quality gates in order, then reports on signing, updater config and built artifacts |
release:readiness:report |
node scripts/release-readiness.mjs --report-only |
The same report without executing the gates. --report-only implies --skip-gates (scripts/release-readiness.mjs:15-18) |
check |
preflight → e2e → sidecar:check → check:tauri-schema → rust:check → rust:test |
Everything. Genuinely long — Playwright, thirteen sequential sidecar smokes and the full Rust suite |
docs:build |
node scripts/build-docs.mjs |
Render the in-repo Markdown at docs/src/ to static HTML in docs/guide/ (scripts/build-docs.mjs:20-21) |
The three rungs#
The gates form a ladder. Each rung contains the one below it, so you never need to run both.
pnpm preflight format:check → lint:src → test → build
│
pnpm check preflight → e2e → sidecar:check → check:tauri-schema
│ → rust:check → rust:test
│
pnpm release:readiness those nine, executed, plus the distribution report
release-readiness.mjs declares the nine gates it executes explicitly
(scripts/release-readiness.mjs:32-42) and reports check as a row
derived from those results rather than executed. Running it as a tenth
gate would run everything a second time. The script re-derives that
relationship from package.json on every run and refuses to claim the
composite if the scripts have drifted (scripts/release-readiness.mjs:22-31).
pnpm check is slow enough that release-readiness.mjs defaults to
a 45-minute per-gate timeout, overridable with
PACKETBENCH_RELEASE_GATE_TIMEOUT_MS (scripts/release-readiness.mjs:19).
That default is a fair indicator of the magnitude.
Match the gate to the change#
pnpm preflight is the floor. Climb from there according to what you touched.
| Changed | Also run |
|---|---|
agent-sidecar/, provider routing, protocol types, supervisor |
pnpm sidecar:check |
| Shared contracts, generated types, persisted state, request/response payloads | pnpm check:tauri-schema |
| Backend commands, providers, state, orchestration | pnpm rust:test |
| Anything user-facing in the browser | pnpm e2e |
Release-facing work climbs the whole ladder and then runs pnpm release:readiness. dev/local-quality-gates.md is the canonical ladder
document in the repository — and it is itself covered by format:check, so
editing it with the wrong Prettier formatting breaks preflight.
What the composites expand to#
| Composite | Expansion |
|---|---|
lint |
lint:src |
preflight |
format:check, lint:src, test, build |
sidecar:check |
sidecar:install, sidecar:build, then sidecar:smoke, sidecar:remote-project-smoke, sidecar:registry-smoke, sidecar:protocol-smoke, sidecar:session-ordering-smoke, sidecar:gating-smoke, sidecar:anthropic-edit-correlation-smoke, sidecar:anthropic-multi-turn-smoke, sidecar:mcp-config-smoke, sidecar:mcp-trust-smoke, sidecar:mcp-trust-enforcement-smoke, sidecar:remote-mcp-fromfs-smoke, sidecar:anthropic-apikey-smoke |
prebundle |
clean:dmg-scratch, fetch-node, sidecar:install, sidecar:build, sidecar:prune, release:gate |
build:all |
sidecar:build, build |
check |
preflight, e2e, sidecar:check, check:tauri-schema, rust:check, rust:test |
release:readiness |
format:check, lint:src, test, build, e2e, sidecar:check, check:tauri-schema, rust:check, rust:test — check derived |
Every chain uses &&, so the first non-zero exit stops the run. There is no
--continue-on-error anywhere in the block.
Scripts you do not type#
| Script | Invoked by |
|---|---|
postinstall |
pnpm, on every pnpm install |
prebundle |
Tauri, as the first half of beforeBuildCommand (src-tauri/tauri.conf.json:9) |
build |
Tauri, as the second half of the same command, and by preflight |
dev |
Tauri, as beforeDevCommand (src-tauri/tauri.conf.json:7) |
release:gate |
prebundle, on every pnpm tauri build |
lint:src, format:check, test |
preflight |
Sharp edges#
These bite, and they are documented rather than fixed.
format and format:check cover disjoint file sets. format writes
src/**/*.{ts,tsx,css}. format:check reads package.json,
eslint.config.js, dev/local-quality-gates.md and e2e/**/*.{ts,tsx}.
There is no overlap at all, so running pnpm format cannot fix a
format:check failure, and a format:check pass says nothing about src/.
Fix the four checked targets by hand, or point Prettier at them directly.
pnpm sidecar:build fails after a production build. prune-sidecar.js
runs pnpm -C agent-sidecar install --prod --ignore-scripts, which removes
typescript and @types/node from the sidecar's node_modules. Re-run pnpm sidecar:install to restore them. The script header says so at
scripts/prune-sidecar.js:14-24, and it catches everyone once.
Run the bare pnpm test, not vitest src. Scoping to a directory
silently skips the repository fences, which are pulled in by the scripts/**
glob in vitest.config.ts:15. Those fences walk the whole source tree, which
is why pnpm test can fail with no test file anywhere near your change.
pnpm dev and pnpm e2e both want port 1420. Vite is configured with
strictPort (vite.config.ts:76-77) and Playwright starts its own server on
the same port, with reuseExistingServer on outside CI
(playwright.config.ts:34-40). Locally the e2e run attaches to a dev server
you already have up; set PLAYWRIGHT_PORT to separate them.
lint:strict gates nothing. preflight runs lint:src, which tolerates
warnings. The 0.13.1 release recorded pnpm lint as green with nine
pre-existing warnings — see Testing & gates.
build:macos, not pnpm tauri build, on macOS. bundle_dmg.sh runs a
cosmetic Finder AppleScript that fails on roughly half of first attempts and
abandons a mounted scratch image when it does. The wrapper builds once,
detaches the leaked image and retries just the DMG step; the Rust artifacts
are cached, so the retry is cheap (scripts/build-macos.mjs:5-15).
pnpm docs:build renders docs/src/ into docs/guide/ inside
the PacketBench repository (scripts/build-docs.mjs:20-21). It does not build
this site, which lives in a separate repository with its own generator.
Related#
- Testing & gates — what each gate proves, and what was green at the last release
- Build & release — the toolchain, the bundle chain and the release checklist
- Contributing — commit conventions and the review bar these gates enforce
- Agent orientation — the machine-readable briefing that points agents at this ladder
- Environment variables —
PACKETBENCH_RELEASE_GATE_TIMEOUT_MSand the other knobs these scripts read - Troubleshooting — when a gate fails for a reason that is not your change