# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## What this repo is This is **not an application codebase**. It is an operations toolkit: PowerShell wrapper scripts plus context/runbook documentation that let an agent diagnose and manage a single local Proxmox host (`192.168.0.200`, node `thinkcentre`) and the self-hosted Coolify stack running inside its LXC `102`. There is no build, lint, or test step — the "commands" are the operational scripts in `scripts/` and `coolify_skill/scripts/`. User-facing docs are in Spanish; scripts and skill files are in English. ## Core architecture **Everything reaches the host through one SSH path.** There is no direct Docker or local network access. The layering is: ``` PowerShell script → Invoke-ProxmoxSshCommand (scripts/ProxmoxAgent.ps1) → ssh root@192.168.0.200 → pct exec 102 -- docker ... (for any Docker/Coolify container work) ``` - [scripts/ProxmoxAgent.ps1](scripts/ProxmoxAgent.ps1) is the shared library. **Dot-source it** (`. .\scripts\ProxmoxAgent.ps1`) to get `Get-ProxmoxConfig`, `Invoke-ProxmoxSshCommand`, and `Invoke-ProxmoxApi`. Every other script dot-sources it rather than reimplementing connection logic. - **Config resolution:** `Get-ProxmoxConfig` reads env vars (`PROXMOX_HOST`, `PROXMOX_NODE`, `PROXMOX_SSH_KEY`, `PROXMOX_COOLIFY_LXC`, etc.) and falls back to hardcoded local defaults. SSH works with defaults alone; **API calls require `PROXMOX_API_TOKEN_ID` + `PROXMOX_API_TOKEN_SECRET`** (otherwise `Invoke-ProxmoxApi` throws). The Coolify LXC ID (`102`) comes from config — don't hardcode it in new scripts; use `$config.CoolifyLxc`. - Two independent APIs: the **Proxmox REST API** (via `curl.exe -k`, PVE token header) and the **Coolify API** (via `Invoke-RestMethod`, Bearer token, base `https://coolify.urieljareth.org/api/v1`). They use different scripts and different env vars. - Docker is **not** managed on the Proxmox host directly — it lives inside LXC `102`. Any container command must be wrapped as `pct exec 102 -- docker ...`. ## Common commands Run from the project root in PowerShell. ```powershell # Load private secrets (gitignored) — needed for any API call . .\.env.local.ps1 # Smoke test: config + SSH read + Docker sample + API auth (exits 1 on any FAIL) .\scripts\Test-ProxmoxConnection.ps1 # Full inventory snapshot (host, LXC, QEMU, Docker in LXC 102) .\scripts\Get-ProxmoxInventory.ps1 # Arbitrary read-only SSH command .\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct list" .\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct exec 102 -- docker ps -a" # Proxmox REST API (after env token loaded) . .\scripts\ProxmoxAgent.ps1 Invoke-ProxmoxApi -Path "/version" # Coolify container status through LXC 102 .\coolify_skill\scripts\Get-CoolifyDockerStatus.ps1 -All # Coolify API (requires COOLIFY_TOKEN) .\coolify_skill\scripts\Invoke-CoolifyApi.ps1 -Path "/projects" .\coolify_skill\scripts\Invoke-CoolifyApi.ps1 -Method POST -Path "/projects" -BodyJson $body ``` For the Coolify API reference: don't read the whole tree. Search `coolify_skill/references/` with `rg`, then open the single matching `references/ops/*.md` operation file. ## Operating rules (enforced by the skills — follow them) - **Read-only first.** Default to diagnostics: list, status, logs, inspect, health checks. - **Confirm before any state change.** Explicitly ask the user before: `pct`/`qm` start/stop/reboot/destroy; `docker` restart/stop/rm/compose up/down; Coolify deploys or any `POST`/`PUT`/`PATCH`/`DELETE`; env-var writes; and any firewall/network/storage/volume/key/token change. For risky actions, capture current state and state the rollback path first. - **Never write secrets into the repo.** No tokens, passwords, private keys, cookies, or PVE token secrets in Markdown, scripts, or logs. Secrets live only in `.env.local.ps1` (gitignored) or the OS secret store. `.gitignore` also blocks `ACCESS.md`, `*.key`, `*.pem`, `*.crt`, etc. When debugging databases, verify connectivity without echoing credentials. - **Prefer repo scripts over long manual command strings**, and don't run broad destructive commands built from generated strings. ## Docker networking gotcha When a Coolify app and its database are sibling containers on the same Docker network, the app must reach the DB by its **Docker service name, not `localhost`** (e.g. Nextcloud uses host `nextcloud-db`). Service-to-service DNS is the usual root cause of "database connection" failures here — check with `pct exec 102 -- docker exec getent hosts `. ## Where context lives - [docs/proxmox-inventory.md](docs/proxmox-inventory.md) — verified topology, LXC list, observed containers, access model. Treat as the source of truth for current state. - [docs/runbooks/](docs/runbooks/) — concrete procedures: `conexion.md`, `diagnostico.md`, `coolify-docker.md`, `seguridad.md`, plus app-specific `nextcloud.md` and `baserow.md`. - [agent/SKILL.md](agent/SKILL.md) + [agent/TOOLS.md](agent/TOOLS.md) — Proxmox agent operating skill. - [coolify_skill/SKILL.md](coolify_skill/SKILL.md) + [coolify_skill/TOOLS.md](coolify_skill/TOOLS.md) — Coolify agent operating skill and API reference index. - `PROXMOX/`, `proxmox-agent/`, `proxmox-skill/` are **legacy pointer folders** — they only redirect to the live docs above. Don't add content there.