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)

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/
  • 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)

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

  • Three events — ready, waiting, and context pressure (80% / 95%) — 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's inter-process control is opt-in. Without it, Irrlicht can raise the kitty window but cannot switch to the tab that owns the clicked session — the last-focused tab stays visible. Enable remote control in ~/.config/kitty/kitty.conf:

allow_remote_control yes
listen_on            unix:/tmp/kitty-{kitty_pid}

Restart kitty after editing — a config reload alone has no effect. New sessions started inside kitty will then have KITTY_LISTEN_ON set, and clicks land on the exact tab via kitten @ focus-window. (Note: macOS does not support Linux-style abstract sockets, so a filesystem path is required.)