# Flywheel Admin

> Operator skill for driving the Agentic Coding Flywheel (ACFS) fleet from outside. Use when the user wants to provision, connect to, inspect, deploy PRDs to, or recover Flywheel VPS instances; spawn or tend multi-agent swarms on a flywheel; mirror the local skills bundle to flywheels; or troubleshoot fleet-wide issues. Works for both Claude Code (Windows host) and Hermes agents (WSL/Linux). Triggers: "deploy to flywheel", "spawn a swarm on flywheel-N", "check flywheel health", "provision a new flywheel", "send PRD to flywheel", "what's running on the fleet", "sync skills to flywheels", "flywheel doctor".

- Skill: `evolv3-ai/flywheel-admin` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add evolv3-ai/flywheel-admin`
- Raw SKILL.md: https://api.skillmd.com/api/skills/evolv3-ai/flywheel-admin/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Product & Planning
- Author: evolv3-ai (https://skillmd.com/u/evolv3-ai)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/evolv3-ai/flywheel-admin

---


<!-- TOC: Mental Model | Fleet Resolution | Operator Loop | Skill Mirror | Provisioning | Quirks | References | Companions -->

# 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 tagged `flywheel`) 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](https://github.com/Dicklesworthstone/agentic_coding_flywheel_setup): 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:

1. **Transport** — SSH over Tailscale. If Tailscale is down, fall back to public IP.
2. **Project** — a directory under `/data/projects/<name>` on the flywheel with a `PRD.md`, `AGENTS.md`, and (usually) a beads database.
3. **Swarm** — an `ntm` session 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`:

```json
{
  "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):

```bash
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](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](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?

```bash
# 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

```bash
# 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`:

```bash
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

```bash
# 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.

```bash
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](references/operator-loop.md).

### 6. Wrap / recover

```bash
# 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](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:

```bash
# 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](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.

1. 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.
2. Bring the VM up via the provider's skill; install Ubuntu 24.04 LTS (LTS, not interim).
3. Join your tailnet (`sudo tailscale up --authkey=...`).
4. Bootstrap ACFS: `curl -fsSL https://raw.githubusercontent.com/Dicklesworthstone/agentic_coding_flywheel_setup/main/install.sh | bash -s -- --easy-mode --skip-ubuntu-upgrade`.
5. Verify with `acfs doctor`; expect ≥ 40/45 green.
6. Patch known ACFS-v0.5.0/v0.6.0 quirks — see [references/known-quirks.md](references/known-quirks.md) (ARM64 DCG binary, agent-mail Rust vs Python, bubblewrap, SSH keepalive).
7. Mirror the skills bundle (see above).
8. Add the new host to `profile.servers[]` (tagged `flywheel`) and a `Host` block to
   `~/.ssh/config` on each operator surface (see [references/connect.md](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.yaml` before `acfs-update --stack` or 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 doctor` recommending the Python repo.
- `ntm send` excludes the operator pane by default. `--all` includes it. Don't blast a `--all` to 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/known-quirks.md).

## References

- [connect.md](references/connect.md) — every SSH path from every operator surface (Windows / WSL / tailnet / public-IP fallback) with keys.
- [operator-loop.md](references/operator-loop.md) — phase 5 in depth: tending cadence, unstick ladder, when to checkpoint vs respawn vs swarm-stop.
- [known-quirks.md](references/known-quirks.md) — every ACFS / flywheel-specific gotcha with the exact fix.
- [hermes-notes.md](references/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 |

