Add Multi-Host Deploy Targets to docs-publisher

High todo
2026-06-08 agentics feature High effort

Extend docs-publisher to publish to GitLab Pages and Cloudflare Pages alongside GitHub Pages — one docs-init run detects the git host and drops in the right deploy pipeline, while the host-agnostic build scripts stay completely untouched.

Implement Read and implement all steps in the plan at docs/plans/add-multi-host-deploy-targets.md — Add Multi-Host Deploy Targets to docs-publisher. Verify against the plan's Tests, Verification, and Acceptance Criteria before reporting done. If everything passed, mark completion in docs/plans/add-multi-host-deploy-targets.md — tick each step's [x] marker and each criterion's - [x], set status: completed — and re-render the HTML from the spec. If any check failed, leave status: in-progress and say which.
More ways to run this plan — goal & workflow prompts, file path
Pursue as goal — optimize for the outcome, in parallel
Achieve this goal: Add Multi-Host Deploy Targets to docs-publisher. The plan at docs/plans/add-multi-host-deploy-targets.md describes one approach — use it as reference, but optimize for the outcome. Fan out across parallel subagents where that serves the outcome. Verify against the plan's Tests, Verification, and Acceptance Criteria before reporting done. If everything passed, mark completion in docs/plans/add-multi-host-deploy-targets.md — tick each step's [x] marker and each criterion's - [x], set status: completed — and re-render the HTML from the spec. If any check failed, leave status: in-progress and say which.
Run as workflow — launch parallel subagents
Run a workflow to implement the plan at docs/plans/add-multi-host-deploy-targets.md — Add Multi-Host Deploy Targets to docs-publisher. Brief subagents with the plan file at docs/plans/add-multi-host-deploy-targets.md. Reserve a final verification phase for the lead agent, not a subagent. Verify against the plan's Tests, Verification, and Acceptance Criteria before reporting done. If everything passed, mark completion in docs/plans/add-multi-host-deploy-targets.md — tick each step's [x] marker and each criterion's - [x], set status: completed — and re-render the HTML from the spec. If any check failed, leave status: in-progress and say which.
File add-multi-host-deploy-targets.html
Path docs/plans/add-multi-host-deploy-targets.html
Spec docs/plans/add-multi-host-deploy-targets.md
Definition of done 0 / 8 done

Context

The story behind this plan — what prompted the work and why it matters now.

The docs-publisher plugin (planned in docs/plans/create-docs-publishing-skills.html , still status: todo ) packages the agentics docs pipeline as installable skills: a docs-init command scaffolds docs/ , copies build scripts into the user's project, and drops a GitHub Actions deploy workflow into .github/workflows/ . Today that deploy stage is GitHub-only.

This plan is the verbatim "GitLab Pages and Cloudflare Pages support" Wish List item from that parent plan, promoted to a real feature. It adds two more deploy targets without touching the build scripts — those already emit static HTML into docs/ and are host-agnostic. Only the deploy wrapper changes per host: GitHub Pages uploads a docs/ artifact via Actions, GitLab Pages publishes a public/ artifact from a pages CI job, and Cloudflare Pages either connects the repo through the dashboard or runs wrangler pages deploy in CI.

Dependency: this plan layers onto the docs-publisher plugin skeleton, docs-init , and docs-publish . If the parent plan has not been implemented yet, implement it first — the steps below modify files that parent plan creates.

Resolved decisions: (1) Cloudflare ships both mechanisms — a wrangler.toml for dashboard Git-integration and an optional deploy-cloudflare.yml CI workflow — and docs-init asks the user which to use. (2) docs-publish becomes host-aware so it reports the correct published URL ( github.io / gitlab.io / pages.dev ) per target.

Files that change

Every file this plan touches, and what happens to each one.

agentics/
  • kit/plugins/docs-publisher/reference/
    • .gitlab-ci.yml new GitLab Pages deploy job
    • deploy-cloudflare.yml new Cloudflare CI deploy workflow
    • wrangler.toml new Cloudflare Pages config
  • kit/plugins/docs-publisher/commands/
    • docs-init.md modified host detection + template copy
    • docs-publish.md modified host-aware published URL
  • kit/plugins/docs-publisher/
    • README.md modified document three deploy targets
    • CHANGELOG.md modified multi-host feature entry
  • kit/plugins/docs-publisher/scripts/detect-host.sh new shared git-host classifier
  • .claude-plugin/marketplace.json modified minor version bump
  • tests/pages/
    • deploy-templates.test.sh new template validity smoke test
    • detect-host.test.sh new host-detection unit test
    • docs-init-host-copy.test.sh new copy-mapping integration test

Steps

