Skip to content

Latest commit

 

History

History
278 lines (225 loc) · 14.5 KB

local-workspace.md

File metadata and controls

278 lines (225 loc) · 14.5 KB

Local workspace and MCP reference

This guide covers the file-based Bun CLI, stdio MCP server, gallery, and optional Herdr integration. For the full application with scripts, backends, and scheduled runs, use the Artifacts host.

Get started

Install the CLI with bun add --global @sidequery/artifacts. In your project, start a browser gallery for local artifact files:

artifacts web --port 4784

Open localhost:4784. To let your coding agent work with these files, configure a stdio MCP server with command artifacts and arguments mcp --dir /absolute/path/to/your/project/artifacts. Ask the agent to read artifact_guide, then create an artifact.

This workflow stores source files in your project. It is separate from the full application at port 4786 and does not synchronize with that application's library. Herdr is optional; browser previews and MCP Apps work without it.

Agent workflow

Call artifact_guide before creating an artifact if you have not read it in the current conversation. It covers the SDK contract, host APIs, restrictions, and validation. Import standard React hooks from sidequery/artifacts for component state and effects. Use useArtifactState(key, defaultValue) when you want host-backed state; persistence depends on the view.

Artifacts live at <workspace>/artifacts/<name>.artifact.tsx. Import the SDK from sidequery/artifacts (herdr/canvas and cursor/canvas remain compatibility aliases). Projects can also import their declared helper files and pinned dependencies. Use the CLI or MCP:

artifacts list
artifacts write overview --file examples/overview.artifact.tsx
artifacts typecheck overview
artifacts web --port 4784
artifacts mcp

With Herdr configured, artifacts open overview typechecks and bundles with Bun, then opens the herdr.artifacts artifacts pane entrypoint. That pane starts its own loopback server and runs Terminal Browser internally in --app-mode. Closing the pane closes its browser session and loopback server. --no-open is the explicit development-only path that starts a detached server and returns its URL.

MCP tools: artifact_list, artifact_read, artifact_edit, artifact_write, artifact_typecheck, artifact_compile, artifact_open. artifact_write returns Artifact TypeScript check diagnostics in the tool result.

Inline artifacts in chat

Configure the stdio MCP server above in a client that supports MCP Apps. Ask the agent to create an artifact: a successful artifact_write displays the actual React artifact inline, including charts, forms and interactive controls. To show an existing artifact, call artifact_open({name: "overview"}). Successful artifact_edit and artifact_restore also return an updated inline preview. These are artifact views, without the gallery or tool-management controls.

Inline views fit their content, grow and shrink as it changes, and scroll within a 600px maximum height (or a smaller maximum supplied by the host). A host with a fixed container height takes precedence. The chat controls the width; narrow views wrap text and keep oversized content scrollable.

When the host advertises fullscreen support, Expand opens the artifact in the host's fullscreen view. Exit fullscreen returns it to the conversation. Fullscreen uses the available viewport with an independently scrolling artifact. Switching modes preserves controls and their current state. Hosts can also change the mode themselves; unavailable controls are hidden, and rejected requests leave the current view usable. This uses MCP Apps display modes, not browser fullscreen.

The viewer is a self-contained ui://artifacts/viewer.html MCP App resource. Tool results carry the compiled snapshot in UI-only _meta; normal text results stay compact. No web server, external asset hosting or Herdr installation is needed. Clients without MCP Apps support receive the normal text/diagnostic results; they cannot display the interactive artifact.

Inline views begin with saved artifact state and keep subsequent interactions local to that view, like gallery previews. They do not overwrite the working artifact's state sidecar. Archived views support version_id and optional event_id, and recompile the saved raw source with the installed SDK. Delivering a preview archives raw source and records a preview event; it does not prove a human saw it. Compiled JavaScript is never stored in the history database.

The artifact follows the chat host's theme. promptAgent requests a user message through the host, and openUrl requests opening an HTTP(S) link. Host rejection is shown in the view. openFile reports that local file opening is unavailable in chat. These actions remain subject to the host's capabilities and permissions.

MCP artifact_open now defaults to inline display. To open a Herdr pane explicitly, use artifact_open({name: "overview", target: "herdr"}). Similarly, artifact_write({name, contents, target: "herdr"}) also opens a pane. The legacy write open flag is accepted, but inline display is automatic regardless of it. CLI open continues to open a Herdr pane.

Targeted reads and edits

Use read / artifact_read to retrieve only the needed working-source lines, and edit / artifact_edit to change them without resending the whole artifact. These operations share the same implementation across CLI and MCP. They accept an artifact name (with optional .artifact.tsx suffix), not a path; symlinks are rejected.

bun run src/cli.ts read overview --start-line 5 --end-line 12
bun run src/cli.ts edit overview --stdin <<'JSON'
{"edits":[{"old_text":"<H1>Overview</H1>","new_text":"<H1>Issue overview</H1>"}]}
JSON

read returns JSON containing source, start_line, end_line, total_lines, next_line, and source_hash (SHA-256 of the entire file). Line numbers are 1-based and inclusive. The default is 200 lines starting at line 1; next_line identifies the next page or is null. Explicit end lines are clamped to EOF; a start past EOF is rejected. Empty files return empty source and end_line: 0. Line endings are preserved so returned text can be used for exact replacements.

MCP uses artifact_read({name, start_line?, end_line?}) and artifact_edit({name, edits, expected_hash?}). CLI edit reads the same JSON body without name from stdin or --file PATH. Each edit has old_text and new_text. Include the hash returned by read as expected_hash to reject stale edits.

Replacements run sequentially in memory. Each non-empty old_text must match exactly once in the result of earlier replacements; missing or ambiguous matches reject the entire batch without writing. Use more surrounding text to disambiguate. Empty new_text deletes the match. The completed batch is written with atomic replacement and an optimistic source check, then typechecked once. As with write, typecheck errors leave the changed source applied; edit reports applied: true, ok: false, CLI exits 1, and MCP marks the result as an error. This is not a strict filesystem compare-and-swap against arbitrary external writers.

Edit results include changed, edits_applied, the new source_hash, and diagnostics, but no source echo. Edits do not modify saved UI state or create history revisions until successfully served. Existing write/open behavior is unchanged: MCP supports artifact_write with open: true; CLI uses separate write and open commands.

Artifact history

Every successfully served source revision is archived automatically, including edits made directly to a .artifact.tsx file. History stores authored source, dependency snapshots, and metadata, using Bun's built-in bun:sqlite; compiled artifact JavaScript stays in memory. Unchanged source and project reuse their latest revision. Each page response records a separate serve event with its initial UI state, pane/session context, and runtime identity. A serve event means the server returned a page, not that a human viewed it. Unserved intermediate edits are not captured automatically.

bun run src/cli.ts history                    # all artifacts in this workspace
bun run src/cli.ts history midnight-greenhouse
bun run src/cli.ts show VERSION_ID            # raw source, metadata, serve events
bun run src/cli.ts show VERSION_ID --source   # raw TSX on stdout
bun run src/cli.ts open --version VERSION_ID  # open an archived version in a pane
bun run src/cli.ts open --version VERSION_ID --event EVENT_ID
bun run src/cli.ts restore VERSION_ID         # restore source as a new revision

Equivalent MCP tools: artifact_history (optional name), artifact_version (version_id), artifact_open (version_id, optional event_id and placement), and artifact_restore (version_id). Existing artifact_list lists working files; artifact_history also includes artifacts whose files have been deleted. artifact_open accepts either name for a working file or version_id for history.

Reopening compiles the saved source with the currently installed SDK and Bun. An SDK upgrade can change its appearance or make old source fail to compile. The archived view starts with the selected event's state (by default the latest live serve), and its interactions remain local to that page. It does not poll the working file or write to the working artifact's saved state. This preserves initial state, not a recording of every interaction. Page bundle URLs identify the source version and in-memory SDK generation so concurrent source/SDK edits cannot mix the page and bundle. If an old SDK generation has been evicted from memory, its bundle request asks for a page reload instead of serving different code.

