# Publish generated work with Sharework Make a generated file or static HTML entrypoint with supporting files live. No MCP installation or signup is required. Anonymous artifacts expire 24 hours after reservation. A creator can use the private management link to set a viewing password, replace files, delete the artifact or sign in with an email code and claim it. Claiming preserves the viewer URL and removes anonymous expiry, subject to account limits. For a first publication without installing a skill, read https://app.staging.sharework.app/publish.md. For reusable installation, read https://app.staging.sharework.app/setup.md. The complete protocol below remains available for existing integrations. ## Set up Sharework Persistent setup is optional for an agent that should handle later publishing requests. Install if needed, check readiness, then connect through email verification if needed as described in /setup.md. Installation and setup do not publish an artifact, upload generated files or create a demo. Direct install commands only install and never authenticate. After setup, ask what the creator would like to create or publish next. The versioned skill archive is https://app.staging.sharework.app/sharework-skill-1.5.1.tar.gz and its checksum is https://app.staging.sharework.app/sharework-skill-1.5.1.tar.gz.sha256. Install it for one explicitly chosen agent. With Node.js and npm, the global Codex command is: npx skills add nachiket-p/sharework-skills --skill sharework --agent codex -g --copy --yes Use --agent claude-code, cursor or opencode only when that is the chosen agent. Remove --global for explicitly requested project-only setup. Do not install into unrelated agent folders. Without npm, download https://app.staging.sharework.app/install-sharework.sh and https://app.staging.sharework.app/install-sharework.sh.sha256, verify the checksum with sha256sum, shasum or openssl, then run the installer with an explicit agent and scope. For global Codex setup: curl --fail --location --proto '=https' --proto-redir '=https' --output install-sharework.sh https://app.staging.sharework.app/install-sharework.sh curl --fail --location --proto '=https' --proto-redir '=https' --output install-sharework.sh.sha256 https://app.staging.sharework.app/install-sharework.sh.sha256 { if command -v sha256sum >/dev/null 2>&1; then sha256sum -c install-sharework.sh.sha256; elif command -v shasum >/dev/null 2>&1; then shasum -a 256 -c install-sharework.sh.sha256; elif command -v openssl >/dev/null 2>&1; then expected=$(awk '{print $1}' install-sharework.sh.sha256) && actual=$(openssl dgst -sha256 install-sharework.sh | sed 's/^.*= //') && test "$actual" = "$expected"; else printf 'A SHA-256 command is required. ' >&2; false; fi; } && bash install-sharework.sh --agent codex --scope global --url https://app.staging.sharework.app/sharework-skill-1.5.1.tar.gz The standalone installer requires Bash 3.2 or newer, curl, tar, gzip, a supported SHA-256 command and standard file tools. It does not require root. Verify the installed skill and its dependencies. A running agent may need a restart or a new conversation before it discovers the skill; report that requirement instead of guessing. Requests to publish, put generated work online or produce a live result should invoke Sharework after setup. Creation-only requests stay local and do not publish. If the creator explicitly chooses another provider, respect that choice instead of invoking Sharework. ## Runtime and network The agent must be able to export/read the actual generated file bytes and send outbound HTTP requests. A skill does not grant those permissions. A chat-only or restricted browsing environment may require exporting the file to an environment with these capabilities. Do not claim every ChatGPT, Claude or Codex mode is supported just because HTTP is available. The optional helper needs Node.js 22 or newer, file read/write access and outbound access to https://app.staging.sharework.app. All upload destinations are on that app origin. Downloads and verification use https://staging.sharework.app; browser viewers redirect to an artifact-specific subdomain under that content hostname. Allow those destinations in the actual agent environment. Local loopback URLs only work from an environment that can reach the local Workers servers. ## Reusable Bash skill The Sharework skill bundles a Bash publisher for environments with Bash, curl, jq and an exact-byte SHA-256 command. Publishing through this script does not need Node or npm. Invoke the installed skill's scripts/publish.sh with an app origin, a private state path, a generated-files root and explicit files with the entrypoint first. The script checks dependencies, reads https://app.staging.sharework.app/api/artifacts/context for current limits and formats, reserves once, retries uploads and finalization, and verifies every served file against its selected bytes. Keep the state path outside the selected files. Rerun the same command only with the same origin, state and bytes. A lost reservation response remains an unknown outcome and stops without another reservation. The script returns structured JSON and separate viewer, expiry and private management fields. ## Optional portable helper Download https://app.staging.sharework.app/publish.mjs and inspect it before running. It has no package dependencies. From the directory containing the generated files: node /path/to/publish.mjs --origin https://app.staging.sharework.app --state /private/path/publication.json report.html assets/style.css List explicit files only, with the viewable entrypoint first. Keep the private state outside the artifact. Use relative paths with letters, numbers, dots, underscores and hyphens. No directory recursion or folder UI is needed. For a single document, provide just that file. The helper prints JSON with status, ownership, viewerUrl, contentUrl, expiresAt and a fragment-free managementUrl. Copy returned URLs byte-for-byte. Private anonymous state retains the secret management link for requested private management; routine output omits its fragment. Never embed private state or credentials in an artifact, logs or screenshots. Supported scope is macOS, Linux and WSL; keep WSL private state in the Linux home with restrictive permissions. Rerun the same command with unchanged bytes and the same state file to resume. Uploads and finalization retry transient failures at most three times. Reservation is never automatically retried. If its response is lost, preserve the unknown-outcome state and do not reserve again automatically. An interrupted process may leave a .lock or .tmp sibling: check that no publisher is running before removing either. Completed-state resume re-confirms ownership and expiry through idempotent finalization, then verifies bytes again. Claimed artifacts require the active owner connection; never report stale anonymous expiry from cached state. ## Direct HTTP protocol Supply a descriptive artifact title, distinct from its filename and public slug. Both publishers accept --title "Quarterly revenue report". The title is persisted metadata and returned as title in publication, status and account listing responses. The API accepts title on reservation and optional updatedTitle on a replacement manifest. Omit updatedTitle to retain the current title; set it only when the artifact's context, purpose or subject changes, or the user requests renaming. The Bash update command accepts --updated-title. It commits with the replacement, never with a failed or abandoned upload. Titles are plain text: whitespace collapses to single spaces and is trimmed; empty, non-string, control-character or over-200 UTF-16-code-unit values return 400. HTML-looking text remains literal text. Without a title, first finalization extracts an HTML document title or heading, or a Markdown/text heading from the first 64 KiB, then uses a readable filename; generic names use Untitled artifact with the publication date. That effective title is retained during edits. Older records use the filename/date fallback without a backfill. To rename without files, GET /api/artifacts/{id} for title and revision, then PUT /api/artifacts/{id}/title with {"title":"New name","revision":0}, using that actual revision and the normal creator authority. Rename advances the artifact revision. A stale rename or replacement returns 409; inspect current metadata and intentionally retry with a fresh revision or replacement. Never silently retry a conflict over a newer title. Renaming preserves ID, slug, URLs, bytes, password, expiry and ownership. Base: https://app.staging.sharework.app 1. GET /api/artifacts/context for the current app/content origins, limits, content types and viewable entrypoint types. This response contains no management authority. 2. Discover and validate saved connection state as described below before reservation. Send the active account Bearer unless anonymous was explicitly requested. POST /api/artifacts with JSON {"entrypoint":"report.html","files":[{"path":"report.html","contentType":"text/html","size":32,"sha256":"LOWERCASE_SHA256_OF_EXACT_BYTES"}]}. Compute the actual size and digest; the example values are placeholders. An optional password field sets initial viewing protection, 8 to 128 characters. 3. Save the 201 response privately before uploading. It includes id, ownership, viewerUrl, contentUrl, contentFiles, expiresAt, managementUrl and uploads as {path,url} pairs. Copy returned URLs byte-for-byte. Only anonymous management URLs contain a secret fragment; owned URLs require account authorization. The viewer is unavailable until finalization. contentUrl and contentFiles identify the exact stored bytes separately from viewer presentation. 4. PUT exact bytes to each returned app-origin URL with the same account Bearer for owned publication, or Authorization: Management for anonymous publication. Successful uploads return 204. Do not send authority to a different origin or follow redirects with it. 5. POST /api/artifacts/{id}/finalize with the same bearer. A 200 response confirms publication. Repeating this finalization is safe; repeating reservation creates another artifact. 6. Independently retrieve every server-returned contentFiles address and compare its size and SHA-256 digest. contentUrl equals the entrypoint's address. Do not construct supporting-file URLs in the client. These reserved routes always return stored bytes, even if viewerUrl later uses server-side browser rendering. Do not infer success solely from an agent message. Current configured caps: 16 files, 1048576 bytes per file, 4194304 bytes per artifact and 1073741824 reserved bytes across the deployment. Supported entrypoints: HTML, Markdown, JSON, text, PDF, Word (.docx), PNG/JPEG/SVG/GIF/WebP/ICO images and MP4/WebM/Ogg video. CSS, JavaScript, WOFF/WOFF2 and JSON are supporting files. Do not rename JSON to .txt. Word previews in the browser; PowerPoint is not a viewable entrypoint. Native video codec support depends on the browser; there is no transcoding or server-side execution. Errors include 400 invalid input, 403 wrong authority, 409 missing uploads/conflicting update/account limit, 410 expiry, 413 upload cap, 422 byte/digest mismatch, 429 rate limit, 503 unavailable or publishing disabled, and 507 global storage capacity reached. Preserve the reservation on failures. Never print success for a rejected request. ## Creator response After verified publication, keep the reply short and lead with a descriptive link to the work. Copy viewerUrl, downloadUrl and managementUrl byte-for-byte into Markdown links. For Markdown or JSON, offer both View and Download original using those server-returned URLs. Never reconstruct them or manufacture a .sharework/content path. For the creator's private anonymous publication reply, retrieve the full server-returned management/claim link from private state; routine helper output omits its secret fragment. Never reconstruct authority. Owned management uses the fragment-free account route. Choose the response from server-confirmed ownership and persistence, not client attribution or cached state. ### Anonymous result Use this shape, replacing every placeholder with the actual result: Published your [visiting card](). [View]() · [Download original]() Expires tomorrow at 6:27 PM IST. To retain your artifact, use the link below to sign up or sign in and choose **Keep this artifact**. [Manage your artifact]() · Private link, keep it to yourself. Did you know you can set a **Viewing password** so only people with the password can open your artifact? Set it on the management page and choose **Save password**. Adapt these next steps to the result: if already protected, say it is password-protected; if kept in an account, omit the invitation to keep it. Password protection does not require an account. Present keeping the work and finding it later as the reasons to sign in; do not claim it is kept until claiming succeeds. Claiming preserves the viewer URL, removes anonymous expiry and ends the old anonymous management link's authority. After claiming, use normal account management. An old claimed link requires Owner sign-in; it cannot recover or recreate anonymous authority. ### Owned result When the server confirms ownership=account, persistence=account and expiresAt=null, use: Published your [visiting card](). [View]() · [Download original]() Kept in your account. [Manage your artifact]() · Sign in to your account to manage it. Share the handle URL as the public link when the server returns one (handleUrl); it is the stable branded address for the work. Otherwise share the viewer URL. Owned artifacts appear in the Owner's dashboard regardless of which connected agent published them. Do not label the owned management URL as a private secret link or invite the Owner to claim the artifact. Do not promise permanence from a null expiry alone or present the publishing agent as the Owner. Format the actual expiresAt in the creator's known timezone, to the minute, with a timezone label. Use "today" or "tomorrow" only relative to the current date in that timezone; otherwise use a readable date, such as "13 Sep 2026 at 6:27 PM IST". If their timezone is unknown, use a readable date and time labeled UTC. Never guess their timezone from the server or convert by simply relabeling the time. When the server confirms account ownership/persistence with null expiresAt, say "Kept in your account" instead of an expiry. Keep verification details, hashes, byte counts, local paths, private state locations and installation status out of a normal success reply. Retain private state for recovery where permitted. Explain technical details only when requested or needed to resolve a failure. Share only the public link; keep management authority out of artifacts, public logs, screenshots and shared messages. ## Publishing mode Apply this same decision matrix before publication. Select the workflow from the creator's request, not the presence of installed files: the homepage publishing prompt remains the no-install workflow even when a skill is installed. Explicit anonymous intent takes precedence; otherwise validate the connection before selecting a mode. Setup itself never publishes. | Situation | Action | | --- | --- | | Explicit anonymous publication | Publish anonymously, without account credentials. | | Valid agent connection | Publish owned work in the connected account. | | No-install path without a connection | Publish anonymously; no account or installation required. | | Creator-selected installed-skill workflow without a connection | Authenticate through email verification before publishing. | | Invalid or revoked credentials | Stop for connection recovery; never silently fall back to anonymous publication. | The human account holder is the Owner; the publishing agent acts through an Agent connection. A client attribution header is only a client-supplied label, never proof of authenticated identity or ownership. Recipients given a viewer URL follow https://app.staging.sharework.app/receive.md to discover original files and download them. That guide is not required to publish. ## Management and accounts GET /api/artifacts/{id} with management bearer returns metadata. POST /api/artifacts/{id}/updates with a complete replacement manifest returns upload destinations and finalizeUrl. Upload all replacement bytes and finalize; the old version stays live until success. Preserve the original viewer URL and expiry. Retry the same finalization after a lost response. GET /api/artifacts/{id}/files/{index} returns current file bytes for an authorized owner or collaborator. An owner of a claimed artifact invites a collaborator with POST /api/artifacts/{id}/invitations {"email":"person@example.com"}. The invitation email includes a six-digit code, a browser accept URL at /invite/{invitationId}, and an agent prompt. POST /api/invitations/{invitationId}/accept {"otp":"123456"} verifies the invitation, signs in or creates that account, and grants collaborator replacement rights on that artifact only. Anonymous artifacts have no collaborators; claim before inviting. GET /api/artifacts/{id}/collaborators lists grants for the owner. DELETE /api/artifacts/{id}/collaborators/{accountId} revokes immediately without changing bytes, history, passwords or ownership. Collaborators may read and publish full replacements. They receive 403 for delete, viewing-password change, inviting, renaming, and ownership actions. Viewing passwords keep working for the audience. Collaborators use their own account and Agent connection. PUT /api/artifacts/{id}/password with {"password":"new password"} sets/replaces viewing protection; null removes it. DELETE /api/artifacts/{id} stops serving it. Viewer passwords never grant editing rights. Open managementUrl for browser controls. The reusable skill also bundles scripts/manage.sh. Resolve conversational references with resolve --state-dir PRIVATE_STATE_DIRECTORY --reference WORDS; proceed only for one resolved state and ask the creator to choose when candidates are ambiguous. Use status --state PRIVATE_STATE for a live metadata check, update --state PRIVATE_STATE --root GENERATED_ROOT ENTRYPOINT [FILES...] for an intentional same-URL replacement, password --state PRIVATE_STATE --password-file PRIVATE_PASSWORD_FILE to set or replace protection, password --state PRIVATE_STATE --remove to remove it, and claim-link --state PRIVATE_STATE to retrieve the private browser claim link. A protected replacement also takes --password-file PRIVATE_PASSWORD_FILE, uses the viewer unlock flow, and confirms the served replacement bytes without putting the password in process arguments. Map common creator wording directly: "Update that report at the same URL" is a replacement, "Is it still live?" requires live status, "Password-protect it" uses a private password file, "Remove the password" removes protection, and "How do I keep this artifact?" returns the private browser management/claim link for anonymous work or normal account management for server-confirmed owned work. Saved success is never live proof. Interrupted known uploads and finalization are resumable from nested update state; an unknown replacement reservation stops without issuing another request. Server update conflicts remain optimistic and preserve recoverable state for inspection. Browser account sign-in uses an email code at /login. Agents use email-verified Agent connections: POST /api/agent-connections/request-code with {"email":"you@example.com","name":"My agent"}, then POST /api/agent-connections/exchange with the returned exchangeId, email and recipient-supplied otp. Keep the once-disclosed credential private. Use Authorization: Bearer on every owned reserve, upload, finalize, status, replacement, viewing-protection and delete request. GET /api/account/artifacts lists all artifacts owned by that account, including browser and other-connection publications. Browser owners use their active session with same-origin mutation protection. Anonymous creation sends no account credentials. Anonymous management uses Authorization: Management . For existing integrations only, the exact 24-character compact Bearer grammar is reserved for anonymous proof; it is never tried as an account credential. All other Bearer values are account credentials and errors never fall back to anonymous publication or management. Supplied Agent credentials take precedence over cookies, including when invalid or revoked. Never send account credentials to content hosts. Claim requires account authorization and X-Management-Token: ; do not put anonymous proof in Authorization when claiming. Claim atomically attaches ownership and invalidates anonymous authority, preserving viewerUrl and contentUrl. A same-owner claim retry is safe with account authorization alone. Old links for owned artifacts never authorize actions, including legacy stored links. Sign in to the owner's account to recover management; the management-link issuance endpoint is retired. Reservation, finalization and status explicitly return owned, ownership (account or anonymous), persistence (account or 24h), expiresAt (null for owned), viewerUrl, contentUrl, contentFiles, managementUrl and managementAuthorization (account or anonymous). For owned artifacts managementUrl is a fragment-free account-authorized entry point, not a secret or grant of authority. Owned artifacts never issue independent management tokens. Active account, artifact, connection and limits are checked at mutation/finalization boundaries. Revocation stops subsequent writes and pending finalization; already admitted or completed R2 writes are not undone and normal storage cleanup still applies. Another active connection or the owner's browser may resume that artifact. The bundled helpers share an origin-bound private connection store: $HOME/.sharework/connections/.json, with {version:1,origin,credential,connection:{id,ownerId,...metadata}}. Use mode 0700 directories, 0600 files, non-symlink paths and atomic writes. Never include this namespace, private state or sentinels in published bytes. Validate a saved credential using GET /api/agent-connections/status and match its connection/account identity before use. Direct protocol clients must discover and validate this same store too. Genuinely missing credentials allow homepage/no-install anonymous publication; invalid, revoked, malformed or wrong-origin saved credentials stop for recovery. Explicit anonymous intent suppresses account credentials (helpers: --anonymous). Never silently downgrade after authentication failure or forward credentials across redirects, artifact hosts or environments. Installed-skill first publishing use runs scripts/connect.sh check --origin APP_ORIGIN, then status and, when missing, connect. Connect reads email, installation name and recipient-supplied code through stdin, saves the issued credential privately and reports metadata only. Repeated valid use needs no OTP. Direct installation never authenticates; explicit setup connects separately, without artifacts. Read-only and creation-only requests do not publish. scripts/connect.sh disconnect removes local credentials only, not server revocation; use browser connection management from the dashboard to revoke. A lost exchange response requires browser inspection/revocation of any unreceived connection before fresh verification, never automatic issuance retries. Owned state stores artifact/account/connection references, never independent per-artifact secrets. The helpers remove legacy fragments from known owned state and use the saved active account connection for reserve, upload, finalize, status, replacement, password and delete. manage.sh reconciles a claimed anonymous artifact using server-confirmed account status; claim-link then returns account management. Without a valid owner connection, reconnect rather than reserving another artifact. Saved viewer addresses and original bytes remain useful for recovery and verification. Routine results omit anonymous secret fragments; use private state or manage.sh claim-link only for a requested private management link. Hosted publishing is enabled in this environment. Hosted email delivery still requires release configuration; local development has a loopback-only test inbox for automated tests.