Implementation Plan

Add a ship-pages skill — one-command publish for plans & media galleries

todo
2026-06-18 agentics feature

Ship a one-command /git-agent:ship-pages that takes a user's plans gallery (docs/plans/) and social-share gallery (docs/media/social/) live on GitHub Pages — or any static host — scaffolding every first-run prerequisite so publishing works in any repo with zero manual setup.

Implement Read and implement all steps in the plan at docs/plans/add-ship-pages-skill.html — Add a one-command ship-pages skill to git-agent for publishing galleries
File add-ship-pages-skill.html
Path docs/plans/add-ship-pages-skill.html
Acceptance criteria 0 / 8 done

Context

Publishing today is a three-stage pipeline split across plugins: plan-agent + social-media-tools generate gallery HTML into docs/, git-agent commits and pushes, and a GitHub Actions workflow auto-deploys docs/ to Pages. No single tool chains generate → commit → push → deploy.

Worse, that automatic deploy only works because this repo already ships .github/workflows/deploy-pages.yml and docs/.nojekyll. A plugin user's own repo has none of that scaffolding — so "just push docs/" silently fails to publish.

ship-pages closes the gap by orchestrating the existing gallery and git skills and scaffolding the missing Pages prerequisites, with a --static escape hatch that treats docs/ as a portable bundle for Netlify, Vercel, Cloudflare Pages, or S3. It lives in git-agent (next to ship) and is command-only, mirroring ship's deliberate, manual-invoke posture. It locates the plans gallery through the same plansDirectory resolution as plans-library (project → global settings, fallback docs/plans/), so it publishes from wherever plans are configured to live.

Files to Modify

agentics/
  • kit/plugins/git-agent/skills/ship-pages/
    • SKILL.md new the command-only ship-pages skill
    • assets/deploy-pages.yml new bundled Pages workflow template
  • kit/plugins/git-agent/
    • CHANGELOG.md modified v3.12.0 entry
    • README.md modified document /git-agent:ship-pages
  • .claude-plugin/marketplace.json modified bump git-agent to 3.12.0
  • tests/plugins/test-ship-pages.sh new smoke + scaffold tests
  • CLAUDE.md modified update git-agent row in plugins table

Diagram

ship-pages publish flow
1 · Detect
/git-agent:ship-pages
scan plansDirectory + docs/media/social
2 · Rebuild
plans-library · media-library
only if index is missing or stale
3 · Scaffold
deploy-pages.yml · .nojekyll · index.html
write only when absent (Pages mode)
4 · Enable
gh api …/pages
fallback to printed Settings steps
5 · Publish
branch-agent · pr-agent
scoped commit (docs/ [+ workflow]) → PR
6 · Live
owner.github.io/repo
deploys on merge + Actions run
Two publish modes
Default · GitHub Pages
  • scaffolds deploy-pages.yml
  • creates docs/.nojekyll
  • scaffolds docs/index.html
  • enables Pages via gh api
  • branch + PR (deploys on merge)
  • URL: owner.github.io/repo
--static · Any host
  • no scaffolding, no gh api
  • treats docs/ as the bundle
  • netlify deploy --dir=docs
  • vercel deploy docs --prod
  • wrangler pages deploy docs
  • aws s3 sync docs s3://bucket

Steps