The step-by-step work, in order — each step says what to do, why it matters, and how to check it worked.

1
todo Author the GitLab Pages reference workflow at reference/.gitlab-ci.yml
Why
GitLab Pages publishes whatever a pages CI job leaves in public/ . The build scripts already emit static HTML into docs/ , so the template only needs a pages job that copies docs/ → public/ and declares public as its artifact path, scoped to the default branch.
Verify
Open kit/plugins/docs-publisher/reference/.gitlab-ci.yml . Confirm it (1) defines a pages job, (2) runs cp -r docs public (or rsync ) in its script , (3) sets artifacts: paths: [public] , and (4) restricts to the default branch via rules or only . Validate it parses: python3 -c "import yaml,sys; yaml.safe_load(open('kit/plugins/docs-publisher/reference/.gitlab-ci.yml'))" exits 0.
2
todo Author the Cloudflare config and CI workflow at reference/wrangler.toml and reference/deploy-cloudflare.yml
Why
A wrangler.toml alone only configures a Pages project — it does not deploy. Shipping both a wrangler.toml (with pages_build_output_dir = "docs" , for the dashboard Git-integration path) and a deploy-cloudflare.yml workflow (running wrangler pages deploy docs , for the fully-automated path) lets docs-init offer the user either route.
Verify
Confirm reference/wrangler.toml contains pages_build_output_dir = "docs" and a name placeholder. Confirm reference/deploy-cloudflare.yml runs wrangler pages deploy docs (e.g. via cloudflare/wrangler-action ) and references ${{ secrets.CLOUDFLARE_API_TOKEN }} and ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} — never hard-coded credentials. Parse checks: python3 -c "import tomllib;tomllib.load(open('.../wrangler.toml','rb'))" and a yaml.safe_load on the workflow both exit 0.
3
todo Create the shared host classifier at scripts/detect-host.sh
Why
Both docs-init and docs-publish need the same github/gitlab/other decision. Extracting one small, testable shell helper avoids duplicating fragile URL-parsing prose across two markdown command files and gives the unit test a real target. It is copied into the user's project by docs-init alongside the other build scripts.
Verify
Read kit/plugins/docs-publisher/scripts/detect-host.sh . Confirm it defines a detect_host() function (or accepts a remote URL arg) that prints github for a URL containing github.com , gitlab for gitlab.com , and other for anything else (including an empty/missing remote). Confirm it handles both https:// and git@ SSH forms and is POSIX-sh / bash compatible (runs on macOS and Linux).
4
todo Wire host detection and template copying into docs-init
Why
This is the entry point that adapts the deploy pipeline to the user's host. A single invocation must detect the host via detect-host.sh , copy the matching template to the right location, and — for the non-github/gitlab case — ask via AskUserQuestion whether the user wants the Cloudflare CI workflow or the dashboard route, copying deploy-cloudflare.yml only for the CI choice. All copies must be idempotent.
Verify
Read kit/plugins/docs-publisher/commands/docs-init.md . Confirm the body: (1) calls detect-host.sh on origin ; (2) for github copies deploy-pages.yml → .github/workflows/ ; (3) for gitlab copies .gitlab-ci.yml → repo root; (4) for other uses AskUserQuestion to choose Cloudflare CI vs dashboard, copying wrangler.toml → root in both cases and deploy-cloudflare.yml → .github/workflows/ only for CI; (5) never overwrites an existing deploy file without explicit user confirmation. Confirm detect-host.sh is added to the list of scripts docs-init copies into the project.
5
todo Make docs-publish host-aware when reporting the published URL
Why
After a push, docs-publish currently reports a GitHub Pages URL. Publishing to GitLab or Cloudflare should report the correct destination, not a misleading github.io link. Reusing detect-host.sh keeps the classification identical to what docs-init used.
Verify
Read kit/plugins/docs-publisher/commands/docs-publish.md . Confirm it derives the published URL per host: github → https://<owner>.github.io/<repo>/ , gitlab → https://<owner>.gitlab.io/<repo>/ , Cloudflare → https://<project>.pages.dev (project name read from wrangler.toml when present, else noted as dashboard-defined). Confirm the existing --dry-run behaviour is preserved.
6
todo Document the targets and bump the marketplace version
Why
Marketplace convention requires a manual version bump plus a CHANGELOG entry for any plugin change, and users need docs explaining the three deploy targets and how docs-init picks one. Adding deploy targets is a new feature → a MINOR bump.
Verify
Confirm kit/plugins/docs-publisher/README.md has a "Deploy targets" section listing GitHub / GitLab / Cloudflare and describing host auto-detection. Confirm kit/plugins/docs-publisher/CHANGELOG.md has a new entry. Confirm the docs-publisher version in .claude-plugin/marketplace.json is bumped one MINOR above its main value, and that python3 -m json.tool .claude-plugin/marketplace.json exits 0.

