Skip to main content

Artifacts from the CLI

An artifact is a private, multi-file HTML project with an immutable version history. Every save stores a complete file manifest as a new numbered version; nothing is edited in place. You can pin one version as the shared version, attach comments to an element of an exact version, keep JSON data for a dashboard next to the code, and read or export a deck that follows the Slides profile. The commands live under crewship page artifact, because an artifact is stored on a Page record. The full flag reference stays on Page Commands; this page is the task guide, with output recorded from a real workspace. Design canvases (crewship page design) and Craft documents (crewship craft) have their own commands and are not covered here.

Before you start

Each group of commands needs a workspace feature flag, which an OWNER or ADMIN turns on with crewship feature-flag enable, or an instance switch set to true in the server environment. artifact_projects is on by default; artifact_dashboard_data and artifact_slides are off: The CREWSHIP_ARTIFACT_DASHBOARD_DATA_ENABLED and CREWSHIP_ARTIFACT_SLIDES_ENABLED switches replace only the artifact_dashboard_data and artifact_slides flags. Data and Slides still need artifact_projects (or CREWSHIP_ARTIFACT_PROJECTS_ENABLED) to be on.
When artifact_projects is off and its bypass is not set, availability returns {"enabled": false}. It does not report the Dashboard or Slides sub-flags: it can still return true when those are off. A command whose required flag is off fails with 404 (artifact projects are not enabled or dashboard data is disabled). The CLI itself needs no web build-time variable; the url that commands return, /artifacts/<page-id>?workspace_id=<workspace-id>, opens the artifact in the web app. Older /pages/<slug>?artifact=1 links still work: with the Artifacts library in the build they redirect to /artifacts/<page-id> with the same workspace and version; without it they open the Pages project viewer. crewship doc create returns the same canonical url for a new document. Credentials and roles:
  • A human CLI token with the pages:read scope can read; saving, commenting, restoring, sharing and data writes need pages:write.
  • Creating an artifact needs the OWNER, ADMIN or MANAGER role, or a MEMBER with the page-create capability.
  • Restore, share, replies, retained history and archive belong to the artifact owner (or an authorized workspace admin for archive).
  • Saving a version and data writes are open to the owner and to anyone with an Edit share, always against the latest version. Read and Comment shares are read-only.
  • workspace artifact-policy needs OWNER or ADMIN and a token with the workspace:admin scope.
  • Someone who has no grant on a private artifact receives 404, not 403, so the artifact’s existence is not revealed.

Output and errors

Artifact commands always print the server’s JSON document. The default table format and quiet both print indented JSON; -f yaml and -f ndjson re-encode the same document. There is no separate --json flag. archive and unarchive are the exception: table prints the raw compact JSON line and quiet prints nothing. Errors go to standard error. With -f json the error is a JSON envelope whose extensions.code carries the machine-readable reason:
A conflict or quota error never discards anything: earlier versions and data are kept, and the CLI never retries with a newer base. Keep your local file, read the current state and decide what to save. Validation that happens in the CLI before any request (a missing, unknown or invalid flag, a manifest that cannot be read, is not valid or is over 9 MiB) exits with 2. One exception: the checks page artifact data and the Slides commands run after parsing their flags, such as a data batch without --file, exit with 1. It prints the message only, or with -f json an envelope without status or extensions:

Create and save versions

crewship page artifact availability

Read whether artifact projects are enabled in the current workspace.
With --agent, the reply adds can_create. It is true only when artifact projects are enabled, the agent’s crew is allowed by the agent publishing policy and you may create Pages in the workspace. When the crew is not allowed, or the agent is not in this workspace, the reply also carries "code": "artifact_crew_not_allowed":

crewship page artifact storage

Read the workspace’s aggregate artifact storage: bytes used by every artifact family, bytes reserved by uploads in flight, the limit, and warning levels. Only workspace owners and admins can run it; other members get 403.
When level reaches full, saves fail with artifact_storage_quota: nothing is saved, your --file input is unchanged and every existing version is kept. History is never deleted automatically.

crewship page artifact create <slug>

Create a new artifact and save its first version. --file is a JSON manifest with entrypoint, files and an optional message; each file has path, media_type and UTF-8 content. Use --file - to read standard input. The manifest is limited to 9 MiB, and other top-level keys are rejected.
Creating the same slug again fails with 409 artifact_slug_taken.

crewship page artifact publish <slug>

Save a complete new manifest as the next version. --base-version must be the latest version you read; there is no partial update.
Running the same command again, still with --base-version 1, returns 409 artifact_version_conflict and exit code 5. As an alternative to the publish command above, read the current version, build a manifest from it and publish with .latest_version as the base. Run only one of the two publish examples after creating version 1. The remaining examples assume this read/edit/publish recipe produced version 2 with the message “Shorter title”; running both recipes would create version 3 and require newer base/version numbers below. The manifest object that get returns also carries created_at, restored_from and version, which the CLI rejects (unknown manifest field "restored_from"), so copy only entrypoint and files and add your own message:
A user with an explicit Edit grant can publish under their own identity; owner history stays private.

crewship page artifact get <slug>

Read the artifact snapshot: the manifest of the latest version (or of --version), the version list, comments, your permissions and storage usage.
quota shows history usage. Every version is kept (keep-all); when used_bytes reaches limit_bytes, new versions fail with 413 artifact_history_quota and existing versions stay. No CLI command changes the quota or prunes versions. Readers with a Read or Comment grant see only the shared version.

crewship page artifact versions <slug>

Print the same snapshot as get for the latest version. Use the versions array in it; pass get --version <n> to read an older manifest.

Restore and share

crewship page artifact restore <slug>

Copy a retained version into a new latest version. History is never rewritten. Owner only.
The new version has "restored_from": 1 and the message Restore version 1. An unknown --version returns 404.

crewship page artifact share <slug>

Pin an existing version as the shared version. People with a Read or Comment grant see only this version; the latest version is unchanged. Owner only.
The share url opens the shared version: a reader of that link sees version 2, never the latest one. A stale --base-version returns 409 artifact_version_conflict.

Library publication and pins

A Library is an artifact project with a design-system.json. Its owner publishes one version; other projects in the workspace pin a self-contained copy of that version’s tokens. Editing, restoring or deleting the Library, or losing access to it, never changes a pinned project.

crewship page artifact library show <slug>

Read the published version. Any reader of the Library may call it.
published_version is 0 while nothing is published. can_publish is true only for the Library’s owner.

crewship page artifact library publish <slug>

Publish a retained version. Owner only: editors save draft versions but cannot publish, workspace owners and admins keep their audited read access but cannot publish someone else’s Library, and agent runs cannot publish. The version must contain design-system.json, a JSON object of at most 32 KiB.
Publishing the version already published is a no-op. A non-owner gets 403.

crewship page artifact pin set <slug>

Pin the Library’s published version into project <slug>, or update the pin to a newer publication. You need Edit on the project, and you must be able to read the published version through your own access: the owner reads any version, an editor of the Library only its latest version, everyone else only its shared version. The workspace owner and admin read path does not count: an administrator can read a private Library (with an audit record), but cannot turn that read into a copy. Agent runs cannot pin. Every flag below describes the state you reviewed. If anything differs when the request arrives (another published version, another pinned Library or pinned version), nothing changes and you get 409 artifact_version_conflict. The same applies when --if-pinned-library names a slug that no longer resolves (the Library was renamed or deleted): pass @<library_page_id> from pin show instead.
Pinning the version already pinned returns "changed": false. A Library you cannot read, one with nothing published and one that does not exist all return the same 404. What a pin shares. The copy (the tokens, the Library’s name at the time, and the font and licence files the pin carries) belongs to the project. Everyone who can read the project can read it with pin show, including people who cannot read the Library. The copy stays when the Library is unshared, made private or deleted. Pin only a Library whose tokens every reader of the project may see. There is no unpin command yet.

