- TypeScript 89.2%
- JavaScript 10.8%
The check command now reports a non-fatal warning when an artifact imports the runtime but never calls submit, helping catch runs that would otherwise appear valid yet never return a result. |
||
|---|---|---|
| dist | ||
| skills/bespoke-web-artifact | ||
| src | ||
| tests | ||
| .gitignore | ||
| AGENTS.md | ||
| LICENSE | ||
| package.json | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| tsconfig.json | ||
| tsup.config.ts | ||
| vitest.config.ts | ||
bespoke-web-artifact
bespoke-web-artifact provides bwa, a CLI for writing one-file React/TSX web artifacts without creating a local Vite project beside the artifact.
The artifact stays as one meaningful .tsx file. bwa creates the temporary Vite runtime elsewhere, serves it on a random local port by default, and lets the artifact send a result back to stdout when useful.
CLI overview
bwa add artifact.tsx lucide-react
bwa check artifact.tsx
bwa run artifact.tsx
bwa run artifact.tsx --port 5173
bwa run artifact.tsx --json
bwa run artifact.tsx --bg
bwa bg list [--json]
bwa wait <pid> [--timeout 60]
bwa bg clear [pid...]
bwa completion bash
bwa build is present only as a reserved command. It intentionally fails until export/share/deploy semantics are designed.
Artifact format
A BWA artifact is a single .tsx file with an optional metadata block at the top:
// /// bwa
// title = "Artifact title"
// vibe = "specific visual and interaction direction"
// deps = ["lucide-react"]
// ///
The artifact should default-export a React component:
import { submit, close } from "bespoke-web-artifact/runtime";
export default function Artifact() {
return (
<main>
<button onClick={() => submit({ choice: "yes" })}>Submit</button>
<button onClick={() => close()}>Close</button>
</main>
);
}
submit(data) prints the result to bwa run/bwa wait, shows a small success/error toast in the page, and shuts the server down. The default output is TOON; pass --json to bwa run when a script needs JSON. close() shuts the server down without a submit payload.
Metadata and dependencies
Prefer bwa add for metadata edits:
bwa add artifact.tsx lucide-react recharts
If the file does not exist, bwa add creates a starter artifact. If it exists, the command updates only the deps list in the metadata block and preserves the artifact body.
Declared deps are made available to the temporary Vite runtime. This package currently carries the common artifact dependencies it expects agents to use, including React 19, Vite, lucide-react, and recharts.
Running artifacts
Foreground run:
bwa run artifact.tsx
bwa run prints the artifact title and local URL to stderr, does not open a browser, and keeps running until the page submits, closes, the floating Exit button is clicked, or the process receives Ctrl-C/SIGTERM. By default it asks the OS for a random available port.
Use a specific preferred port only when that exact port matters. Explicit ports are strict; if the port is already in use, BWA fails instead of moving to another port:
bwa run artifact.tsx --port 5173
Use JSON submit output for command chains:
bwa run artifact.tsx --json
Background runs for agent workflows
Use --bg when an agent needs to keep working after starting the artifact server, especially before registering the random port with local-router:
run=$(bwa run artifact.tsx --bg)
pid=${run%%;*}
# the same line includes the ready URL and port, e.g. "12345; url: http://127.0.0.1:43210/ port: 43210"
bwa wait "$pid"
Background contract:
bwa run --bgwaits until the server is listening, then prints one stdout line:<pid>; url: <url> port: <port>.bwa bg listprints active/completed runs as TOON;bwa bg list --jsonprints the raw registry JSON for scripts.bwa wait <pid>blocks until the artifact submits, closes, or fails. Submit results are printed in the same format foregroundbwa runwould use. Closed runs with no submit payload print nothing.bwa wait <pid> --timeout <seconds>fails if the run does not finish before the timeout.bwa bg clear [pid...]closes background runs through the same runtime close path as the floating Exit button and removes them from the registry. With no PIDs, it clears all registered background runs.
Background run state is stored under the BWA cache directory. Set BWA_CACHE_DIR to isolate runs for tests or scripted workflows.
Checking artifacts
bwa check artifact.tsx
bwa check parses the metadata, prepares the temporary Vite entry, and starts Vite in middleware mode far enough to catch obvious loading/configuration breakage. It is intentionally forgiving: if the artifact can run, it should usually pass.
Shell completion
Bash completion can be generated with:
bwa completion bash
Source the output from your shell setup or redirect it into a completion file managed by your environment.
Install and update
There are two pieces to install:
- the Pi package, which gives Pi the
bespoke-web-artifactskill; - the CLI executable, which puts the
bwacommand on your shellPATH.
This package declares its Pi skill in package.json:
"pi": {
"skills": ["skills"]
}
From the git remote
Install or update the Pi package from the remote repo:
pi install ssh://git@git.dikka.dev:2222/lab/bespoke-web-artifact.git
pi update ssh://git@git.dikka.dev:2222/lab/bespoke-web-artifact.git
For a pinned install, include a tag or commit ref. Move to a newer pinned version by installing the same source with the new ref:
pi install ssh://git@git.dikka.dev:2222/lab/bespoke-web-artifact.git@v0.1.0
pi install ssh://git@git.dikka.dev:2222/lab/bespoke-web-artifact.git@v0.1.1
Pi installs the package checkout under its git package cache. Expose that checkout's built CLI with a symlink:
mkdir -p ~/.local/bin
ln -sf ~/.pi/agent/git/git.dikka.dev/lab/bespoke-web-artifact/dist/cli.js ~/.local/bin/bwa
chmod +x ~/.pi/agent/git/git.dikka.dev/lab/bespoke-web-artifact/dist/cli.js
bwa --help
Make sure ~/.local/bin is in PATH.
After updating the remote Pi package, refresh/check the CLI executable too:
pi update ssh://git@git.dikka.dev:2222/lab/bespoke-web-artifact.git
chmod +x ~/.pi/agent/git/git.dikka.dev/lab/bespoke-web-artifact/dist/cli.js
bwa --help
From a local checkout
From this checkout, install dependencies, build the CLI, and expose the local bwa command:
vp install
vp run build
mkdir -p ~/.local/bin
ln -sf "$(pwd)/dist/cli.js" ~/.local/bin/bwa
chmod +x dist/cli.js
bwa --help
Then install the local package into Pi so Pi can load the skill from this checkout:
pi install "$(pwd)"
A local path Pi install points Pi at this checkout, so skill edits are picked up from the working tree after restarting Pi. After pulling local changes, rebuild the CLI:
vp install
vp run build
chmod +x dist/cli.js
bwa --help
Avoid vp add -g ., vp add -g "$(pwd)", and vp link for this local CLI flow; they are not reliable for this project setup.
Status
Early implementation. bwa build is intentionally not defined yet.