Local distribution

One workstation.
Two clean packages.

Forge Local separates the governed Python server from the static browser client. They install together on one Mac, bind on loopback, and need no remote worker, shared control plane, Docker host or source checkout.

1

Package shape

Server and client have different jobs

Local server

Compiled Python runtime, Forge APIs, governance, integrations, workspace templates and native-tool orchestration. It contains no browser frontend in the split build and reads no credential from the package.

server/forge-local-server · forge.backend-package.v1

Browser client

Static HTML, JavaScript, CSS and images only. Inline code is split into fingerprinted assets; Settings is lazy-loaded; immutable assets can be cached independently from the HTML shell.

client/forge-local-client · forge.frontend-package.v1
The binding is explicit.

The local launcher sets FORGE_FRONTEND_DIR to the verified client directory. The server remains the security and data boundary; the client contains no Python, configuration, credentials, tests or repository history.

Measured current client.

The verified v3.1 package serves a 105,970-byte HTML shell. The complete compressed client archive is 5.7 MB; roughly 5.3 MB is optional image content, principally the Forge Pet atlas. The shell is light; the visual asset pack remains the next meaningful client-size target.

2

Build

Create the local package set

venv/bin/python tools/build_local_packages.py \
  --output dist/local/forge-local-<release> \
  --runtime-root /path/to/self-contained/python-3.12 \
  --site-packages venv/lib/python3.12/site-packages \
  --signing-key /private/path/to/forge-release-key.pem

Development builds may replace --signing-key with the explicit --unsigned-development flag. Never put a signing key, connector token, runtime state or generated evidence inside either artifact.

3

Verify and run

Prove the bytes before startup

1

Verify both manifests

Run ./scripts/verify-local.sh. It checks the package-set archive checksums and every server/client file digest. A signed server package also verifies its signature.

2

Run without installing

Use ./scripts/run-local.sh, then open http://127.0.0.1:8787/. Unsigned development builds additionally require FORGE_ALLOW_UNSIGNED_PACKAGE=1.

3

Install for the current user

Run ./scripts/install-macos.sh. Add --service to install the launchd user service. The installer writes a private environment file that joins the server to the client.

4

State and upgrades

Packages are replaceable; evidence is durable

Installed packages

Versioned server and client folders live under ~/Library/Application Support/Forge/releases. A current symlink selects the active pair, making an upgrade or rollback explicit.

Durable local state

Configuration stays under ~/.config/forge; run and evidence state stays under ~/.local/share/forge/state. Upgrading or removing binaries does not silently delete either location.

Uninstall is recoverable.

uninstall-macos.sh removes the launcher and service while preserving packages and state. --remove-packages moves release binaries to Trash; it still does not remove credentials or runtime evidence.

5

Readiness

What green means locally

A release is ready when package verification passes, the UI and /api/health return HTTP 200 on loopback, and the automated suite is green. Optional connectors may remain warnings. A capability that depends on an unavailable connector remains blocked honestly; that warning does not prevent unrelated local capabilities from running.

Source-level instructions: packages/local/SETUP.md. Architecture decision: ADR-0002.