91 lines
4.4 KiB
Markdown
91 lines
4.4 KiB
Markdown
# Plan: Migrate `bin/homelab` CLI to Go `oikos homelab`
|
|
|
|
**Status:** Planned (2026-07-07)
|
|
|
|
## Goal
|
|
|
|
Replace `bin/homelab` (265-line Python CLI) with the Go `oikos homelab`
|
|
subcommand already in `cmd/oikos/main.go`. The Python CLI imports the
|
|
now-deleted Python kernel modules (`oikos.approve`, `oikos.decide`, etc.)
|
|
and reads from `/opt/homelab-context/inventory.yaml` — it's disconnected
|
|
from the new DB-backed Go stack. Once the Go CLI matches the Python one,
|
|
`bin/homelab` becomes `ln -s "$(which oikos)" bin/homelab` and the `oikos`
|
|
binary resolves its role from `os.Args[0]`.
|
|
|
|
## Current state
|
|
|
|
| Layer | Python | Go | Gap |
|
|
|-------|--------|-----|-----|
|
|
| `list` | inventory.yaml scan | DB-backed `list_entities` | ✅ done |
|
|
| `whoami` | hostname → inventory lookup | `hostname()` → DB query | ✅ done |
|
|
| `ssh` | resolve mesh IP → `ssh` | same | ✅ done |
|
|
| `secret` | `sops -d` wrapper | `secret list/migrate/export-sops` | ✅ done (Infisical) |
|
|
|
|
## Subcommand migration plan
|
|
|
|
### Phase 1 — Operational commands (P0, this week)
|
|
Core CLI ops every homelab operator uses daily.
|
|
|
|
| Subcommand | Risk | Notes |
|
|
|-----------|------|-------|
|
|
| `pct` | low | SSH to Proxmox host + `pct exec/list`. Currently proxies via SSH. Trivial Go wrapper. |
|
|
| `logs` | low | `journalctl` SSH wrapper. Reuse ssh path from existing Go code. |
|
|
| `restart` | low | `systemctl restart` SSH wrapper. |
|
|
| `status` | medium | Ping + HTTP health check of every host/service. Use DB entity data + scheduler health checks. |
|
|
| `ssh-config` | low | Generate `~/.ssh/config.d/homelab` from DB hosts list. Output-only. |
|
|
| `open` | low | Open a service's URL via `open` (macOS) / `xdg-open` (Linux). |
|
|
|
|
### Phase 2 — Agentic layer (P1, next 2 weeks)
|
|
Oikos agentic commands that already have Go equivalents in `internal/`.
|
|
|
|
| Subcommand | Risk | Notes |
|
|
|-----------|------|-------|
|
|
| `doctor` | low | Health check enrollment: verify age key, homelab-context clone, mesh connectivity. |
|
|
| `service` | medium | Service Console: `explain/health/docs/log/actions/history`. DB-backed — `get_entity_knowledge()` + `tail_log()`. |
|
|
| `decide` | low | Policy classification. Go: `internal/policy/classify.go` already exists. |
|
|
| `approval` | low | Approval requests. Go: `internal/domain/approval.go` exists. |
|
|
| `signal` | medium | Attention layer. Go: `internal/domain/signal.go` exists. |
|
|
| `node` | low | Ontology queries. Go: `internal/ontology/` exists. |
|
|
| `change` | medium | Mutation workflow. Combine `decide` + `approval` + actuator execution log. |
|
|
|
|
### Phase 3 — Infrastructure management (P2, 2-4 weeks)
|
|
|
|
| Subcommand | Risk | Notes |
|
|
|-----------|------|-------|
|
|
| `render-vps-configs` | medium | Renders `vps/*.tmpl` with Infisical secrets. Needs template engine + SSH to VPS. |
|
|
| `sync` | low | Trigger homelab-context sync via launchd/systemd timer. |
|
|
| `apt-audit` | low | dpkg audit per host. SSH wrapper. |
|
|
| `apt-upgrade` | medium | `apt update/upgrade` in detached screen. Needs confirmation. |
|
|
|
|
### Phase 4 — Cleanup (P3, when ready)
|
|
|
|
| Action | Risk | Notes |
|
|
|--------|------|-------|
|
|
| `refresh-creds` | low | **Drop.** Infisical handles secrets now. |
|
|
| `nuke` | destructive | Port or drop. Rarely used; destructive — keep as manual SSH. |
|
|
| `client add/remove` | medium | Client enrollment. Needs secrets-issuance replacement (manual age-keygen now). |
|
|
| `mcp` | low | MCP tool wrapper. Could call the Go MCP client library. |
|
|
| Remove `bin/homelab` | **high** | Replace with symlink `oikos` → `bin/homelab`. The `oikos` binary checks `os.Args[0]` for the `homelab` role. |
|
|
| Remove `bin/oikos` | low | Stale pre-built arm64 binary. Delete. |
|
|
|
|
## Implementation approach
|
|
|
|
Each subcommand is a separate file in `cmd/oikos/homelab/`. The dispatcher
|
|
in `main.go`'s `runHomelabSubcommand()` routes `os.Args` to the right handler.
|
|
All subcommands use `internal/config` for DB connection and share the SSH
|
|
helper from the existing `ssh` subcommand.
|
|
|
|
SSH connectivity (for pct, logs, restart) reuses the mesh-address resolution
|
|
from `internal/domain/` — entity slug → inventory attributes → mesh IP →
|
|
`ssh user@ip`.
|
|
|
|
## Verification
|
|
|
|
- `oikos homelab` without args prints subcommand list (matching Python parity)
|
|
- Each P0 subcommand works end-to-end from mac-mini
|
|
- `bin/homelab` → `oikos` symlink; `homelab list` = `oikos homelab list`
|
|
- `bin/oikos` removed
|
|
|
|
## Changelog
|
|
|
|
- 2026-07-07 — plan created. Cataloged 27 Python subcommands vs 4 Go subcommands. |