# Artifacts hub — plan _Drafted 2026-10-14. Status: all three phases built 2026-10-14 (the session view's own Artifacts tab is not built; the page has the per-workspace file picker)._ ## Goal One place to keep what agents PRODUCE, and (in server mode) to share it: | Kind | What it is | Where it comes from | |---|---|---| | `page` | A claude.ai Artifact a session published (`claude.ai/…/artifact/…`) | the `Artifact` tool's PostToolUse hook, or a link pasted by hand | | `file` | A file an agent wrote (HTML, Markdown, PDF, image, CSV, Office…) | Write/Edit/NotebookEdit hook events, kept on the user's pin; or uploaded from the computer | | `skill` | A Claude Code skill folder (`SKILL.md` + files) | the user's own `~/.claude/skills/` or a workspace's `.claude/skills/`; or uploaded (a Markdown file, files, a folder, a .zip/.skill — several skills at once too) or written in the dialog, under a name the user chooses | | `plugin` | A plugin by marketplace source + name (no files) | picked from the list a marketplace link answers (`POST /api/artifacts/plugin/inspect`), or typed as `name@marketplace` | - **Local mode:** one personal library, no sharing UI. - **Server mode:** every artifact is the OWNER's and private by default. The owner can **Share** it; a shared artifact appears in the **Hub** for every signed-in user. A shared skill or plugin can be **installed** into the viewer's own account. ## Rules (binding, same spirit as CLAUDE.md) - **What is shared is a SNAPSHOT, never the owner's live file.** Sharing a `file`/`skill` copies it (size-capped, regular files only, no symlinks followed) into `/artifacts//`, written once like `session_snapshots`. Viewers read only that copy, so no route ever reads another user's home for them. Re-sharing makes a new snapshot. - **Nothing shared runs on the dashboard's origin.** HTML/SVG previews are served under the `/git/raw` headers (`sandbox` CSP + `nosniff`) and shown in a sandboxed iframe; a type that sandbox cannot show (Office files, zip, PDF — the sandbox blocks both a download and the PDF viewer) gets Download only, never a blank Preview. A `page` is only a link out, accepted only as `https://claude.ai/…`. - **Installing is the viewer's explicit click, into the viewer's own account only.** For a skill, the hub writes the snapshot's files into `~/.claude/skills//` of the VIEWER (S3: as their member, through `write-as`). It never overwrites an existing skill without `conflict: replace`, and the old one goes to the trash first. For a plugin, the hub runs `claude plugin marketplace add ` + `claude plugin install @ --scope user` as the viewer (the `applyPluginBaseline` path). The marketplace source passes an allowlist (`owner/repo` or a `validateRemoteUrl` URL), and no argv comes from the request beyond those two validated values. - **Before installing, the dialog lists every file of the skill** (a skill may carry scripts that the viewer's agent will run). Every share, unshare and install is written to `audit_log`. - **Visibility follows ownership:** a developer sees their own artifacts plus shared ones; admin/analyst see per `scope.js`, like sessions. Unshare removes an artifact from the Hub but does not uninstall copies others already installed. ## Data New table `artifacts` (`CREATE TABLE IF NOT EXISTS` in `server/db.js`): `id, kind, title, description, owner_id, lane_id, session_id, source (path | url | market spec), url, snapshot (dir name | NULL), size, shared (0/1), shared_at, installs, created_at, updated_at`, plus an index on `(owner_id, kind)` and on `(shared, kind)`. ## Phases 1. **Library (local + server, private).** Table, `server/lib/artifacts.js`, `/api/artifacts` (list/get/create/patch/delete). `page` rows are captured from the `Artifact` PostToolUse hook (URL taken from `tool_response` by an `https://claude.ai/…artifact/…` match). `file` candidates are listed per workspace from Write events with a document extension, and the user pins them. New **Artifacts** page (sidebar) plus an **Artifacts** tab in the session view's right panel. Scope wiring: `PATH_RULES`, `broadcastAudience`. 2. **Hub (server mode).** Share/Unshare buttons, snapshot, `Hub` tab, sandboxed preview, download, `artifact_shared` broadcast. 3. **Skills & plugins.** "Share a skill/plugin" picker, the install flow (S3 included), conflict handling, audit. Each phase ships with its server and client tests and an update to `docs/API.md`. ## Open questions - No `Artifact` tool call has happened on this machine yet, so the exact hook payload of a publish is unverified. Phase 1 matches the URL loosely and keeps "paste a link" as the fallback. - Should an admin be able to disable Hub installs for everyone (one switch in Settings)? Proposed: yes, on by default.