Files
command-center/agent/managed-skills/ssh-fish-host-remote-exec/SKILL.md
T
Frank 689228e60d docs: purge the retired workstation from the knowledge base
Second half of the purge (the first covered the persona, AGENTS.md, README.md,
and the distillation of the per-host pages). Every remaining identifier is
gone: hostname, both LAN addresses, and the Wi-Fi SSID.

34 count-checked substitutions across 22 files — indexes, tool/research pages,
the inventory census, the changelog, one generated HTML report, and five
managed skills. Facts kept, names dropped: a history entry keeps its four-page
listing as a nameless summary, the syslog excerpts keep every timestamp and
line, and the census keeps the .zcompdump rows (the zsh version stamps are the
useful part, the hostname was not).

Deliberately unchanged: install.sh's --host case list and the
packages/<hostname>.pkgs filename, where the hostname is the lookup key.

Left out of scope by Frank's call: agent/memories/** — past-session records the
learn pipeline rewrites.

kb-lint: 0 violations. Residual grep for the hostname, its two IPs, and the
SSID across omp-docs/ and agent/managed-skills/: no hits.
2026-09-28 16:37:38 -07:00

17 lines
1.8 KiB
Markdown

---
name: ssh-fish-host-remote-exec
description: "Runbook for password-auth SSH exec/file-ship to fleet hosts whose login shell is fish (e.g. blankpad), avoiding the fish-parsing and heredoc-swallow traps"
---
## When
Running remote commands or shipping files over SSH to a host whose login shell is **fish** (blankpad: user `blank`, reachable only as mDNS FQDN `blankpad.local` / 192.168.0.83 — bare hostname does not resolve from the workstation).
## Procedure
1. **Auth**: `SSHPASS='<pw>' sshpass -e ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no user@host '...'` — password via env, never argv (ps-visible).
2. **Remote exec**: `ssh host 'cmd'` pipes the command string to the login shell (fish). Bashisms like `for ... do`, `$?`, heredoc markers fail at *parse* time on fish (`Missing end to balance this for loop`). Always wrap compound commands: `ssh host 'bash -c "for b in a b c; do command -v $b || echo MISSING; done"'` (escape inner `$`).
3. **File shipping**: never combine `cat > /remote/path <<EOF` with a trailing `bash -s` in the same ssh command — `cat` drains stdin, so the interpreter silently runs on empty stdin and prints nothing (silent no-op that *looks* like success). Ship real bytes via local-file stdin redirect: `ssh host 'cat > /remote/path' < localfile`, then verify byte-truth with md5sum on both ends.
4. **Exit codes**: `$?` in an unquoted remote command is parsed by fish (`$status` there) — wrap in bash or drop the status echo; ssh's own exit code propagates to the caller anyway.
## Why
Both traps fired during the 2026-09-09 blankpad dotfiles deploy: first probe attempt died on fish loop parsing; a `cat >` ship silently swallowed the heredoc that was meant for `bash -s`, deploying the wrong file bytes until md5-compared.