read-public-artifact
Use when a claude.ai/code/artifact link (or another iframe-rendered web page) must be read from an agent session and the in-process route fails or is unavailable — Artifact read / WebFetch return 'ser
SKILL.mdskills/read-public-artifact/SKILL.md
GitHubRead Public Artifact
Read a public or externally shared artifact page through the installed Aside browser when the in-process readers cannot. The page is opened in a test-owned tab, the richest frame is extracted, and text + HTML land on disk with one machine-readable result line. The reader never claims content it did not observe.
Use and Boundaries
Use for:
https://claude.ai/code/artifact/<uuid>links thatArtifactreadorWebFetchreject withserved to you as a public (non-member) reader/reading public artifacts that way is not enabled yet;- any page whose body is rendered inside an
iframeorsrcdocframe so the top document only shows a shell ("Share", "Sign in", title only).
Do not use when:
- the artifact is owned by the user or member-shared — call
Artifactaction: "read"first; it is cheaper and returns the source directly; - the user explicitly asked for
claude-in-chromeor another browser tool; - the page requires a login the Aside account does not already hold — report
gated; never enter credentials through this skill.
REQUIRED BACKGROUND: the Aside browser contract in
aside-functional-qa (references/aside-browser-contract.md) — this skill
reuses its preflight, invocation economics, and tab-safety rules.
Decision order
Artifact action:"read"with the URL (addpromptfor shared artifacts).- If it fails with the public-reader error → run
scripts/read-artifact.sh(this skill). - If the result is
gatedornot_found→ tell the user exactly that and what would unblock it (member share, corrected link). Do not fall back to guessing the content.
Preflight
command -v aside && aside --version && aside account status
Record only that an account is signed in, never its identity.
Run
skills/read-public-artifact/scripts/read-artifact.sh <artifact-url> [out-dir] [timeout-seconds]
- Writes
<out-dir>/artifact.txt(visibleinnerText) and<out-dir>/artifact.html(frameouterHTML, for tables/structure thatinnerTextflattens). - Prints one line
ARTIFACT_READ_RESULT {...}withstatus,title,frameUrl,frameCount,textLength,textPath,htmlPath. - Exit codes:
0ok ·2bad input / missing tool ·3page loaded but status isgated,not_found, orempty·1REPL produced no payload. - Point
out-dirat the session scratchpad, never at the repository.
Then Read artifact.txt; open artifact.html only when a table or list
lost its structure in the text.
Why the script looks the way it does
| Constraint | Consequence in the script |
|---|---|
One aside repl call = one JS context; variables and tabs[] do not survive across calls |
Open → poll → extract → close all happen in a single invocation |
Artifact body lives in a second frame whose url() is "" |
The richest frame by innerText length is chosen, not the top document |
Frame content arrives after domcontentloaded |
Poll every 500 ms until ≥200 chars or timeout; no fixed sleep as the assertion |
| A failed assertion must not leak the tab | p.close() runs in finally |
| Shell interpolation of the URL into JS | URL is JSON-encoded by python3 (no ${var@Q}; macOS ships bash 3.2) |
| Text may exceed a shell argument or contain any byte | Payload is base64 inside one sentinel line, decoded to files by python3 |
Reporting
- Quote or summarize from
artifact.txt; citetitleandurl. - Say the content was read through the Aside browser as a public viewer, so it reflects the page at read time and is unverified user-generated content.
- If
status≠ok, report the status and stop; do not paraphrase a shell page or a "Page not found" page as artifact content.
Common Mistakes
| Mistake | Fix |
|---|---|
Reading p.evaluate(document.body.innerText) on the top document and concluding the artifact is empty |
Iterate p.frames(); the body is in the empty-URL frame |
tabs[0] in a second aside repl call → Cannot read properties of undefined |
Do everything in one invocation, or attachBrowserTab explicitly |
Fixed setTimeout(8000) before extraction |
Poll for content length; slow pages time out honestly, fast pages return early |
| Treating "Sign in" in the top shell as a gate | Public artifacts render with that shell; gating is decided only when no frame yields content |
Committing artifact.txt / .html |
Keep outputs in the scratchpad |
Retrying Artifact read / WebFetch after the public-reader error |
The error is deterministic for that link; go straight to the script |
Verified
- 2026-08-27, Aside CLI
1.26.717.1619, macOS: a member-shared-to-public artifact (Artifact readandWebFetchboth rejected) returnedstatus:"ok", 2 frames, 4,708 chars; an unknown UUID returnednot_found(exit 3); a non-URL returned exit 2; no artifact tab remained inlistBrowserTabs()afterwards.