# Developing Wild PC How to work on **Wild PC's own code** — the CLI, core library, control-plane API, and dashboard. For *using* Wild PC to manage software (create/deploy/expose programs), see the operator guide in [`AGENTS.md`](../AGENTS.md). ## The Wild PC monorepo Wild PC's own programs live in **this git repo** (`source: repo:`) — distinct from the programs you manage, which live under `/data/repos//`: - `cli/` — the `wildpc` CLI (installed via `uv tool install --editable cli/`) - `core/` — `wildpc_core`: manifest models, config loader, generators - `wildpc-api/` — the FastAPI control-plane service (port 9020) - `app/` — the dashboard frontend (React/Vite; program name `wildpc`, served at `wildpc.`) The root `pyproject.toml` is the **uv workspace** (core, cli, wildpc-api). ## Key files - `core/src/wildpc_core/manifest.py` — Pydantic models: `ProgramSpec`, `DeploymentSpec` (discriminated union on `manager`), `LaunchSpec`, `AgentSpec`, … - `core/src/wildpc_core/config.py` — config loader (`wildpc.yaml` + `programs/` + `deployments/` → `WildpcConfig`), the two roots, `source:` resolution - `core/src/wildpc_core/generators/` — systemd unit/timer + Caddyfile generation - `cli/src/wildpc_cli/` — resource-first CLI commands; `templates/scaffold.py` - `wildpc-api/src/wildpc_api/` — routes, health polling, SSE `stream.py`, mesh, and the agent terminal UX (`agents.py`, `pty_session.py`, `agent_sessions.py`, `agent_registry.py`) - `ruff.toml` / `pyrightconfig.json` — shared lint/type config ## Commands (all projects use uv) ```bash uv sync uv run pytest tests/ -v uv run ruff check . && uv run ruff format . uv run pyright ``` Running `uv sync` from a member subdir trims the shared workspace venv — resync from the repo root to restore all members. Code style: **ruff** (100-char lines), **pyright**, **pytest** + **pytest-asyncio**; Python **3.13** for services, **3.11+** for tools/libraries. ## wildpc-api endpoints (port 9020) - Core: `GET /health`, `GET /stream` (SSE: health, service-action, mesh) - Converge: `POST /apply` (`{name?, plan?}`) — the one lifecycle endpoint - Deployments: `GET /deployments[/{name}]`, `GET /status` - Catalog + editing: `GET /programs[/{name}]`, `POST /programs/{name}/{action}` (dev verbs only), `PUT|DELETE /programs/{name}`; likewise `/services`, `/jobs` - Config: `GET|PUT /`, `POST /config/apply`, `PUT /config/deployments/{name}/enabled` - Gateway: `GET /gateway`, `GET /gateway/caddyfile`, `PUT /gateway/config` (making routes live is convergence: `POST /apply`) - Mesh: `GET /mesh/status`, `GET /nodes[/{hostname}]` - Agents (dashboard terminal UX): `GET /agents`, `GET /agents/sessions`, `GET /agents/history`, `DELETE /agents/sessions/{id}`, `WS /agents/{name}/session` - Service actions: `POST /services/{name}/restart`, `GET /services/{name}/unit` ## Infrastructure internals - Generated Caddyfile at `~/.wildpc/artifacts/specs/Caddyfile`; a **plugin Caddy** at `/usr/local/bin/caddy` when `tls: acme`. - Systemd user units at `~/.config/systemd/user/wildpc-*.service` (+ `.timer`); the unit for program `X` is `wildpc-X.service`. Use drop-in `*.service.d/*.conf` for extra env `wildpc apply` shouldn't overwrite. - The `container` launcher resolves docker via `shutil.which("docker")` (preferred over rootless podman on this box). - Service data at `$WILDPC_DATA_DIR//`; secrets at `~/.wildpc/secrets/` (mode 700) — never in project directories.