# Claude Code home directory (default: ~/.claude) # Override this if your Claude Code data is in a different location, e.g.: # CLAUDE_HOME=~/.codefuse/engine/cc # CLAUDE_HOME=~/.claude # A value saved from Settings (CLAUDE_HOME, CODEX_HOME, a pinned DASHBOARD_DATA_DIR) # goes to ~/.config/agenthub/settings.env (AGENTHUB_SETTINGS_FILE). This file wins # over it, and the real environment wins over both; a key set here or in the real # environment is reported as env-owned in Settings (a value saved there would be # overridden again at the next start). # ── Server / network ──────────────────────────────────────────────────────── # Port to listen on (default: 4820) # DASHBOARD_PORT=4820 # Directory the built client is served from in production (default: client/dist). # The `agenthub` plugin install points this at ~/.claude/agenthub/runtime/client-dist # because the plugin cache directory is read-only and replaced on every update. # DASHBOARD_CLIENT_DIST= # Interface to bind. SECURITY: defaults to 127.0.0.1 (loopback) so the dashboard # is NOT reachable from the network out of the box (GHSA-gr74-4xfh-6jw9). The # server reads transcripts, exports all data, and can spawn `claude`, so binding # it to the network without auth exposes all of that. Only widen the bind if you # understand the risk — and set DASHBOARD_TOKEN when you do. # DASHBOARD_HOST=0.0.0.0 # bind all interfaces (LAN-reachable) # Optional auth token. When set, every /api/* request and the WebSocket must # present it (Authorization: Bearer , x-dashboard-token header, or # ?token=). Strongly recommended whenever DASHBOARD_HOST is non-loopback. Unset # by default — the loopback bind is the trust boundary. # DASHBOARD_TOKEN=change-me-to-a-long-random-string # Extra Host-header names allowed besides loopback (comma-separated). Needed when # you bind to a LAN and reach the dashboard by hostname/IP — entries here pass # the anti-DNS-rebinding Host allowlist. Also required when Prometheus-in-Docker # scrapes a host-native dashboard: # DASHBOARD_ALLOWED_HOSTS=host.docker.internal # DASHBOARD_ALLOWED_HOSTS=dashboard.internal,192.168.1.50 # ── Background sweeps / sync ───────────────────────────────────────────────── # Minutes of inactivity before an active session is marked "abandoned" by the # periodic maintenance sweep (default: 180 = 3h). # DASHBOARD_STALE_MINUTES=180 # Idle-working timeout (seconds) for recovering a turn cancelled with Esc BEFORE # any output (which leaves no transcript marker). When the main agent has been # "working" with no tool in flight and neither a hook nor the transcript has # advanced for this long, the watchdog moves the session to Waiting (default: 120). # DASHBOARD_WORKING_IDLE_SECONDS=120 # Dead-session liveness reap. The watchdog lists running `claude` CLI processes # (ps + lsof on macOS, /proc on Linux) and completes any active session whose # cwd has no live claude process — recovering sessions whose SessionEnd hook # was lost because the dashboard was down when the user quit (e.g. Ctrl+C). # Set to 0 to disable (do this when hooks arrive from another machine); it is # auto-disabled on Windows and inside containers (default: enabled). # DASHBOARD_LIVENESS_PROBE=1 # Idle gate (seconds) for WATCHDOG-TICK liveness reaps: a session is only # completed when its transcript hasn't been written for at least this long # (the last hook write is the fallback clock when no transcript exists on # disk), so mid-turn or just-resumed sessions never flicker out on a transient # probe miss. The startup passes skip this gate entirely — at boot the probe # alone decides, so sessions quit moments before launch clear immediately # (default: 60). # DASHBOARD_LIVENESS_IDLE_SECONDS=60 # Poll interval (ms) for the continuous ~/.claude/projects sync that surfaces # projects added after startup whose sessions never flow through hooks. The # fs.watch watcher fires near-instantly regardless; this poll is the safety net. # Set to 0 to disable the poll while leaving the watcher running (default: 30000). # DASHBOARD_SESSION_SYNC_MS=30000 # Hourly database upkeep: a non-blocking WAL checkpoint (the WAL then shrinks # to 64 MB), PRAGMA optimize, the opt-in retention below and a bounded # incremental_vacuum. 0 turns it off. Never a full VACUUM (that is Settings → # Data → Compact, on a click). # DASHBOARD_DB_MAINTAIN_MS=3600000 # Automatic retention (OFF unless set): finished sessions that started more # than N days ago (1–3650) are purged by the hourly upkeep. Usually set from # Settings → Data → Session cleanup, which writes it to the settings file. # AGENTHUB_RETENTION_DAYS=90 # Update check interval (ms, default 3600000 = 1 h, minimum 60000). A tick # with no browser connected is skipped; the next browser to connect gets one. # DASHBOARD_UPDATE_CHECK=0 turns the scheduled check off. # DASHBOARD_UPDATE_CHECK_INTERVAL_MS=3600000 # Poll interval (ms) for Antigravity CLI sessions and tokens, read from agy's # own ~/.gemini/antigravity-cli/conversations/*.db (0 disables; default: 15000). # DASHBOARD_ANTIGRAVITY_POLL_MS=15000 # Where agy keeps its data, when not ~/.gemini (agy itself has no override). # AGENTHUB_GEMINI_DIR=~/.gemini # Poll interval (ms) for Codex's rollout journals ($CODEX_HOME/sessions/**): # drives both the codex lane running/idle mirror and Codex sessions + tokens # (0 disables both; default: 15000). # DASHBOARD_CODEX_POLL_MS=15000 # Automatic pricing: a model seen in token usage with no rate row of its own # gets one from LiteLLM's public price list. 0 / false / off disables it # (default: enabled). # AGENTHUB_PRICING_SYNC=0 # The status bar's Usage panel reads Antigravity's quota by running # `agy --print /usage --output-format json` (no model call), which may let agy # update itself. 0 never runs it, and Antigravity shows no quota (default: on). # AGENTHUB_AGY_USAGE=0 # Heavy read-only aggregates (GET /api/workflows) run in a worker thread on # their own connection so they never stall other requests. 0 runs them inline # on the event loop instead (default: worker). A job past the timeout answers # 503 EREADTIMEOUT and the next one gets a fresh worker (default: 60000). # AGENTHUB_READ_WORKER=0 # AGENTHUB_READ_TIMEOUT_MS=60000 # Where settings saved from the dashboard persist (default: # $XDG_CONFIG_HOME/agenthub/settings.env, i.e. ~/.config/agenthub/settings.env). # Here or in the real environment; the file is located after this one loads. # AGENTHUB_SETTINGS_FILE=/home/you/.config/agenthub/settings.env # ── Remote Data Sources (SSH multi-machine collection) ─────────────────────── # The dashboard can pull Claude Code history from other machines over SSH: # it rsyncs each enabled remote's ~/.claude/projects into a sandboxed staging # dir, feeds it through the same importer used for local history, and tags the # imported sessions with the source. Authentication defers entirely to the host's # own SSH stack (~/.ssh/config, ssh-agent, keys, known_hosts) — no passwords or # secrets are stored here. # Poll interval (ms) for the background poller that syncs each enabled remote # source. Set to 0 to disable the poller (manual / on-demand syncs still work) # (default: 15000 = 15s). # DASHBOARD_REMOTE_SYNC_MS=15000 # Per-source timeout (ms) for a single remote sync (rsync pull + import) before # it is aborted (default: 600000 = 10min). # DASHBOARD_REMOTE_SYNC_TIMEOUT_MS=600000 # Timeout (ms) for the Test SSH probe that verifies a remote source is # reachable (default: 15000 = 15s). # DASHBOARD_REMOTE_TEST_TIMEOUT_MS=15000 # Freshness window (ms) for a remote source session's live status. On each sync, # a remote session whose mirrored transcript changed within this window is kept # active; once the mirror stops advancing for longer, it is reconciled to # completed. Remote sessions get no live hooks, so this replaces the local # liveness/stale sweeps (which skip them). (default: 600000 = 10min). # DASHBOARD_REMOTE_ACTIVE_WINDOW_MS=600000 # ── Privacy and push ingest (Settings → Data) ──────────────────────────────── # All three are normally saved from Settings into the settings file; set here, # they are pinned and the Settings page shows them read-only. # Redact secrets (API keys, tokens, bearer headers, private keys, password=…) # from stored event payloads and summaries: 1 = on (default: off). # AGENTHUB_REDACT_SECRETS=1 # Folders whose hooks are dropped whole (and skipped by the history import and # the Codex reader) — absolute paths, ':'-separated (';' on Windows); a folder # and everything under it. # AGENTHUB_IGNORE_CWD=/home/you/clients/secret:/home/you/private # SHA-256 (hex) of the token POST /api/hooks/ingest-batch accepts. Unset = push # ingest off. Settings → Data → Push ingest makes the token and stores only this. # AGENTHUB_PUSH_TOKEN_SHA256= # ── Lanes (durable parallel-work units and managed git worktrees) ──────────── # Directory dashboard-managed worktrees are provisioned under. It is also the # boundary safety check 2 resolves every destructive lane path against: nothing # outside it can be reset or removed. Keep it readable only by the service user # (default: ~/.claude/agenthub-lanes). # LANES_ROOT=~/.claude/agenthub-lanes # Default base branch a new managed worktree resolves against when the request # omits `base`. An explicit --base / request body `base` always wins # (default: main). # LANE_BASE_BRANCH=main # Prefix for a new managed worktree's feature branch name, as # (default: feat/). # LANE_BRANCH_PREFIX=feat/ # Seconds of silence after which a lane whose stage matches /watch|poll/i flips # from `active` to `dead` liveness. A silent *idle* lane is at rest, not dead # (default: 300 = 5min). # LANE_DEAD_SEC=300