From d0ae31c24c3c98ae89eebd67227c0c0d01606ed5 Mon Sep 17 00:00:00 2001 From: Clawd Date: Sat, 11 Apr 2026 20:43:41 -0700 Subject: Add ship-* Claude skills and plan Introduces a skills/ directory with 8 Claude skills that reimagine ship as a set of composable, human-driven deployment tools backed by Claude's reasoning rather than a rigid CLI. Skills: - ship-setup: one-time VPS config, saves host to ~/.config/ship/config.json - ship-status: derives live state from server, no local state file - ship-env: read/write env vars with merge semantics, never overwrites - ship-binary: deploy Go binaries with SQLite backup, correct restart behavior - ship-caddy: manage per-app Caddyfile with validate-before-reload - ship-service: systemd management and log inspection - ship-static: rsync static sites with SPA routing support - ship-deploy: orchestration runbook tying the others together Also adds SKILLS_PLAN.md documenting the architecture and rationale. Co-Authored-By: Claude Sonnet 4.6 --- skills/ship-deploy/SKILL.md | 126 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 skills/ship-deploy/SKILL.md (limited to 'skills/ship-deploy/SKILL.md') diff --git a/skills/ship-deploy/SKILL.md b/skills/ship-deploy/SKILL.md new file mode 100644 index 0000000..60cc263 --- /dev/null +++ b/skills/ship-deploy/SKILL.md @@ -0,0 +1,126 @@ +--- +name: ship-deploy +description: Deploy an app to a ship VPS. Orchestrates ship-binary or ship-static depending on what you're deploying. Use when you want to deploy or redeploy an app and want Claude to guide the process. +argument-hint: " [host-nickname]" +--- + +# ship-deploy + +Orchestration runbook for deploying apps to a ship VPS. Guides the full deployment +process by calling the appropriate ship skills in the right order. + +## Prerequisites + +- `/ship-setup` must have been run at least once +- `~/.config/ship/config.json` must exist and contain at least one host +- The app must already be built locally (binary compiled or dist folder ready) + +## Read Config + +```bash +python3 -c " +import json, os +cfg = json.load(open(os.path.expanduser('~/.config/ship/config.json'))) +nick = '' +h = cfg['hosts'].get(nick, cfg['hosts'][cfg['default']]) +print(h['host']) +print(h['domain']) +" +``` + +## Step 1 — Understand what we're deploying + +Ask the user (or infer from context): + +- **What is the app name?** (e.g. `foodtracker`) +- **What type?** Binary or static site? +- **Where is the artifact?** Path to binary or dist folder +- **What host?** Default unless specified +- **Any env vars needed?** Especially for first-time deploys +- **Custom domain?** Or use `.` + +If any of these are unclear, ask before proceeding. + +## Step 2 — Check if app already exists + +```bash +ssh "test -f /etc/ship/ports/ && echo exists || echo new" +``` + +Tell the user whether this is a fresh deploy or an update to an existing app. + +## Step 3 — Deploy + +### For a binary app → follow ship-binary + +Key steps in order: +1. Backup any SQLite databases in `/var/lib//` +2. Allocate or retrieve port +3. Upload binary via scp +4. Write/merge env file +5. Write systemd unit +6. `systemctl restart` (existing) or `systemctl enable --now` (new) +7. Write Caddy config and reload + +### For a static site → follow ship-static + +Key steps in order: +1. Validate `index.html` exists in dist folder +2. Rsync dist folder to `/var/www//` +3. Fix ownership to `www-data` +4. Write Caddy config and reload + +## Step 4 — Verify + +After deploying, confirm the service came up: + +**Binary:** +```bash +ssh "sudo systemctl is-active " +``` + +If not active, immediately check logs: +```bash +ssh "sudo journalctl -u -n 30 --no-pager" +``` + +**Static:** +```bash +ssh "curl -sI https:// | head -5" +``` + +## Step 5 — Confirm to user + +Report: +- App name and live URL +- Type (binary / static) +- New deploy or update +- Port (binary only) +- Any SQLite backups made +- Any env vars that were set +- Whether the service is running + +## Checklist (reference) + +Use this to make sure nothing is missed: + +- [ ] Config file read, host resolved +- [ ] App type confirmed (binary / static) +- [ ] Artifact path confirmed and exists locally +- [ ] App name and domain confirmed +- [ ] Existing app check done +- [ ] SQLite backed up (binary, if db files exist) +- [ ] Port allocated or retrieved +- [ ] Artifact uploaded +- [ ] Env file written with merge semantics +- [ ] Systemd unit written and service started/restarted (binary) +- [ ] Caddy config written and reloaded +- [ ] Service confirmed running + +## Notes + +- Never skip the SQLite backup step for binary apps — always check even if you don't expect a db +- Always merge env vars — never overwrite the whole env file +- If anything fails mid-deploy, tell the user exactly where it failed and what state the server is in +- Use `systemctl restart` for existing apps, `enable --now` for new ones — not the other way around +- If the user says "deploy X" without more context, ask the minimum necessary questions before starting -- cgit v1.2.3