Skip to main content

Artifacts reference

Follow Share pages from Claude to share and open pages. The HTTP routes are in the endpoint reference, under privacy and observability and the connect contract. Who owns a page's data, and what an erase removes, is in Data boundary.

What can be shared​

TypeFilesLargest
HTML.html, .htm5 MiB
Markdown.md, .markdown5 MiB
SVG.svg5 MiB. Shown as an image, so its scripts do not run
React.jsx, .tsx200 KiB of source, compiled into an HTML page of at most 2 MiB

A React file needs a default-exported component and gets five seconds to build. Imports may use only react, react/jsx-runtime, react-dom and react-dom/client; others, including recharts and lucide-react, are refused. Use inline styles or include your CSS in the component. Tailwind-style classes compile and render unstyled because no Tailwind stylesheet is included.

LimitValue
Title200 characters
Share list100 people and 50 teams
Publishing10 a minute per key
Kept per owner500 pages or 250 MiB

What a page can load​

The console shows a page in a sandboxed frame with an origin of its own. The page can't read your console session, call the console's API, or reach other pages. HTML pages run under a content security policy: inline scripts (with eval) and inline styles only, fonts as data: URLs, images and media as data: or blob: URLs, and no network requests, frames, workers or form posts, including requests to the console itself. Anything else it loads from outside shows blank.

Markdown pages run under a stricter policy with no scripts at all. Images must use data: or blob: URLs, including images in raw HTML within Markdown. SVG is shown as an image, so its scripts do not run.

When a page loads one of these libraries with a classic <script src> from jsDelivr, unpkg, cdnjs, cdn.tailwindcss.com, d3js.org or code.jquery.com, at the file path that library publishes as its browser build (such as chart.js@4/dist/chart.umd.min.js or react@18/umd/react.production.min.js), the console embeds its own copy in the page before showing it. The version the page asks for is ignored. Other file paths, ES module imports and other libraries stay external, and the policy blocks them.

LibraryVersion served
Chart.js4.5.1
D37.9.0
React and ReactDOM18.3.1
Mermaid12.2.0
Babel standalone7.29.10
Tailwind (browser build)4.3.3
jQuery3.7.1

Pages using the Tailwind v3 CDN get Tailwind 4, without CDN plugins such as ?plugins=forms. A type="module" script is not replaced.

A Google Fonts <link> or @import for these families is embedded in the page (Latin and Latin Extended): Archivo, Geist, Geist Mono, Hanken Grotesk, IBM Plex Mono, IBM Plex Sans, IBM Plex Sans Condensed, JetBrains Mono, Newsreader, Public Sans and Schibsted Grotesk.

WebRTC is not blocked

Browsers give a page no way to block WebRTC, so a page's own code could still use it to send what it reads elsewhere. Share a page that holds sensitive data only with people you trust with that data.

Page data​

An HTML page keeps data through the claude.ai runtime. claude.use(name) returns a promise:

NameResolves to
dbThe page's documents. null on a gateway older than page data
userThe viewer
permissionsstate(name) returns granted for db and user and unavailable for anything else; state() returns { db: "granted", user: "granted" }. request(names) returns a name-to-status object (request() the same default object). manage() rejects with unavailable
Any other namenull

If the page gets no answer about its data within 10 seconds of loading, every name resolves null until the page reloads. If that first answer is a refusal instead, db resolves null while user and permissions still work, and user.id() returns null.

One vote per person
<script>
(async () => {
const db = await claude.use("db");
const user = await claude.use("user");
if (!db) return; // no page data on this gateway
const me = await user.id();
await db.doc("votes/" + me).set({ choice: "blue" });
db.collection("votes").onSnapshot((snap) => {
document.title = snap.size + " votes";
});
})();
</script>

Documents​

Paths alternate collection and document: votes is a collection, votes/a1 a document in it, and votes/a1/notes a collection under that document.

CallWhat it gives
db.collection(path).doc(id) (a new random id when omitted), .add(data), .where(field, op, value), .orderBy(field, "asc" or "desc"), .limit(n), .get(), .onSnapshot(next, error)
db.doc(path).get(), .set(data), .update(data), .delete(), .acquire({ holder, ttlMs, data }), .onSnapshot(next, error), .collection(path)

where compares a top-level field with ==, !=, <, <=, >, >=, in, not-in or array-contains, and a query reads only the collection's own documents. set replaces a document; update merges into one that exists. acquire takes a short lease (30 seconds unless ttlMs says otherwise) and answers acquired and expiresAt; a busy lease never says who holds it. onSnapshot re-reads when the page's data changes, checking every 5 seconds while the tab is visible. A document snapshot has id, exists and data(); a query snapshot has docs, size, empty and docChanges().

The viewer​

user.id() is the id this page sees for the viewer. It differs on every page, and it is the <id> in data/users/<id>. isOwner() and canEdit() are true for the author only, and can("data.write") says whether publishing is on and the rules let the viewer write at the page's root. A deeper rule can still refuse or allow a single document, so handle a refused write either way. Names, avatars and emails stay empty: name() is "", email() and avatarUrl() are null, and search() finds nobody.

Errors​

A data call that fails rejects with { code, message }. db.doc(), db.collection() and .doc(id) throw a TypeError at once for a path or id that breaks the path rules. A read the rules hide is not an error: the document reads as absent and drops out of queries.

codeCause
invalid_argumentA bad value, a write the access rules refuse, or a write while publishing is off
quota_exceededThe page holds its limit of documents or bytes
resource_exhaustedToo many calls, or a query on a collection holding more than 5,000 documents or 8 MiB. Listeners back off and retry on their own, but a retry cannot fix an oversized collection
revokedThe page is no longer shared with the viewer, or their sign-in ended
unavailableThe gateway did not answer, or the page is a read-only Desktop copy

