$npx -y skills add Soul-Brews-Studio/arra-oracle-skills-cli --skill oracle-up[standard] G-SKLL | Bring up a whole oracle node on a remote host — provision the user, install the full toolchain (maw-js, arra-oracle-skills, arra-oracle MCP v3, omx), create the oracle repo, and stand up its Claude-leader + omx-coder team. Idempotent, dry-run by default. Use w
| 1 | # /oracle-up — Bring Up a Whole Oracle Node |
| 2 | |
| 3 | > "/bud makes a body, /awaken gives a soul — /oracle-up puts the body on a host, hands it tools, and wakes its team." |
| 4 | |
| 5 | Provisions a remote user, installs the full oracle toolchain, creates the oracle repo, and brings up |
| 6 | the standard team (Claude leader + 2 omx coders + 1 sonnet digger) — the proven `noah`/`world.wg` recipe. |
| 7 | |
| 8 | **Idempotent. Dry-run by default. Each phase verifies before the next.** Real mutation only with `--apply`. |
| 9 | |
| 10 | ## Usage |
| 11 | |
| 12 | ``` |
| 13 | /oracle-up oracle-world-oracle --host world.wg --user oracle --port 3463 # dry-run (default) |
| 14 | /oracle-up oracle-world-oracle --host world.wg --user oracle --port 3463 --apply # execute, 1-by-1 |
| 15 | ``` |
| 16 | |
| 17 | Flags: `--name` (positional), `--host`, `--user`, `--port` (maw bind port; pick an unused one), |
| 18 | `--mirror` (default `nat`), `--org` (default `Soul-Brews-Studio`), `--code-root` (default `~/Code`), `--apply`. |
| 19 | |
| 20 | ## Step 0: Timestamp + preflight context |
| 21 | |
| 22 | ```bash |
| 23 | date "+🕐 %H:%M %Z (%A %d %B %Y)" |
| 24 | ``` |
| 25 | |
| 26 | ## The recipe (each phase idempotent; prints "would" unless --apply) |
| 27 | |
| 28 | ### P0 — Preflight (read-only) |
| 29 | - Connectivity: WireGuard ping + `ssh <host> 'whoami'`; out-of-band path (e.g. cloudflared alias) noted as fallback. |
| 30 | - `ssh <host> 'sudo -n true'` (need NOPASSWD sudo on the mirror account), OS check, `getent passwd <user>`. |
| 31 | |
| 32 | ### P1 — User + base tooling |
| 33 | ``` |
| 34 | maw user-onboard --host <host> --user <user> --sudo --mirror <mirror> --with-tooling --port <port> # dry-run |
| 35 | maw user-onboard ... --apply --yes # apply |
| 36 | ``` |
| 37 | Installs: useradd `-m -s /bin/zsh`, sudo group + mirrored `/etc/sudoers.d/<user>`, mirrored |
| 38 | authorized_keys, bun, maw-js, pm2, claude, ghq, fzf, .zshrc v4, .tmux.conf, git-config, maw.config(port), ed25519. |
| 39 | |
| 40 | ### P2 — sshd AllowUsers (the gap user-onboard misses — see homelab#20) |
| 41 | If `/etc/ssh/sshd_config` has an `AllowUsers` line, the new user is denied login with a *generic* |
| 42 | `Permission denied (publickey)` even with perfect keys. Fix: |
| 43 | ``` |
| 44 | sudo sed -i -E '/^AllowUsers /{/\b<user>\b/!s/$/ <user>/}' /etc/ssh/sshd_config |
| 45 | sudo sshd -t && sudo systemctl reload ssh |
| 46 | ``` |
| 47 | Then verify: `ssh <user>@<host> 'whoami && sudo -n true && echo SUDO-OK'`. |
| 48 | ⚠ **fail2ban hazard**: user-onboard's `verify` phase ssh's in *before* the user can log in → |
| 49 | publickey failures → can self-ban your IP (esp. `bantime=-1`). Recover via the out-of-band path: |
| 50 | `fail2ban-client set sshd unbanip <ip>`; persist `ignoreip` for the trusted subnet. |
| 51 | |
| 52 | ### P3 — GitHub key (tool does not push it) |
| 53 | ``` |
| 54 | ssh <user>@<host> 'cat ~/.ssh/id_ed25519.pub' | gh ssh-key add - --title "<user>@<host>" |
| 55 | ``` |
| 56 | |
| 57 | ### P4 — Oracle toolchain |
| 58 | ``` |
| 59 | ssh <user>@<host> 'zsh -lc "bun add -g arra-oracle-skills && arra-oracle-skills install -g -y --agent claude-code"' |
| 60 | # omx (oh-my-codex) for the codex coders — install per its own method |
| 61 | # arra-oracle MCP v3 into the user's ~/.claude.json mcpServers (stdio: bunx --bun arra-oracle-v2@github:Soul-Brews-Studio/arra-oracle-v3#main) |
| 62 | # HEADLESS FLAGS (else claude stops at onboarding/trust dialog): set in ~/.claude.json: |
| 63 | # hasCompletedOnboarding=true, hasTrustDialogAccepted=true, |
| 64 | # projects[<repo>].hasTrustDialogAccepted=true + hasCompletedProjectOnboarding=true |
| 65 | ``` |
| 66 | |
| 67 | ### P4.5 — Code root override (Nat prefers ~/Code, not /opt/<user>/Code) |
| 68 | ``` |
| 69 | ssh <user>@<host> 'git config --global ghq.root /home/<user>/Code && mkdir -p ~/Code' |
| 70 | ``` |
| 71 | |
| 72 | ### P5 — Oracle repo |
| 73 | ``` |
| 74 | gh repo create <org>/<name> --private |
| 75 | # on host as <user>: clone into ~/Code, scaffold ψ/ + CLAUDE.md (or maw bud / run /awaken) |
| 76 | ``` |
| 77 | |
| 78 | ### P6 — Team (the-team-is-a-file, 3-file pattern) |
| 79 | Write **charter** `ψ/teams/<name>-team.yaml` (lead claude48 + coder-1/2 omx + digger sonnet) and |
| 80 | **engine map** `.maw/maw.config.80.json` (commit both; live state in `~/.claude/teams/` is never committed). Spawn: |
| 81 | ``` |
| 82 | maw wake <org>/<name> --wt coder-1 -e omx --session <s> # org-qualified REQUIRED |
| 83 | maw wake <org>/<name> --wt coder-2 -e omx --session <s> |
| 84 | maw wake <org>/<name> --wt digger -e sonnet --session <s> |
| 85 | # lead = claude48 |
| 86 | ``` |
| 87 | **Verify isolation by cwd** (walk each pane pid→cwd; distinct paths), never trust the roster. |
| 88 | Or just `/team-up --gather` (reads the charter). `maw swarm` = shared cwd (read-only); `maw wake --wt` = isola |