Ship
Skill shipstatic/ship
The simplest way to publish a static site.
npx -y skills add shipstatic/shipAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Deploy static websites to ShipStatic. Use when the user wants to deploy a site, publish a website, upload to hosting, go live, set up a custom domain, manage deployments, or share a site URL. No account required — instant deployment. CLI (`ship`) and Node.js/browser SDK.
SKILL.md
10.1 KB, as published. Nobody here has run it
Deploy static sites. No account, no config — just ship it.
No-install usage (recommended for agents)
You don't need to install anything. Run any command via npx:
npx -y @shipstatic/ship ./dist # deploy (shortcut)
npx -y @shipstatic/ship deployments list # any subcommand works the same
npx -y @shipstatic/ship domains set www.example.com # ...
-y skips the install prompt — important for non-interactive runtimes (CI, sandboxes, agent containers). Every example below uses the bare ship command for readability; substitute npx -y @shipstatic/ship if it isn't installed globally.
Deploy
ship ./dist
Site is live. Output includes the URL and a claim link.
Pass a build output directory (e.g. ./dist, ./build, ./out) or a single file. Ship strips the directory prefix for clean URLs — dist/assets/app.js serves at /assets/app.js. A single file keeps its name: ship page.html deploys as /page.html. Deploying a project root (contains package.json, node_modules) is rejected — build first, then deploy the output.
Without credentials, deployments are public and expire in 3 days. Always show the user both the deployment URL and the claim link — the claim link lets them keep the site permanently.
The deployment ID is the URL hostname. Use the full ID (e.g. happy-cat-abc1234.shipstatic.com) as the argument to all other commands. The site lives at https://<deployment>.
Parsing output
ship ./dist --json
{
"deployment": "happy-cat-abc1234.shipstatic.com",
"url": "https://happy-cat-abc1234.shipstatic.com",
"files": 12,
"size": 348160,
"status": "success",
"config": false,
"password": false,
"labels": [],
"via": "cli",
"created": 1743552000,
"expires": 1743811200,
"claim": "https://my.shipstatic.com/claim/abc123"
}
claim only appears on the initial deploy without credentials. expires is null for authenticated (permanent) deploys. config: true indicates a ship.json is present in the deployment; password: true indicates the deployment is password-protected.
Piping
ship ./dist -q # → happy-cat-abc1234.shipstatic.com
-q outputs only the identifier — use it when piping or scripting.
Labels
ship ./dist --label v1.0 --label production
Labels replace all existing, not append. Include current labels to keep them.
Password protection
ship ./dist --password "hunter22" # protect deployment
SHIP_PASSWORD="hunter22" ship ./dist # via env var
Visitors get an unlock page until they enter the password. Length: 6–128 characters. Set per-deployment at upload time — cannot be added or changed later (deploy a new version to rotate). Works on both internal (*.shipstatic.com) and custom domains. Always show the password to the user if you set one — they need it to view the site.
SPA routing
Ship auto-detects single-page apps from index.html content and configures client-side routing rewrites — all paths serve index.html. No action needed. Skipped if a ship.json config is already included in the deployment. Disable with --no-spa-detect.
Authentication
Deploy works without credentials. Everything else requires an API key.
| Needs API key | No auth needed |
|---|---|
| Permanent deploys, domains, tokens, account | Deploy (public, 3-day TTL) |
export SHIP_TOKEN=<token> # Environment variable (best for automation)
ship --token <token> ... # Per-command override
ship config # Interactive setup → ~/.shiprc (requires TTY)
Any ship token works: an API key (ship-…, durable, full account) or a deploy token (deploy-…, scoped, revocable — set a short TTL for one-shot CI/CD workflows).
Free API key: https://my.shipstatic.com/api-key
Custom Domains
Requires an API key. Full workflow:
# 1. Validate
ship domains validate www.example.com
# 2. Deploy + link in one pipe
ship ./dist -q | ship domains set www.example.com
# 3. Show DNS records to the user
ship domains records www.example.com
# 4. After user configures DNS → verify
ship domains verify www.example.com
Step 2 auto-prints DNS records and a setup link in text mode. With --json, call domains records separately.
Verification is async — DNS propagation takes minutes to hours. Check status with ship domains get <name> --json and look for "status": "success".
Domain types
| Type | Example | DNS needed | Goes live |
|---|---|---|---|
| Internal | my-site.shipstatic.com | No | Instantly |
| Custom | www.example.com | CNAME + A | After DNS verified |
No apex domains. Always www.example.com, not example.com. The A record only redirects apex to www.
Upsert operations
domains set creates if new, updates if exists:
ship domains set www.example.com # Reserve (no deployment yet)
ship domains set www.example.com <deployment> # Link to deployment
ship domains set www.example.com <other-dep> # Switch (instant rollback)
ship domains set www.example.com --label prod # Update labels
Reads deployment from stdin when piped: ship ./dist -q | ship domains set www.example.com
No unlinking. Once linked, switch deployments or delete the domain. Setting deployment to null returns 400.
Parsing domain output
ship domains set www.example.com <dep> --json
{
"domain": "www.example.com",
"url": "https://www.example.com",
"deployment": "happy-cat-abc1234.shipstatic.com",
"status": "pending",
"labels": [],
"created": 1743552000,
"linked": 1743552000,
"links": 1
}
ship domains records www.example.com --json
{
"domain": "www.example.com",
"apex": "example.com",
"records": [
{"type": "A", "name": "@", "value": "76.76.21.21"},
{"type": "CNAME", "name": "www", "value": "cname.shipstatic.com"}
]
}
DNS helpers (custom domains only)
ship domains dns www.example.com # Provider name
ship domains share www.example.com # Shareable setup link
ship domains records www.example.com -q # TYPE NAME VALUE (one per line)
Validation
Exit codes as the answer:
ship domains validate www.example.com -q && echo "valid" || echo "invalid"
Exit 0 = valid (outputs normalized name). Exit 1 = invalid (no output).
Output Modes
Every command supports three modes:
| Flag | Output | When to use |
|---|---|---|
| (default) | Human-readable | Showing results to the user |
--json | JSON on stdout | Parsing programmatically |
-q | Identifier only | Piping between commands |
Errors go to stderr in all modes. Exit 0 = success, 1 = error.
List commands return {"<resource>s": [...], "cursor": null, "total": N}. domains list text mode omits status — use --json to see pending vs success.
Commands
Deployments
ship ./dist # Deploy (shortcut)
ship deployments upload <path> # Deploy (explicit)
ship deployments list # List all
ship deployments get <deployment> # Details
ship deployments set <deployment> # Update labels (--label)
ship deployments remove <deployment> # Delete (async)
Domains
ship domains list # List all
ship domains get <name> # Details
ship domains set <name> [deployment] # Create, link, or update
ship domains validate <name> # Check validity (exit code)
ship domains records <name> # Required DNS records
ship domains dns <name> # DNS provider lookup
ship domains share <name> # Shareable setup link
ship domains verify <name> # Trigger DNS verification
ship domains remove <name> # Delete
Account & Tokens
ship whoami # Account info
ship ping # Connectivity check
ship tokens create # New deploy token (shown once)
ship tokens create --ttl 3600 # With expiry (seconds)
ship tokens list # List tokens
ship tokens remove <token> # Revoke
Flags
| Flag | Purpose |
|---|---|
--json | JSON output |
-q, --quiet | Identifier only |
--token <token> | Any ship token: API key or deploy token |
--label <label> | Set label (repeatable, replaces all) |
--password <pwd> | Password-protect deployment (6–128 chars) |
--no-path-detect | Skip build output auto-detection |
--no-spa-detect | Skip SPA rewrite auto-configuration |
--no-color | Disable colors |
--config <file> | Custom config path |
Errors
| Message | Cause | Fix |
|---|---|---|
too many requests | Rate limited | Wait, or set an API key |
authentication failed | Bad credentials | Check key/token |
not found | No such resource | Verify the ID/name |
path does not exist | Bad deploy path | Check file/directory |
invalid domain name | Not a subdomain | Use www.example.com, not example.com |
<resource> limit reached | Plan caps hit (deployments, domains) | Suggest upgrading the plan; do not retry |
Account has been deleted / Account terminated | Account is gone | Stop; the account cannot deploy |
DNS information is only available for external domains | DNS op on internal domain | Only custom domains need DNS |
DNS verification already requested recently | Rate limited | Wait |