# Sites Hosting

> Host websites with Sites. Always use after `sites-building`, and use for website publishing, deployment, hosting management, or projects containing `.openai/hosting.json`.

- Skill: `steffencarlsen/sites-hosting` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add steffencarlsen/sites-hosting`
- Raw SKILL.md: https://api.skillmd.com/api/skills/steffencarlsen/sites-hosting/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: SteffenCarlsen (https://skillmd.com/u/steffencarlsen)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/steffencarlsen/sites-hosting

---


# Sites hosting

Publish the exact validated source with the shortest safe sequence. Treat the Sites connector descriptions as the source of truth for arguments and archive requirements.

## Site lifecycle ownership

Only the Site-owning agent responsible for the user's requested Site may run `sites-hosting`, call `create_site` or any other Sites tool, edit the Site checkout or `.openai/hosting.json`, obtain source credentials, commit or push, save a version, deploy, or perform the final browser handoff. A spawned subagent must return its assigned image, asset, or research result without invoking this skill or any Sites tool. An independently started background or invisible task that owns the requested Site remains its Site-owning agent.

## Communicate clearly

Assume the user is a nontechnical knowledge worker. Keep source control, credentials, IDs, commits, branches, archives, versions, packaging, connector calls, and deployment polling out of user-facing messages. Usually send one update when publishing begins, then the final URL or a plain-language blocker.
For example: `Your site is ready. I’m publishing it privately now.`

## Rules

- Publish after a successful build unless the user requested local-only work.
- Publishing does not require additional browser testing or visual QA. Preserve the existing Site tab as its single user-facing view; a failed browser handoff does not block publishing.
- Treat `public/screenshot.jpeg` as an optional deployment thumbnail. Preserve an existing file. Create or refresh it only when the user explicitly requests a Sites deployment thumbnail; a generic screenshot request does not count. Missing or failed capture never blocks validation, version saving, or deployment.
- Store only `project_id`, optional logical `d1` and `r2` bindings, and requested supported `capabilities` in `.openai/hosting.json`. Manage runtime values through Sites.

## OpenAI API keys

When a site needs `OPENAI_API_KEY`, use the ["OpenAI Developers"](plugin://openai-developers@openai-curated-remote) plugin's `openai-platform-api-key` skill to create or reuse a key with the user's approval, then configure it as a site secret before deployment. If the skill is unavailable, ask the user to install or enable the plugin.

## Fast publish sequence

1. Reuse the successful build from `sites-building` when the source has not changed. Rebuild only when needed.
2. Call `create_site` once for a new site. Persist its `project_id` in `.openai/hosting.json` and reuse the source write credential returned by that call. Reuse these values instead of rediscovering them. Retry only when the error explicitly identifies a temporary failure or slug conflict. Treat quota, permission, and access errors as terminal; do not change the slug speculatively.
3. Use a Git repository rooted at the selected Site project, initializing one there if needed; do not commit or push an unrelated parent repository. Commit the exact validated source. Push it with the returned credential as a per-command HTTP authorization header. Keep the credential out of remote URLs and Git configuration. Use the pushed branch-head SHA as `commit_sha`.
4. Package with this plugin's root-level `scripts/package-site.sh` helper, passing the project directory and archive path. It stages `dist/`, hosting metadata, and migrations; validates required files; and creates the archive.
5. Save one version with the connector using that `commit_sha` and archive.
6. Choose deployment from the site's current access, not tool availability. A site created in this flow remains owner-only until its access changes, so use `deploy_private_site_version` for that case. For an existing site, call `get_site` before deployment and use `deploy_private_site_version` only when `current_user_role` is `owner` and `access_policy` verifies `access_mode: "custom"`, exactly one `allowed_account_user_ids` entry, zero `external_visitor_count`, and no workspace or tenant group IDs. Treat missing or ambiguous access as not verifiably owner-only. For a shared, public, or not verifiably owner-only site, call `request_user_input` with an approval choice that names the resolved access level, such as `Publish publicly` or `Publish to existing shared access`, plus `Not now`; wait for the response, and call `deploy_site_version` only after approval. If a private deployment returns `site_not_owner_only`, do not retry it; follow this approval path.
7. Poll `get_deployment_status` directly until deployment succeeds or fails. Use discovery calls only when an error requires them.

## Existing sites and advanced capabilities

- Reuse an existing `project_id` and valid source credential when available.
- If a credential is absent or expired, obtain one with `create_source_repository_write_credential` and reuse it until expiry.
- If the D1 schema changed, ensure generated migrations are present before packaging.
- Require `dist/server/index.js`, static assets when emitted, `dist/.openai/hosting.json`, and `dist/.openai/drizzle/**` when migrations exist.
- For non-vinext projects, use the established Cloudflare Workers-compatible build output and adapt staging only as required by the connector contract.

## Handoff

After `get_deployment_status` reports `status: "succeeded"`, use `open_in_codex` to show the exact deployed URL in the existing Site tab using the stable browser-tab ID established for its first preview.
If no Site tab exists, open one with a stable browser-tab ID.
Reuse that same tab after subsequent fixes and redeployments so the user finishes with one working view of the deployed Site.

Then return the deployed Sites URL and a concise description of what the user can do. If the deployment is unsuccessful, do not call `open_in_codex`; explain the user-visible reason and next step. Keep source credentials and temporary archives private. Do not include file paths, commands, build details, IDs, commits, or version information unless the user asks.

