Repo-side rename only (Phases 1-3 of the migration plan); the live box (~/.castle, systemd units, /data/castle, domains) is a separate cutover. - Slug `castle` -> `wildpc`: CLI command, module names (wildpc_core/cli/api), dist names, entry point `wildpc = wildpc_cli.main:main`. - Identifiers: CastleConfig/NATSClient/DirError/MDNS -> Wildpc*. - Env/constants: CASTLE_* -> WILDPC_*; ~/.castle -> ~/.wildpc, castle.yaml -> wildpc.yaml, /data/castle -> /data/wildpc. - Systemd UNIT_PREFIX castle- -> wildpc-; own programs castle-api/gateway/etc. - Display prose "Castle" -> "Wild PC" in docs, agent-guide files, README, frontend. - Package dirs and bootstrap yaml renamed via git mv; lockfiles regenerated; redundant nested uv.lock files dropped (workspace root lock is authoritative). Tests: core 273, cli 47, wildpc-api 120 all pass. Frontend type-checks + builds. Fixed a stale test fixture (secret_env_path kind arg) broken pre-rename.
3.5 KiB
3.5 KiB
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.
The Wild PC monorepo
Wild PC's own programs live in this git repo (source: repo:<name>) — distinct
from the programs you manage, which live under /data/repos/<name>/:
cli/— thewildpcCLI (installed viauv tool install --editable cli/)core/—wildpc_core: manifest models, config loader, generatorswildpc-api/— the FastAPI control-plane service (port 9020)app/— the dashboard frontend (React/Vite; program namewildpc, served atwildpc.<gateway.domain>)
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 onmanager),LaunchSpec,AgentSpec, …core/src/wildpc_core/config.py— config loader (wildpc.yaml+programs/+deployments/→WildpcConfig), the two roots,source:resolutioncore/src/wildpc_core/generators/— systemd unit/timer + Caddyfile generationcli/src/wildpc_cli/— resource-first CLI commands;templates/scaffold.pywildpc-api/src/wildpc_api/— routes, health polling, SSEstream.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)
uv sync
uv run pytest tests/ -v
uv run ruff check . && uv run ruff format .
uv run pyright <paths>
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/caddywhentls: acme. - Systemd user units at
~/.config/systemd/user/wildpc-*.service(+.timer); the unit for programXiswildpc-X.service. Use drop-in*.service.d/*.conffor extra envwildpc applyshouldn't overwrite. - The
containerlauncher resolves docker viashutil.which("docker")(preferred over rootless podman on this box). - Service data at
$WILDPC_DATA_DIR/<name>/; secrets at~/.wildpc/secrets/(mode 700) — never in project directories.