crewship page artifact pin show <slug>

Read the pinned copy. Any reader of the project may call it; the Library is not read, so the copy stays available after the Library changes or your access to it ends. The SHA-256 is of the stored source bytes and is checked on every read. The response carries tokens as JSON, whose whitespace and escaping may differ. A copy that no longer matches is never served and returns 409 artifact_library_pin_corrupt (“The pinned copy is damaged; pin the library again.”). pin check reports the same error. An editor who still has read access to the reviewed publication can run pin set with that publication and the previous pin’s Library and version. The server replaces the damaged copy only when that reviewed pin still matches. Project previews render from this copy: see Previews render from the pin.

crewship page artifact pin files <slug>

Read the font and licence files the pin carries, bytes in base64. Any reader of the project may call it; the Library is not read. A font left behind is listed with status licence (no redistributable licence) or too_large (over 1 MiB, or past 4 MiB for the pin, licence files included) and empty content. Each copy is checked against its SHA-256; a damaged one returns 409 artifact_library_pin_corrupt.
How a Library stores fonts and which licences count: What a pin carries.

crewship page artifact pin check <slug>

Review an update before applying it.
update_available is true when the Library’s published version differs from the pinned one, including when the owner republished an older version. Paths are dot-joined token keys; each list holds at most 200 entries and truncated says when one was cut. file_changes compares the carried font and licence files by path and content, and not_copied names the published version’s fonts an update would leave behind, as path:reason. dependencies_missing is true for a pin made before fonts travelled: it holds the published version but none of its files, update_available is true too, and pin set --version <pinned_version> copies the fonts without changing the tokens. When you can no longer read the Library, library_available is false and nothing about it is reported. Apply a reviewed update with pin set --version <published_version> --if-pinned-library <library> --if-pinned-version <pinned_version>.

Comments

crewship page artifact comment <slug>

Add a comment anchored to an element of an exact version. The owner comments on the latest version; a comment on an older version returns 409 artifact_version_conflict. --quote must match the element’s text, or the server returns 409 artifact_anchor_mismatch. A comment has no idempotency key. If the reply is lost, run crewship page artifact comments <slug> before sending it again: a retry after a commit stores a second comment.
Queuing with --send-to-agent does not confirm that an agent received the task. --wait does what the viewer does after you send a comment to the agent. It posts the task message into the chat the artifact was created from, confirms that the chat saved it, then reads the comment every two seconds. Progress goes to stderr. When the comment becomes answered or needs_clarification, the command prints the comment with its replies. Run it as a person: an agent run cannot dispatch artifact tasks.
The comment is saved and queued before the wait starts, so a failure later on leaves it queued:
  • The artifact has no source chat: exit code 2. It was not created from an agent chat.
  • The task message could not be delivered, for example because the agent is busy: the command prints a crewship run … --artifact-target command that retries the delivery.
  • The timeout passes first: the command says so and exits non-zero. Read the result later with crewship page artifact comments.

crewship page artifact comments <slug>

Read comments with the artifact snapshot. The output has the same shape as get, with the comments of the selected version in comments.

crewship page artifact reply <slug> <comment-id>

Answer a comment. A normal reply describes a change, so --version must be a version newer than the comment’s version. With --needs-clarification you ask the author to select the element again, and --version may be the comment’s own version. Any other combination returns 404.

Dashboard data

Requires artifact_dashboard_data as well as artifact_projects. A version declares its collections in a dashboard.json file in the manifest, with the media type application/json and the content {"schema_version":1,"collections":["sales"]}. The examples below use an artifact created from this manifest:
Data is versioned per document, separately from code versions. Writing data does not create a code version, and restoring code does not rewind data. Every read names an exact code version, and only collections declared by that version are reachable. The owner and Edit-share holders read and write at the latest version; a batch whose base_version is not the latest version returns 409 and writes nothing. Shared readers (Read or Comment) can read the collections of the shared version and cannot write (403). Limits: 256 KiB per document, 50 writes and 1 MiB per batch, 4096 documents and 8 MiB per collection, 32 collections per artifact. Collection and document IDs are 1–128 ASCII letters, digits, _ or -, starting with a letter or digit. Values are JSON objects.

