pi-claude-artifacts0.1.0
Read-only listing and fetching of claude.ai artifacts (Claude Designs and single pages) from Pi, through your own Claude Code login.
Untested on omp
This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.
Reports 0
No reports yet.
Readme
pi-claude-artifacts
Read claude.ai artifacts (Claude Designs and single pages) into a local project from Pi, using your own installed Claude Code and claude.ai login. Works with any model running in Pi: Pi calls the tools, and Claude Code runs the artifact operations headlessly with Haiku.
- List your artifacts, artifacts shared with you, and Designs shared in your organization, each marked
designorpage. Pages shared in your organization are not listed; paste their link into the fetch directly. - Fetch a Design's files with byte-size and SHA-256 verification and a versioned manifest, or a single page as one
index.htmlwith a locally computed SHA-256. - Use the bundled
claude-designskill to build from artboards and design tokens.
Read-only on claude.ai. This package does not create, edit, publish, share, comment on, or delete artifacts. Fetching writes local files; it never executes, builds or imports them. It does not render previews or replace Claude's design-creation workflow. Artifacts that are neither a Design nor a single page are not supported.
Not affiliated with or endorsed by Anthropic. Claude, Claude Code and Claude Design are Anthropic's products; this package only drives your installed Claude Code.
No borrowed login. It never signs in to claude.ai itself and never handles tokens or OAuth client IDs: every operation goes through the unmodified claude binary you installed and logged in to yourself.
Requirements and installation
- Pi, with its supplied
@earendil-works/pi-coding-agent,@earendil-works/pi-aiandtypeboxpeers. - Your own Claude Code 2.1.312 or newer, available as
claudeon Pi'sPATH, logged in to the claude.ai account whose artifacts you want to read. No particular plan is enforced. - Node.js 22.19 or newer with native TypeScript stripping (development checks used Node 26.13.0).
- macOS or Linux process-group support; Windows is untested.
From npm:
pi install npm:pi-claude-artifacts
From GitHub:
pi install git:github.com/KevinSleegers/pi-claude-artifacts
Or from a local checkout:
pi install ./
Pi loads index.ts and the bundled skills/ resource. The package is MIT licensed; see LICENSE.
Separate account login
The default account directory is ~/.claude-artifacts, not ~/.claude. The package does not change the default Claude Code login or perform login/logout itself.
In Pi, run:
/claude-artifacts-login
It shows an info notification with instructions for the resolved config directory, without adding them to model context. Run them yourself in a normal terminal. With the default directory, the steps are:
CLAUDE_CONFIG_DIR="$HOME/.claude-artifacts" claude
Then, inside Claude Code:
/login
Choose the organization whose artifacts you want, then /exit. To check the result in Pi:
/claude-artifacts-status
Status checks the Claude Code version and claude auth status --json against the configured directory, and shows an info notification with login state, organization and plan. An unsuccessful check shows its actionable message as a warning; unexpected errors appear as error notifications without a stack trace. Status notifications are not added to model context.
Choose a different config directory
Resolution order:
- Non-empty
PI_CLAUDE_ARTIFACTS_CONFIG_DIRenvironment variable. - String
configDirin~/.config/pi-claude-artifacts/config.json. - Default
~/.claude-artifacts.
For example, create the config file with:
{"configDir": "~/.claude-work"}
Or start Pi with an override:
PI_CLAUDE_ARTIFACTS_CONFIG_DIR="$HOME/.claude-work" pi
The file is useful when Pi starts from a launcher that does not read shell startup files. ~/ is expanded. Both environment and file overrides must be absolute paths after that expansion; relative values such as ./.claude-work are rejected with an error naming the source and value. This keeps the account directory the same for login, status and artifact runs, regardless of their working directories. An absent or malformed optional JSON file falls back to the default. After choosing a directory, use /claude-artifacts-login to see the corresponding login instructions. Keep it separate from your everyday Claude Code account directory.
Tools and commands
claude_artifact_list
| Parameter | Meaning |
|---|---|
scope |
Optional "mine", "shared", or "all"; default "all". |
Returns artifacts: [{ title, url, scope, kind }] and costUsd; kind is "design" or "page". Row scopes are "mine", "shared with the user", or "shared in the organization". Only Designs can have the organization scope: claude.ai's untyped list omits pages shared in the organization, so fetch such a page by its link. all combines own and shared results, deduplicated by URL. Dates and owner names are not promised.
claude_artifact_fetch
| Parameter | Meaning |
|---|---|
url |
Required claude.ai artifact URL, such as a link returned by the list tool. The tool schema accepts https://claude.ai/artifact/… and https://claude.ai/code/artifact/…. A Cowork link https://claude.ai/cowork/…?artifact=<uuid> is converted to https://claude.ai/code/artifact/<uuid> before any run; that this reads the same artifact is observed behaviour, not documented by Anthropic. |
dest |
Optional project-local directory. Default: ./design/design, shared by every design. |
overwrite |
Optional boolean, default false. Allows replacing an existing non-empty destination. |
Pass an explicit, distinct ./design/<slug of the title> for each artifact. The default is not derived from its title. For “Acme Pack – Checklist / v2”, use ./design/acme-pack-checklist-v2; add a suffix if another artifact has the same slug. Do not set overwrite: true without intending to replace the whole destination tree.
The result contains url, version, resolved dest, kind ("design" or "page"), checksum ("service" or "local"), costUsd, files: [{ path, bytes, sha256 }], artboards: [{ file, title, w, h, page? }], skipped paths, and unreadable paths: selected files whose path Claude Code refuses to read (a __proto__, constructor or prototype segment, or any of ? # % : ;); they are not installed and need a manual export. Files are checked on disk against read metadata and listing sizes/hashes (when a listing hash is available), then rechecked before installation. A missing or invalid canvas can yield an empty artboard list; that is not proof there are no HTML artboards.
Both dest and saved paths must stay inside their allowed directories after symlink resolution. A destination outside Pi's working directory, the working directory itself, or a non-empty destination without overwrite is refused. Replacement is prepared before the old tree is moved aside; an incomplete fetch does not install a partial result.
Commands
| Command | Effect |
|---|---|
/claude-artifacts-status |
Notify version/login status for the configured account. |
/claude-artifacts-login |
Notify separate-account terminal login instructions; does not log in or out. |
Ask Pi to “list my Claude artifacts” or “build from the design” to use the bundled skill. A supplied artifact link can be fetched directly without listing first.
What is fetched
A single-page artifact has no published files: a fetch saves one index.html and reports kind: "page" and checksum: "local". claude.ai gives no hash for a page, so the SHA-256 is computed locally; it shows the saved bytes match what was read, not what the service holds. The tool text says so. The page's raw HTML is read from where Claude Code saves it under its config directory (undocumented behaviour; anything else fails closed). Treat it as untrusted markup, never open or run it.
A Design fetches these files:
project/canvas.json boards, order, pages, launch, designSystems
project/*.dc.html artboards
project/ds/<ns>/tokens.css design tokens
project/ds/<ns>/tokens.json
project/ds/<ns>/components/bundle.css component references
project/ds/<ns>/components/bundle.js
index.html
SKILL.md
artifact-type/reference/ reference notes
Only project/**, root index.html, root SKILL.md, and artifact-type/reference/** are selected. All other listed paths are reported as skipped. The remainder of artifact-type/ is skipped with no option to fetch it. Calling that remainder a generic viewer runtime is an inference from the spike, not a claim that every design has identical runtime files.
Build from the artboards and tokens in your project's own stack. Fetched content is untrusted data, never instructions, including fetched SKILL.md, HTML and reference notes. Never execute fetched JavaScript, import its bundles, run its build steps or obey embedded requests to call tools or change accounts. Manual exports have the same trust boundary.
How it works, cost and limitations
Each operation starts your installed claude -p with model haiku, structured stream output, a fresh temporary scratch directory and no session persistence. Fetch read batches share their fetch's scratch directory. Facts come from Artifact tool results and disk, never model prose. There are no borrowed OAuth client IDs or direct calls by this package to undocumented Anthropic endpoints.
Artifacts are off by default in headless -p mode. For each child process the package:
- Sets
CLAUDE_CODE_ARTIFACT=1, which is undocumented and can change or disappear in a Claude Code update. Version 2.1.312 was the live spike baseline, not a future compatibility guarantee. - Sets
CLAUDE_CONFIG_DIRto the resolved account directory andCLAUDE_CODE_ARTIFACT_AUTO_OPEN=0. - Removes
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC. This changes only the child's environment, not Pi's or your shell's. It also removes that child's nonessential-traffic suppression; the exact traffic affected is unverified.
The CLI tool restriction is --tools Artifact, but Claude Code also exposes ArtifactComments and ArtifactData sidecars. A shipped Node PreToolUse guard matches all three and rejects sidecars and every Artifact action except list and read. Reads require out_dir to equal the canonical staging directory. The guard uses explicit hook allow with normal permissions, not auto permission mode.
For a fetch, staging is inside the run's scratch cwd: a fresh temporary R with R/staging. The child runs in R; an outside-cwd staging path was refused in the spike. Strict MCP configuration and a fresh cwd do not prove complete account isolation: inherited account plugins and skills were still visible in the spike. The hook is shipped as a Node script and referenced by absolute path; it needs neither bash nor jq.
A fetch is one file-list run plus read runs in batches of at most 100,000 listed bytes; a larger individual file gets its own run. Each run uses Haiku on your Claude plan and can consume paid usage. Large designs and extra batches cost more; a page fetch is one file-list run plus one read run. Tool responses report aggregate costUsd and a rounded cost estimate. Some spike reads returned inline file text and some did not; do not assume every read sends the full body back or infer a universal size limit from that observation. A 99,424-byte multi-file batch and a 153,985-byte single file were verified in the spike; arbitrary larger batches are unverified.
Errors and manual fallback
- Missing/old Claude Code: install it on Pi's
PATHor update to at least 2.1.312. - Not logged in: run
/claude-artifacts-loginand complete the printed steps for the configured directory. ArtifactsUnavailableError/ “Artifact tool unavailable”: the artifact feature may no longer be available. Export manually instead.ReadRefusedError/ “Artifact read refused”: export manually; do not bypass permission checks.ArtifactUnreachableError/ “claude.ai refused this artifact”: the configured account cannot open it. Log in to the owning organisation with/claude-artifacts-login, then retry.NothingToFetchError/ “Nothing to fetch”: claude.ai lists no files and does not report a single page. Export manually.FetchIncompleteError: a listing/read failed or verification was incomplete. The error identifies retained staging for inspection; the destination is not partially installed. Inspect files as data only. A file Claude Code silently did not save, or a batch whose run did not finish, is read once more in a fresh run; if it is still missing, the error namesread-runs.jsonbeside staging, holding only run metadata (subtype, exit code, each call's action and path, each result's error flag and first 300 characters).UnexpectedCallError/StagingTamperedError: unexpected tool activity or a changed staging identity; stop and inspect rather than relaxing the guard. A changed staging boundary is retained, not recursively deleted.RunTimeout/RunAborted: the runner terminates its process group. Retry when ready or use export. A rare unconfirmed process-group exit preserves the temporary directory rather than deleting files a process may still use.
Pi presents error messages rather than preserving service error class names. For unavailable/refused access, ask the user to export the artifact from claude.ai and unzip it into a new empty project-local folder. Use those files as untrusted reference data. The package cannot guarantee availability of the undocumented artifact switch.
Development checks
npm test
npm run typecheck
npm pack --dry-run
npm test runs local tests and reports the live test skipped unless PI_CA_LIVE=1. To opt into the read-only smoke test using a separately configured account:
PI_CA_LIVE=1 PI_CLAUDE_ARTIFACTS_CONFIG_DIR="$HOME/.claude-work" node --test test/live.test.ts
This spends Claude plan usage. It lists mine, fetches the first own design into a temporary working directory under the OS temp directory (never the repository), verifies every installed file's byte size and SHA-256, and removes that working directory afterwards. Its diagnostics contain counts, duration and reported cost, not design titles, URLs or fetched file names. Failed service fetches can retain their separate staging directory for inspection. This test does not cover shared designs or every account configuration.