Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.yourhq.ai/llms.txt

Use this file to discover all available pages before exploring further.

Configuration

This is the authoritative reference for every environment variable and configuration knob in yourhq. If you’re trying to figure out what a variable does, whether you need to set it, or why a change you made didn’t take effect, start here. Related reading:
  • Networking — deep dive on NETWORKING_MODE and host vs container networking
  • Agents — agent-specific runtime config (not covered here; lives in agent.json per branch)
  • Features — product-level explanation of workspace features and gateway management

1. Where configuration lives

All stack-level config lives in a single file: .env at the repo root (or at $YOURHQ_HOME/.env, typically ~/.yourhq/.env, if you installed via the curl installer). Docker Compose loads this file automatically — the values are substituted into docker-compose.yml (and the dev overlay docker-compose.dev.yml) at docker compose up time. The installer (installer/install.sh) prompts for the minimum required values and writes .env for you with sensible defaults for everything else. .env.example is the canonical list of supported keys — if a variable isn’t there, it isn’t read by the stack. There are two flavors of variable that behave very differently:
  • Runtime variables — read by the container process when it starts. Change the value in .env, run docker compose up -d <service>, and the new value takes effect. Most variables are runtime.
  • Build-time variables — baked into the container image when docker compose build runs. Changing the value in .env does nothing until the image is rebuilt. HQ no longer uses NEXT_PUBLIC_SUPABASE_* for project config; Supabase browser config is injected at runtime from the project registry.
The installer always runs docker compose pull (and falls back to build if the image isn’t in the registry), so on a fresh install the distinction is invisible. It only matters when you edit .env later.

2. Grouped environment variable reference

Each variable below lists: Name / Required / Default / What it does / When to override.

2.1 Supabase (managed by the UI, not .env)

The gateway, dispatcher, and runner each read Supabase credentials from two sources in this order:
  1. Environment variables (SUPABASE_URL + SUPABASE_SERVICE_ROLE_KEY) if set.
  2. Project registry at /config/projects.json + /config/secrets.json (written by the UI’s onboarding screen and mounted read-only into the gateway services).
The normal path is (2) — you never touch .env for Supabase. The onboarding screen writes the creds to the shared ui-config volume, the gateway polls /config on boot and picks them up automatically. Use (1) only as an override — e.g. a remote gateway that must always point at a specific project regardless of what the UI’s active project is.
  • SUPABASE_URLOptional override. No default. If set, takes precedence over the registry.
  • SUPABASE_SERVICE_ROLE_KEYOptional override, secret. No default. If set, takes precedence over the registry.
  • EMBEDDING_API_KEYOptional. Empty. OpenAI API key used by the gateway to embed documents when the knowledge-base vector search is enabled. Override to enable embeddings; leave empty to disable.
Where the real creds live: the project registry files (/config/projects.json for URL + anon key, /config/secrets.json for service role key). Don’t edit these by hand — use the onboarding screen on first boot, or Settings → Projects afterward. secrets.json is mode 0644 inside the Docker-managed config volume so the UI, gateway, runner, and dispatcher containers can all read it despite running as different users. The host-level Docker volume directory is the real filesystem boundary. Treat the host and every container in the Compose stack as trusted.

2.2 Gateway identity

These let one Supabase project host multiple independent gateway hosts (your laptop, a Mac mini, a VPS) without them stepping on each other.
  • GATEWAY_IDRequired. Default default. Unique slug per gateway within a Supabase project. Becomes the slug column in the gateways table. Override when you bring up a second gateway against the same Supabase (e.g. mac-mini, vps-eu).
  • GATEWAY_LABELOptional. Default Primary gateway. Human-readable label shown in the UI’s gateway picker. Override for anything you’d show a person.
  • WORKSPACE_SLUGRequired. Default my-workspace. The workspace slug you pick in the setup wizard. Used as the prefix for per-agent git branches in the gateway’s local repo (branches are named ${WORKSPACE_SLUG}/${agent_slug}). Must match the slug in the UI’s workspace record — if you change it after install, rename branches accordingly.
  • COMPOSE_PROJECTOptional. Default yourhq. Namespaces Compose containers and volumes (you’ll see yourhq-ui, yourhq-gateway, etc.). Override if you’re running two parallel stacks on one host (e.g. yourhq-staging).