crewship page artifact data batch <slug> <collection>

Apply up to 50 document writes atomically. ifVersion: 0 creates a document; an update gives the document’s current version. base_version is the current code version.
Sending the same batch again returns 409 artifact_data_conflict and nothing is written. A document over 256 KiB is refused by the CLI before sending (artifact dataset quota exceeded); the server returns 413 artifact_data_quota for the same request.

crewship page artifact data get <slug> <collection>

Read every document of one collection at an exact code version.
The output has the same shape as batch. A collection that the version does not declare returns 404.

crewship page artifact data collections <slug>

List the declared collections that already hold documents, with their size. A declared collection with no documents is not listed.

Slides

Requires artifact_slides as well as artifact_projects. A deck is an ordinary artifact version that follows a closed Slides profile. Content outside the profile returns 422 artifact_slides_unsupported. Both commands need an exact --version (at most 9007199254740991); owners can read any retained version, Edit grants the latest version, and readers only the shared version. This manifest creates a two-slide deck with every supported element:
The profile rules:
  • The manifest holds exactly deck.json (application/json) and one slides/<id>.html file (text/html) for each ID in order, and no other files. deck.json has only schema_version: 1 and order (1–100 slide IDs).
  • A slide file is a single <section id="<id>"> whose ID matches its file name. Its children are p, div, table and at most one aside, with no further nesting; headings, images, span and other tags are rejected.
  • Every element has a unique id (a letter, then up to 63 letters, digits, _ or -) and a style attribute with exactly the properties below; any other attribute or property, including position, is rejected.
