# Local Setup This guide runs the active Zopu stack locally, including the browser chat and the AgentOS issue-to-PR path. ## What runs ```text Browser (React Router/Vite, :5173) -> Convex Cloud (durable product state, auth, workflows) -> Flue agent server + AgentOS registry (:3585, one Node process) -> Rivet Engine control plane (:6420) -> AgentOS workspace actor (Git + repo clone mounted from the local checkout) -> Gitea branch and pull request ``` The active stack does not use `repos/`; that directory is archived reference code. In particular, the old standalone server on port `3590` is not part of this setup. ## Requirements - macOS or Linux - Bun and Node.js matching the repository toolchain (`packages/agents` requires Node `>=22.18 <23 || >=23.6`) - pnpm 11 - Git with SSH access to `git.openputer.com` - [Tea](https://gitea.com/gitea/tea) authenticated to `https://git.openputer.com` - a Convex account with access to the development deployment - an OpenAI-completions-compatible model endpoint and API key Install dependencies from the repository root: ```bash bun install --frozen-lockfile ``` Confirm Git and Tea access before testing issue or PR tools: ```bash git ls-remote origin HEAD tea login list tea issues list ``` The default Tea login should target `https://git.openputer.com`. Never put credentials in committed files. ## Environment Create the local environment file: ```bash cp .env.example .env ``` At minimum, configure these groups. ### Application and Convex ```env CONVEX_DEPLOYMENT=dev: CONVEX_URL=https://.convex.cloud CONVEX_SITE_URL=https://.convex.site SITE_URL=http://localhost:5173 VITE_AUTH_URL=http://localhost:5173 VITE_CONVEX_URL=https://.convex.cloud ``` ### Flue and model provider ```env FLUE_DB_TOKEN= FLUE_URL=http://127.0.0.1:3585 AGENT_MODEL_PROVIDER= AGENT_MODEL_NAME= AGENT_MODEL_API=openai-completions AGENT_MODEL_BASE_URL=https:///v1 AGENT_MODEL_API_KEY= AGENT_MODEL_CONTEXT_WINDOW= AGENT_MODEL_MAX_TOKENS= ``` `FLUE_DB_TOKEN` must match the value stored in the Convex deployment. ### Rivet and AgentOS ```env # The private Engine control plane the registry connects to. RIVET_ENDPOINT=http://127.0.0.1:6420 RIVET_WORKSPACE_TOKEN= AGENT_WORKSPACE_ROOT=/absolute/path/to/zopu-agent-workspaces # Optional: bump when the actor definition changes to drain old actors. RIVET_ENVOY_VERSION=0.0.0 ``` The Hono/Flue Node process hosts the AgentOS registry in **native envoy Mode A** (`registry.startAndWait()`). The registry opens one persistent outbound connection to the Rivet Engine; the Engine routes actor calls back over that connection, so no inbound HTTP callback is required. Port `6421` is an internal Engine API-peer port and must not be used as `RIVET_ENDPOINT`. Do not set `RIVET_SERVERLESS_URL` or `RIVET_SERVERLESS_TOKEN`; they are unused in this topology. ### Gitea ```env GITEA_URL=https://git.openputer.com GITEA_TOKEN= ``` `GITEA_TOKEN` is optional for read-only agent startup but required for the complete issue-to-PR flow unless Tea and Git already have sufficient local credentials. The legacy variables `VITE_FLUE_URL` and `VITE_ZOPU_SERVER_URL` are not used by the active web chat path. ## One-time Convex setup On a new machine, authenticate and configure the Convex development deployment: ```bash bun run dev:setup ``` Then configure the deployment-scoped values from `packages/backend`: ```bash cd packages/backend bunx convex env set SITE_URL 'http://localhost:5173' bunx convex env set FLUE_DB_TOKEN '' bunx convex env set FLUE_URL 'http://:3585' ``` Convex runs in the cloud, so `FLUE_URL` must be reachable from the deployment. `127.0.0.1` and `localhost` point at Convex's machine, not your laptop. For the current Mac setup, expose Flue on the Mac's Tailscale address, for example `http://100.x.y.z:3585`. `SITE_URL` is deployment-scoped and single-valued. Set it to the exact browser origin currently being tested: ```bash # Browser opened locally bunx convex env set SITE_URL 'http://localhost:5173' # Browser opened from another device over Tailscale bunx convex env set SITE_URL 'http://:5173' ``` If work execution uses a separate agent URL, set `AGENT_BACKEND_URL`; otherwise it falls back to `FLUE_URL`. ## Start the stack Run each process in its own terminal. The Engine must be healthy before the agents process starts. ### 1. Start Convex development ```bash # Publish once after backend changes pnpm --filter @code/backend dev:once # Watch and republish while developing pnpm dev:server ``` Both commands run from `packages/backend` and explicitly load the repository-root `.env` with `--env-file=../../.env`. `packages/backend/.env.local` remains Convex CLI metadata for the selected deployment; keep the shared runtime settings in the root `.env`. ### 2. Start the Rivet Engine Start exactly one Engine listening on `127.0.0.1:6420` using the local Engine deployment mechanism. Do not use port `6421` as the application endpoint. ### 3. Start the agents process ```bash # Laptop-only access pnpm --filter @code/agents dev -- --port 3585 # Convex callbacks or access from another device HOST=0.0.0.0 \ RIVET_ENDPOINT=http://127.0.0.1:6420 \ FLUE_URL=http://:3585 \ pnpm --filter @code/agents dev -- --port 3585 ``` This single process serves the Hono/Flue routes **and** starts the AgentOS registry in native envoy Mode A during app module initialization (`registry.startAndWait()`). The registry opens an outbound connection to the Rivet Engine; actor calls are routed back over that connection, so there is no separate runner process and no inbound serverless callback route. If shell exports override `.env`, set `RIVET_ENDPOINT` explicitly. ### 4. Start the web application If you are not using the root `dev` script, start the web app separately. For laptop-only access: ```bash pnpm dev:web ``` For phone or other Tailscale-device access: ```bash pnpm dev:tailscale:web ``` Open `http://localhost:5173`, or `http://:5173` when using the Tailscale command. ## Verify the setup Check the listeners: ```bash curl -fsS http://127.0.0.1:6420/health curl -fsS http://127.0.0.1:3585/health curl -I http://127.0.0.1:5173 ``` The first two commands must return a successful health response; the web root may redirect or return `404` if its functional routes live elsewhere. Then verify behavior in order: 1. Open the web app and sign in. 2. Send a simple chat message and confirm the response streams back through Convex. 3. Ask Zopu to list open Gitea issues. 4. For the full execution path, send `Create a PR for issue #N` for an open, unassigned test issue. 5. Confirm chat immediately reports that the issue was accepted. 6. Follow the Flue server logs for `[create_pr_for_issue]` and wait for a `completed` line with the PR URL. 7. Confirm the branch and pull request in Gitea. The PR pipeline is asynchronous: the initial chat turn acknowledges acceptance, while AgentOS implements, commits, pushes, and opens the pull request in the background. ## Request flow ```text Web sends a conversation mutation to Convex -> Convex persists the exact message -> Convex dispatches to FLUE_URL/agents/zopu/ -> Flue runs the Zopu agent and its typed tools -> responses return to Convex -> the web observes Convex's reactive projection For code execution: -> Flue calls the AgentOS actor through the Rivet Engine -> a Rivet actor boots an AgentOS VM with the project workspace -> the actor clones the repository and runs validated commands -> the actor writes artifacts back through the actor RPC ``` ## Common failures ### Chat stays pending or reports that Flue is unavailable - Confirm Flue is listening on `3585`. - Confirm the Convex deployment's `FLUE_URL` uses a host-reachable address, not `localhost`. - Confirm `FLUE_DB_TOKEN` is identical in `.env` and the Convex deployment. ### Sign-in fails or the browser reports CORS errors Set Convex `SITE_URL` to the exact browser origin. The shared development deployment trusts only the current single value. ### AgentOS fails while mounting the repository - Confirm the Engine is healthy at `http://127.0.0.1:6420/health`. - Confirm the agents process is running and the registry started the envoy connection on startup. - Confirm the process has `RIVET_ENDPOINT=http://127.0.0.1:6420`. - Confirm `AGENT_WORKSPACE_ROOT` is writable. - Restart the agents process after changing the actor configuration; the registry re-registers actor type changes with the engine on startup. The actor client requires CBOR encoding for actor RPC. Do not remove the `encoding: "cbor"` configuration in `packages/agents/src/adapters/agentos.ts`. ### AgentOS reports an ACP completed-message resource limit Restart the agents process so the registry re-registers its updated actor configuration with the engine. ### The process connects to a remote Rivet deployment unexpectedly Environment variables exported by the shell override values loaded from `.env`. Start the agents process with explicit `RIVET_ENDPOINT=http://127.0.0.1:6420`. ### Gitea issue or PR commands fail Run: ```bash tea login list git ls-remote origin HEAD tea issues list ``` Confirm the default Tea login, SSH key, repository remote, and token all target `git.openputer.com`. ## Repository checks After changing source or configuration: ```bash bunx ultracite check bun run check-types bun run check ``` For agent-only changes, run `bun run check-types` from `packages/agents` before the root check. See also: - [`DEPLOYMENT_PLAN.md`](DEPLOYMENT_PLAN.md) for the staging topology and VDS release path - [Rivet AgentOS quickstart](https://rivet.dev/docs/agent-os/quickstart) - [Flue Node deployment](https://flueframework.com/docs/ecosystem/deploy/node)