Restore saves the current working source first—even an invalid, unserved draft— then writes the selected source and appends a new revision linked to the original. It keeps later history and the working artifact's .artifact.data.json state. Restore uses an atomic file replacement and an optimistic source check; if an edit is detected after the preservation snapshot it stops and leaves that edit untouched. Symlinked source files are rejected for serving and restoration. Typecheck diagnostics are returned after restoration. File replacement and SQLite are separate operations: the original working source is durably archived before replacement; an interrupted restore may be captured on the next successful serve.

The database survives pane closure and lives at:

  • macOS: ~/Library/Application Support/artifacts/history.sqlite
  • Linux: $XDG_DATA_HOME/artifacts/history.sqlite, defaulting to ~/.local/share/artifacts/history.sqlite

Override with ARTIFACTS_HISTORY_DB or --history-db PATH. All commands also accept --dir PATH to select an artifacts directory. Artifact IDs are stable within that directory and name; renames or different worktrees are separate artifacts. SQLite uses WAL mode with a busy timeout for concurrent panes. History is retained without automatic pruning; it may contain embedded data and saved UI state. For backups, use SQLite's backup facilities rather than copying an active database file without its WAL.

Web gallery

bun run src/cli.ts web --port 4784

Open http://127.0.0.1:4784 to search working artifacts and archived versions, preview one at a time, inspect raw source, or download a .artifact.tsx file. The gallery defaults to this project; its all-projects filter includes archived artifacts from other projects in the same database. It does not scan other projects for unarchived working files. Use --dir PATH and --history-db PATH to select a workspace and database, or --port 0 for an available port printed on startup.

The server runs in the foreground until Ctrl-C. Gallery previews have isolated, temporary interaction state and run in sandboxed frames; they cannot access the gallery page. Viewing a working copy archives its current source. Closing a browser tab does not stop this explicitly started web server. The gallery offers no restore or delete action; restoring working source remains an explicit CLI/MCP operation.

Trust boundary

The file-based workspace runtime has no multi-user authentication. Keep the web server on loopback; do not expose it through a public proxy. Source checks reject unsupported imports and APIs, but they are not a general-purpose security sandbox for hostile JavaScript. Gallery previews run in isolated browser frames. Inline artifacts execute inside the chat host's MCP Apps sandbox; use trusted local artifact source, as for the other local views. Artifact source and saved state can contain private data; keep the history database private.

Optional Herdr integration

herdr plugin install zenbu-labs/terminal-browser/herdr-plugin --yes
herdr plugin link /path/to/artifacts

Run bun install --frozen-lockfile in the checkout before linking it. The plugin ID and pane entrypoint are herdr.artifacts and artifacts. Relink an existing checkout to register the new plugin name.

Upgrading from Canvas

Use the artifacts CLI and artifact_* MCP tools. New sources use .artifact.tsx, sidequery/artifacts, and SDK names such as useArtifactState and artifactFetch. Existing .canvas.tsx sources, their sidecars, historical SDK imports and exported names remain readable and compilable. Existing workspace and application-data directories are reused when no new directory exists; files and databases are not moved. New ARTIFACTS_DIR, ARTIFACTS_HISTORY_DB, and ARTIFACTS_DATA_HOME overrides take precedence over their legacy equivalents. Existing hosted storage identities are retained; see Cloudflare setup.

Development checks

See the source map for runtime boundaries, MCP modules, hosted services, and Herdr action entrypoints.

bun run test
bun run test:e2e
bun run test:mcp-ui
bun run test:package
bun run typecheck

bun run test is the unit/service suite. bun run test:e2e builds a Docker image with real Herdr and Terminal Browser, starts Herdr on a PTY, verifies that the pane is owned by herdr.artifacts, and proves its server stops when the pane closes.

GitHub Actions runs the typecheck and unit/service suite with Bun 1.4.0. e2e/Dockerfile is the Herdr integration-test environment. The root Dockerfile builds the standalone celld image. bun run test:mcp-ui exercises the real artifact in Chromium with an MCP Apps host. Install its browser first with bun x playwright install chromium. CI runs this browser suite, the unit/service suite, and a clean tarball install that exercises the installed CLI, gallery, compilation, and stdio MCP server.