1
todo Scaffold the skill directory and SKILL.md frontmatter
Establishes one command-only entry point (/git-agent:ship-pages), mirroring ship so Claude never auto-publishes from loose intent. Create kit/plugins/git-agent/skills/ship-pages/SKILL.md with a three-part description, disable-model-invocation: true, and allowed-tools limited to Bash(git *), Bash(gh *), Bash(python3 *), Read, Write, Skill, ToolSearch, ExitPlanMode.
Verify
head -8 of the SKILL.md shows name: ship-pages and disable-model-invocation: true; the file resolves under git-agent/skills/ship-pages/.
2
todo Write pre-flight + gallery auto-detection (skill Steps 0–2)
The skill must run with zero required args by detecting what exists, and refuse early when there is nothing to publish. Step 0 exits plan mode (deferred ExitPlanMode); Step 1 verifies a git repo + gh auth status, resolves owner/repo via gh repo view --json owner,name, and parses --static, --plans-only, --media-only, --dir; Step 2 resolves the plans gallery directory via the plansDirectory pattern — read plansDirectory from project .claude/settings.json, then global ~/.claude/settings.json, falling back to docs/plans/ (the exact resolution plans-library uses) — and detects *.html there (excl index.html); cards are detected under docs/media/social/. STOP with guidance if neither gallery exists.
Verify
Step 2 resolves the plans dir via the plansDirectory pattern (project → global → docs/plans) rather than a hard-coded path, detects both galleries, and includes a STOP branch when both are empty.
3
todo Write the stale-aware rebuild step reusing plans-library / media-library
Keeps the published index current without paying a rebuild every run, and reuses gallery logic instead of duplicating it. For each detected gallery, rebuild only when index.html is missing or older than the newest plan/card (mtime compare), invoking Skill(plan-agent:plans-library) and/or Skill(social-media-tools:media-library).
Verify
Step 3 names both library skills and includes the mtime/staleness check; nothing in the skill re-implements gallery HTML.
4
todo Write the Pages scaffold + auto-enable step and the bundled workflow asset
Closes the core gap — a user's repo lacks the workflow, .nojekyll, and a root index. Create assets/deploy-pages.yml (the repo's proven workflow with pinned SHAs). When not --static: write the workflow if absent, create docs/.nojekyll if absent, scaffold a minimal docs/index.html linking both galleries if absent (never overwrite), then enable Pages via gh api --method POST repos/{owner}/{repo}/pages -f build_type=workflow, falling back to printed Settings → Pages steps on any error (already-enabled, missing scope). Deploy-source guard: the workflow uploads path: docs, so if the resolved plansDirectory falls outside docs/, warn that the docs-based Pages workflow won't include it and recommend moving plansDirectory under docs/ or using --static pointed at the gallery dir (media always lives under docs/media/social/).
Verify
assets/deploy-pages.yml is valid YAML containing path: docs and the .nojekyll assertion; Step 4 covers all four scaffold artifacts plus the fallback path.
5
todo Write the scoped publish step reusing branch-agent + pr-agent
Honors the "scope to publish paths" + "branch + PR" decisions while still reusing git-agent's branch/PR skills. Stage ONLY publish paths — always git add docs/, and stage .github/workflows/deploy-pages.yml only in Pages mode when it exists (in --static mode no workflow is scaffolded, so adding that pathspec would abort git add with a pathspec error before the docs bundle is staged); warn about and leave unrelated changes uncommitted; if on main/master create a branch via Skill(git-agent:branch-agent); make a scoped conventional commit (docs(pages): publish plans/media galleries); push + open a PR via Skill(git-agent:pr-agent). Explicitly do NOT call ship — its git add -A would defeat scoped staging.
Verify
Step 5 stages docs/ (plus the workflow file only in Pages mode, when present), calls branch-agent and pr-agent, and carries a note explaining why ship is bypassed.
6
todo Write the confirm + static-host export step (skill Steps 6–7)
Gives a definitive "where is it" answer for Pages and a host-agnostic export satisfying "any static host" with no extra build. Pages mode: print https://{owner}.github.io/{repo}/ (handle the {owner}.github.io root-site case), noting it goes live after merge + the Actions run. --static mode: skip scaffolding/enable, treat docs/ as the bundle, and print deploy commands for Netlify (netlify deploy --dir=docs --prod), Vercel (vercel deploy docs --prod), Cloudflare (npx wrangler pages deploy docs), and S3 (aws s3 sync docs s3://<bucket> --delete).
Verify
Step 6 prints the github.io URL; Step 7 lists at least the four host commands, all pointing at docs/.
7
todo Register the skill and sync docs (marketplace, CHANGELOG, README, CLAUDE.md)
For relative-path plugins the marketplace version is what ships, and repo rules require docs + changelog updated in the same PR. Bump git-agent version 3.11.03.12.0 (minor, new skill) in .claude-plugin/marketplace.json; add a v3.12.0 entry to kit/plugins/git-agent/CHANGELOG.md; document /git-agent:ship-pages in kit/plugins/git-agent/README.md; update the git-agent row in the root CLAUDE.md plugins table.
Verify
git-agent reads 3.12.0 in marketplace.json (JSON-validation hook passes) and grep -l ship-pages lists CHANGELOG.md, README.md, and CLAUDE.md.
8
todo Add smoke + scaffold tests
Locks in the objective with executable tests that ship with the repo. Create tests/plugins/test-ship-pages.sh following the repo's shell-test convention: assert SKILL.md frontmatter (name, disable-model-invocation), validate the bundled deploy-pages.yml parses as YAML and contains path: docs, assert marketplace registration ≥ 3.12.0, and run a scaffold dry-run against a temp git fixture asserting the three Pages artifacts and a scoped branch/commit are produced without pushing.
Verify
bash tests/plugins/test-ship-pages.sh exits 0.

Tests

Tier 1 — Code-touching plan
Objective ship-pages publishes galleries end-to-end with no manual setup

File: tests/plugins/test-ship-pages.sh

Type: smoke test

Asserts: against a temp git repo seeded with docs/plans/ + docs/media/social/ and no pre-existing Pages config, the scaffold+publish path writes .github/workflows/deploy-pages.yml, docs/.nojekyll, and docs/index.html, creates a publish branch with a commit touching only docs/ + the workflow, and prints the owner.github.io/repo URL.

Run: bash tests/plugins/test-ship-pages.sh

Unit Bundled deploy-pages.yml is valid and correct

File: tests/plugins/test-ship-pages.sh (asset-validation section)

Targets: kit/plugins/git-agent/skills/ship-pages/assets/deploy-pages.yml