Sizes are whole pixels (80px), colors are six-digit hex (#112233), text-align is left, center or right, font-size is 1–160 pixels and border-width 0–16 pixels. font-family is optional on text and tables and accepts only Go Regular or sans-serif. The canvas is 1920 × 1080.

Rich profile (optional)

A deck may also use the additions below. A deck that uses any of them is returned with schema_version: 3; a deck that uses none keeps the schema_version: 1 projection byte for byte. Each addition has a fixed syntax and anything else is refused with 422 artifact_slides_unsupported. Icon names: arrow-down, arrow-left, arrow-right, arrow-up, bell, bot, briefcase, building, calendar, chart-column, chart-line, chart-pie, check, circle-check, clock, cloud, code, database, download, file-text, flag, folder, globe, heart, house, info, layers, lightbulb, link, lock, mail, map-pin, message-circle, message-square, phone, play, presentation, rocket, search, send, settings, shield, sparkles, star, target, terminal, trending-up, triangle-alert, upload, user, users, x, zap. They are Lucide icons (ISC) bundled with Crewship; a deck can name one but never supply SVG. In the projection these become font_weight, letter_spacing (pixels) and line_height (percent of the font size, so 1.05 is 105) on text; corner_radius, gradient ({"angle", "stops": [{"color", "position"}]}) and, for kind: "line", line ({"x1", "y1", "x2", "y2", "start", "end"}) on shape; an element of type: "icon" with icon: {"name", "color"}; and transition on the slide. Each is omitted when it holds its default.

crewship page artifact slides <slug-or-id>

Read the projected deck and the anchors that comments can use. Use @<id> to select by Page ID. The example output below is abridged: it omits the intro shape, the summary slide and the summary table anchor.

crewship page artifact export-pdf <slug-or-id>

Export the deck of an exact version to a local PDF file. The file is written atomically and the command prints a receipt, not PDF bytes. --out - is rejected.
The CLI checks the media type, the %PDF- header and an 8 MiB limit before writing.

Archive

crewship page artifact archive <page>

Remove an artifact from default lists without deleting content or changing access. page artifact archive and page artifact unarchive are the same commands as page archive and page unarchive. Run a dry run first, then confirm with the returned token.
The confirmation returns "changed": true and the new pages_version. Reusing the token afterwards returns 409 pages_version changed; preview again.

crewship page artifact unarchive <page>

Return an archived artifact to default lists. Flags and flow are the same as for archive.

Agent guides per kind

Each artifact kind ships a versioned guide that agents follow when they work on an artifact of that kind: the exact data shapes and size limits, the write order (on create the index first; on revise the data first and the index last), the read-before-write version check, the conflict rule (stop after the third refusal and report), the agent modes (Ask, Comment, Propose, Edit; only the Owner delegates Edit, and a comment is never a proposal) and when not to verify. The guides are built into the server; they describe supported product paths and required policy and grant nothing.

crewship artifacts kind-guide [kind]

Without a kind, list the guides with their version, shared-rules version and SHA-256 digest. With a kind (docs, slides, design, library, dashboard, app; design-system and project are accepted as aliases), print that guide. Word and Sheet are Craft documents and have no artifact guide (404).
The digest is over content, so a changed guide is visible even when only the shared rules moved. Agents get the same text. When a chat message carries an artifact as context, the server-built Page context block ends with a line such as Kind: docs; agent guide 1.2.0 (artifact_kind_guide), and the agent reads the guide with the artifact_kind_guide tool of its sidecar. The kind comes from the version the sender may read; Word, Sheet, panel and board Pages carry no Kind line. Each guide also declares modes (the agent modes the kind has a path for: ask, comment, propose, edit) and capabilities with supported and unsupported names. A client hides an unsupported feature instead of imitating it; neither list grants access. Docs declare Propose for schema 4–6 Documents (propose.schema4, propose.schema5, propose.schema6 supported, propose.schema1 to propose.schema3 unsupported), Design has no proposal path (propose is unsupported), and an App’s scripts reach only data.get, data.list, data.batch and viewer: user profiles, presence, model calls, connectors, uploads, downloads, in-page comments and publishing are declared unsupported. On a Dashboard, a data write counts as Edit, not Propose: it changes what readers see at once, so it needs the Owner’s authorization for that run. A code change is a Propose: a new retained version that does not move the shared version.

Agent publishing policy

The workspace artifact policy is the administrative ceiling for agent work on artifacts: an agent can create or change an artifact on a person’s behalf only when the policy is enabled and the agent’s crew is on the allowlist. --enabled=true with an empty allowlist admits no crew. The policy does not limit what people do themselves.

crewship workspace artifact-policy show

version: 0 means no policy has been saved yet. A non-admin receives 403 active trusted workspace administrator required.

crewship workspace artifact-policy set

Replace the whole policy. Pass the version from show as --base-version. Use exactly one of --crew-id and --clear-crews.
A stale --base-version returns 409 stale_policy; a crew from another workspace or a deleted crew returns 400. Each change is recorded in the workspace audit log. See also Workspace Commands.

Inside an agent run

When CREWSHIP_AGENT_TOKEN holds a run capability (agtv2.…), the artifact commands do not use a saved profile. They call the run’s scoped MCP tools instead, on behalf of the person who authorized the run: share, comment and availability are not available to an agent and fail with artifact or Design operation unavailable to an agent run. archive and unarchive do not use the run capability: they send the saved profile’s request with the normal CLI credentials, and the server refuses an agent or run caller with 403. In this mode the --server, --profile, --workspace and --server-allow-mismatch flags are rejected, and a token that is not a run capability fails with original live run capability required; no human profile fallback. A refused tool call prints artifact tool refused: {…}. If the outcome is unknown, the CLI prints artifact outcome unavailable; preserve candidate and inspect before retrying: keep your manifest and read the artifact before saving again. These tools also need the agent publishing policy to be enabled with the agent’s crew on the allowlist.