2.3 Networking

Host-level networking decisions: local-only vs Tailscale vs public HTTPS. The installer sets all five of these together based on the mode you pick. See Networking for the full topology.
  • NETWORKING_MODERequired. Default local. One of local / tailscale / public. Purely informational for the containers — it’s written into the gateways.meta.networking_mode column so the UI knows how to build URLs. The actual binding behavior is controlled by the *_HOST_PORT variables below.
  • HOST_REACHABLE_URLRequired. Default http://localhost. The URL users hit in their browser, minus the port. Installer sets this to http://localhost for local, http://<host-ts-ip> for tailscale, or https://<your-domain> for public. The gateway writes it into Supabase so the UI can build links to noVNC and the files-API.
  • UI_HOST_PORTOptional. Default 127.0.0.1:3000 (loopback-only, safe). The installer flips this to 0.0.0.0:3000 when you pick Tailscale or Public mode. Manually override to 0.0.0.0:3000 when you want the host’s network interfaces (Tailscale, public) to decide reachability.
  • NOVNC_HOST_PORTOptional. Same shape as UI_HOST_PORT, default 127.0.0.1:6901. Installer flips to 0.0.0.0:6901 for Tailscale/Public modes. Keep loopback-only unless you trust the host’s network — noVNC only has a generated VNC password as auth and should never be on the public internet without a reverse proxy.
  • FILES_API_HOST_PORTOptional. Default 127.0.0.1:18790 (loopback-only). The files-API only needs to be reachable from outside the host when the UI lives on a different machine (Tailscale cross-host). Single-host installs can leave it on loopback — the UI reaches it internally via Docker DNS (http://gateway:18790).
  • NOVNC_BINDOptional. Default local. One of local (websockify binds 0.0.0.0:6901 inside the container, Docker port-mapping decides real exposure) or off (don’t start noVNC at all). Override to off if you don’t need remote desktop.
  • VNC_PASSWORDOptional, secret. Empty. The VNC password for the in-container desktop. Auto-generated on first boot if empty; the generated value is saved to $OPENCLAW_HOME/.vnc-password inside the gateway-state volume. Override if you want a specific known password.

2.4 Files-API (UI file browser)

The gateway runs an HTTP API (files_api.py) that the UI calls to read/write files inside per-agent git worktrees. Auth is a shared bearer token.
  • GATEWAY_AUTH_TOKENRequired (secret) if you want the file browser. Empty by default. Shared secret between the UI and the gateway’s files-API. Generate with openssl rand -hex 32. Must be identical in both the ui and gateway services — since both read the same .env, this is automatic. If empty, the gateway doesn’t start the files-API at all.
  • GATEWAY_URLOptional. Default http://gateway:18790. Where the UI reaches the files-API. Leave at the default for same-host Compose stacks (uses Docker’s internal DNS). Override to http://<gateway-host-ts-ip>:18790 when UI and gateway live on different machines connected over Tailscale.
  • FILES_API_BINDOptional. Default docker. One of docker (listens on the Docker internal network only — UI reaches via gateway:18790), any (binds 0.0.0.0 inside container; host port-mapping decides exposure), or off (disable the files-API). Override to any when the UI is on a remote host.
  • FILES_API_PORTOptional. Default 18790. In-container port for the files-API. Rarely worth changing.

2.5 Templates

  • TEMPLATES_SOURCEOptional. Empty. When empty, the gateway seeds its bare repo from the templates bundled in /opt/templates inside the image. Override with git+https://github.com/your-org/your-templates.git to seed from your own repo instead. Only read on first boot when the gateway creates its bare repo — changing it later won’t re-seed existing branches.

2.6 Git remote sync (optional, backup)

Lets the gateway push per-agent branches to an external git remote so your agents’ memory and skills are backed up and optionally reachable from other devices. Two configuration paths — pick one. Path A: generic remote (works for any git host — GitHub, Gitea, self-hosted)
  • GIT_REMOTE_URLOptional. Empty. If set, added as the origin remote of the gateway’s bare repo. Examples: https://x-access-token:[email protected]/org/repo.git, [email protected]:org/repo.git, https://git.example.com/agents.git.
  • GIT_DEPLOY_KEYOptional, secret. Empty. SSH private key (full multiline PEM, keep surrounding double-quotes in .env so newlines survive). Only needed for SSH remotes.
Path B: GitHub shorthand (for GitHub only, no URL construction) If GIT_REMOTE_URL is empty AND all three GITHUB_* vars below are set, the gateway synthesizes https://x-access-token:[email protected]/$GITHUB_REPO_OWNER/$GITHUB_REPO_NAME.git at boot.
  • GITHUB_TOKENOptional, secret. Empty. Fine-grained PAT with Contents: Read and write on the target repo. Classic PATs with repo scope also work.
  • GITHUB_REPO_OWNEROptional. Empty. GitHub user or org that owns the repo.
  • GITHUB_REPO_NAMEOptional. Empty. Repo name only (no owner prefix).
How sync works. When either path is configured, the gateway installs a post-commit git hook on the bare repo that async-pushes every commit to origin. No scheduled sync, no batching — every commit (from add-agent.sh, file-browser edits, or an agent calling save_progress) lands on the remote within seconds. The runner also runs a GIT_SYNC_INTERVAL-second backup sweep that commits dirty worktrees and fast-forwards any branches that moved on the remote. Without a remote, all of this still works locally — commits just don’t leave the gateway’s volume.

2.8 Runtime tuning

Control loops in the dispatcher and runner daemons. Defaults are sensible; override only when instrumenting or tuning latency.
  • POLL_INTERVALOptional. Default 30. Seconds between command-queue polls by the runner. Lower for faster command pickup at the cost of more Supabase requests.
  • COMMAND_TIMEOUTOptional. Default 120. Seconds a single command can run before the runner kills it and marks it failed.
  • RECONCILE_INTERVALOptional. Default 60. Seconds between dispatcher reconciliation passes (checking for orphaned inbox items, stale leases, etc.).
  • WAKE_COOLDOWNOptional. Default 30. Seconds the dispatcher waits before re-waking an agent that just failed.
  • GIT_SYNC_INTERVALOptional. Default 1800 (30 min). Seconds between backup-sweep passes in the runner (commits dirty worktrees, fast-forwards branches that moved on the remote). Set to 0 to disable the sweep entirely — event-driven commits and the post-commit auto-push still work.

2.9 Image overrides

Pin specific image tags for reproducible production deploys. All four default to :latest.
  • UI_IMAGEOptional. Default ghcr.io/yourhq/yourhq-ui:latest.
  • GATEWAY_IMAGEOptional. Default ghcr.io/yourhq/yourhq-gateway:latest.
  • DISPATCHER_IMAGEOptional. Default ghcr.io/yourhq/yourhq-dispatcher:latest.
  • RUNNER_IMAGEOptional. Default ghcr.io/yourhq/yourhq-runner:latest.
Override to ghcr.io/yourhq/yourhq-<svc>:2026.04.20 (or similar date-pinned tag) for production. Don’t pin in dev — you want to track :latest.

2.10 Codespaces / reverse-proxy origin allowlist

Next.js enforces an origin allowlist on server actions and form submissions. When the UI is fronted by a reverse proxy or GitHub Codespaces port-forward, the apparent origin differs from localhost:3000 and requests get rejected as CSRF. These variables extend the allowlist.
  • CODESPACE_NAMEAuto-set by GitHub Codespaces. Don’t set manually.
  • GITHUB_CODESPACES_PORT_FORWARDING_DOMAINAuto-set by GitHub Codespaces. Don’t set manually. Combined with CODESPACE_NAME by the UI to whitelist the forwarded URL.
  • ALLOWED_ORIGINSOptional. Empty. Comma-separated list of extra origins to allow (e.g. https://hq.example.com,https://staging.example.com). Set this when running behind any non-Codespaces reverse proxy with a public domain.

3. Runtime Supabase config — no more NEXT_PUBLIC bake-in

The UI used to bake NEXT_PUBLIC_SUPABASE_* into the client bundle at build time, which meant every user had to docker compose build ui locally to stamp in their own Supabase values. That’s gone. Now the UI reads its Supabase config at runtime from the project registry (/config/projects.json + /config/secrets.json). The root layout renders a <script>window.__HQ_CONFIG__ = {...}</script> tag based on the active project’s cookie, so the client bundle picks up whoever’s connected without a rebuild. Practical consequences:
  • The GHCR yourhq-ui:latest image works for every user. No docker compose build ui required — ever.
  • Changing Supabase creds is a UI action (Settings → Projects → Rotate), not a rebuild.
  • NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY env vars are no longer read by the UI. Leave them unset.

4. Secrets handling

Every secret lives in plaintext in .env on disk. The installer chmod 600 the file, which is the only layer of protection. Don’t commit .env, don’t paste it into issues, don’t ship it in backups unencrypted. If one of these leaks:
  • SUPABASE_SERVICE_ROLE_KEY — bypasses RLS and can read/write every row. High severity. Rotate in Supabase dashboard (Project Settings → API → “Generate new service_role key”). Update the affected project in Settings → Projects, or update .env if you use env overrides. Restart gateway services after changing env overrides. Audit audit_log for suspicious activity.
  • UI anon key (stored in /config/projects.json per project) — subject to RLS, so damage is bounded by your policies. Rotate in the Supabase dashboard, then update it via Settings → Projects → the affected project in the UI.
  • GATEWAY_AUTH_TOKEN — auth between UI and files-API. Rotate by picking a new value (openssl rand -hex 32), writing it to .env, and running docker compose up -d ui gateway (both services must restart together so they agree on the token).
  • GIT_DEPLOY_KEY — rotate in the git host (GitHub → repo settings → Deploy keys), put the new key in .env, then docker compose up -d gateway. The gateway recreates ~/.ssh/openclaw_deploy_key if it’s missing, but it doesn’t overwrite an existing one — you may need to docker compose exec gateway rm /home/openclaw/.ssh/openclaw_deploy_key first.
  • GITHUB_TOKEN — rotate the PAT on GitHub (or revoke it), update .env, then docker compose up -d gateway so the entrypoint rebuilds the remote URL with the new token. Existing commits stay local even if the token is revoked — they push to the new remote on the next boot.
  • VNC_PASSWORD — rotate by changing the value in .env, then delete the existing hash: docker compose exec gateway rm /home/openclaw/.vnc/passwd, then docker compose up -d gateway.
  • TAILSCALE_AUTH_KEYhost-level, not container-level. The stack no longer runs Tailscale inside any container. The auth key is used once by the installer to run tailscale up on the host. If leaked, revoke in the Tailscale admin console (Settings → Keys) and generate a new one — no container restart needed. Use single-use keys in production and reusable keys only for convenience during setup.

5. Configuring for development

docker-compose.dev.yml is an overlay that runs the UI in next dev mode with source mounted for live-reload, and mounts the gateway daemons from source so edits take effect on restart (no rebuild). Usage:
docker compose -f docker-compose.yml -f docker-compose.dev.yml up
No environment variables change between production and development — the dev overlay only changes volume mounts, commands, and the UI image (node:24-slim instead of the prebuilt UI image). Your .env works as-is. Supabase creds for the UI come from the project registry in both modes, so there’s no “did I rebuild” confusion.

6. First-boot setup (non-env configuration)

A lot of yourhq’s configuration is runtime-configurable via the UI, not via environment variables. Once the stack is up and you’ve logged in, visit:
  • /setup — the six-step workspace setup wizard. Seeds workspace (name, slug, owner profile), pipeline_stages, field_definitions, and initial streams in one RPC call. New workspaces are redirected here automatically until workspace.initialized = true.
  • /dashboard/settings — add or edit pipeline stages, custom field definitions, streams, automations, and agent identities after the initial setup. Most per-workspace behavior lives here, not in .env.
  • /dashboard/agents — the agent creation wizard (three steps: template → identity → Telegram). See Agents for agent-specific configuration (each agent has its own agent.json committed to its git branch).
Rule of thumb: if it varies between workspaces of the same deployment, it’s probably in the DB and configured in the UI. If it’s infrastructure-level (where Supabase lives, how the host is networked, which git remote to back up to), it’s in .env.

7. Changing configuration after install

Edit .env, then run the appropriate Compose command to pick up the change. The right command depends on which service owns the variable and whether it’s build-time or runtime.

UI runtime variables (non-NEXT_PUBLIC_*)

SUPABASE_SERVICE_ROLE_KEY, GATEWAY_URL, GATEWAY_AUTH_TOKEN, ALLOWED_ORIGINS:
docker compose up -d ui

UI project config (no rebuild required)

Supabase URL, anon key, service role key per project live in the project registry on the ui-config volume, not in .env. Change them via the UI (Settings → Projects → Edit / Rotate) — takes effect immediately on the next request.

Gateway variables

TEMPLATES_SOURCE, GIT_REMOTE_URL, GIT_DEPLOY_KEY, GITHUB_TOKEN, GITHUB_REPO_OWNER, GITHUB_REPO_NAME, GATEWAY_AUTH_TOKEN, FILES_API_BIND, FILES_API_PORT, NOVNC_BIND, VNC_PASSWORD, NETWORKING_MODE, HOST_REACHABLE_URL:
docker compose up -d gateway
Note: TEMPLATES_SOURCE is only read on first boot when the bare repo is seeded. Changing it later has no effect unless you also wipe the gateway-state volume (destructive — you lose all agent branches).

Dispatcher / runner variables

POLL_INTERVAL, COMMAND_TIMEOUT, RECONCILE_INTERVAL, WAKE_COOLDOWN:
docker compose up -d dispatcher runner

Networking / port-binding changes

UI_HOST_PORT, NOVNC_HOST_PORT, FILES_API_HOST_PORT — changing a port binding doesn’t register with a plain up -d; Compose considers the container “already running” with no relevant change. Force recreation:
docker compose up -d --force-recreate

Compose project / gateway identity

COMPOSE_PROJECT, GATEWAY_ID — changing either creates new containers and (for COMPOSE_PROJECT) new volumes. Your old stack’s state is orphaned but not deleted. Only change these when you actually want a fresh namespace; otherwise the safer path is to leave them alone.

Image overrides

UI_IMAGE, GATEWAY_IMAGE, DISPATCHER_IMAGE, RUNNER_IMAGE:
docker compose pull && docker compose up -d

Gateway Supabase keys

Changing the gateway’s Supabase connection (SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY) affects the gateway, dispatcher, and runner. UI Supabase creds live in the project registry and don’t need any restart:
docker compose up -d gateway dispatcher runner

Troubleshooting checklist

  • “The UI loads but login fails” — the active project in the registry may have wrong creds. Open Settings → Projects → Edit or Rotate to fix, no restart needed.
  • “File browser says 401 / auth error”GATEWAY_AUTH_TOKEN differs between UI and gateway, or is empty. Set it identically in .env and run docker compose up -d ui gateway.
  • “Changed the port but the old one still works” — port bindings need --force-recreate (section 7).
  • “Changed TEMPLATES_SOURCE but I still see old templates” — it’s only read on first boot. See section 2.5.
  • “Gateway keeps trying to reach the wrong URL”HOST_REACHABLE_URL is written into Supabase by the gateway at startup; fix .env and restart the gateway, not the UI.