Preview local HTML reports, Markdown docs, and static mini apps, then publish them to shareable Cloudflare Pages URLs — from the terminal or your coding agent.
> /plugin marketplace add Amal-David/pagecast> /plugin install pagecast@pagecast
Repo: Amal-David/pagecast
What's inside
Preview local HTML reports, Markdown docs, and static mini apps, then publish them to shareable Cloudflare Pages URLs — from the terminal or your coding agent.
Site: https://pagecasthq.pages.dev/ ·
Agent skill: publish-report on Skills.sh ·
Architecture: ARCHITECTURE.md
Pagecast is a local-first publishing tool for agent-generated reports and small
static web projects: preview files, publish, re-sync, rename links,
password-protect pages, and revoke URLs — from a local admin UI or headless
pagecast commands. Good fits: HTML reports and dashboards, Markdown docs and
plans, static mini apps from dist/build/out. Not a fit: server-rendered
apps that need a running backend (export static assets first).
Requires Node.js 20.19+ and a Cloudflare account (for publishing). No global install:
npx pagecast
This starts the local app and opens the admin UI:
http://pagecast.localhost:4173http://pagecast.localhost:4174~/.pagecast/home/ (Cloudflare target, publication registry, settings).pagecast/ in the current directoryOne OS user profile owns one Pagecast Home and Cloudflare subdomain. Run the CLI
from the relevant project; use --data-dir only for an intentionally isolated
CI/container profile. If the default ports are busy, Pagecast falls forward to
the next free pair and remembers it.
In the admin UI, confirm the suggested Home subdomain and click Connect
Cloudflare — Pagecast runs Wrangler's scoped browser OAuth flow (Cloudflare
labels the app Wrangler) and resumes setup after consent. From a source
checkout, run npm start instead. Prefer containers? See
Run with Docker.
Run in the background, or (macOS) install a login service plus a local-only
http://pagecast.localhost redirect:
npx pagecast background start && npx pagecast open
npx pagecast setup-local-url
# manage: pagecast local-url status|remove, pagecast background service status|uninstall
Headless/advanced setup:
npx pagecast pages setup --project your-pagecast-home
# multiple accounts? add --account <account-id>
# automation? export CLOUDFLARE_API_TOKEN (scoped Pages:Edit) + CLOUDFLARE_ACCOUNT_ID
Upgrading from 0.5: stop the old process (npx pagecast@0.5.0 background stop),
reinstall the macOS login service if you use it (npx pagecast@0.7.0 background service install), and reload the unpacked Chrome extension from the matching
release. The first 0.6 launch creates ~/.pagecast/home/ and imports compatible
workspace publications without changing URLs; publications on other Cloudflare
projects remain legacy targets until you explicitly attach or move them.
# An HTML or Markdown file → a memorable /p/<slug>/ link (source folder included)
npx pagecast publish "/absolute/path/report.html" --json
# Set an expiry — 7d, 12h, or never (default 30d)
npx pagecast publish "/absolute/path/report.html" --expires 7d --json
# Force a new URL, or explicitly update a known one
npx pagecast publish "/absolute/path/report.html" --new-link --json
npx pagecast publish "/absolute/path/report.html" --update <url-or-token> --json
# A built static project → publish its entry file
npm run build && npx pagecast publish ./dist/index.html --json
# A whole folder → replace a named Pages project directly (--branch defaults to main)
npx pagecast pages deploy ./dist --project my-static-site --json
Things to know:
publish copies every non-hidden, non-symlink file under the source folder,
referenced or not — publish from a clean folder and keep secrets elsewhere.--context-id,
PAGECAST_CONTEXT_ID, CODEX_THREAD_ID, CLAUDE_SESSION_ID, then a
workspace/source fallback; override matching with --new-link or --update.pages deploy is a separate, stateless whole-site operation on the named
project. It never changes the project used for managed /p/... links —
use a separate project unless replacing the managed site is intentional.statusCode 401 → authentication required (interactive runs start Wrangler
auth automatically); statusCode 409 → conflict, follow the returned message.Optional, enabled in Settings: Pagecast deploys a Worker + D1 database to your Cloudflare account and shows views, anonymous uniques, and recent events beside each link, plus a global Activity view. Events carry coarse geo, device class, and referrer hostname; raw IPs are HMACed with a per-Home secret and discarded, and detailed events expire after 30 days. Analytics is audit visibility, not access control — use password protection to restrict access.
Gate any published page from the admin UI (Password protection toggle) or headlessly:
npx pagecast publish "/absolute/path/report.html" --password "your-password" --json
npx pagecast publish "/absolute/path/report.html" --no-password --json # remove it
Enforced at the edge by a generated Cloudflare Pages Function covering every file of a multi-file report. Older immutable deployments keep the gate state they shipped with — prune deploy history if an unprotected snapshot must stop being reachable. Crypto and security model: PASSWORD-PROTECTION.md.
Every publish or re-sync creates an immutable whole-site Cloudflare deployment
with its own <hash>.pages.dev URL. Manage them from the admin UI
(Settings → Deploy history) or the terminal:
npx pagecast pages deployments list --json
npx pagecast pages deployments delete <id> --json # the live deployment is protected
npx pagecast pages deployments prune --keep 5 --yes --json
Removing a snapshot never affects your live site or pages. But expiry, password changes, and revoke apply only to the replacement deployment — prune history when old snapshot URLs must stop working.
Pagecast ships a Codex-native skill and a portable Agent-Skills file. An explicit "Publish this as a Pagecast" instruction publishes immediately; a proactive agent suggestion still asks once.
# Skills.sh (Codex, Claude Code, Cursor, Gemini CLI, and other supported agents)
npx skills add https://github.com/amal-david/pagecast --skill publish-report
# Claude Code plugin (includes the report-detection hook)
/plugin marketplace add Amal-David/pagecast
/plugin install pagecast@pagecast
# Manual install from a clone
cp -R .codex/skills/publish-report ~/.codex/skills/ # Codex
cp plugin/skills/publish-report/SKILL.md /path/to/your-agent/skills/publish-report/SKILL.md # any agent
More detail in plugin/README.md.
Pagecast can run as a Model Context Protocol server, so MCP-capable agents can publish, inspect, and revoke through a bounded tool surface. Configure the stdio server:
{
"mcpServers": {
"pagecast": {
"command": "npx",
"args": ["pagecast", "mcp"]
}
}
}
It shares the same user-level Home, Cloudflare credentials, expiry, and
password behavior as npx pagecast publish; add "--data-dir" only for an
intentionally isolated MCP profile.
| Tool | Purpose | Safety notes |
|---|---|---|
status | Show Cloudflare/Pagecast connection state. | Redacted by default; verbose: true only for trusted local clients. |
list_pages | List known reports and published links. | Redacted by default; verbose: true reveals local paths/build settings. |
publish_content | Publish supplied HTML or Markdown content. | Supports mode: upsert|new|update, contextId, publication; deterministic upserts need itemKey. |
publish_file | Publish a local .html/.htm/.md/.markdown file. | Isolates the entry file; sibling assets require includeAssets: true and confirmAssets: true. |
revoke_publication | Take a published token offline and redeploy. | Requires confirm: true because it changes a live URL. |
The MCP server is separate from the admin API, which stays loopback-only — do not expose the admin port to a VPN or shared network. This release supports local stdio MCP only; an org-hosted HTTP endpoint would need its own auth, audit, and threat model, and a VPN would gate who can invoke Pagecast, not who can reach the published URL. Use password protection or your organization's access layer for restricted recipients.
A single image bundles the whole pagecast CLI — it serves the admin dashboard
and runs every publish/deploy command.
# Serve the dashboard (then open http://localhost:4173)
docker compose up --build
# Or run the released image from GHCR
docker pull ghcr.io/amal-david/pagecast:latest
docker run --rm \
-p 127.0.0.1:4173:4173 -p 127.0.0.1:4174:4174 \
-v "$PWD/.pagecast:/app/.pagecast" \
ghcr.io/amal-david/pagecast:latest serve
Publishing from a container uses an API token, not the dashboard's OAuth
button. Copy .env.example to .env with CLOUDFLARE_API_TOKEN
(+ CLOUDFLARE_ACCOUNT_ID), or run headlessly:
docker run --rm -v "$PWD:/work" -w /work \
-e CLOUDFLARE_API_TOKEN -e CLOUDFLARE_ACCOUNT_ID \
ghcr.io/amal-david/pagecast:latest publish ./report.html --json
Notes:
-p 127.0.0.1:4173:4173, never bare -p mappings).node); mkdir -p .pagecast before
compose up (or chown 1000:1000 .pagecast) avoids bind-mount permission
errors.src/platform.js) and baked into the image, so
deploys don't contact npm at runtime.⚠️ Experimental — load-unpacked only, not yet on the Chrome Web Store.
When an agent opens an HTML file as file:///…/report.html, the bundled
extension adds a one-click Publish to Pagecast button (the server must be
running). Load extension/ from a source checkout — or the
pagecast-extension-v<version>.zip from the matching release —
via chrome://extensions → Developer mode → Load unpacked, then enable
"Allow access to file URLs". See extension/README.md.
.html/.md files by path or file:///… URL, deployable static folders,
or source folders with a build command and output directory./p/<slug>/ links; revoked links 404
after the replacement deploy. Older immutable deployment URLs retain their
snapshot until pruned.Pagecast can collect anonymous usage stats — command name, Pagecast/Node version, OS/arch — never file contents, paths, URLs, or Cloudflare tokens/account IDs. Fresh interactive installs are opt-out with a one-time disclosure; telemetry is automatically off in CI. Exact fields: PRIVACY.md.
npx pagecast telemetry status|disable|enable
# env overrides: PAGECAST_TELEMETRY=0|1, DO_NOT_TRACK=1 (always wins)
npm start # run the packaged app from source
npm run check && npm test # verification suite
npm run build # rebuild the React admin UI (web/) into public/
UI work requires pnpm 10: pnpm -C web install --frozen-lockfile --ignore-scripts,
then pnpm -C web run dev (proxied to the server on 4173). The root CLI/server
has no runtime npm dependencies. Layout: src/ (CLI, server, publisher),
public/ (built UI), web/ (React source), plugin/ + .codex/skills/
(agent skills), test/ (Node tests). Source-folder build commands run through
the platform's native shell (sh -lc / %ComSpec%) — author portable commands.
Issues and pull requests are welcome. Fork and branch from main, keep the root
CLI/server free of runtime npm dependencies, run npm run check && npm test
before opening a PR, and rebuild the admin UI (npm run build) if you touched
web/. Please don't file public issues for security problems — report them
privately via SECURITY.md.
MIT — see LICENSE.
.claude-plugin/
marketplace.json
.codex/
skills/
publish-report/
agents/
openai.yaml
SKILL.md
.dockerignore
.env.example
.gitattributes
.github/
workflows/
ci.yml
release.yml
.gitignore
ARCHITECTURE.md
assets/
og-fonts/
fraunces-600.ttf
inter-400.ttf
OFL-Fraunces.txt
OFL-Inter.txt
CHANGELOG.md
docker-compose.yml
Dockerfile
extension/
background.js
discovery.js
errors.js
expiry.js
icons/
icon128.png
icon16.png
icon32.png
icon48.png
manifest.json
popup.css
popup.html
popup.js
README.md
store/
listing.md
PRIVACY.md
promo/
marquee-1400x560.png
small-tile-440x280.png
screenshots/
01-one-click.png
02-click-publish.png
03-right-click.png
SUBMIT.md
feedback/
schema.sql
worker.js
LICENSE
llms.txt
media/
admin.png
screenshots/
deploy-history.png
og-card-example-long.png
og-card-example.png
package-lock.json
package.json
PASSWORD-PROTECTION.md
plugin/
.claude-plugin/
plugin.json
hooks/
detect-artifacts-on-stop.mjs
detect-report.mjs
hooks.json
lib-offered.mjs
lib-path-token.mjs
README.md
skills/
publish-report/
SKILL.md
PRIVACY.md
public/
assets/
code-mirror-html-BiQZnmUQ.js
dnd-vendor-Br0jK2Mq.js
index-DFCQP-5i.js
index-DtWv1oN0.css
inter-latin-400-normal-C38fXH4l.woff2
inter-latin-400-normal-CyCys3Eg.woff
inter-latin-500-normal-BL9OpVg8.woff
inter-latin-500-normal-Cerq10X2.woff2
inter-latin-600-normal-CiBQ2DWP.woff
inter-latin-600-normal-LgqL8muc.woff2
inter-latin-700-normal-BLAVimhd.woff
inter-latin-700-normal-Yt3aPRUw.woff2
motion-vendor-CVkjz7oo.js
index.html
README.md
SECURITY.md
skills-lock.json
src/
admin-security.js
app-error.js
cli.js
crypto.js
index.js
link-policy.js
local-system.js
markdown.js
mcp.js
nameGenerator.js
og-card.js
pagecast-home.js
path-token.js
platform.js
project-ref.js
publication-context.js
publication-service.js
server.js
state-coordinator.js
telemetry.js
tunnel.js
wrangler-gateway.js
telemetry/
README.md
worker.js
wrangler.toml
test/
admin-security.test.js
analytics-ui.test.js
cli-runtime.test.js
client-security.test.js
crypto.test.js
csrf-client.test.js
expiry.test.js
extension-discovery.test.js
extension-errors.test.js
extension-expiry.test.js
feedback.test.js
link-kind-dto.test.js
link-policy.test.js
local-system.test.js
mcp.test.js
module-boundaries.test.js
name-generator.test.js
og-card.test.js
onboarding-ui.test.js
operation-journal-ui.test.js
pagecast-home.test.js
password-protection.test.js
platform.test.js
plugin-hooks.test.js
product-state-contract.test.js
project-ref.test.js
project-target-adoption.test.js
project-targets-main.test.js
project-targets.test.js
public-api.test.js
public-token.test.js
publication-context.test.js
publication-service-boundary.test.js
release-contract.test.js
security-boundary.test.js
security-main.test.js
server.test.js
skill-agent-first.test.js
social-meta.test.js
state-coordinator.test.js
state-failure-proofs.test.js
state-recovery.test.js
telemetry.test.js
vite-proxy.test.js
wrangler-gateway.test.js
web/
.npmrc
components.json
index.html
package.json
pnpm-lock.yaml
postcss.config.js
src/
App.tsx
components/
activity-panel.tsx
add-report.tsx
cloudflare-connect.tsx
default-expiry-card.tsx
deploy-history.tsx
editor/
code-mirror-html.tsx
editor-sheet.tsx
feedback-card.tsx
feedback-stats.tsx
operation-journal.tsx
pagecast-home-onboarding.tsx
preview-dialog.tsx
publication-row.tsx
ui/
alert-dialog.tsx
badge.tsx
button.tsx
card.tsx
dialog.tsx
dropdown-menu.tsx
input.tsx
label.tsx
select.tsx
separator.tsx
sheet.tsx
sonner.tsx
switch.tsx
tooltip.tsx
hooks/
use-cloudflare.ts
use-pagecast.ts
index.css
lib/
activity.ts
api.ts
cloudflare.ts
csrf-recovery.d.ts
csrf-recovery.js
format.ts
types.ts
utils.ts
main.tsx
tailwind.config.js
tsconfig.json
vite-proxy.js
vite.config.tsFAQ
pagecast is a Claude Code plugin with 1 hand-picked skill for deployment work, indexed on Flowy. Install it with the command on its page. It includes publish-report. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.