Files
zopu-code/docs/LOCAL_SETUP.md
2026-07-31 18:26:41 +05:30

10 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 (:3585)
  -> Rivet Engine guard endpoint (:6420)
  -> AgentOS registry runner
  -> isolated Pi workspace mounted from the local repository
  -> 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

RIVET_ENDPOINT=http://127.0.0.1:6420
RIVET_PUBLIC_ENDPOINT=http://127.0.0.1:6420
RIVET_WORKSPACE_TOKEN=<random-string-at-least-32-characters>
ZOPU_SOURCE_REPOSITORY=/absolute/path/to/zopu-code
AGENT_WORKSPACE_ROOT=/absolute/path/to/zopu-agent-workspaces

Use the same repository checkout for ZOPU_SOURCE_REPOSITORY. The harness creates Git worktrees beneath AGENT_WORKSPACE_ROOT, copies the source checkout's .env, installs dependencies, and mounts the isolated checkout into AgentOS.

Port 6420 is the Rivet Engine guard endpoint used by the application. 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://<host-reachable-ip>:3585'

Convex runs in the cloud, so FLUE_URL must be reachable from the Convex deployment. 127.0.0.1 and localhost point at Convex's machine, not your laptop. For the current Mac setup, expose Flue over Tailscale and use 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 order matters for the AgentOS path.

1. Start Convex development

bun run dev:server

This watches and publishes functions to the configured Convex cloud development deployment.

2. Start the whole stack

The root dev script starts Rivet Engine, the AgentOS registry runner, Convex, Flue agents, and the web app in one terminal:

pnpm dev

For phone or Tailscale-device access, start the stack with the web server bound to all interfaces:

pnpm dev:tailscale

3. Start Rivet Engine

If you prefer separate terminals, start the engine from the agents package:

cd packages/agents
bun run dev:engine

There must be exactly one local engine listening on 127.0.0.1:6420. Do not start a second engine, and do not use npx rivetkit dev; that command is unavailable in the installed version.

4. Start the AgentOS registry runner

cd packages/agents
bun run runner

The runner registers the AgentOS workspace actor with Rivet Engine. Keep it running whenever a coding attempt or issue-to-PR request may execute.

5. Start Flue agents

For laptop-only access:

pnpm dev:agents

For Convex callbacks or access from another device, bind Flue to all interfaces:

pnpm dev:tailscale:agents

The dev scripts already use port 3585; the Flue CLI defaults to 3583, but the current Zopu configuration and Convex environment use 3585.

If the shell already exports remote Rivet values, shell values override .env. Start Flue with explicit local values:

RIVET_ENDPOINT=http://127.0.0.1:6420 \
RIVET_PUBLIC_ENDPOINT=http://127.0.0.1:6420 \
bun run dev:tailscale:agents -- --port 3585

6. 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 -I http://127.0.0.1:6420
curl -I http://127.0.0.1:3585
curl -I http://127.0.0.1:5173

Any HTTP response confirms the process is reachable; these roots may redirect or return 404 because their 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 both Rivet endpoints use port 6420.
  • Confirm the engine and bun run runner are both running.
  • Confirm ZOPU_SOURCE_REPOSITORY contains .git.
  • Confirm AGENT_WORKSPACE_ROOT is writable.
  • Restart the runner after changing AgentOS registry configuration; Flue hot reload is not enough.

The harness clients require CBOR encoding for host-directory mount descriptors. Do not remove the encoding: "cbor" configuration in packages/agents/src/runtime/agent-os.ts.

AgentOS reports an ACP completed-message resource limit

The workspace registry raises limits.acp.maxCompletedMessageBytes for long Pi coding runs. Restart the runner so the updated registry configuration is registered with Rivet Engine.

Flue connects to a remote Rivet deployment unexpectedly

Environment variables exported by the shell override values loaded from .env. Start Flue and the runner with explicit RIVET_ENDPOINT and RIVET_PUBLIC_ENDPOINT values pointing to 127.0.0.1:6420.

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: