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-setup/SKILL.md | 122 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 skills/ship-setup/SKILL.md (limited to 'skills/ship-setup/SKILL.md') diff --git a/skills/ship-setup/SKILL.md b/skills/ship-setup/SKILL.md new file mode 100644 index 0000000..e3d08ee --- /dev/null +++ b/skills/ship-setup/SKILL.md @@ -0,0 +1,122 @@ +--- +name: ship-setup +description: Set up ship for the first time or add a new VPS host. Saves host config to ~/.config/ship/config.json and installs server dependencies. Use when configuring ship for the first time, or adding/changing a host. +argument-hint: "[host-nickname]" +--- + +# ship-setup + +Configure ship and prepare a VPS for deployments. + +## Config File + +All ship skills read from `~/.config/ship/config.json`. This skill creates or updates it. + +Structure: +```json +{ + "default": "prod", + "hosts": { + "prod": { + "host": "ubuntu@1.2.3.4", + "domain": "example.com" + }, + "staging": { + "host": "ubuntu@5.6.7.8", + "domain": "staging.example.com" + } + } +} +``` + +## Steps + +### 1. Read existing config + +Check if `~/.config/ship/config.json` exists: + +```bash +cat ~/.config/ship/config.json 2>/dev/null +``` + +If it exists, show the user the current hosts so they know what's already configured. + +### 2. Get host details + +If no nickname was provided as an argument, ask the user: +- **Nickname** — a short name for this host (e.g. `prod`, `staging`, `vps`) +- **SSH connection string** — e.g. `ubuntu@1.2.3.4` or an SSH config alias like `alaskav6` +- **Base domain** — the domain pointing to this server (e.g. `example.com`) + +If this is the first host, ask if it should be the default. If hosts already exist, ask if this should replace the current default. + +### 3. Test SSH connection + +Verify the connection works before saving anything: + +```bash +ssh -o ConnectTimeout=5 "echo ok" +``` + +If it fails, tell the user and stop. Don't save config for an unreachable host. + +### 4. Save config + +Write or update `~/.config/ship/config.json` with the new host. Merge with existing hosts — never overwrite the whole file. Use Python to safely read/write JSON: + +```bash +python3 -c " +import json, os +path = os.path.expanduser('~/.config/ship/config.json') +os.makedirs(os.path.dirname(path), exist_ok=True) +cfg = json.load(open(path)) if os.path.exists(path) else {'default': None, 'hosts': {}} +cfg['hosts'][''] = {'host': '', 'domain': ''} +if not cfg['default']: + cfg['default'] = '' +json.dump(cfg, open(path, 'w'), indent=2) +print('saved') +" +``` + +### 5. Install server dependencies + +SSH in and ensure the required directories and software exist. This is idempotent — safe to run multiple times. + +**Install Caddy** (if not present): +```bash +ssh "which caddy || (sudo apt-get install -y debian-keyring debian-archive-keyring apt-transport-https curl && curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg && curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list && sudo apt-get update && sudo apt-get install -y caddy)" +``` + +**Create directory structure:** +```bash +ssh "sudo mkdir -p /etc/ship/env /etc/ship/ports /etc/caddy/sites-enabled /var/www && sudo chmod 755 /etc/ship" +``` + +**Configure main Caddyfile** (only if not already set up): +```bash +ssh "sudo test -f /etc/caddy/Caddyfile && echo exists || echo '{ +} + +import /etc/caddy/sites-enabled/*' | sudo tee /etc/caddy/Caddyfile" +``` + +**Enable and start Caddy:** +```bash +ssh "sudo systemctl enable caddy && sudo systemctl start caddy" +``` + +### 6. Confirm + +Tell the user: +- Host nickname and SSH target saved +- Whether it's the default host +- That the server is ready for deployments +- How to add another host: `/ship-setup ` +- How to deploy: `/ship-deploy` + +## Notes + +- Never overwrite the entire config file — always merge +- If a nickname already exists in config, confirm before overwriting it +- The SSH host can be an alias from `~/.ssh/config` — no need to require raw IP +- Default host is used by all other ship skills when no host is specified -- cgit v1.2.3