Access rules​

Without rules, everyone who can open the page reads and writes all of its data except each person's data/users/<id> part, which nobody else can read or write, the author included. The author sets rules as JSON in the page's Data access rules section in the console (Save, or Clear to remove them). Publishing through POST /connect/artifacts takes them as dataRules; Claude's anyray_share sends none.

Data access rules
[
{ "path": "settings", "write": "owner" },
{ "path": "votes", "read": "owner", "write": "owner" },
{ "path": "votes/{self}", "read": "interact", "write": "interact" }
]

Everyone reads settings and only the author changes it. Each person reads and writes only their own votes/<id> document, and the author reads all of them.

PartRule
pathA collection or document path, or "" for the whole page. A rule covers everything below its path; the deepest matching rule wins, for read and write separately
{self}As the last segment, the viewer's own id. Other people's documents at that level stay hidden unless a rule on the parent path sets read, and that parent rule must then set write too
Levelsview, interact, admin, owner, lowest first. The author holds owner and everyone else the page is shared with holds interact, so admin and owner both mean the author
Defaultsread is view, write is interact
ChecksA rule sets read, write or both; write is never view and never resolves lower than read; a path appears once; at most 64 rules. A list that fails is refused whole

Saving rules moves the page's data version, so open views re-read under the new rules on their next poll (a view in a hidden tab waits until it is visible again). If the save answers 503 with reason retry, the rules were saved but open views were not told: save again. Rules need a content key. They can still be changed while only the Artifacts switch is off, but not while content mode is off.

Limits​

LimitValue
Path16 segments and 1,000 bytes. A segment is 1 to 200 of A-Z a-z 0-9 _ . ~ : @ + -, never . or ... A document path has an even number of segments, a collection an odd number
Document256 KiB of JSON, nested at most 32 deep. For update, the merged document
Request300 KiB
Query10 filters, 30 values in an in or not-in list, limit 1 to 1,000 (1,000 when omitted)
Query reads5,000 documents or 8 MiB from one collection, else resource_exhausted
Page25,000 documents and 50 MiB
Lease1 second to 10 minutes
Calls300 a minute per person on one page, 1,200 a minute per person across pages, on each gateway replica

Claude Desktop copies​

Tools on managed Claude Desktop​

On MDM-managed Macs, Connect adds a local connector named anyray-share for publishing when publishing is on and the profile has a personal key. Keep Anyray Connect running and restart Claude Desktop after setup. This connector has not been verified on Windows. A static profile with no anyray row gets Connect's full anyray server instead, which shares too (static profiles).

On a Claude Desktop managed with the console's MDM profile, Mac or Windows, anyray_list_shared and anyray_open_shared come from the managed anyray server your gateway serves, so no local connector is needed. That server is left out while content mode is off (details). The list shows title, owner, date and console link, 25 pages by default and up to 50, and a page opens as text up to 64 KiB.

The Artifacts page​

Connect copies pages in on its refresh and only while Desktop is closed, because Desktop overwrites that list while it runs. The Connect tray says how many new pages arrived ("2 new pages shared with you"); the first sync after you enroll adds your existing pages without a notice.

Connect keeps up to the newest 50 pages within 25 MiB in all, and only ever touches the ones it added. A page that drops out of that window is removed. A page you can no longer see is removed after two complete listings in a row leave it out; a listing that fails or is cut short counts for nothing. Signing out or offboarding removes them. If that happens while Desktop is open, the page text is deleted at once and its title is removed the next time connect runs with Desktop closed. status --json shows the last run and why it skipped, if it did (reasons).

Markdown shows as plain text in Desktop. Desktop's page store is not a public format, so a Desktop update can stop the copies until connect catches up. This was verified on macOS; it has not been verified on Windows yet.

Pages with data​

An HTML page with data carries a snapshot of what you may read: what its rules allow, and your own data/users/<id> part. Connect refreshes it, while Desktop is closed, when the data changes. Writes from the copy fail with unavailable. Edit in Anyray opens the page in the console when the gateway knows its console URL. A snapshot over 1,000 documents or 1 MiB of what you may read is left out, and so is any snapshot of a page holding more than 5,000 documents or 8 MiB in all. The copy then shows the page without its data.

A copy with data runs under the same content security policy as the console, but without the console's libraries and fonts, so a page that loads them from a CDN renders without them in Desktop. Each snapshot fetched by someone other than the author is audited.

Signed in to claude.ai​

When Desktop is signed in to claude.ai (Claude Desktop is not turned on in Connect), the tray asks Show your Anyray pages in Claude Desktop? before copying anything. Your pages are listed under Yours. If someone else signs in to Desktop, the tray asks again and connect removes your pages from the previous account. Stop showing in the tray removes them too.

These copies carry no page data and no Edit in Anyray link, because Share in Desktop republishes the page to claude.ai. The claude.ai copy runs on macOS only.

claude.ai import​

The import brings the current version of each page. A page that was private on claude.ai stays private to its owner. One shared with the organization, or by public link, is shared with the organization. Each page lands in its owner's Mine tab and their Claude Desktop.

A page's shared data comes with it, up to 25,000 documents; each person's private data and the comments stay behind. The export holds no rules for that data, so everyone the page is shared with can change it, as claude.ai allows by default.

Pages made of several files are not imported, and neither is a page whose owner is deactivated in your identity provider or missing from the export. Importing again skips what is already here, but brings back a page that was deleted since. The export stays in your browser: the console sends your gateway one page at a time.