Skip to main content

irclaw-cluster-ops

Use when operating the fleet of Raspberry Pis, NAS hosts, and workstations via irclaw IRC bots, Ansible, Ollama (kimi-k2.5:cloud), or long-running deploys. Covers IRC DM protocol, bot security policy, zellij for long tasks, OS upgrades, and gastown/polecat deployments.

ソース情報

リポジトリ
ryanmaclean/skills
ソースの最終更新活動
2026年4月15日 03:58
検出された SKILL.md の言語
英語
スター
1
フォーク
0

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
irclaw-cluster-ops
description
Use when operating the fleet of Raspberry Pis, NAS hosts, and workstations via irclaw IRC bots, Ansible, Ollama (kimi-k2.5:cloud), or long-running deploys. Covers IRC DM protocol, bot security policy, zellij for long tasks, OS upgrades, and gastown/polecat deployments.
# irclaw Cluster Ops ## IRC / irclaw bot protocol **IRC server:** `ergo:6697` (TLS, Ergo IRC) **Bot nicks:** match hostname — `ubrpiYYY`, `ubrpiYYY`, `i9-zfs-popular`, etc. **Bot model:** `kimi-k2.5:cloud` via Ollama on each host ### DM a bot via irssi (preferred) Use the running irssi session — do NOT try raw OpenSSL connections (bots won't reply to unregistered nicks in time): ```bash # From irssi: /msg ubrpiYYY what's the status of the mix release build? # Or check a command: /msg ubrpiYYY run: df -h ``` To send programmatically from Claude Code, use ansible to poke the bot's local irclaw gateway instead: ```bash ansible ubrpi502 -i ansible/inventory -m raw \ -a "curl -s http://localhost:3000/status 2>/dev/null || journalctl -u irclaw-gateway -n 5 --no-pager" ``` ### Bot security policy — [autonomy] allowed_commands Bots will **refuse** destructive OS-level commands regardless of approval: - `do-release-upgrade` — blocked, use Ansible playbook instead - `rm -rf /` level commands — blocked - Anything not in `allowed_commands` in `~/.irclaw/config.toml` To check what a bot allows: ```bash ansible ubrpi401 -i ansible/inventory -m raw \ -a "grep -A20 '\[autonomy\]' ~/.irclaw/config.toml" ``` To expand allowed commands: edit via `ansible/16-qnas-autonomy-block.yml` pattern or `irclaw-config` skill. ## Long-running tasks — always use Zellij **NEVER use `nohup` or background tasks for deploys.** They get killed by timeouts. ```bash # Create/reuse a named session zellij attach --create gas-city # Run a long task in a named pane (stays alive after command exits for inspection) zellij --session gas-city run --name "pi-deploy-ubrpiYYY" -- bash -c " cd $HOME/rust-town/irclaw && \ ansible-playbook -i ansible/inventory ansible/22-gastown-pis.yml \ --limit ubrpiYYY \ -e 'gastown_cookie=ELIXIR_GASTOWNBEAM2026' \ -v 2>&1 | tee /tmp/pi-deploy-ubrpi502.log echo EXIT: \$? " # Watch log in another pane zellij --session gas-city run --name "log-tail" -- bash -c "tail -f /tmp/pi-deploy-ubrpi502.log" ``` Note: `zellij attach --create` only works interactively. From Claude Code, check for an existing session first: ```bash zellij list-sessions --no-formatting 2>/dev/null | grep -v EXITED | head -5 ``` If no live session exists, ask the user to open one: `! zellij attach --create gas-city` ## Ollama / kimi-k2.5:cloud Ollama runs on coordinators (pop4090, i9, i7). Bots use `kimi-k2.5:cloud` — a cloud-routed model, not local weights. ```bash # Check Ollama on pop4090 curl -s http://10.10.2.34:11434/api/tags | jq '.models[].name' # Query kimi directly curl -s http://10.10.2.34:11434/api/generate \ -d '{"model":"kimi-k2.5:cloud","prompt":"status check","stream":false}' | jq '.response' # Check which model each bot is using ansible ubrpi401 -i ansible/inventory -m raw \ -a "grep 'model\|api_url' ~/.irclaw/config.toml | head -5" ``` ## OS upgrades (22.04 → 24.04) **Always Ansible, never via bot.** Use the existing playbook: ```bash # Dry-run check first ansible ubrpiYYY -i ansible/inventory -m raw \ -a "sudo do-release-upgrade -c" # Full upgrade — run in Zellij, takes 20-30 min + reboot zellij --session gas-city run --name "upgrade-ubrpiYYY" -- bash -c " cd $HOME/rust-town/irclaw && \ ansible-playbook -i ansible/inventory ansible/upgrade-pis.yml \ --limit ubrpiYYY -v 2>&1 | tee /tmp/upgrade-ubrpiYYY.log echo EXIT: \$? " ``` The playbook (`ansible/upgrade-pis.yml`) runs: 1. `dpkg --configure -a` + fix broken packages 2. `apt-get upgrade -y` 3. `DEBIAN_FRONTEND=noninteractive do-release-upgrade -f DistUpgradeViewNonInteractive` 4. Post-upgrade Python install ## ELIXIR_gastown / Polecat deploys **Key facts:** - Release name: `elixir_gastown` (not `gastown`) — path is `_build/prod/rel/elixir_gastown/bin/elixir_gastown` - BEAM node names use `egt@` prefix: `egt@7950x4090pop`, `egt@i9-zfs-pop`, `egt@i7-zfs-pop` - Cookie: `ELIXIR_GASTOWNBEAM2026` - NIF (gastown_nif.so) must be compiled on-host — never rsync macOS `.so` to Linux - `:zstd` is gated on `zstd_available?()` — safe on ARM64 without the NIF **Networking and naming:** - sname (short names) is correct for this cluster — all nodes use sname. Do NOT change to name/longnames. Requires bidirectional /etc/hosts entries on both coordinators and workers for cross-host resolution. - After any deploy, patch /etc/hosts on new workers: add coordinator IPs (i9-zfs-pop=10.0.2.230, 7950x4090pop=10.0.2.34, i7-zfs-pop=10.0.3.117). Also add worker IPs to coordinator /etc/hosts for bidirectional resolution. - GASTOWN_PEERS env var must be set in /etc/gastown-worker.env — this is what application.ex:connect_peers/0 reads. **Build strategy for Pis:** Build once on ubrpi502 (Pi 5, 16GB), distribute tarball to others. ```bash # Verify federation ansible pop4090 -i ansible/inventory -m shell \ --become --become-user $USER \ -a "/opt/gastown/_build/prod/rel/elixir_gastown/bin/elixir_gastown rpc 'Node.list() |> inspect()'" # Clean stale _build before retry (fixes File.RenameError on mix release) ansible ubrpi502 -i ansible/inventory -m shell \ --become --become-user ubuntu \ -a "rm /opt/gastown/_build && cd /opt/gastown && git pull" ``` ## Common mistakes | Mistake | Fix | |---|---| | Assuming BEAM name | Always check with `Node.self()` — it's `egt@7950x4090pop` | | Running long ansible via nohup | Use Zellij — nohup tasks get killed | | DM-ing bots via raw | Use irssi or check status via ansible | | Expecting bot to run `do-release-upgrade` | Use `ansible/upgrade-pis.yml` | | Deploying to all Pis at once | Canary on ubrpi401 first, then roll out | | Pi with ubuntu user | Pis uses `ansible_user=string` — always pass `-e gastown_user=string` | | rsync from macOS for NIF | Compile on-host; exclude `priv/native/` from rsync | | env.sh overrides systemd env | Mix release env.sh runs after EnvironmentFile and hardcodes RELEASE_COOKIE and RELEASE_DISTRIBUTION — fix in rel/env.sh.eex using ${VAR:-default} syntax | | ELIXIR_GASTOWN_PEERS vs ELIXIR_GASTOWN_COORDINATOR_NODE | Application reads ELIXIR_GASTOWN_PEERS but playbook wrote ELIXIR_GASTOWN_COORDINATOR_NODE — workers silently don't auto-connect |
GitHubで見る