# Wild PC > Standing to author, run, govern, and maintain your own software. A personal software platform. Wild PC manages independent services, tools, and frontends — and launches your coding agents — from a single CLI, with a unified gateway, systemd integration, and a web dashboard. Historically, applications have usually been developed by third parties, packaged for distribution, installed through app stores or package managers, and updated through channels controlled by someone other than the user. That model still works for large applications, but it is often too heavy for the small, personal, situational software people increasingly want to create. AI-assisted development changes the shape of this problem. Users can now create useful software directly: small services, scripts, dashboards, agents, automations, and configurations of existing tools. Many of these programs do not need a public release process, an app store listing, or a conventional distribution channel. They need a reliable place to run. Wild PC provides that place. Wild PC gives simple applications a consistent local environment for development, registration, deployment, discovery, and operation. Programs remain independent, but Wild PC provides the surrounding structure: process management, routing, metadata, service lifecycle, logs, and a common interface for running and inspecting the software in your domain. In this sense, Wild PC is a **personal software estate**: a practical way to organize the software you create and run yourself, without requiring every tool to become a fully packaged product. ## How it works Wild PC separates *what software exists* from *how it runs*: - **Programs** — the catalog. A program is a source repo Wild PC knows how to work with (dev verbs, build) and where it lives. One file per program under `~/.wildpc/programs/.yaml`. - **Deployments** — how a program is realized on this node. One file per deployment under `~/.wildpc/deployments/.yaml`, discriminated by its **manager**: | manager | what it is | derived **kind** | |---------|------------|------------------| | `systemd` | a supervised process — or, with a `schedule`, a timer | **service** / **job** | | `caddy` | a static site served by the gateway from a build dir | **static** | | `path` | a CLI installed on your PATH (`uv tool install`) | **tool** | | `none` | an external service on another node (reference only) | **reference** | For `systemd`, a nested `run.launcher` (`python` / `command` / `container` / `compose` / `node`) says *how* the process starts. The **kind** is always *derived* from the manager (+ `schedule`) — never stored. A program can have several deployments — a CLI that is both a `tool` on PATH and a scheduled `job` — so a program has no single kind of its own; it *has deployments*, each with its own. Standing everything up is one honest step: `wildpc apply` renders systemd units and gateway config from your config, then reconciles the runtime to match — activating what's enabled, restarting what changed, deactivating what's disabled. Edit config, `wildpc apply`; `wildpc apply --plan` shows the diff first. ## Stacks Wild PC **stacks** are pre-configured development environments that provide starting points for building Wild PC programs. A stack can define the language, framework, dependencies, tools, conventions, and Wild PC integration needed for a particular kind of application — `python-fastapi`, `python-cli`, `react-vite`, `supabase`. Stacks are designed to work well with coding assistants. They give assistants a consistent target when generating Wild PC programs, making it easier to produce applications that are correctly structured, configured, and ready to run under Wild PC. If your coding assistant understands Wild PC, it can help you create, register, manage, and evolve custom applications more efficiently. A stack seeds a new program's scaffold and default dev-verb commands, but it's optional at runtime: a program stands on its own via its declared `commands:` and `source:`, so you can adopt any existing repo with `wildpc program add` — no stack required. ## Agents Wild PC can launch your coding agents. Declare them in `wildpc.yaml` under `agents:` — each entry is just a command Wild PC runs in a terminal: ```yaml agents: claude: command: claude description: Anthropic Claude Code aider: command: aider args: ["--no-auto-commits"] cwd: /data/repos/my-project ``` The dashboard has a terminal dock that launches any declared agent in a pseudo-terminal (over a WebSocket) and manages live sessions (list, resume, kill). Wild PC is **assistant-agnostic** — it only ever runs `command args` in a pty and never parses the agent's output, so any interactive CLI works. With no `agents:` block set, a sensible default set (`claude`, `opencode`, `amplifier`, …) is offered. ## Quick start **Prerequisites:** a Debian/Ubuntu-family Linux with `apt` and `sudo`, `systemd` (user services), and `git`. `install.sh` sets up everything else — Docker, Caddy, `uv`, and the `wildpc` CLI itself. ```bash git clone ~/wildpc && cd ~/wildpc # One command: installs uv + the wildpc CLI, sets up infra (Docker, Caddy, MQTT, # Postgres), creates ~/.wildpc, registers Wild PC's own control plane, builds the UI. ./install.sh wildpc apply # converge the runtime to config (units, routes, run) wildpc doctor # verify — every check should be green open http://localhost:9000 # the dashboard ``` `wildpc doctor` is your friend at every step: it inspects setup *and* runtime and, for anything not green, prints the exact next command. Run it any time something looks off — after an install, a deploy, or a config change. ### Exposure: from localhost to your own HTTPS domain Localhost is the first rung; you climb only as far as you need. Each rung is a small config change plus `wildpc apply`, and `wildpc doctor` tells you what a rung still needs. | Rung | You get | What it takes | |------|---------|---------------| | **localhost** *(default)* | dashboard + services on `:9000` / `host:port` | nothing — this is the quick start above | | **LAN HTTPS** | real `https://.` on every device on your network, publicly-trusted cert, services stay internal | own a domain; set `gateway.tls: acme` + `domain:`; one wildcard DNS record on your router; a Cloudflare token. → [docs/dns-and-tls.md](docs/dns-and-tls.md) | | **Public** | a chosen service reachable from the internet | `public: true` on the service + a Cloudflare tunnel. → [docs/tunnel-setup.md](docs/tunnel-setup.md) | The jump to LAN HTTPS is the involved one (DNS + a token + binding `:443`). Set `gateway.tls: acme` and run `wildpc doctor` — it enumerates exactly the pieces that are still missing, each with its fix. ## Creating programs `wildpc program create` scaffolds the source **and** its deployment from a stack: ```bash # A service — FastAPI app + a systemd service deployment (health, unit, route) wildpc program create my-api --stack python-fastapi --description "Does something" wildpc program test my-api wildpc apply my-api # render unit + route, then start it # A tool — a CLI installed on your PATH wildpc program create my-tool --stack python-cli --description "Does something" wildpc apply my-tool # installs its path deployment on PATH # A static frontend — built once, served by the gateway wildpc program create my-app --stack react-vite --description "Web interface" wildpc program build my-app && wildpc apply # Adopt an existing repo (no stack needed — dev verbs detected or declared) wildpc program add ~/projects/some-rust-tool ``` ## CLI Operations live under the resource they act on. `program` is the catalog; `service`, `job`, and `tool` are **views** over the one deployment set. Lifecycle is convergence — `wildpc apply` — not a pile of per-kind verbs. ``` # Programs — the software catalog wildpc program list|info|create|add|clone|delete|run wildpc program build|test|lint|type-check|check [name] # dev verbs # Deployment lenses (service = systemd, job = systemd + schedule, tool = path) wildpc service list|info|create|delete|restart|logs wildpc job …same verbs; create takes --schedule wildpc tool list|info # CLIs on your PATH # Platform-wide wildpc apply [name] [--plan] # converge runtime to config — the workhorse wildpc list [--kind K] [--stack S] [--json] # catalog + every deployment view wildpc status # unified runtime status wildpc doctor # diagnose setup + health, with fix hints wildpc restart [name] # imperative bounce (one or all) wildpc gateway # status + route table (inspection) ``` To turn a deployment off, set `enabled: false` in its config and `wildpc apply` — there's no start/stop/enable/install verb; the manager decides the mechanism (systemd unit, PATH install, gateway route), the verb is always `apply`. `wildpc tool list --json` is the machine-readable tool catalog assistants use to build context — it surfaces each tool's actual **executable** (which can differ from the program name, e.g. `litellm-intent-router` installs `intent-router`), its description, and whether it's installed. ## Configuration The registry lives under `~/.wildpc/`: a global `wildpc.yaml` plus one file per resource under `programs/` and `deployments/`. ```yaml # ~/.wildpc/wildpc.yaml — globals gateway: port: 9000 repo: /data/repos/wildpc # resolves `source: repo:` for wildpc's own programs ``` ```yaml # ~/.wildpc/programs/my-api.yaml — the catalog entry description: Does something useful source: /data/repos/my-api stack: python-fastapi ``` ```yaml # ~/.wildpc/deployments/my-api.yaml — a systemd service (derived kind: service) program: my-api manager: systemd run: { launcher: python, program: my-api } expose: { http: { internal: { port: 9001 }, health_path: /health } } proxy: true # served at my-api. manage: { systemd: {} } defaults: env: MY_API_PORT: ${port} # = expose.http.internal.port MY_API_DATA_DIR: ${data_dir} # = $WILDPC_DATA_DIR/my-api API_KEY: ${secret:MY_API_KEY} ``` `defaults.env` is the **single, explicit source** of a deployment's environment — Wild PC injects nothing implicitly. The placeholders `${port}`, `${data_dir}`, `${name}`, `${public_url}`, and `${secret:NAME}` map your program's own env var names to Wild PC's computed values. Secrets live in `~/.wildpc/secrets/` (never in a repo). ## Gateway, DNS & TLS Every gateway-exposed deployment gets its own subdomain — `.` — routed to it by the Caddy gateway (there are no path-prefix routes). Exposure is a single checkbox: `proxy: true` on a service, while a static deployment is inherently served. The dashboard is `wildpc.` and the API `wildpc-api.`; on a node with no domain, `:9000` serves the dashboard plus a `/api` proxy. `gateway.tls` is a per-node choice: `off` (plain HTTP on `:9000`) or `acme` (a real Let's Encrypt wildcard `*.` via a DNS-01 challenge — publicly trusted, no CA to install, while the services stay internal-only). Reaching a service from the public internet is separately opt-in via a Cloudflare tunnel (`public: true`). See [docs/dns-and-tls.md](docs/dns-and-tls.md). ## Layout ``` ~/.wildpc/ # instance: config, artifacts, secrets wildpc.yaml # globals (gateway, repo, agents) programs/ deployments/ # one file per program / deployment secrets/ # secret files (mode 700) artifacts/specs/ # generated Caddyfile, registry.yaml /data/repos// # your program source (absolute source:) /data/wildpc// # per-deployment data volume / # wildpc itself: cli/ core/ wildpc-api/ app/ docs/ ``` **Independence principle:** your programs never depend on Wild PC. They accept configuration (data dir, port, URLs) via environment variables; only Wild PC's own programs (CLI, API, gateway) know Wild PC internals. ## Dashboard & API The **dashboard** (`app/`, served at `wildpc.` or `http://localhost:9000`) lists programs and deployments, edits their config, drives lifecycle, shows the gateway route table and logs, and hosts the agent terminal dock. **`wildpc-api`** (port 9020, proxied at `wildpc-api.`) is the control plane: `/deployments`, `/programs`, `/services`, `/jobs`, `/gateway`, `/status`, an SSE `/stream`, config editing under `/config/…`, and the agent session endpoints under `/agents`. The full endpoint reference is in [CLAUDE.md](CLAUDE.md). ## Mesh (opt-in) Wild PC nodes can discover each other via MQTT + mDNS to form a personal infrastructure mesh — the gateway can route to services on other nodes and the dashboard shows discovered nodes and cross-node routes. It's all off by default; single-node needs none of it. Enable on `wildpc-api` via `WILDPC_API_MQTT_ENABLED` and `WILDPC_API_MDNS_ENABLED`. ## Docs - [docs/registry.md](docs/registry.md) — the registry model, `wildpc.yaml`, deployment fields, lifecycle - [docs/dns-and-tls.md](docs/dns-and-tls.md) — gateway routing, DNS, the `off` / `acme` TLS modes - [docs/stacks/](docs/stacks/) — per-stack guides (python-fastapi, python-cli, react-vite, supabase) - [AGENTS.md](AGENTS.md) — the canonical, assistant-agnostic operator guide (recipes, gateway, tunnel, mesh)