June

Configuration reference

Every env var june reads, grouped by section. The Ctrl-F page. Source of truth: [`src/config.mjs`](../src/config.mjs).

Every env var june reads, grouped by section. The Ctrl-F page. Source of truth: src/config.mjs.

Env vars are loaded in this order (first-set wins):

  1. process.env as inherited from the shell / process supervisor.
  2. ~/.config/june/.env — written by jun setup, the canonical location for global installs.
  3. <repo>/.env — fallback for the git clone && npm link flow.

process.env beats every file. Use the XDG file for normal installs; use launchd / systemd / Docker --env-file to inject in production.

jun config show prints the resolved value of every key below and which file each came from. jun config edit opens the .env in $EDITOR.

Required

VariableNotes
LINEAR_API_KEYLinear personal API key (lin_api_…). june fails to boot without it. See setup.md → Linear personal API key.
LINEAR_WEBHOOK_SECRETHMAC-SHA256 signing secret for incoming webhook bodies. Must match the secret set on the Linear webhook. june fails to boot without it.

For the setup scripts (register-webhook, ensure-states, ensure-labels, acceptance:live) and the waiting sweep, JUNE_TEAM_KEY is also required.

Network

VariableDefaultNotes
JUNE_PORT8787TCP port the HTTP server listens on. Also accepts the legacy PORT env var.
JUNE_HOST127.0.0.1Interface to bind. Leave on loopback when behind a reverse proxy / tunnel; set to 0.0.0.0 only inside a container.
JUNE_PUBLIC_WEBHOOK_URL(unset)The publicly-reachable URL for the Linear webhook (e.g. https://example.com/webhook/linear). jun setup writes this; jun doctor re-verifies it.
JUNE_ALLOW_UNSIGNED_WEBHOOKS0Set to 1 to skip HMAC verification on /webhook/linear. Only for local testing. See security.md.

Paths

VariableDefaultNotes
JUNE_APP_DIRThe repo root.Where data/, logs/, and guards/ live. Override to point at a different install location.
JUNE_AGENT_ROOTprocess.cwd()Working directory the runners chdir to before exec. Set this to your actual workspace.
JUNE_DB<appDir>/data/agent.sqliteSQLite database path. june creates the directory if missing.
JUNE_LOG<appDir>/logs/agent.logPlain-text log file. Tail it with jun logs -f.

Linear

VariableDefaultNotes
JUNE_TEAM_KEY(unset)Linear team key (e.g. ENG). Required for register-webhook, ensure-states, ensure-labels, acceptance:live, and the waiting sweep. At runtime the orchestrator reads the team from each webhook, so serving works without this.
JUNE_BOT_USER_EMAILS(empty)Comma-separated list of Linear user emails to suppress as bot input. The orchestrator's own viewer email is added automatically at boot; use this for additional bot accounts in your workspace.

Runner: Claude (default)

VariableDefaultNotes
JUNE_CLAUDE_BINclaudePath to the Claude Code CLI. Use an absolute path under launchd / systemd if the binary isn't on the stripped PATH.
JUNE_RUN_TIMEOUT_MS0 (off)Per-run hard timeout that applies to every runner. Per-runner overrides below win when set.
JUNE_CLAUDE_TIMEOUT_MS0 (off)Per-run hard timeout. 0 disables. When positive, the run is SIGTERMed at the deadline (then SIGKILLed 5 s later).
JUNE_CLAUDE_TRIAGE_ENABLED1When JUNE_CLAUDE_TIMEOUT_MS fires, spawn a read-only triage Claude to decide RESUMABLE vs BLOCKED. Set 0 to skip.
JUNE_CLAUDE_TRIAGE_TIMEOUT_MS300000Budget for the triage Claude (5 min).
JUNE_CLAUDE_HEALTH_CHECK_INTERVAL_MS900000Watchdog tick interval (15 min). 0 disables the watchdog entirely.
JUNE_CLAUDE_WATCHDOG_TIMEOUT_MS120000Budget for the watchdog Claude (2 min).
JUNE_CLAUDE_WATCHDOG_MODEL(unset)Override the model the watchdog Claude uses. Unset = Claude's default.
JUNE_CLAUDE_WATCHDOG_HARD_IDLE_MINUTES25If the main run's session log hasn't been written to in this many minutes, takeover without consulting the watchdog.
JUNE_CLAUDE_POST_RESULT_GRACE_MS30000After Claude emits its final result event, wait this long for the CLI to exit cleanly before SIGTERMing.

See concepts.md → Timeout triage and → Health watchdog for the behaviour.

Runner: Codex

VariableDefaultNotes
JUNE_CODEX_BINcodexPath to the Codex CLI.
JUNE_CODEX_TIMEOUT_MSJUNE_RUN_TIMEOUT_MSPer-run hard timeout for Codex runs.
JUNE_CODEX_LABELcodexLinear label that routes to Codex. Useful if you want a different label name.

Codex's model and effort come from codex config (its own persisted settings); june doesn't pin them. The codex label still forces xhigh and fast still forces medium via the label-modifier path inside the orchestrator.

Runner: OpenCode

VariableDefaultNotes
JUNE_OPENCODE_BINopencodePath to the OpenCode CLI.
JUNE_OPENCODE_ROOTJUNE_AGENT_ROOTWorking directory OpenCode runs in. Override to sandbox OpenCode to a subdirectory.
JUNE_OPENCODE_PERMISSION(see below)JSON policy passed as OPENCODE_PERMISSION. Default denies external-directory access and arbitrary bash while allowing pwd, ls, git status, git diff, git log, npm test, node --test.
JUNE_OPENCODE_TIMEOUT_MSJUNE_RUN_TIMEOUT_MSPer-run hard timeout for OpenCode runs.
JUNE_OPENCODE_EXPORT_TIMEOUT_MS30000Budget for the opencode export <session-id> post-run harvest.
JUNE_OPENCODE_LABELopencodeLinear label that routes to OpenCode.
OPENCODE_PERMISSION(see above)Read as a fallback when JUNE_OPENCODE_PERMISSION is unset.

OpenCode's model / agent / variant come from opencode config (its own persisted settings); june doesn't pin them.

Runner: Antigravity (gemini label)

VariableDefaultNotes
JUNE_ANTIGRAVITY_BINagyPath to Google's Antigravity CLI.
JUNE_ANTIGRAVITY_TIMEOUT_MSJUNE_RUN_TIMEOUT_MSPer-run hard timeout for Antigravity runs.
JUNE_GEMINI_LABELgeminiLinear label that routes to Antigravity. (The label name is gemini for historical reasons.)

The legacy Gemini CLI runner is still in the codebase as a rollback path but is not currently routed to. Its env vars (JUNE_GEMINI_BIN, JUNE_GEMINI_TIMEOUT_MS) are read for legacy callers but Google has deprecated the gemini CLI for non-Enterprise tiers on 2026-06-18.

Runner: Hermes

VariableDefaultNotes
JUNE_HERMES_BINhermesPath to the Hermes Agent CLI.
JUNE_HERMES_TOOLSETSterminal,web,skills,session_search,todo,code_executionComma-separated toolset list. Default omits the file / search_files toolsets, which loop on large prompts.
JUNE_HERMES_TIMEOUT_MSJUNE_RUN_TIMEOUT_MSPer-run hard timeout for Hermes runs.
JUNE_HERMES_LABELhermesLinear label that routes to Hermes.

Hermes' provider and model come from ~/.hermes/config.toml; june doesn't pin them.

Routing labels

VariableDefaultNotes
JUNE_DEFAULT_RUNNERclaudeRunner used when no routing label matches. Don't change this from claude — Claude is the only runner whose absence blocks boot.
JUNE_CODEX_LABELcodexSee above.
JUNE_OPENCODE_LABELopencodeSee above.
JUNE_GEMINI_LABELgeminiSee above.
JUNE_HERMES_LABELhermesSee above.
JUNE_GOAL_LABELgoalLinear label that wraps the first prompt with /goal . See runners.md → Modifier labels.

States

JUNE_*_STATES are all comma-separated lists of Linear workflow state names. The first match wins; matches are case-insensitive. The orchestrator looks each list up against the current team and falls back to a state type when no name matches.

VariableDefaultFallback typeWhat it controls
JUNE_WORKING_STATESWorking,In ProgressstartedState the issue moves into while a run is active.
JUNE_REVIEW_STATESReady for Review,DonecompletedState the issue moves into when a run succeeds.
JUNE_BLOCKED_STATESBlocked,CanceledcanceledState the issue moves into when a run fails verification or is manually stopped.
JUNE_WAITING_STATESWaiting(none)State the waiting sweep moves stale Ready for Review issues into.
JUNE_WAITING_FROM_STATESReady for Review(none)States the waiting sweep considers stale-candidates. Comma-separated.

Behaviour tuning

VariableDefaultNotes
JUNE_COMMENT_DEBOUNCE_MS30000Wait this long after a first comment to gather follow-ups into a single run. 0 disables debounce.
JUNE_COMMENT_MAX_AUTO_FLUSHES3Cap on consecutive steer-flush restarts triggered by back-to-back comments arriving during a run.
JUNE_PROGRESS_COMMENTS_ENABLED1Include the Progress comments block in the first-run prompt. Set 0 to suppress it.
JUNE_THREAD_REPLIES0When 1, threaded comments instead of top-level. Both progress and final comments are threaded under the triggering comment root.
JUNE_WAITING_SWEEP_ENABLED1Run the waiting sweep on an interval. Set 0 to disable.
JUNE_WAITING_SWEEP_INTERVAL_MS300000Sweep tick interval (5 min).
JUNE_WAITING_AFTER_MS3600000An issue is sweep-eligible if its latest comment is from the bot and is older than this (1 h).

Admin

VariableDefaultNotes
JUNE_ADMIN_TOKEN(unset)Bearer token gating the /admin/* endpoints. Unset means 403 admin disabled on both endpoints.

Defaults at a glance

If you want to bring everything up explicitly, here's a .env with every key set to its current default:

# Required
LINEAR_API_KEY=lin_api_...
LINEAR_WEBHOOK_SECRET=...

# Network
JUNE_PORT=8787
JUNE_HOST=127.0.0.1
# JUNE_PUBLIC_WEBHOOK_URL=
JUNE_ALLOW_UNSIGNED_WEBHOOKS=0

# Paths
# JUNE_APP_DIR=...       # defaults to the repo root
# JUNE_AGENT_ROOT=...    # defaults to process.cwd()
# JUNE_DB=<appDir>/data/agent.sqlite
# JUNE_LOG=<appDir>/logs/agent.log

# Linear
# JUNE_TEAM_KEY=ENG
# JUNE_BOT_USER_EMAILS=

# Run timeouts (apply to every runner; per-runner overrides win)
JUNE_RUN_TIMEOUT_MS=0

# Claude
JUNE_CLAUDE_BIN=claude
# claudeEffort is hardcoded to "max" — Claude doesn't persist /effort between
# runs, so the orchestrator passes --effort max every spawn. No env var.
JUNE_CLAUDE_TIMEOUT_MS=0
JUNE_CLAUDE_TRIAGE_ENABLED=1
JUNE_CLAUDE_TRIAGE_TIMEOUT_MS=300000
JUNE_CLAUDE_HEALTH_CHECK_INTERVAL_MS=900000
JUNE_CLAUDE_WATCHDOG_TIMEOUT_MS=120000
JUNE_CLAUDE_WATCHDOG_HARD_IDLE_MINUTES=25
JUNE_CLAUDE_POST_RESULT_GRACE_MS=30000

# Codex
JUNE_CODEX_BIN=codex
JUNE_CODEX_LABEL=codex

# OpenCode
JUNE_OPENCODE_BIN=opencode
JUNE_OPENCODE_LABEL=opencode
JUNE_OPENCODE_EXPORT_TIMEOUT_MS=30000

# Antigravity (gemini label)
JUNE_ANTIGRAVITY_BIN=agy
JUNE_GEMINI_LABEL=gemini

# Hermes
JUNE_HERMES_BIN=hermes
JUNE_HERMES_LABEL=hermes
JUNE_HERMES_TOOLSETS=terminal,web,skills,session_search,todo,code_execution

# Routing
JUNE_DEFAULT_RUNNER=claude
JUNE_GOAL_LABEL=goal

# States
JUNE_WORKING_STATES=Working,In Progress
JUNE_REVIEW_STATES=Ready for Review,Done
JUNE_BLOCKED_STATES=Blocked,Canceled
JUNE_WAITING_STATES=Waiting
JUNE_WAITING_FROM_STATES=Ready for Review

# Behaviour
JUNE_COMMENT_DEBOUNCE_MS=30000
JUNE_COMMENT_MAX_AUTO_FLUSHES=3
JUNE_PROGRESS_COMMENTS_ENABLED=1
JUNE_THREAD_REPLIES=0
JUNE_WAITING_SWEEP_ENABLED=1
JUNE_WAITING_SWEEP_INTERVAL_MS=300000
JUNE_WAITING_AFTER_MS=3600000

# Admin
# JUNE_ADMIN_TOKEN=

You almost certainly don't want all of these in your .envjun setup writes the minimal shape and june fills in defaults from src/config.mjs at boot. Run jun config show to see what your install actually resolved to.

What's not here

These were env vars in earlier versions; they've been removed because the per-runner CLI is the canonical place to set them, and double-pinning was just noise:

  • JUNE_CLAUDE_EFFORT — Claude Code doesn't persist /effort, so the orchestrator hardcodes --effort max per spawn. The xhigh / fast label modifiers still apply.
  • JUNE_CODEX_EFFORT, JUNE_CODEX_MODEL — set via codex config instead.
  • JUNE_OPENCODE_MODEL, JUNE_OPENCODE_AGENT, JUNE_OPENCODE_VARIANT — set via opencode config instead.
  • JUNE_GEMINI_MODEL — Antigravity binds the model to the desktop session; the legacy gemini CLI is deprecated anyway.
  • JUNE_HERMES_MODEL, JUNE_HERMES_PROVIDER — set in ~/.hermes/config.toml instead.

On this page