summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-07-18 20:44:23 +0300
committerPaul Buetow <paul@buetow.org>2026-07-18 20:44:23 +0300
commitc67ce0a6e167258df7286084de8b967901c1d4f3 (patch)
tree9aa38566c8a2f8074aaf3545e747e505fdcdef43
parent876ad3e3b8db7a554602b535cf16703409fdc6bb (diff)
plans: add f3s skill split plan (us0)
Plan to sub-divide the oversized f3s skill (38 references, ~4846 lines) into six focused sibling skills (f3s-storage, f3s-k3s, f3s-observability, f3s-raspberry-pi, f3s-workloads, f3s-dtail), leaving f3s as a slim hub index. Documents exact file moves, DRY canonical homes, cross-link fixes, execution order, and risks. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-rw-r--r--plans/f3s-skill-split-plan.md345
1 files changed, 345 insertions, 0 deletions
diff --git a/plans/f3s-skill-split-plan.md b/plans/f3s-skill-split-plan.md
new file mode 100644
index 0000000..9f3e615
--- /dev/null
+++ b/plans/f3s-skill-split-plan.md
@@ -0,0 +1,345 @@
+# Plan: Split the `f3s` skill into smaller sibling skills
+
+Task: **us0** — "look at skill f3s, it has many references within the skill; make a
+plan to create multiple skills out of it so the f3s skill becomes smaller."
+
+This is a **planning-only** document. No skill files are created, moved, or deleted
+here. A future task executes the migration described below.
+
+---
+
+## 1. Where the skill lives (repo scoping)
+
+- `~/.claude/skills` is a symlink chain that resolves into this repo:
+ `~/.claude/skills` → `~/Notes/Prompts/skills` → `/home/paul/git/dotfiles/prompts/skills`.
+- Verified: `git -C ~/.claude/skills/f3s rev-parse --show-toplevel` →
+ `/home/paul/git/dotfiles` (the **same** tree as this dotfiles repo).
+- Consequence: the f3s skill and its future siblings **are committable within
+ dotfiles**. A new directory created under
+ `/home/paul/git/dotfiles/prompts/skills/<name>/` automatically appears under
+ `~/.claude/skills/<name>/` through the symlink — **no per-skill symlink is
+ needed**.
+- This plan document itself lives at `plans/f3s-skill-split-plan.md` (a new
+ `plans/` directory), deliberately **outside** `prompts/skills/` so it is never
+ loaded as skill content.
+
+---
+
+## 2. Current state (grounded numbers)
+
+`prompts/skills/f3s/SKILL.md` — **120 lines / ~13.3 KB**. It is *mostly* a
+"Reference Files" index, but it also **re-inlines** three large sections that
+duplicate their own reference files (a DRY violation flagged by the
+`skill-maintenance` sub-division rules):
+
+- "Raspberry Pi Nodes" + "Webserver Configuration" (SKILL.md lines ~70–110) ⇄
+ duplicates `references/bootstrap-netbsd-pi.md` and `references/pihole-pi.md`.
+- "DTail (dserver)" (SKILL.md lines ~111–115) ⇄ duplicates `references/dtail.md`.
+
+`references/` — **38 files, ~4846 lines total.** Line counts by file:
+
+| Cluster | Files (lines) |
+|---|---|
+| **FreeBSD host / bhyve layer** | hardware.md (60), freebsd-setup.md (202), ups-power.md (77), console-jetkvm-shutdown.md (118), shelly-plug.md (120), rocky-linux-vms.md (226), bootstrap-rocky-bhyve.md (251), f3-rocky-vm.md (113) |
+| **Networking** | wireguard.md (309), remote-access.md (90) |
+| **Storage** (already an index + subfolder) | storage.md (29) → storage/{zfs 90, zrepl 237, carp 95, nfs 204, nfs-mount-monitor 107, troubleshooting 198, usb-keys 116, backups 40} |
+| **k3s** (already an index + subfolder) | k3s-setup.md (12) → k3s-setup/{install 169, remote-access 108, ingress 120, troubleshooting 49}; r-node-deploy.md (144) |
+| **Observability** (already an index + subfolder) | observability.md (35) → observability/{stack 158, freebsd 112} |
+| **Raspberry Pi nodes** | bootstrap-netbsd-pi.md (337), pihole-pi.md (45) |
+| **Workloads (k8s apps)** | immich.md (98), garage.md (158), player.md (167), ychat.md (82), goprecords-uptimed.md (130) |
+| **DTail / dserver** | dtail.md (233), dserver.d (7) |
+
+Existing siblings already carved out of f3s (precedent for this pattern):
+`pkgrepo` (package repositories) and `rocky-vm-setup` (the plain `rocky` VM).
+
+---
+
+## 3. Design principles applied
+
+- **Index pattern** (from `skill-maintenance/references/sub-division.md`): each
+ carved-out skill is a slim `SKILL.md` (overview + When to Use + Reference Files
+ list + optional tiny quick-reference) with all detail in `references/`.
+- **DRY — one canonical home per fact.** Nothing is copied; content is *moved*
+ and everything else *cross-links*. Canonical homes after the split:
+ - **Master host/IP inventory** → stays in `f3s/SKILL.md` (the "Quick Reference:
+ Host IPs" table). Every sibling links back to it instead of copying rows.
+ - **WireGuard mesh / IP assignments** → stays in `f3s/references/wireguard.md`.
+ - **zrepl config** → moves with storage into `f3s-storage`
+ (`rocky-vm-setup` already cross-links this file — see §7).
+ - **DTail package build** stays owned by `pkgrepo`; **DTail dserver
+ deployment/ops** becomes the `f3s-dtail` skill (see §5.6).
+- **Self-triggering descriptions.** Each new `SKILL.md` frontmatter `description`
+ (≤1024 chars, lowercase-`name` ≤64, hyphens) carries distinct keywords so the
+ agent loads the *right* skill for a task instead of the whole f3s bundle.
+- **Refs one level deep.** Subfolders (`storage/`, `k3s-setup/`,
+ `observability/`) migrate wholesale — they are already correctly nested.
+
+### Naming convention
+
+Recommend an **`f3s-` prefix** for every carve-out so they read as one family and
+sort together in the skills list (`f3s-storage`, `f3s-k3s`, …). This is spec-valid
+(lowercase, hyphens, ≤64 chars). The existing siblings (`pkgrepo`,
+`rocky-vm-setup`) are unprefixed subject-names; that alternative is acceptable too,
+but the prefix is preferred here because these skills are tightly bound to the f3s
+homelab and benefit from grouped discoverability. If the user prefers unprefixed,
+use `homelab-storage`, `homelab-k3s`, etc. — pick one convention and apply it
+uniformly.
+
+---
+
+## 4. Proposed target structure
+
+`f3s` shrinks to a **hub/index skill**: overview, When to Use, the master Host-IP
+table, the FreeBSD-host + networking references (the connective tissue every other
+skill depends on), and a "Related skills" list cross-linking the carve-outs.
+
+**Stays in `f3s`:** `hardware.md`, `freebsd-setup.md`, `ups-power.md`,
+`console-jetkvm-shutdown.md`, `rocky-linux-vms.md`, `bootstrap-rocky-bhyve.md`,
+`f3-rocky-vm.md`, `shelly-plug.md`, `wireguard.md`, `remote-access.md`.
+(Rationale: the physical hosts, bhyve layer, power, WireGuard mesh, and off-LAN
+access are cross-cutting context that all other skills reference — the hub keeps
+them so cross-links point *inward* to one stable place.)
+
+**Carved out** into six sibling skills (§5). After the split f3s drops from 38
+reference files to **10**, and the SKILL.md loses its three inlined duplicate
+sections.
+
+---
+
+## 5. New skills — one section each
+
+Each subsection gives: proposed `name`, a spec-style one-line `description`, exactly
+what moves in, and what the f3s hub keeps as a one-line index entry.
+
+### 5.1 `f3s-storage` — highest priority, cleanest move
+
+- **description:** "Reference skill for the f3s homelab storage layer: ZFS
+ (`zdata`), zrepl replication, CARP storage VIP (f0/f1, `f3s-storage-ha`
+ 192.168.1.138), NFS over stunnel, the nfs-mount-monitor watchdog, USB key
+ material, local-path/backups, and storage troubleshooting (incl. thermal). Use
+ when working on homelab storage, ZFS/zrepl, NFS mounts, CARP failover, or disk
+ issues."
+- **Moves in:** `references/storage.md` → **becomes this skill's `SKILL.md`**
+ (converted from index-into-subfolder to a full skill index); the entire
+ `references/storage/` subfolder (`zfs.md`, `zrepl.md`, `carp.md`, `nfs.md`,
+ `nfs-mount-monitor.md`, `troubleshooting.md`, `usb-keys.md`, `backups.md`) →
+ `f3s-storage/references/` (flatten one level: the files sit directly under the
+ new skill's `references/`).
+- **f3s keeps:** one bullet under "Related skills": *Storage → `f3s-storage`
+ skill*.
+- **Why first:** it is the largest cluster (~1116 lines) and is *already* an
+ index+subfolder, so the move is almost mechanical.
+
+### 5.2 `f3s-k3s` — k3s cluster
+
+- **description:** "Reference skill for the f3s k3s Kubernetes cluster: 3-node HA
+ install on r0/r1/r2 Rocky VMs (bootstrap, kubeconfig, PVs, ArgoCD), off-LAN
+ access (jump via OpenBSD frontend → root@r0.wg0 → kubectl), ingress (relayd,
+ cert-manager), etcd recovery, and the reusable Rex r-node rollout. Use when
+ installing, accessing, or troubleshooting the k3s cluster or deploying to r0/r1/
+ r2."
+- **Moves in:** `references/k3s-setup.md` → **becomes this skill's `SKILL.md`**;
+ `references/k3s-setup/` (`install.md`, `remote-access.md`, `ingress.md`,
+ `troubleshooting.md`) → `f3s-k3s/references/`; `references/r-node-deploy.md` →
+ `f3s-k3s/references/r-node-deploy.md`.
+- **f3s keeps:** *k3s cluster → `f3s-k3s` skill*.
+
+### 5.3 `f3s-observability` — monitoring stack
+
+- **description:** "Reference skill for the f3s homelab observability stack:
+ Prometheus, Grafana Alloy, Loki, Tempo, and alerting on the k3s cluster, plus
+ FreeBSD host monitoring (node_exporter + recording rules). Use when working on
+ metrics, logs, traces, dashboards, or alerts for the homelab."
+- **Moves in:** `references/observability.md` → **becomes this skill's
+ `SKILL.md`**; `references/observability/` (`stack.md`, `freebsd.md`) →
+ `f3s-observability/references/`.
+- **f3s keeps:** *Observability → `f3s-observability` skill*.
+
+### 5.4 `f3s-raspberry-pi` — the four Pi nodes
+
+- **description:** "Reference skill for the four Raspberry Pi 3 nodes of the f3s
+ homelab: pi0/pi1 run NetBSD 10.1 (aarch64) serving static f3s.buetow.org /
+ snonux.foo via bozohttpd behind OpenBSD relayd over WireGuard; pi2/pi3 run Rocky
+ Linux 9 with Pi-hole in Docker and LAN wildcard DNS (`*.f3s.lan.buetow.org` →
+ 192.168.1.138). Covers doas/pkgin bootstrap, bozohttpd vhosting, npf, uptimed,
+ content sync, and the doas-alias shutdown pitfall. Use when configuring or
+ troubleshooting the Pi nodes, the static site, or Pi-hole/LAN DNS."
+- **Moves in:** `references/bootstrap-netbsd-pi.md`, `references/pihole-pi.md` →
+ `f3s-raspberry-pi/references/`. **Plus** the inlined SKILL.md sections
+ "Raspberry Pi Nodes" and "Webserver Configuration" — that prose moves into this
+ skill's `SKILL.md`/references (this **fixes** the DRY duplication in §2).
+- **f3s keeps:** *Raspberry Pi nodes → `f3s-raspberry-pi` skill* (one bullet; the
+ master IP table rows for pi0–pi3 stay in the f3s hub table).
+
+### 5.5 `f3s-workloads` — the hosted applications
+
+- **description:** "Reference skill for the application workloads running on the
+ f3s homelab: Immich (photos), Garage (S3), the Player service, yChat (legacy C++
+ chat), and goprecords/uptimed uploads. Covers image build/push, Helm charts,
+ ArgoCD sync, NFS PV/PVC wiring, edge domain routing, and per-app
+ troubleshooting. Use when deploying, updating, or debugging a specific homelab
+ application."
+- **Moves in:** `references/immich.md`, `references/garage.md`,
+ `references/player.md`, `references/ychat.md`,
+ `references/goprecords-uptimed.md` → `f3s-workloads/references/`.
+- **f3s keeps:** *Hosted applications (Immich/Garage/Player/yChat/goprecords) →
+ `f3s-workloads` skill*.
+- **Note:** `ychat.md` explicitly declares itself "the single home for f3s
+ deployment details" — preserve that canonical-home claim in the moved file.
+
+### 5.6 `f3s-dtail` — dserver deployment/ops (recommended)
+
+- **description:** "Reference skill for DTail/dserver deployment across the f3s
+ fleet: distributed log access over SSH on port 2222 — Pis arm64 (NetBSD +
+ Rocky) vs r0–r2 amd64, r-VM root + root.authorized_keys cache, firewalld/npf
+ 2222 rules, systemd timers. Package building lives in the `pkgrepo` skill. Use
+ when deploying, configuring, or troubleshooting dserver on homelab hosts."
+- **Moves in:** `references/dtail.md`, `references/dserver.d` →
+ `f3s-dtail/references/`. **Plus** the inlined SKILL.md "DTail (dserver)"
+ section (fixes the remaining DRY duplication in §2).
+- **f3s keeps:** *DTail / dserver → `f3s-dtail` skill*.
+- **Boundary with `pkgrepo`:** `pkgrepo` owns *package building/publishing*
+ (`dtail-package.md`); `f3s-dtail` owns *runtime deployment/operations*. Keep the
+ existing link `dtail.md` → `../../pkgrepo/references/package-repos.md` — the path
+ depth is unchanged (`skills/<x>/references/` → `../../pkgrepo/...`), so it stays
+ valid after the move.
+- **Alternative:** if a separate skill feels too granular, fold `dtail.md` into
+ `pkgrepo` instead. Recommendation: keep it separate — deployment/ops vs
+ packaging are distinct trigger contexts.
+
+---
+
+## 6. What the slim `f3s` hub looks like afterwards
+
+```
+f3s/SKILL.md (overview, When to Use, master Host-IP table,
+ "Reference Files" for the 10 host/network refs,
+ "Related skills" cross-links to the 6 carve-outs)
+f3s/references/
+ hardware.md freebsd-setup.md ups-power.md console-jetkvm-shutdown.md
+ rocky-linux-vms.md bootstrap-rocky-bhyve.md f3-rocky-vm.md
+ shelly-plug.md wireguard.md remote-access.md
+```
+
+The three inlined duplicate sections are deleted from SKILL.md (their content now
+lives once, in `f3s-raspberry-pi` and `f3s-dtail`). SKILL.md gains a short
+"Related skills" block:
+
+```
+## Related skills
+- f3s-storage — ZFS, zrepl, CARP, NFS/stunnel, backups
+- f3s-k3s — k3s cluster install, ingress, ArgoCD, etcd, r-node Rex
+- f3s-observability — Prometheus/Alloy/Loki/Tempo, node_exporter
+- f3s-raspberry-pi — pi0/pi1 NetBSD static site, pi2/pi3 Pi-hole/DNS
+- f3s-workloads — Immich, Garage, Player, yChat, goprecords
+- f3s-dtail — dserver deployment/ops (port 2222)
+- pkgrepo — package repositories (existing)
+- rocky-vm-setup — the plain `rocky` VM on f3 (existing)
+```
+
+---
+
+## 7. Cross-reference / broken-link fixes (do these as part of each move)
+
+These links exist **today** and will break unless updated. Path rule: a link
+between two skills is `../../<other-skill>/references/<file>.md` (both skills sit
+at `skills/<name>/references/`, same depth).
+
+**Internal f3s links that become cross-skill links:**
+
+| File (after move) | Current link | New link |
+|---|---|---|
+| `f3s-k3s/references/install.md:12` | `../wireguard.md` | `../../f3s/references/wireguard.md` |
+| `f3s-k3s/references/install.md:13` | `../rocky-linux-vms.md` | `../../f3s/references/rocky-linux-vms.md` |
+| `f3s-k3s/references/install.md:110` | `../storage/nfs.md` | `../../f3s-storage/references/nfs.md` |
+| `f3s-k3s/references/install.md:111` | `../storage/nfs-mount-monitor.md` | `../../f3s-storage/references/nfs-mount-monitor.md` |
+| `f3s-k3s/references/troubleshooting.md:49` | `../storage/troubleshooting.md` | `../../f3s-storage/references/troubleshooting.md` |
+| `f3s-observability/references/stack.md:71` | `../k3s-setup/install.md` | `../../f3s-k3s/references/install.md` |
+
+**External skills that link INTO f3s (update these repos' skills too):**
+
+| File | Current reference | Fix |
+|---|---|---|
+| `rocky-vm-setup/references/zrepl.md:12` | `skills/f3s/references/storage/zrepl.md` | → `skills/f3s-storage/references/zrepl.md` |
+| `rocky-vm-setup/SKILL.md:29` (prose) | "full config in `f3s` skill" | → point to `f3s-storage` |
+| `pkgrepo/SKILL.md:35` (prose) | "the `f3s` skill's `bootstrap-netbsd-pi.md`" | → "the `f3s-raspberry-pi` skill" |
+| `pkgrepo/references/client-setup.md:104` (prose) | "the `f3s` skill's `bootstrap-netbsd-pi.md`" | → "the `f3s-raspberry-pi` skill" |
+
+**Stays valid (no change needed):** `f3s-dtail/references/dtail.md:205` →
+`../../pkgrepo/references/package-repos.md` (same nesting depth after the move).
+
+**f3s/SKILL.md index entries** for every moved topic must be rewritten from
+`[Topic](references/<file>.md)` bullets into the "Related skills" cross-links shown
+in §6.
+
+---
+
+## 8. Execution order (for the future implementation task)
+
+Do the carve-outs **one at a time**, cleanest first, verifying links after each:
+
+1. **`f3s-storage`** (largest, already a subfolder index — lowest risk). Move
+ files, promote `storage.md` → `SKILL.md`, write frontmatter, fix the inbound
+ `rocky-vm-setup/references/zrepl.md` link, update f3s SKILL.md.
+2. **`f3s-k3s`** (also a subfolder index). Move files, promote `k3s-setup.md`,
+ fix the 5 outbound links in §7, add `r-node-deploy.md`.
+3. **`f3s-observability`** (subfolder index). Move, promote, fix `stack.md`→k3s
+ link.
+4. **`f3s-workloads`** (flat file cluster — no subfolder). Create skill, move 5
+ files, write a fresh `SKILL.md` index, preserve ychat's canonical-home note.
+5. **`f3s-raspberry-pi`** (flat cluster + de-inline). Move 2 files, **move the
+ inlined SKILL.md Pi/webserver prose out**, update `pkgrepo` prose links.
+6. **`f3s-dtail`** (flat cluster + de-inline). Move `dtail.md`/`dserver.d`, move
+ the inlined DTail section out.
+7. **Slim `f3s/SKILL.md`**: rebuild the "Reference Files" list to the 10 remaining
+ host/network refs, add the "Related skills" block, keep the master Host-IP
+ table as the single canonical inventory.
+8. **Verify** (per `skill-maintenance` "After sub-dividing"): no information lost
+ (moved, not deleted); every SKILL.md bullet resolves; no SKILL.md duplicates a
+ reference; all cross-skill links resolve. Grep sweep:
+ `grep -rn "references/storage\|references/k3s-setup\|references/observability\|bootstrap-netbsd-pi\|pihole-pi\|dtail" prompts/skills/` should return **only** the new skills and updated cross-links.
+9. Commit with `commit-skills`, or a normal dotfiles commit.
+
+For each new skill, write valid frontmatter (`name`, `description`) and validate
+with `pi` — a missing `description` means the skill never loads.
+
+---
+
+## 9. Risks & watch-items
+
+- **Broken cross-references** (§7) are the primary risk — six internal links, four
+ external prose/link references. Fix them in the same commit as each move.
+- **Symlink/discovery:** none needed — `~/.claude/skills` resolves into
+ `prompts/skills/`, so new dirs appear automatically. But confirm each new
+ `SKILL.md` is picked up (`pi` skill list) after creation.
+- **Description keyword overlap:** all six carve-outs mention "f3s homelab". Make
+ the *distinguishing* keywords strong (storage/ZFS, k3s/kubernetes, Pi/Pi-hole,
+ Immich/Garage, dserver) so the agent doesn't load the wrong one — and so it
+ still loads `f3s` (the hub) for host/network/context questions.
+- **DRY regressions:** the master Host-IP table and WireGuard IPs stay canonical in
+ f3s; carve-outs must *link*, not copy rows. Watch that de-inlining the Pi/DTail
+ sections doesn't leave a trimmed copy behind in SKILL.md.
+- **Scope creep:** `wireguard.md` (309 lines) and `remote-access.md` are tempting
+ to carve into an `f3s-network` skill, but they are the connective tissue every
+ other skill links to — keeping them in the hub keeps cross-links pointing to one
+ stable place. Revisit only if the hub is still too large after the six splits.
+- **pkgrepo/rocky-vm-setup live in the same dotfiles repo**, so their link fixes
+ are committable here too (no foreign-repo problem).
+
+---
+
+## 10. Summary of the proposed split
+
+| New skill | Moves in | Approx. lines |
+|---|---|---|
+| `f3s-storage` | storage.md + storage/ (8 files) | ~1116 |
+| `f3s-k3s` | k3s-setup.md + k3s-setup/ (4) + r-node-deploy.md | ~602 |
+| `f3s-workloads` | immich, garage, player, ychat, goprecords-uptimed | ~635 |
+| `f3s-raspberry-pi` | bootstrap-netbsd-pi, pihole-pi + inlined Pi/webserver prose | ~420 |
+| `f3s-observability` | observability.md + observability/ (2) | ~305 |
+| `f3s-dtail` | dtail.md, dserver.d + inlined DTail prose | ~245 |
+| **`f3s` (hub, remains)** | hardware, freebsd-setup, ups-power, console-jetkvm-shutdown, rocky-linux-vms, bootstrap-rocky-bhyve, f3-rocky-vm, shelly-plug, wireguard, remote-access + host-IP table | ~1670 |
+
+Result: `f3s` goes from **38** reference files to **10**, sheds its three inlined
+duplicate sections, and becomes a clean hub that cross-links six focused sibling
+skills (alongside the existing `pkgrepo` and `rocky-vm-setup`).