Tests

The tests that prove the change does what it promises.

Tier 1 — Code-touching plan
Objective All three deploy templates ship valid and host-correct File: tests/pages/deploy-templates.test.sh Type: smoke test Asserts: the plan's objective &mdash; that docs-publisher gained GitLab + Cloudflare deploy support. Validates that reference/.gitlab-ci.yml and reference/deploy-cloudflare.yml parse as YAML and reference/wrangler.toml parses as TOML; that .gitlab-ci.yml contains a pages job publishing public ; that deploy-cloudflare.yml invokes wrangler pages deploy and references the two secrets (never literal tokens); and that wrangler.toml sets pages_build_output_dir = "docs" . Run: bash tests/pages/deploy-templates.test.sh
Unit detect-host.sh maps remote URLs to the right host File: tests/pages/detect-host.test.sh Targets: detect_host() in kit/plugins/docs-publisher/scripts/detect-host.sh Key cases: https://github.com/o/r.git → github ; git@github.com:o/r.git → github ; https://gitlab.com/o/r → gitlab ; a self-hosted/unknown host → other ; empty/missing remote → other .
Integration docs-init copies the correct template per host, idempotently File: tests/pages/docs-init-host-copy.test.sh Targets: the docs-init host-detection + copy logic exercised against temp git repos Key cases: a temp repo with a github.com remote yields .github/workflows/deploy-pages.yml ; a gitlab.com remote yields a root .gitlab-ci.yml ; the Cloudflare-CI path yields both wrangler.toml and deploy-cloudflare.yml while the dashboard path yields only wrangler.toml ; a second run does not overwrite an edited deploy file.

Definition of done

The plan counts as done when every statement below is true — check each one off as you verify it.

Final check

One last pass to confirm the whole change works end to end.

Run bash tests/pages/deploy-templates.test.sh and bash tests/pages/detect-host.test.sh &mdash; both exit 0. Then create three throwaway git repos and set their origin remotes to a github.com , a gitlab.com , and a self-hosted URL respectively; run the docs-init copy logic (via tests/pages/docs-init-host-copy.test.sh ) and confirm each repo receives only its host's template in the right place, that the Cloudflare prompt branches correctly between the CI and dashboard file sets, and that a second run leaves an edited deploy file untouched. Finally, run docs-publish --dry-run in each repo and confirm the reported published URL matches the host ( github.io / gitlab.io / pages.dev ). Confirm python3 -m json.tool .claude-plugin/marketplace.json succeeds and the docs-publisher version is higher than on main .

Wrapping up

Three gates that must all pass before this plan is marked completed.

Required

Completion Report

No items to report — all requirements met.

Next steps

Follow-up ideas that came up along the way — none of them are required to finish this plan.

Support self-hosted GitLab and GitHub Enterprise hosts

Paste this prompt into Claude to execute this follow-up:

Extend kit/plugins/docs-publisher/scripts/detect-host.sh so it recognizes self-hosted GitLab and GitHub Enterprise instances (non-.com domains). Add an optional .docs-publisher.json config key "host_override" (values: github | gitlab | cloudflare) that detect-host.sh and docs-init read first, falling back to URL-substring detection. Update docs-init.md to document the override and add unit cases to tests/pages/detect-host.test.sh for a self-hosted gitlab.example.com remote resolving to gitlab via the override.
Add custom-domain (CNAME) support per host

Paste this prompt into Claude to execute this follow-up:

Add custom-domain support to docs-publisher's deploy templates. For GitHub, write a docs/CNAME file from a --domain flag on docs-init; for GitLab, document the Pages domain settings; for Cloudflare, set the custom domain in wrangler.toml or document the dashboard step. Update docs-publish.md so its reported URL uses the custom domain when one is configured, and add a test asserting docs/CNAME is created for the GitHub path when --domain is passed.
Auto-provision the Cloudflare Pages project during docs-init Wish List

Speculative / blue-sky idea — not on the critical path. Paste into Claude when ready to explore:

Paste this prompt into Claude to execute this follow-up:

Explore having docs-publisher's docs-init optionally create the Cloudflare Pages project automatically via the Cloudflare API (wrangler pages project create) instead of requiring manual dashboard setup. Prompt for an API token, create the project, and write its name into wrangler.toml. Treat this as a design spike first: enumerate the auth/secret-handling risks of running an authenticated API call from a scaffolding command, and recommend whether it should ship at all given docs-publisher's "no peer dependencies / survives uninstall" principle.