pagecast 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,99 @@
1
+ # Pagecast — agent plugin
2
+
3
+ Lets your coding agent (Claude Code, Codex, or any Agent-Skills-compatible tool)
4
+ offer to publish a freshly created **HTML or Markdown** report, plan, or doc to a
5
+ shareable public URL.
6
+
7
+ How it works: a passive `PostToolUse` hook notices when an HTML/Markdown file is
8
+ written and hints the agent. The `publish-report` skill tells the agent to offer
9
+ (once, only for finished/shareable artifacts) *"Want me to publish this with
10
+ Pagecast?"* and, on an explicit **yes**, run the headless CLI:
11
+
12
+ ```sh
13
+ npx pagecast publish "/absolute/path/file.md" --json
14
+ # → {"ok":true,"url":"https://pagecast.pages.dev/p/<token>/", ...}
15
+ ```
16
+
17
+ ## Setup (one time)
18
+
19
+ ### 1. Install the agent integration
20
+
21
+ **Codex CLI / Codex desktop** — copy the Codex-native skill:
22
+
23
+ ```sh
24
+ mkdir -p ~/.codex/skills
25
+ # from a clone of the repo:
26
+ cp -R .codex/skills/publish-report ~/.codex/skills/
27
+ ```
28
+
29
+ Start a new Codex session so the skill is discovered. Then you can ask:
30
+
31
+ ```text
32
+ Use $publish-report to publish /absolute/path/report.md with Pagecast.
33
+ ```
34
+
35
+ **Claude Code** — add the marketplace from the public repo, then install:
36
+
37
+ ```sh
38
+ /plugin marketplace add Amal-David/pagecast
39
+ /plugin install pagecast@pagecast
40
+ ```
41
+
42
+ This wires up both the `publish-report` skill and the report-detection hook.
43
+
44
+ **Other Agent-Skills tools** — copy the portable skill:
45
+
46
+ ```sh
47
+ # from a clone of the repo:
48
+ cp plugin/skills/publish-report/SKILL.md /path/to/your-agent/skills/publish-report/SKILL.md
49
+ ```
50
+
51
+ The portable `SKILL.md` is the Agent-Skills format. The detection hook is
52
+ Claude-Code-specific; elsewhere the skill still triggers when a report is created
53
+ or when you ask to publish one.
54
+
55
+ ### 2. Connect Cloudflare
56
+
57
+ ```sh
58
+ npx pagecast
59
+ ```
60
+
61
+ Click **Connect Cloudflare** in the panel. Or sign in directly:
62
+
63
+ ```sh
64
+ npx pagecast pages setup --project pagecast
65
+ ```
66
+
67
+ That's the whole setup. **After this, publishing is headless** — when your agent
68
+ makes a report and you say "yes", it publishes with no further prompts.
69
+
70
+ ## What to expect
71
+
72
+ Once installed and connected: when your agent writes a report, plan, dashboard, or
73
+ other shareable HTML/Markdown, it offers *"Want me to publish this with Pagecast?"*
74
+ Say **yes** and you get back a public `pagecast.pages.dev` link you own. Say no and
75
+ it drops it — it won't nag. You can rename, re-sync, or revoke any link from
76
+ `npx pagecast`.
77
+
78
+ For static web projects that should get a new share link, build first and publish
79
+ the generated entry file, such as `dist/index.html`.
80
+
81
+ For whole-site Cloudflare Pages deploys, use Pagecast's Wrangler abstraction:
82
+
83
+ ```sh
84
+ npx pagecast pages deploy "/absolute/path/dist" --project pagecasthq --branch main --json
85
+ ```
86
+
87
+ If you omit `--branch`, Pagecast deploys to `main`:
88
+
89
+ ```sh
90
+ npx pagecast pages deploy "/absolute/path/dist" --project pagecasthq --json
91
+ ```
92
+
93
+ Direct site deploys replace the target Pages project contents. Use `npx pagecast`
94
+ for source-folder build settings, URL renaming, re-sync, and revoke controls.
95
+
96
+ ## Requirements
97
+
98
+ - Node.js >= 20 and `npx` (Wrangler is fetched via `npx` on first use).
99
+ - A Cloudflare account.
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env node
2
+ // Passive PostToolUse hook: when a Write/Edit/MultiEdit creates or updates an
3
+ // HTML or Markdown file (a report, plan, doc, or dashboard), inject a
4
+ // non-blocking hint so the agent can offer to publish it with Pagecast. This
5
+ // hook NEVER blocks and NEVER publishes anything — it only adds context, and the
6
+ // skill decides whether the file is actually worth offering. Any error exits 0
7
+ // silently so it can't disrupt the agent.
8
+
9
+ // Obvious non-artifacts the agent should not be nudged to publish. The skill
10
+ // applies the real judgment; this just keeps the common noise down.
11
+ const SKIP_BASENAMES = new Set([
12
+ "readme.md",
13
+ "readme.markdown",
14
+ "changelog.md",
15
+ "contributing.md",
16
+ "license.md",
17
+ "code_of_conduct.md",
18
+ "security.md",
19
+ "agents.md",
20
+ "claude.md",
21
+ "todo.md",
22
+ "tasks.md",
23
+ "notes.md"
24
+ ]);
25
+
26
+ function readStdin() {
27
+ return new Promise((resolve) => {
28
+ let data = "";
29
+ if (process.stdin.isTTY) {
30
+ resolve("");
31
+ return;
32
+ }
33
+ process.stdin.setEncoding("utf8");
34
+ process.stdin.on("data", (chunk) => {
35
+ data += chunk;
36
+ });
37
+ process.stdin.on("end", () => resolve(data));
38
+ process.stdin.on("error", () => resolve(""));
39
+ });
40
+ }
41
+
42
+ function reportPathFrom(toolInput) {
43
+ if (!toolInput || typeof toolInput !== "object") {
44
+ return null;
45
+ }
46
+ const candidate = toolInput.file_path || toolInput.path || toolInput.filePath;
47
+ if (typeof candidate !== "string") {
48
+ return null;
49
+ }
50
+ const lower = candidate.toLowerCase();
51
+ const isPublishable =
52
+ lower.endsWith(".html") ||
53
+ lower.endsWith(".htm") ||
54
+ lower.endsWith(".md") ||
55
+ lower.endsWith(".markdown");
56
+ if (!isPublishable) {
57
+ return null;
58
+ }
59
+
60
+ const base = candidate.split("/").pop() || "";
61
+ // Skip obvious non-artifacts: build/dependency dirs, hidden files, and common
62
+ // repo-meta files that nobody wants to publish.
63
+ if (
64
+ candidate.includes("/node_modules/") ||
65
+ candidate.includes("/dist/") ||
66
+ candidate.includes("/.git/") ||
67
+ base.startsWith(".") ||
68
+ SKIP_BASENAMES.has(base.toLowerCase())
69
+ ) {
70
+ return null;
71
+ }
72
+ return candidate;
73
+ }
74
+
75
+ async function main() {
76
+ try {
77
+ const raw = await readStdin();
78
+ if (!raw.trim()) {
79
+ process.exit(0);
80
+ }
81
+ const event = JSON.parse(raw);
82
+ const filePath = reportPathFrom(event.tool_input);
83
+ if (!filePath) {
84
+ process.exit(0);
85
+ }
86
+
87
+ const additionalContext =
88
+ `An HTML or Markdown file was just written at "${filePath}". ` +
89
+ `If it is a substantial, finished artifact worth sharing (a report, plan, doc, or dashboard) — ` +
90
+ `not a scratch/internal file — offer once: ask the user "Want me to publish this with Pagecast?" ` +
91
+ `and only on an explicit yes run \`npx pagecast publish "${filePath}" --json\` to get a shareable ` +
92
+ `public URL. Never publish without confirmation, and don't re-ask for this file.`;
93
+
94
+ process.stdout.write(
95
+ JSON.stringify({
96
+ hookSpecificOutput: {
97
+ hookEventName: "PostToolUse",
98
+ additionalContext
99
+ }
100
+ })
101
+ );
102
+ process.exit(0);
103
+ } catch {
104
+ // Never disrupt the agent loop.
105
+ process.exit(0);
106
+ }
107
+ }
108
+
109
+ main();
@@ -0,0 +1,16 @@
1
+ {
2
+ "hooks": {
3
+ "PostToolUse": [
4
+ {
5
+ "matcher": "Write|Edit|MultiEdit",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/detect-report.mjs",
10
+ "timeout": 10
11
+ }
12
+ ]
13
+ }
14
+ ]
15
+ }
16
+ }
@@ -0,0 +1,117 @@
1
+ ---
2
+ name: publish-report
3
+ description: Use when an HTML or Markdown report, plan, doc, dashboard, or built static web project has just been created (or the user wants to share one) and it is worth publishing as a public link. Offers to publish it with Pagecast, then returns the URL.
4
+ version: 0.2.0
5
+ ---
6
+
7
+ # Publish with Pagecast
8
+
9
+ Pagecast turns a local **HTML or Markdown** file (a report, plan, doc, or
10
+ dashboard) into a shareable public URL. Use this skill to offer that at the
11
+ right moment, then do it on a yes.
12
+
13
+ ## When to offer
14
+
15
+ Offer **once** when a substantial, finished, shareable artifact appears:
16
+
17
+ - An `.html`/`.htm` or `.md`/`.markdown` file was just generated that a person
18
+ would actually want to share — a test/coverage/Lighthouse/Playwright report, a
19
+ data dashboard, a written plan or proposal, a "here's what I built" summary, a
20
+ design doc, release notes, etc.
21
+ - A static web project was just built and has a generated entry file such as
22
+ `dist/index.html`, `build/index.html`, `out/index.html`, or `public/index.html`.
23
+ - The user asks to "share", "publish", "make a link for", or "send" a report/doc.
24
+ - A `PostToolUse` hint says an HTML/Markdown file was created (the bundled hook).
25
+
26
+ **Use judgment — do not nag.** Offer only for finished, worth-sharing artifacts.
27
+ Do **not** offer for scratch notes, internal repo files (README, CHANGELOG,
28
+ CONTRIBUTING, LICENSE, AGENTS.md, TODO/tasks), config, source code, or anything
29
+ under `node_modules`/`dist`/`.git`. Ask **at most once per file**; if the user
30
+ declines or ignores it, drop it and don't re-ask.
31
+
32
+ ## The one question to ask
33
+
34
+ > "Want me to publish this with Pagecast? It'll create a shareable public link."
35
+
36
+ Only on an explicit **yes** do you proceed. Publishing makes the file publicly
37
+ reachable — **never publish without confirmation.**
38
+
39
+ ## How to publish
40
+
41
+ Run the headless CLI with the **absolute path** and `--json`:
42
+
43
+ ```sh
44
+ npx pagecast publish "/absolute/path/to/file.md" --json
45
+ ```
46
+
47
+ (HTML and Markdown both work — Markdown is rendered to a clean page. If `pagecast`
48
+ is installed globally/in the project, `pagecast publish "<path>" --json` is the same.)
49
+
50
+ For static web projects that should get a new shareable `/p/<token>/` link,
51
+ build first and publish the generated entry file:
52
+
53
+ ```sh
54
+ npm run build
55
+ npx pagecast publish "/absolute/path/to/dist/index.html" --json
56
+ ```
57
+
58
+ If the user asks to deploy or update an entire static site/project, deploy the
59
+ built folder directly to a named Cloudflare Pages project:
60
+
61
+ ```sh
62
+ npx pagecast publish site "/absolute/path/to/dist" --project "project-name" --branch main --json
63
+ ```
64
+
65
+ `--branch` is optional and defaults to `main`, so this also works:
66
+
67
+ ```sh
68
+ npx pagecast pages deploy "/absolute/path/to/dist" --project "project-name" --json
69
+ ```
70
+
71
+ Use this instead of raw Wrangler commands like `npx wrangler pages deploy`.
72
+ Direct site deploys replace the target Pages project contents, so do not guess
73
+ the `--project`; use the user's named project or ask for it.
74
+
75
+ Parse the JSON on stdout:
76
+
77
+ - **Success** → `{ "ok": true, "url": "https://<project>.pages.dev/p/<token>/", ... }`
78
+ - Give the user the `url`. Offer to drop it into a PR/Slack message, and
79
+ mention they can rename the URL, re-sync, or revoke it from `npx pagecast`.
80
+ - **Not signed in** → `{ "ok": false, "statusCode": 401, ... }`
81
+ - This is the one-time setup. Tell the user to run
82
+ **`npx pagecast pages setup`** once, or run **`npx pagecast`** and click
83
+ **Connect Cloudflare**, then offer to retry. After that, publishing is
84
+ headless — a plain "yes" is enough every time.
85
+ - **Multiple accounts** → `{ "ok": false, "statusCode": 409, ... }`
86
+ - Tell the user to run `npx pagecast pages setup --account <account-id>` once,
87
+ or run `npx pagecast` to pick which Cloudflare account to publish from, then
88
+ retry.
89
+ - **Any other error** → relay `error` concisely and offer to retry.
90
+
91
+ ## Cloudflare Pages commands
92
+
93
+ Use these lower-level commands when the user explicitly asks about Cloudflare
94
+ setup, status, project listing, or direct Pages deployment:
95
+
96
+ ```sh
97
+ npx pagecast pages setup --project "project-name" --json
98
+ npx pagecast pages status --json
99
+ npx pagecast pages projects list --json
100
+ npx pagecast pages deploy "/absolute/path/to/dist" --project "project-name" --branch main --json
101
+ ```
102
+
103
+ If the user does not specify a branch, omit `--branch`; Pagecast deploys to
104
+ `main`.
105
+
106
+ ## Notes
107
+
108
+ - Always pass an **absolute** path (resolve relative paths against the cwd first).
109
+ - The first publish auto-creates the user's Pages project — no manual setup beyond
110
+ the one-time Connect Cloudflare login.
111
+ - Use `npx pagecast publish site` or `npx pagecast pages deploy` for direct
112
+ static-folder deploys to a named Pages project.
113
+ - Use `npx pagecast` for source-folder build settings, URL renaming, re-sync,
114
+ and revoke controls.
115
+ - To update a page **in place at the same URL**, the user can re-sync from the
116
+ Pagecast app; re-running `publish` creates a new link. Old links keep working
117
+ until revoked.