Configuration

Zero configuration by default. Environment variables for power users.

Philosophy

Irrlicht is designed to work with zero configuration. Install and run — sessions are discovered automatically. These options exist for power users who need to customize behavior.

Environment Variables

Variable Type Default Description
IRRLICHT_MAX_SESSION_AGE Duration 120h (5 days) Maximum age for transcript sessions before pruning
GT_BIN Path $PATH lookup Override path to Gas Town gt CLI binary
IRRLICHT_UI_DIR Path auto-detect Directory containing the dashboard's index.html; escape hatch when auto-detection fails (see When to use these)
IRRLICHT_BIND_ADDR host:port 127.0.0.1:7837 Override the daemon's TCP bind — use 0.0.0.0:7837 to expose on the LAN
IRRLICHT_MDNS Boolean (1/0) unset Advertise _irrlicht._tcp via Bonjour so other devices on the LAN can discover the daemon
IRRLICHT_DEBUG Boolean (1/0) unset macOS app dumps session state to ~/.irrlicht/debug-state.json on every update
PI_CODING_AGENT_SESSION_DIR Absolute path ~/.pi/coding-agent/sessions Relocate the Pi adapter's transcript root. Read once at daemon startup; restart required after changing. Non-absolute values are rejected with a log warning
CLAUDE_CONFIG_DIR Absolute path ~/.claude Relocate the Claude Code adapter's transcript root (the daemon appends /projects). PID-metadata directory at ~/.claude/sessions/ remains hardcoded
CODEX_HOME Absolute path ~/.codex Relocate the Codex adapter's transcript root (the daemon appends /sessions)
IRRLICHT_PERMISSION_MODE ask | grant-all ask Consent behavior. ask (production default) keeps every per-agent permission pending until answered via the wizard — nothing is read or modified before a grant. grant-all auto-grants everything in-memory for demo / recording / test daemons; it is never persisted
IRRLICHT_READY_SESSION_TTL Duration 30m How long an idle ready session is kept before automatic deletion. Used by test harnesses to expire long-idle sessions in seconds rather than half an hour
IRRLICHT_YIELD_SWEEP_INTERVAL Duration 30m How often the yield sweep correlates git revert commits back to the sessions that authored the reverted work, feeding the History view's productive-vs-reverted ratio
IRRLICHT_HOME Path ~/.local/share/irrlicht Relocate the daemon's entire state tree — socket, addr file, history rollups, session/cost/ledger stores, and recordings — for a fully isolated dev / test daemon that never touches the production install
IRRLICHT_DEMO_MODE Boolean (1/0) unset When 1, disables the process watcher and per-adapter file watchers — the daemon serves only seeded session state. For demos and screenshots
IRRLICHT_RECORD Boolean (1/0) unset When 1 (equivalent to the --record flag), records the session lifecycle event stream to JSONL for replay fixtures
IRRLICHT_RECORDINGS_DIR Path <dataDir>/recordings Override the directory lifecycle recordings are written to. Wins even when IRRLICHT_HOME is set, so a recording run can be pinned somewhere specific (only used while recording is enabled)
IRRLICHT_RELAY_URL URL unset Opt-in outbound relay: forward this daemon's session events to a standalone irrlichtrelay so remote clients can see them. Accepts a bare base (e.g. ws://host:7839); http(s):// is rewritten to ws(s):// and the stream path is appended automatically
IRRLICHT_RELAY_TOKEN String unset Bearer token for an auth-enabled relay. Overrides the token field of <dataDir>/relay-token.json; leave unset against a no-auth relay
IRRLICHT_RELAY_CONTROL on | unset unset When on, lets the relay forwarder act on inbound remote-control frames (the backchannel's outer remote gate). For standalone/headless daemons; the macOS app drives the same toggle via PUT /api/v1/activation/relay-control
IRRLICHT_CACHE_BLOAT_THRESHOLD Float 1.4 Cache-creation regression detector: a working session trips the rule when its median cache-creation-per-turn exceeds the per-project baseline × this factor. 0 (or negative) disables the whole rule — the kill switch
IRRLICHT_CACHE_BLOAT_BASELINE_DAYS Integer 14 Trailing window over completed sessions used to compute the per-project cache-creation-per-turn baseline
IRRLICHT_CACHE_BLOAT_MIN_TURNS Integer 3 Variance guard — the rule won't fire before this many completed turns
IRRLICHT_CACHE_BLOAT_VERSION_DELTA Integer (tokens) 10000 Minimum per-turn cache-creation difference between two agent versions before the regression is attributed to an upstream agent version change
IRRLICHT_MODEL_CAPACITY_CACHE Path auto-detect Override the model capacity / pricing cache file with an explicit path. An escape hatch used by replay tests to pin pricing to a committed snapshot so cost resolution can't drift
NO_COLOR Boolean (presence) unset Standard no-color convention — when set to any value, the irrlicht-ls CLI disables ANSI color in its text output
GT_ROOT Path ~/gt Override the Gas Town root directory the orchestrator adapter probes for daemon/state.json and rig layout
IRRLICHT_DAEMON_PORT Integer 7837 macOS app only — override which daemon port the dashboard connects to, so a dev-build daemon (e.g. port 7838) can coexist with the production daemon
IRRLICHT_RELAY_MAX_MSG_BYTES Integer (bytes) 1048576 Env fallback for irrlichtrelay serve --max-msg-bytes — max inbound WebSocket message size the relay accepts; 0 disables the cap
IRRLICHT_RELAY_MAX_CONNS Integer 256 Env fallback for irrlichtrelay serve --max-conns — max total concurrent connections the relay accepts; 0 disables the cap
IRRLICHT_RELAY_MAX_CONNS_PER_IP Integer 32 Env fallback for irrlichtrelay serve --max-conns-per-ip — max concurrent connections per remote IP; 0 disables the cap (meaningless behind a proxy/NAT)

When to use these

The defaults work for solo, single-machine use. Reach for these overrides when one of the following describes you:

I want to peek at sessions from my phone on the same WiFi

If you run irrlichd yourself from a terminal, set both vars inline:

IRRLICHT_BIND_ADDR=0.0.0.0:7837 IRRLICHT_MDNS=1 irrlichd

If the macOS app auto-spawns the daemon for you (the default for DMG / Homebrew installs), shell env vars never reach it. Set them in the per-user launchd context first, then relaunch the app:

launchctl setenv IRRLICHT_BIND_ADDR 0.0.0.0:7837
launchctl setenv IRRLICHT_MDNS 1
# quit Irrlicht.app from the menu bar, then reopen it

Either way, then open http://<hostname>.local:7837 in any browser on the same network. mDNS lets the phone find the host without you typing an IP.

Security note: the daemon has no authentication today. Anyone on the network you bind to can read all your transcripts. Only do this on networks you trust (your home LAN, your tailnet) — never on a coffee-shop WiFi. See SECURITY.md for the full posture.

Future: these two knobs will be replaced by a single explicit hub mode. See the Relay Server design for the planned consolidation.

The dashboard returned "Dashboard UI not found"

The daemon resolves the dashboard's location in this order (first hit wins):

  1. $IRRLICHT_UI_DIR — escape hatch (what this recipe sets)
  2. <exe>/../Resources/web/ — production .app bundle layout
  3. ~/.local/share/irrlicht/web/ — daemon-only curl install
  4. Walking up from the executable for platforms/web/index.html — dev checkout

If the three auto-detect paths (2–4) all miss — custom install layout, fork with a moved UI, broken symlink — set the env var so it takes precedence:

IRRLICHT_UI_DIR=/path/to/dir/containing/index.html irrlichd

The macOS app is misbehaving and I want to see its session state

Env vars set in your shell do not reach a GUI app launched via open -a — LaunchServices spawns the app without inheriting them. Use one of these instead:

# Most reliable: invoke the binary directly
IRRLICHT_DEBUG=1 /Applications/Irrlicht.app/Contents/MacOS/Irrlicht

# Or, on macOS 13+: forward via open's --env flag
open -a Irrlicht --env IRRLICHT_DEBUG=1

# Or, persist for the launchd session and relaunch normally
launchctl setenv IRRLICHT_DEBUG 1
# quit Irrlicht.app, then reopen it

The current session list, connection state, and history buckets are written to ~/.irrlicht/debug-state.json on every update. Useful when filing a bug report.

Filesystem Paths

Daemon

  • Session instances: ~/Library/Application Support/Irrlicht/instances/
  • Permissions: ~/.local/share/irrlicht/permissions.json — the per-agent consent answers behind the permission wizard. A missing file (or a missing key) means pending: the wizard re-asks and nothing is monitored until granted
  • Logs: ~/Library/Application Support/Irrlicht/logs/
  • Unix socket: ~/.local/share/irrlicht/irrlichd.sock

macOS App

  • Session order: ~/Library/Application Support/Irrlicht/session-order.json

Transcript Locations

  • Claude Code: ~/.claude/projects/<project>/<session-id>.jsonl
  • Codex: ~/.codex/sessions/YYYY/MM/DD/<session-id>.jsonl
  • Pi: ~/.pi/agent/sessions/--<cwd-dashed>--/<session-id>.jsonl
  • Aider: <cwd>/.aider.chat.history.md (markdown, per-CWD)
  • OpenCode: ~/.local/share/opencode/storage/opencode.db (single SQLite WAL, watched via opencode.db-wal)
  • Kiro CLI: ~/.kiro/sessions/cli/<uuid>.jsonl (plus a <uuid>.json metadata sidecar for cwd, model, and context metrics)
  • Gemini CLI: ~/.gemini/tmp/<project>/chats/<session-id>.jsonl
  • Antigravity: ~/.gemini/antigravity-cli/brain/<conv-id>/.system_generated/logs/transcript.jsonl (CLI) or ~/.gemini/antigravity/brain/<conv-id>/.system_generated/logs/transcript.jsonl (IDE)
  • Mistral Vibe: ~/.vibe/logs/session/<session-id>/messages.jsonl (plus a sibling meta.json sidecar for cwd, model, and context metrics)

App Settings

The macOS app has a Settings panel accessible via the gear icon:

Session TTL

  • Controls auto-deletion of idle ready sessions
  • Options: Never, 15 minutes, 30 minutes (default), 1 hour, 4 hours
  • Stored in @AppStorage("sessionTTLMinutes")

Notifications

  • Notifications are opt-in by default — no banners or sounds play until you enable an event in Preferences (part of the consent-first rollout in v0.5.0)
  • Three events — ready, waiting, and context pressure (a single configurable threshold, default 80% of the context window or an absolute token count) — each has its own enable toggle and sound picker in Preferences
  • Built-in sounds: Ping, Chime, Funk, Whoosh, Sosumi; defaults Ready=Funk, Waiting=Ping, Context=Sosumi
  • None — the banner still appears but plays no sound
  • Speak aloud — routes the title and body through AVSpeechSynthesizer (pinned to en-US) with three voice variants: Default, Zoe-Premium (female), Jamie-Premium (male). If a premium voice isn't installed, the row deep-links to System Settings → Accessibility → Spoken Content
  • Custom — imports aiff/wav/mp3/m4a/caf from disk into ~/Library/Sounds/, transcoding mp3/m4a to LPCM-in-CAF so UNNotificationSound can play them
  • Requires macOS notification permission (requested on launch)

Logging

  • Format: Structured JSON
  • Location: ~/Library/Application Support/Irrlicht/logs/
  • Files: events.log (current), events.log.1 through .5 (rotated)
  • Max size: 10MB per file, 5 files retained
  • Log event types: startup, shutdown, session-detector, process-watcher, process-exit

Network

  • TCP: localhost:7837 (HTTP API + WebSocket + Web UI)
  • Unix socket: ~/.local/share/irrlicht/irrlichd.sock
  • mDNS: _irrlicht._tcp (Bonjour/Zeroconf discovery)

Daemon Lifecycle

The daemon (irrlichd) is embedded inside Irrlicht.app and managed automatically. When you launch the app, the daemon starts; when you quit, it stops. If the daemon crashes, the app restarts it with exponential backoff.

If an external daemon is already running (e.g. from a development build), the app detects it and uses the existing instance instead of spawning a new one.

Terminal hosts

Clicking a session in the menu bar or web UI brings the originating terminal's window — and where possible the exact tab — to the front. Most terminals work out of the box. Kitty needs one extra config line for precise tab focus.

Kitty

Kitty needs two lines in ~/.config/kitty/kitty.conf to enable precise tab focus. See macOS Setup → Kitty Terminal for the full steps.