htmlup
Publish HTML to the public web in one command.
# Usage
The shape is always
htmlup <provider> publish <path>. Point it
at a single .html file or a directory of static assets
— directories upload recursively, preserving structure. On success
it prints the public URL and exits.
# publish a directory to GitHub Pages htmlup github publish ./site --repo owner/repo # with options: branch, subdir, custom domain htmlup github publish ./site --repo owner/repo \ --branch gh-pages --dir docs --cname example.com
# upload objects to a bucket htmlup s3 publish ./site --bucket my-bucket # with key prefix and explicit region htmlup s3 publish ./site --bucket my-bucket \ --prefix path/ --region us-east-1
--dry-run # enumerate what would upload + the resulting URL; no writes -v, --verbose # per-file progress and SDK-level detail
# Two backends
Backends are pluggable behind one Provider interface —
adding a target is one new package plus registration, no edits to
the publish flow.
GitHub Pages github
Commits your file set to the target branch via the Git Data API,
creates the branch if missing, optionally writes a
CNAME, and flips Pages on if it isn't already. You
get the *.github.io URL back.
S3 s3
One PutObject per file with content-type inferred
from the extension. No bucket-policy or website-config mutation
— you own public exposure, expected via CloudFront in front of
the bucket.
# Stateless by design
htmlup is single-purpose and boring on purpose. No daemon, no local database, no tracking of what was published.
No lifecycle management. Every invocation publishes and quits. (GitHub Pages expiry, if you want it, is an opt-in cron Action you copy into the target repo — never run by the CLI.)
htmlup never reads, prompts for, or caches secrets. Each official SDK owns its own credential resolution.
Every target implements one interface and self-registers. Contributors add a backend without touching core code.
Cobra commands parse flags and delegate; the real logic lives in provider packages and tested pure helpers.
# Authentication
Auth is delegated entirely to the official SDKs' standard credential chains. htmlup holds nothing.
# 1. $GITHUB_TOKEN → 2. $GH_TOKEN → 3. token from the gh CLI gh auth login # missing token? actionable error points you here
# env vars → ~/.aws/credentials → SSO → role / instance creds # --region only overrides the resolved region
# Also a Claude Code plugin
This repo doubles as a Claude Code plugin marketplace. It publishes the htmlup skill, which teaches Claude how to drive the CLI.
/plugin marketplace add truehhart/htmlup /plugin install htmlup@htmlup