Flywheel Admin — Drive the ACFS Fleet
Scope: orchestration of remote Flywheel VPSs running ACFS. NOT per-tool reference for ntm/agent-mail/cass/etc. — those have their own skills; this one tells you which to reach for and in what order.
Read first. Always resolve the fleet from your device profile before acting —
profile.servers[](entries taggedflywheel) is the source of truth for the current fleet inventory, SSH aliases, and per-host notes. This skill captures the patterns; your profile captures today's state. See Fleet Resolution below.
Found a bug or missing pattern in this skill? Do NOT try to fix it inline. File an issue at https://github.com/evolv3-ai/vibe-skills/issues with a clear title (e.g.
flywheel-admin: <symptom>), what you were trying to do, the exact command(s) that misbehaved, and the actual vs expected outcome. A repo-side dev workflow watches this tracker and will generate a fix + push a commit. The reason: external agents driving this skill rarely have the full operator context (current fleet inventory, Tailscale state, in-flight session notes) and inline fixes tend to drift from the canonical source. Report → don't patch.
Mental Model
A flywheel is a remote VPS running ACFS: Ubuntu + the Dicklesworthstone agent stack (ntm, agent-mail, beads, cass, dcg, slb, …) + Claude Code / Codex CLI / Gemini CLI. The local machine (Windows host or wsl-hermes) is the operator — it never runs agents itself, it drives swarms on flywheels via SSH (preferred over Tailscale MagicDNS).
Three layers, in dependency order:
- Transport — SSH over Tailscale. If Tailscale is down, fall back to public IP.
- Project — a directory under
/data/projects/<name>on the flywheel with aPRD.md,AGENTS.md, and (usually) a beads database. - Swarm — an
ntmsession of tmux panes, one per agent (Claude/Codex/Gemini), coordinated via Agent Mail + Beads.
You operate at layer 3 most of the time. When something breaks, work down: probe transport, then check project state, then inspect panes.
Fleet Resolution
The fleet is defined in your device profile ($ADMIN_ROOT/profiles/$ADMIN_DEVICE.json),
never in this skill. Each fleet host is a servers[] entry tagged flywheel:
{
"name": "flywheel-1",
"role": "swarm-host",
"sshAlias": "flywheel-1",
"provider": "oci",
"tags": ["flywheel"],
"notes": "Ubuntu 24.04 LTS; watch disk headroom"
}
Enumerate the fleet, then pick a host by role (or by notes when several qualify):
source ~/.admin/.env # ADMIN_ROOT, ADMIN_DEVICE
PROFILE="$ADMIN_ROOT/profiles/$ADMIN_DEVICE.json"
# All flywheel hosts: name, role, sshAlias, notes
jq -r '.servers[]? | select((.tags // []) | index("flywheel"))
| [.name, .role, .sshAlias, (.notes // "")] | @tsv' "$PROFILE"
# One host by role
HOST=$(jq -r '.servers[]? | select((.tags // []) | index("flywheel"))
| select(.role == "swarm-host") | .sshAlias' "$PROFILE" | head -n1)
ssh "$HOST" 'acfs doctor'
No matching entries? STOP. Do not guess hostnames or fall back to hardcoded values — run the one-time migration in references/connect.md to register your fleet, then retry.
Connection is always ssh <sshAlias>; the alias→address mapping lives in your
~/.ssh/config (see references/connect.md for every operator
surface and the public-IP fallback pattern). Throughout this skill, flywheel-N (and
flywheel-N-oci in older examples) stands for a resolved sshAlias from your profile.
The Operator Loop
Every Flywheel session follows this loop. Skip phases you've already done.
1. Discover — what's the fleet doing right now?
# Health snapshot per host (run in parallel if you can)
for h in $(jq -r '.servers[]? | select((.tags // []) | index("flywheel")) | .sshAlias' "$PROFILE"); do
ssh "$h" 'uptime; free -h | head -2; df -h / | tail -1; acfs doctor 2>&1 | tail -5; ntm list'
done
Red flags: load > #CPUs, memory >85 %, disk >75 %, acfs doctor red lines, dead ntm list.
2. Pick a target — which flywheel for this work?
Pick by the role and notes fields of your servers[] entries — per-host facts
(OS version, disk headroom, installed extras like PostgreSQL or beads_rust) belong in
notes, not in this skill. Rules of thumb:
| Need | Pick |
|---|---|
| Stable base for a long-running swarm | the host whose notes mark it LTS/stable |
| Newest stack features | the host whose notes mark the newer stack |
| Two independent swarms in parallel | one host each |
If both are loaded, prefer scaling on the host with the most free RAM rather than spinning a third VPS.
3. Prepare the project
# Create the project dir if new
ssh flywheel-N-oci 'mkdir -p /data/projects/<name>'
# Copy in PRD + AGENTS.md
scp PRD.md AGENTS.md flywheel-N-oci:/data/projects/<name>/
# Optional: clone an existing repo to seed
ssh flywheel-N-oci 'cd /data/projects/<name> && git clone <url> .'
Confirm NTM_PROJECTS_BASE resolves to /data/projects:
ssh flywheel-N-oci 'ntm config get projects_base'
The session name MUST equal the directory basename. Cross-tool breakage between ntm, agent-mail, and beads almost always traces to a mismatch here.
4. Spawn the swarm
# 2 Claude + 1 Codex, classic starter swarm
ssh flywheel-N-oci 'cd /data/projects/<name> && ntm spawn <name> --cc=2 --cod=1'
# Add a Gemini for review-only work
ssh flywheel-N-oci 'cd /data/projects/<name> && ntm spawn <name> --cc=2 --cod=1 --gmi=1'
# Worktree isolation when agents will touch the same files
ssh flywheel-N-oci 'cd /data/projects/<name> && ntm spawn <name> --cc=3 --worktrees'
# Kick the swarm
ssh flywheel-N-oci 'ntm send <name> --all "Read PRD.md and AGENTS.md, then begin."'
For all spawn knobs (recipes, workflows, personas, stagger modes), use the ntm
companion skill, not this one.
5. Drive / monitor
Prefer event-driven tending over polling. Bootstrap once with a snapshot, then block on the attention feed until something happens.
ssh flywheel-N-oci 'ntm --robot-snapshot --robot-format=toon'
ssh flywheel-N-oci 'ntm --robot-wait=<name> --wait-until=attention --timeout=5m'
# Tail a specific pane
ssh flywheel-N-oci 'ntm --robot-tail=<name> --panes=2 --lines=50'
# Inbox / coordination
ssh flywheel-N-oci 'ntm mail inbox <name> --json'
ssh flywheel-N-oci 'ntm locks list <name> --all-agents'
# Send corrective input
ssh flywheel-N-oci 'ntm send <name> --pane=2 "Refactor: extract validateInput into auth/validate.go"'
The fully-developed operator loop (probe-before-interrupt, stuck-pane unstick ladder, when to checkpoint vs respawn) is in references/operator-loop.md.
6. Wrap / recover
# Checkpoint before anything risky (migrations, force-pushes, schema changes)
ssh flywheel-N-oci 'ntm checkpoint save <name> -m "before <thing>"'
# Pull artifacts back to the operator
scp -r flywheel-N-oci:/data/projects/<name>/dist ./
# Tear down a finished swarm
ssh flywheel-N-oci 'ntm swarm stop <name>'
If a swarm is stuck and the panes won't respond, use the unstick ladder in references/operator-loop.md before killing anything.
Skill Mirror
The local .claude/skills/ bundle is the canonical source. After non-trivial changes here, push to every flywheel so all three remote agent families (Claude / Codex / Gemini) see the same set:
# Repeat per flywheel
ssh flywheel-N-oci 'mkdir -p ~/skills-staging ~/.claude/skills ~/.codex/skills ~/.gemini/skills'
# SKILLS_SRC = your canonical local skills bundle (e.g. <repo>/.claude/skills)
scp -r "$SKILLS_SRC/." flywheel-N-oci:~/skills-staging/
ssh flywheel-N-oci 'cp -r ~/skills-staging/. ~/.claude/skills/ \
&& cp -r ~/skills-staging/. ~/.codex/skills/ \
&& cp -r ~/skills-staging/. ~/.gemini/skills/ \
&& rm -rf ~/skills-staging'
For Hermes operators, also mirror to ~/.hermes/skills/ on wsl-hermes (the format is
the agentskills.io open standard — identical to Claude Code). See
references/hermes-notes.md.
Provisioning a New Flywheel
This is the rare path. Don't reach for it unless the existing fleet can't absorb the work.
- Pick a provider —
admin-devops:oci,admin-devops:hetzner,admin-devops:digital-ocean, etc. (each has a dedicated skill). OCI ARM64 Always-Free is the current default. - Bring the VM up via the provider's skill; install Ubuntu 24.04 LTS (LTS, not interim).
- Join your tailnet (
sudo tailscale up --authkey=...). - Bootstrap ACFS:
curl -fsSL https://raw.githubusercontent.com/Dicklesworthstone/agentic_coding_flywheel_setup/main/install.sh | bash -s -- --easy-mode --skip-ubuntu-upgrade. - Verify with
acfs doctor; expect ≥ 40/45 green. - Patch known ACFS-v0.5.0/v0.6.0 quirks — see references/known-quirks.md (ARM64 DCG binary, agent-mail Rust vs Python, bubblewrap, SSH keepalive).
- Mirror the skills bundle (see above).
- Add the new host to
profile.servers[](taggedflywheel) and aHostblock to~/.ssh/configon each operator surface (see references/connect.md).
Quirks (must-know)
- ACFS v0.5.0 is the current pinned version on existing fleet hosts; v0.6.0 is upstream. Refresh
~/.acfs/checksums.yamlbeforeacfs-update --stackor it bails. - DCG aarch64 release tarball ships the wrong-arch binary. Build from source.
- Agent Mail comes in Python and Rust flavors; the Rust one is what ACFS actually wants. Don't trust
acfs doctorrecommending the Python repo. ntm sendexcludes the operator pane by default.--allincludes it. Don't blast a--allto a session you haven't checked.- Session name MUST equal
<projects_base>/<name>basename, or agent-mail registers under a different key than ntm. Most common breakage.
Full list with fixes in references/known-quirks.md.
References
- connect.md — every SSH path from every operator surface (Windows / WSL / tailnet / public-IP fallback) with keys.
- operator-loop.md — phase 5 in depth: tending cadence, unstick ladder, when to checkpoint vs respawn vs swarm-stop.
- known-quirks.md — every ACFS / flywheel-specific gotcha with the exact fix.
- hermes-notes.md — adjustments when this skill is driven by a Hermes agent on wsl-hermes instead of Claude Code on the Windows host.
Companion Skills
This skill orchestrates; the per-tool skills do the actual work. Reach for them when:
| Tool | Skill | When |
|---|---|---|
| ntm | ntm |
Anything pane- or session-level on a flywheel |
| agent-mail | agent-mail |
Reservations, inboxes, contact handshakes |
| beads_rust | beads-br |
Task graph on the flywheel |
| bv | beads-bv |
Graph-aware triage / "what's next" |
| cass / cm | cass, cass-memory |
Cross-session retrieval, procedural memory |
| dcg | dcg |
Destructive-command guard rails |
| slb | slb |
Two-person rule for dangerous commands |
| caam | caam |
Swap AI-provider accounts when rate-limited |
| OCI provisioning | admin-devops:oci |
New flywheels on Oracle Cloud |
| Hetzner / DO / Linode / Vultr | admin-devops:<provider> |
Alternate providers |
| Coolify / KASM | admin-devops:coolify, admin-devops:kasm |
App-hosting layer on top of a flywheel |