Key cases: parses as YAML; triggers on push to docs/**; declares pages: write + id-token: write; asserts docs/.nojekyll; uploads path: docs.

Integration Skill registered + plugin structure valid

File: tests/plugins/test-ship-pages.sh (registration section)

Targets: .claude-plugin/marketplace.json + kit/plugins/git-agent/ structure

Key cases: marketplace.json is valid JSON; git-agent version ≥ 3.12.0 and higher than main; SKILL.md frontmatter has name: ship-pages + disable-model-invocation: true.

E2E Scaffold + scoped publish + static mode in a temp repo

File: tests/plugins/test-ship-pages.sh (e2e section, mocked gh)

Targets: the full Pages-mode and --static flows against a throwaway git fixture

Key cases: first run scaffolds all three Pages artifacts + opens a PR; an unrelated uncommitted file is left unstaged; a second run skips scaffolding and rebuilds only the stale gallery; --static prints docs/-based host commands and writes no workflow.

Acceptance Criteria

Verification

Load git-agent locally (claude --plugin-dir ./kit/plugins/git-agent) in a checkout that has docs/plans/ plans and docs/media/social/ cards. Run /git-agent:ship-pages and confirm it: (1) rebuilds only stale galleries, (2) scaffolds deploy-pages.yml, docs/.nojekyll, and docs/index.html when absent, (3) enables Pages via gh api or prints fallback steps, (4) opens a PR whose diff is limited to docs/ + the workflow file, and (5) prints https://<owner>.github.io/<repo>/. Run /git-agent:ship-pages --static and confirm it skips all scaffolding and prints docs/-based Netlify/Vercel/Cloudflare/S3 commands. Finally run bash tests/plugins/test-ship-pages.sh and confirm it exits 0.

Completion Checklist

Required

Completion Report

No items to report — all requirements met.

Next Steps

Add a ship-pages-bg background variant

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

Add a `ship-pages-bg` background command to the git-agent plugin that fires the ship-pages publish flow via a background subagent, mirroring the existing commit-bg / pr-bg / ship-bg commands in kit/plugins/git-agent/commands/. Reuse the ship-pages skill; return control immediately with an ack. Bump git-agent's version in .claude-plugin/marketplace.json and add a CHANGELOG entry.
Add a --watch flag that polls the Pages deploy and reports the live URL

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

Add a `--watch` flag to the git-agent ship-pages skill (kit/plugins/git-agent/skills/ship-pages/SKILL.md) that, after opening the publish PR, polls the GitHub Actions "Deploy to GitHub Pages" run with `gh run watch` and reports the live https://.github.io// URL once the deploy succeeds. Document the flag in the README and bump the git-agent version in marketplace.json.
Wish List
Generate per-host config files (netlify.toml / vercel.json) Wish List

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

Extend the git-agent ship-pages skill with an opt-in `--emit-host-config` flag that writes netlify.toml, vercel.json, and a Cloudflare Pages config pointing at docs/ as the publish directory, so users can connect those hosts with zero manual config. Keep it off by default; document the generated files in the README.
Share a reusable docs/ "site hub" landing template Wish List

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

Design a reusable docs/index.html "site hub" template shared between the agentics landing hub (docs/index.html) and the ship-pages scaffolded landing page, linking the Plans gallery and Media library with consistent dark-mode styling. Factor it into the git-agent ship-pages skill assets and have ship-pages scaffold from it.
Unresolved Questions
  • Scoped-commit reuse vs. extending ship with a --paths flag
    In the git-agent ship-pages skill, decide whether to keep the scoped-commit approach (branch-agent + pr-agent + a scoped `git add` of docs/, plus the deploy-pages.yml workflow only in Pages mode) or instead add a `--paths ` scoping flag to the existing ship skill and have ship-pages call ship with it. Compare maintainability and the risk of ship's `git add -A` capturing unrelated changes, recommend one, and implement the chosen approach.
  • Exact gh api call + token scopes for enabling Pages
    Confirm the exact `gh api` call and token scopes needed to enable GitHub Pages with the GitHub Actions build type (POST repos/{owner}/{repo}/pages with build_type=workflow). Determine whether gh's default auth scopes suffice or whether `gh auth refresh -s` (and which scope) is required, and document the fallback in the git-agent ship-pages skill so first-time users get a clear instruction when enablement fails.
  • Handling a plansDirectory that resolves outside docs/
    Decide how git-agent ship-pages should handle a configured plansDirectory that resolves outside docs/ (the GitHub Pages deploy source): (a) warn only and tell the user to move plansDirectory under docs/ or use --static, (b) copy/sync the plans gallery into docs/ as a build step before publishing, or (c) parameterize the scaffolded deploy-pages.yml upload `path:` (and the .nojekyll location) to the lowest common ancestor of docs/ and plansDirectory. Weigh simplicity against publishing unintended files (e.g. the whole repo root) and recommend one; implement it in the skill.