Files
zopu-code/docs/LOCAL_SETUP.md
2026-08-04 01:38:48 +05:30

9.6 KiB

Local Setup

This guide runs the active Zopu stack locally, including the browser chat and the AgentOS issue-to-PR path.

What runs

Browser (React Router/Vite, :5173)
  -> Convex Cloud (durable product state, auth, workflows)
  -> Flue agent server + in-process AgentOS registry (:3585)
  -> 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 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:

bun install --frozen-lockfile

Confirm Git and Tea access before testing issue or PR tools:

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:

cp .env.example .env

At minimum, configure these groups.

Application and Convex

CONVEX_DEPLOYMENT=dev:<deployment-name>
CONVEX_URL=https://<deployment>.convex.cloud
CONVEX_SITE_URL=https://<deployment>.convex.site
SITE_URL=http://localhost:5173
VITE_AUTH_URL=http://localhost:5173
VITE_CONVEX_URL=https://<deployment>.convex.cloud

Flue and model provider

FLUE_DB_TOKEN=<shared-random-token>
FLUE_URL=http://127.0.0.1:3585

AGENT_MODEL_PROVIDER=<provider-name>
AGENT_MODEL_NAME=<model-name>
AGENT_MODEL_API=openai-completions
AGENT_MODEL_BASE_URL=https://<model-endpoint>/v1
AGENT_MODEL_API_KEY=<model-api-key>
AGENT_MODEL_CONTEXT_WINDOW=<positive-integer>
AGENT_MODEL_MAX_TOKENS=<positive-integer>

FLUE_DB_TOKEN must match the value stored in the Convex deployment.

Rivet and AgentOS

# The private Engine control plane this process connects to.
RIVET_ENDPOINT=http://127.0.0.1:6420
# The path where the Engine calls the registry co-hosted in Flue.
RIVET_SERVERLESS_ENDPOINT=http://127.0.0.1:3585/internal/rivet
RIVET_WORKSPACE_TOKEN=<shared-random-workspace-token>
AGENT_WORKSPACE_ROOT=/absolute/path/to/zopu-agent-workspaces

The registry runs in the Flue process; there is no standalone AgentOS runner. RIVET_ENDPOINT and RIVET_SERVERLESS_ENDPOINT have opposite directions and are not interchangeable. Port 6421 is an internal Engine API-peer port and must not be used as RIVET_ENDPOINT.

Gitea

GITEA_URL=https://git.openputer.com
GITEA_TOKEN=<personal-access-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:

bun run dev:setup

Then configure the deployment-scoped values from packages/backend:

cd packages/backend
bunx convex env set SITE_URL 'http://localhost:5173'
bunx convex env set FLUE_DB_TOKEN '<same value as .env>'
bunx convex env set FLUE_URL 'http://<tailscale-ip>: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:

# 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://<tailscale-ip>: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 Flue starts because Flue serves the in-process registry that uses it.

1. Start Convex development

# 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 Flue and the in-process registry

# 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 \
RIVET_SERVERLESS_ENDPOINT=http://127.0.0.1:3585/internal/rivet \
pnpm --filter @code/agents dev -- --port 3585

The Flue development server serves both agent routes and the AgentOS registry at /internal/rivet/*; never start a separate registry runner. If shell exports override .env, set both endpoints explicitly as shown.

4. Start the web application

If you are not using the root dev script, start the web app separately.

For laptop-only access:

pnpm dev:web

For phone or other Tailscale-device access:

pnpm dev:tailscale:web

Open http://localhost:5173, or http://<tailscale-ip>:5173 when using the Tailscale command.

Verify the setup

Check the listeners:

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

Web sends a conversation mutation to Convex
  -> Convex persists the exact message
  -> Convex dispatches to FLUE_URL/agents/zopu/<organizationId>
  -> 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 local AgentOS harness
  -> the harness creates an isolated Git worktree
  -> a Rivet actor boots an AgentOS VM and mounts the worktree
  -> Pi implements the issue and produces a candidate revision
  -> the host pushes a unique branch
  -> Tea creates a Gitea pull request

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 Flue is running with RIVET_ENDPOINT=http://127.0.0.1:6420.
  • Confirm RIVET_SERVERLESS_ENDPOINT points back to the active Flue listener with /internal/rivet appended.
  • Confirm AGENT_WORKSPACE_ROOT is writable.
  • Restart Flue after changing registry configuration; its development server owns the in-process registry.

The harness clients require 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 Flue so the in-process registry picks up its updated actor configuration.

Flue connects to a remote Rivet deployment unexpectedly

Environment variables exported by the shell override values loaded from .env. Start Flue with explicit RIVET_ENDPOINT=http://127.0.0.1:6420 and RIVET_SERVERLESS_ENDPOINT=http://127.0.0.1:3585/internal/rivet.

Gitea issue or PR commands fail

Run:

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:

bunx ultracite check <changed-files>
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: