CLAUDE.md
Rama main · réplica de lectura del repositorio original.
# AgentPod
Fleet/facilities console for agent runtimes. Three tiers:
- `apps/node-agent` — Go daemon on each host; detects harnesses (hermes, openclaw, claude-code, codex, opencode, pi, muse, kilo — `cmd/agentpod-node/registry.go` is the list), dials the hub over WSS, serves station capabilities (health/logs/fs/terminal/lifecycle/cleanup/acp/changeset), and updates itself from GitHub releases **when asked to** — there is no timer on the node. The trigger is `apn update` on the host, or the hub: one node from the console, or the whole fleet via `fleet nodes update` (which calls `POST /api/nodes/update-all`). Nodes do not drift forward on their own, so after a release the fleet stays where it is until someone rolls it (issue #295).
- `apps/hub` — Bun + Hono + Drizzle/Postgres backend; node gateway, broker, station registry; sign-in and tokens are the organization plane's (`ORG_PLANE_*`). See `apps/hub/CLAUDE.md`.
- `apps/console` — SvelteKit with `adapter-static` (Svelte 5 runes, vite, bits-ui, Tailwind); a client-routed SPA deployed to Cloudflare Pages. It IS SvelteKit — `pnpm check` runs `svelte-kit sync`.
- `packages/contract` — zod schemas shared by hub ↔ agent ↔ console. Change here first when a frame/API shape changes.
## Commands
```bash
cd packages/contract && bun test
cd apps/hub && DATABASE_URL="postgres://agentpod:agentpod-dev-password@localhost:5434/agentpod" bun test
cd apps/node-agent && go test -race ./...
cd apps/console && pnpm check && pnpm test && pnpm build
```
Hub tests REQUIRE both: a **pgvector** postgres on `:5434` (`docker run -d --name agentpod-test-postgres -e POSTGRES_USER=agentpod -e POSTGRES_PASSWORD=agentpod-dev-password -e POSTGRES_DB=agentpod -p 5434:5432 pgvector/pgvector:pg16`) and the explicit `DATABASE_URL` override — bun auto-loads `apps/hub/.env`, which may pin a dev DB. Details: `TESTING.md`.
On an enrolled node, `apn status|stop|start|restart|logs [-f]` and `apn service install|uninstall` manage the node-agent service (systemd on Linux, LaunchAgent on macOS), and `apn telemetry status|enable|disable` (or `fleet nodes telemetry`) sets its OTLP endpoint — see `docs/OPERATING.md`.
## Workflow
- TDD: failing test first, including a regression test for every bug fix.
- Branches: trunk-based on `main` — short-lived branch → PR → `main`. **`develop` is dead** (419 commits behind, last touched 2026-08-08); do not branch from it. Required checks: `contract`, `hub`, `node-agent`, `console`, `worker`; `strict`, so a branch must be up to date before it merges — and nothing, including a workflow, can push straight to `main`. Full flow: `CONTRIBUTING.md`.
- Releases: tag `v*` on `main` → `release-node-agent.yml` publishes binaries + `install.sh` + `SHA256SUMS` (self-update verifies against SHA256SUMS — an incomplete release bricks fleet updates). Nothing else to do: the Fly/worker images default to `releases/latest/download`, so there is no version pin to move. `publish-images.yml` still resolves a concrete release and passes `--build-arg AGENTPOD_VERSION`, so a published image stays reproducible.
- Console production builds need `PUBLIC_HUB_URL=https://hub.agentpod.dev` baked in at build time (a plain build points the deployed console at localhost). Production gets the console only on a `v*` tag, after the hub (`release-hub.yml`); `main` deploys it to staging.
## Gotchas
- Go tests: never leave unreaped children named like pgrep targets (zombies match by comm); macOS SIGKILLs copied system binaries — re-exec the test binary via a `TestMain` env hook for named process stubs.
- Console tests: global teardown in `apps/console/src/vitest-setup.ts` flushes bits-ui's scroll-lock timer — don't remove it, and don't add per-file workarounds.
- Features touching the live fleet get verified against the real deployment before their issue closes; deploy/ops runbooks are `docs/DEPLOYMENT.md` and `docs/OPERATING.md`.