@depths/webknife
v0.1.0
Published
Deterministic tooling for React+TS UI development
Readme
webknife
Webknife is a deterministic CLI for React + TypeScript UI work. It turns UI work into a repeatable loop with artifacts on disk:
- render
- screenshot / interact
- collect runtime signals
- run typecheck/lint/tests
- run a11y/perf audits
- produce a consistent UI-polish checklist
Everything is written under a stable .webknife/ directory so humans and agents can review and iterate.
Requirements
- Node
>= 18 npm(or compatible)
Some commands rely on tools installed in the target repo:
typecheck:typescript(providestsc)lint:eslintformat:prettiertest:viteststory:*:storybook+@storybook/test-runner(providestest-storybook)audit --perf:@lhci/cli(provideslhci)
Webknife intentionally prefers local project binaries (it runs tsc/eslint/prettier/vitest/storybook/test-storybook/lhci from the current working directory when available). This keeps results consistent with the repo’s own toolchain.
Install
In a target repo:
npm i -D webknife
npx webknife --helpSuggested target repo dev dependencies (pick what you use):
# gates
npm i -D typescript eslint prettier vitest
# storybook tools
npm i -D storybook @storybook/test-runner
# perf audits
npm i -D @lhci/cliPuppeteer will download “Chrome for Testing” on install (first install can take a minute).
Recommended: ignore artifacts
echo ".webknife/" >> .gitignoreCI / automation usage
Use --ci + --json to make runs deterministic and machine-readable:
npx webknife --ci --json shot http://localhost:3000 > .webknife/last-shot.json
npx webknife --ci --json interact http://localhost:3000 --steps steps.yaml > .webknife/last-interact.jsonTypical “gate” (run inside your repo CI):
npx webknife --ci typecheck
npx webknife --ci lint .
npx webknife --ci format . --check
npx webknife --ci testQuick visual feedback (recommended flow)
Start your app (example):
npm run devThen run:
# 1) screenshot
npx webknife shot http://localhost:3000
# 2) scripted interaction loop (screenshots + console/page errors/request failures)
npx webknife interact http://localhost:3000 --steps steps.yaml
# 3) correctness gates (uses local repo binaries)
npx webknife typecheck
npx webknife lint .
npx webknife format . --check
npx webknife test
# 4) audits + UI checklist
npx webknife audit --url http://localhost:3000 --no-perf
npx webknife ui:review --url http://localhost:3000Global options
All commands support:
-c, --config <path>: config path (defaultwebknife.config.json)-o, --out <dir>: override artifacts directory (default.webknife)--ci: CI mode (deterministic settings; disables animations where possible)--json: print a machine-readable JSON summary to stdout-v, --verbose: extra logs
Configuration (webknife.config.json)
You can omit the file and rely on defaults. To override defaults, create webknife.config.json:
{
"outDir": ".webknife",
"viewport": { "width": 1440, "height": 900, "deviceScaleFactor": 1 },
"navigation": { "waitUntil": "networkidle2", "timeoutMs": 45000 },
"shot": { "fullPage": false, "selector": null },
"interact": { "screenshotEachStep": true, "console": true, "networkFailures": true },
"storybook": { "url": "http://localhost:6006", "rootSelector": "#storybook-root" },
"audit": {
"lhci": { "assertPreset": "lighthouse:no-pwa", "minScore": { "performance": 0.8, "accessibility": 0.9 } }
}
}Artifacts (.webknife/)
Default layout (some folders appear only if you run the corresponding command):
.webknife/shot/:*.png+ per-run*.jsonsummary.webknife/interact/run-*/:step-*.png,summary.json,console.ndjson,pageerror.ndjson,requestfailed.ndjson.webknife/{typecheck,lint,format,test}/run-*/:stdout.txt,stderr.txt,summary.json.webknife/story/: test-runner runs +.webknife/story/snaps/*.png(fromstory:snap).webknife/audit/run-*/:a11y.json,summary.json, optionallhci/filesystem output.webknife/ui/:review.md,review.json, optionalsources/(seeui:review --sync-sources)
Command reference
shot — deterministic screenshots
npx webknife shot <url> [--width <n>] [--height <n>] [--dpr <n>] [--fullPage] [--selector <css>]Options:
--width <n>: viewport width (default from config)--height <n>: viewport height (default from config)--dpr <n>: device scale factor (default from config)--fullPage: capture full-page screenshot (default from config)--selector <css>: capture only a specific element
Outputs:
.webknife/shot/<timestamp>.png.webknife/shot/<timestamp>.json
Examples:
npx webknife shot http://localhost:3000 --width 1440 --height 900
npx webknife shot https://example.com --fullPage
npx webknife shot http://localhost:3000 --selector "#app"interact — scripted UI interactions (screenshots + logs per step)
npx webknife interact <url> --steps <path> [--width <n>] [--height <n>] [--dpr <n>]Step file format: YAML array.
Supported actions:
goto:{ action: goto, url?, waitUntil?, timeoutMs? }click:{ action: click, selector }type:{ action: type, selector, text, delayMs? }press:{ action: press, key }waitForSelector:{ action: waitForSelector, selector, timeoutMs? }- supports
text=Welcome(waits until page text containsWelcome)
- supports
waitForNetworkIdle:{ action: waitForNetworkIdle, idleTimeMs?, timeoutMs? }wait:{ action: wait, ms }
Notes:
- If the first step is not
goto, Webknife prepends an implicitgototo<url>. - In
--cimode, it enforces reduced motion (where possible) and disables CSS animations/transitions.
Example steps.yaml:
- action: click
selector: "button[data-testid='signup']"
- action: type
selector: "input[name='email']"
text: "[email protected]"
- action: press
key: Enter
- action: waitForSelector
selector: "text=Welcome"
timeoutMs: 10000Outputs (per run):
.webknife/interact/run-*/summary.json.webknife/interact/run-*/step-00.goto.png,.webknife/interact/run-*/step-01.click.png, ….webknife/interact/run-*/console.ndjson(timestamped browser console logs).webknife/interact/run-*/pageerror.ndjson(uncaught exceptions).webknife/interact/run-*/requestfailed.ndjson(failed network requests)
typecheck — TypeScript correctness gate
npx webknife typecheckBehavior:
- Runs
tsc --noEmit(in--cimode: adds--pretty false) - Writes stdout/stderr + summary
lint — ESLint gate
npx webknife lint [paths...]Behavior:
- Runs
eslint <paths...>(in--cimode: adds--max-warnings=0 --no-color) - Uses whatever ESLint config the target repo provides
format — Prettier formatter / formatter check
npx webknife format [paths...] [--check]Behavior:
- Default writes:
prettier <paths...> --write - Check mode:
prettier <paths...> --check
test — Vitest single-run
npx webknife testBehavior:
- Runs
vitest run --no-color
story:serve — start Storybook
npx webknife story:serve [--port <n>]Behavior:
- Runs
storybook dev --port <n> - Defaults to the port from
storybook.urlin config (or6006)
story:test — Storybook Test Runner
npx webknife story:test [--url <url>]Behavior:
- Runs
test-storybook --url <url> - Defaults
--urlfromstorybook.urlin config
story:snap — deterministic Storybook screenshots
npx webknife story:snap [--url <url>]Behavior:
- Ensures
.storybook/test-runner.tsexists (creates a default one if missing) - Runs
test-storybook --url <url>with env vars sopostVisitscreenshotsstorybook.rootSelector
Outputs:
.webknife/story/snaps/<storyId>.png
audit — a11y (axe) + perf (Lighthouse CI)
npx webknife audit --url <url> [--no-a11y] [--no-perf]Behavior:
- a11y: runs axe-core in Puppeteer and writes
a11y.json(fails if violations are found) - perf: runs
lhci autorunwith a generated config and filesystem output (requires@lhci/cliin the target repo)
Outputs:
.webknife/audit/run-*/a11y.json(when a11y enabled).webknife/audit/run-*/lhci/(when perf enabled).webknife/audit/run-*/summary.json
ui:review — UI polish report (deterministic checklist + references)
npx webknife ui:review --url <url> [--sync-sources]Behavior:
- Writes
.webknife/ui/review.md+.webknife/ui/review.json - References the latest
.webknife/shot/*.jsonand latest.webknife/audit/run-*/summary.jsonif present - With
--sync-sources, downloads and fingerprints external “rubric sources” into.webknife/ui/sources/:- Vercel Web Interface Guidelines (
command.md+AGENTS.md) - Rams prompt (
rams.md) - Selected UI Skills prompts (
SKILL.md)
- Vercel Web Interface Guidelines (
ui:install — install external rubric tools into supported agents/editors
npx webknife ui:install [--all] [--vercel] [--rams] [--ui-skills] [--ui-skills-all]What it does:
- Runs the official installer scripts from:
- Vercel Web Interface Guidelines (
curl …/design/guidelines/install | bash) - Rams (
curl https://rams.ai/install | bash)
- Vercel Web Interface Guidelines (
- Installs UI Skills prompts using
npx ui-skills …
It writes logs to .webknife/ui/install/run-*/ (stdout/stderr per step + summary.json).
Note: ui:install is meant to be run on a developer machine; it can write files into editor/agent config directories under your home directory.
JSON output convention
- Each command writes a
summary.jsonartifact (in its run directory). --jsonprints a summary JSON object to stdout (useful for automation/agents).
Troubleshooting
Puppeteer fails to launch (Linux shared libs missing)
If you see errors like libatk-1.0.so.0: cannot open shared object file, install Chromium runtime deps for your distro (common in minimal Docker images).
Storybook test runner issues
test-storybook depends on Playwright. You may need to install browsers:
npx playwright install --with-depsLighthouse CI not found
audit --perf expects lhci to be available in the target repo:
npm i -D @lhci/cliDeveloping Webknife (this repo)
From internal_tools/webknife/:
npm i
npm test
npm run build
node dist/cli.js --helpTo run the CLI from source (no build):
npm run dev -- --help
npm run dev -- shot https://example.comManual UI target:
cd sample_site
npm i
npm run dev