| name | grim:artifacts |
| description | Artifacts: The house standard for artifacts — small interactive pages agents generate. The minimal version is one self-contained static HTML file; artifacts can grow a small server or extra files when the job genuinely needs them. |
| disable-model-invocation | true |
Artifacts
What an artifact is
A small interactive page generated by an agent: a visualization, a calculator, a mockup, a report, a game, a demo. The user opens it in a browser and it works.
This skill is the standard for artifacts in general. If the artifact needs a live data layer that both the user and the agent can edit — persistent state, media review, two-way sync — that is a Workbench Artifact: a standardized, heavier pattern. Read grim:dev:workbench-artifact instead.
The Standard
Start minimal, and only escalate when the job demands it.
The minimal artifact — the default:
- One self-contained
.html file. Inline the CSS and JS. No separate files, no folders. Opening it directly (file://) just works.
- No build step. No bundlers, no frameworks that require compilation, no package.json.
- No dependencies by default. Vanilla HTML/CSS/JS first. If a library genuinely earns its place (a chart, 3D, markdown rendering), load it from a CDN with a pinned version — never more than a couple.
- No network requirements at runtime beyond those pinned CDN tags. The artifact should work on a plane.
- Readable source. The user may open the file in an editor; keep it inspectable, commented where non-obvious, and small.
Escalate deliberately. Artifacts can grow beyond the minimal form when they need to — a small local server (one Python or Node file), a couple of split-out files, a data file to read. Each addition must earn its place; never add a server to something a static page can do. If it grows a persistent agent-editable state file and two-way sync, it has become a workbench artifact — switch to that standard.
Craft
- Design it like a real page, not a code dump: sensible typography, spacing, and a deliberate palette.
- Respect the OS light/dark preference with a
prefers-color-scheme media query.
- Make interactive state obvious: hover states, focus states, disabled states.
- Handle the empty state — the artifact should look intentional before the user touches anything.
- Test it by opening the file, not by reasoning about it.
Where artifacts go
Write artifacts into the project you are working in, named for what they show, e.g. retention-explorer.html, pricing-mockup.html. Delete-me-later throwaways go in the system temp folder instead of cluttering the project.
Share On Your Local Network (Phone Testing)
Default to this when the user wants phone access. Open any artifact (or built web app) on your phone over home WiFi — no internet, no deploy. The whole trick: serve it bound to 0.0.0.0 (all network interfaces) instead of 127.0.0.1/localhost (Mac-only), then hit the Mac's LAN IP from the phone on the same WiFi.
- Get the Mac's LAN IP:
ipconfig getifaddr en0 (WiFi; try en1 if blank). e.g. 192.168.4.182.
If ipconfig is unavailable or errors in a sandbox, use ifconfig en0 and read the inet ... IPv4 line.
- Serve bound to 0.0.0.0 — pick one (prefix with
nohup … & so it survives the terminal):
- Any static folder (zero deps):
python3 -m http.server 8765 --bind 0.0.0.0 --directory <folder>
- Or
npx serve -l tcp://0.0.0.0:8765 <folder>
- The workbench sync server:
node artifacts/server.js --root <project-root> --host 0.0.0.0 so http://<lan-ip>:8765/ works.
- A Vite app: build first (
npm run build → dist/), then vite preview --host 0.0.0.0 --port 4173. (Live dev server: vite --host 0.0.0.0.) vite preview is just a tiny static server that hands out dist/.
- On the phone (same WiFi): open
http://<lan-ip>:<port>/ (e.g. http://192.168.4.182:8765/). Safari → Share → Add to Home Screen opens it like an app.
Caveats — this is a convenience, not a deployment:
- Phone + Mac must be on the same WiFi, and the Mac must be awake with the server still running.
- The LAN IP can change (DHCP) on reconnect/router restart — re-check
ipconfig getifaddr en0.
- Local-only — nobody off the WiFi can reach it. For a persistent public URL (cellular, sharing, days later), deploy it (e.g. Render) instead.
- PWA gotcha: if a service worker caches the shell cache-first, a re-share can serve a stale build — bump the SW cache name / use network-first for navigations, or clear site data on the phone.
When to upgrade to a workbench
Upgrade when any of these appear:
- the user's clicks need to change files the agent reads back;
- state must persist and stay diffable across sessions;
- media files flow in and out of the surface;
- the artifact becomes a reusable tool rather than a one-off view.
The upgrade path and the sync server that powers it live in grim:dev:workbench-artifact and the shared standard skills/artifacts/artifacts/references/workbench-skills.md.