-
Notifications
You must be signed in to change notification settings - Fork 27
Expand file tree
/
Copy path.env.example
More file actions
1171 lines (1105 loc) · 62.9 KB
/
Copy path.env.example
File metadata and controls
1171 lines (1105 loc) · 62.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# Max characters of matched built-in/local skills injected into an agent task prompt.
# Skills are only injected when task title/description/labels match skill tags.
BOSUN_SKILLS_MAX_CHARS=4000
# ─── Bosun — Environment Configuration ───────────────────────────────
# Copy this file to .env and fill in your values.
# Or run: bosun --setup
# All variables are optional unless marked [REQUIRED].
# Boolean flags use true/false (preferred). Legacy 1/0 is still accepted.
# Profile guidance:
# - Local development: DEVMODE=true, *_TRANSPORT=sdk
# - End-user stable: DEVMODE=false, *_TRANSPORT=sdk
# ─── Task Claims and Coordination ─────────────────────────────────────────────
# Shared state manager enables distributed task coordination across multiple
# agents and workstations. Provides atomic claim operations, heartbeat-based
# liveness detection, and conflict resolution.
# Enable/disable shared state coordination (default: true)
SHARED_STATE_ENABLED=true
# Heartbeat renewal interval in milliseconds (default: 60000 = 1 minute)
SHARED_STATE_HEARTBEAT_INTERVAL_MS=60000
# Heartbeat staleness threshold in milliseconds (default: 300000 = 5 minutes)
# Tasks with stale heartbeats are considered abandoned and can be reclaimed
SHARED_STATE_STALE_THRESHOLD_MS=300000
# Maximum retry attempts before permanently ignoring a task (default: 3)
SHARED_STATE_MAX_RETRIES=3
# Task claim owner staleness threshold in milliseconds (default: 600000 = 10 minutes)
TASK_CLAIM_OWNER_STALE_TTL_MS=600000
# ─── Project Identity ─────────────────────────────────────────────────────────
# Project name shown in Telegram messages and logs.
# Auto-detected from package.json or directory name if not set.
# PROJECT_NAME=my-project
# ─── Telegram Bot ─────────────────────────────────────────────────────────────
# Create a bot via @BotFather on Telegram, then paste the token here.
# Run `bosun-chat-id` to discover your chat ID.
TELEGRAM_BOT_TOKEN=
TELEGRAM_CHAT_ID=
# Optional additional allow-list entries (comma-separated chat IDs or user IDs).
# Useful when commands are sent from a group/topic while TELEGRAM_CHAT_ID is your DM user ID.
# TELEGRAM_ALLOWED_CHAT_IDS=
# Minutes between periodic status summaries (default: 10)
TELEGRAM_INTERVAL_MIN=10
# Weekly report scheduler (default: disabled)
# Sends the same report as /weekly automatically on a UTC schedule.
# TELEGRAM_WEEKLY_REPORT_ENABLED=false
# Day of week in UTC: 0=Sunday ... 6=Saturday (default: 0)
# TELEGRAM_WEEKLY_REPORT_DAY=0
# Hour in UTC (0-23) when weekly report is sent (default: 9)
# TELEGRAM_WEEKLY_REPORT_HOUR=9
# Lookback window in days for weekly report generation (default: 7)
# TELEGRAM_WEEKLY_REPORT_DAYS=7
# Long-poll timeout for getUpdates in seconds (default: 20)
TELEGRAM_COMMAND_POLL_TIMEOUT_SEC=20
# Agent execution timeout for Telegram-triggered SDK runs (ms).
# TELEGRAM_AGENT_TIMEOUT_MS=5400000 # 90 minutes
# Or set minutes instead of ms:
# TELEGRAM_AGENT_TIMEOUT_MIN=90
# Max concurrent telegram command handlers (default: 2)
# TELEGRAM_COMMAND_CONCURRENCY=2
# Max commands to pull per batch (default: 25)
# TELEGRAM_COMMAND_MAX_BATCH=25
# Override Telegram API base URL if your network requires a proxy/gateway
# TELEGRAM_API_BASE_URL=https://api.telegram.org
# HTTP timeout per Telegram request in ms (default: 15000)
# TELEGRAM_HTTP_TIMEOUT_MS=15000
# Max retry attempts for transient Telegram network/server failures (default: 4)
# TELEGRAM_RETRY_ATTEMPTS=4
# Base retry backoff in ms (exponential with jitter, default: 600)
# TELEGRAM_RETRY_BASE_MS=600
# Enable curl fallback transport when Node fetch fails (default: true on Linux/macOS, false on Windows)
# TELEGRAM_CURL_FALLBACK=true
# Curl connect timeout in seconds when fallback is used (default: 8)
# TELEGRAM_CURL_CONNECT_TIMEOUT_SEC=8
# Poll timeout in seconds when curl fallback is active (default: 5)
# Lower values help when networks drop long-lived idle HTTPS connections.
# TELEGRAM_CURL_POLL_TIMEOUT_SEC=5
# ─── Telegram Mini App (Control Center Web UI) ───────────────────────────────
# Enable the Mini App server. Set to true and configure a port to activate.
TELEGRAM_MINIAPP_ENABLED=false
# Port for the Mini App HTTP server. Required when MINIAPP_ENABLED=true.
# TELEGRAM_UI_PORT=3080
# Bind address for the server (default: 0.0.0.0 — all interfaces for LAN access)
# TELEGRAM_UI_HOST=0.0.0.0
# Public hostname override. By default the server auto-detects your LAN IP.
# Set this when using a tunnel (ngrok, Cloudflare) or a public domain.
# TELEGRAM_UI_PUBLIC_HOST=your-lan-ip-or-domain
# Browser URL handling:
# manual (default) = never auto-open browser windows/tabs
# auto = permit auto-open when BOSUN_UI_AUTO_OPEN_BROWSER=true
# BOSUN_UI_BROWSER_OPEN_MODE=manual
# Legacy auto-open toggle for UI server (requires BOSUN_UI_BROWSER_OPEN_MODE=auto)
# BOSUN_UI_AUTO_OPEN_BROWSER=false
# Show full /?token=... browser URL in logs (default: false; token is hidden)
# BOSUN_UI_LOG_TOKENIZED_BROWSER_URL=false
# Setup wizard browser auto-open (default: true when mode=auto)
# BOSUN_SETUP_AUTO_OPEN_BROWSER=true
# Full public URL override (takes precedence over host/port auto-detection).
# Use when you have a reverse proxy or tunnel with HTTPS.
# TELEGRAM_UI_BASE_URL=https://your-public-ui.example.com
# ╔══════════════════════════════════════════════════════════════════════╗
# ║ ⛔ DANGER — SECURITY CRITICAL ║
# ║ ║
# ║ Setting ALLOW_UNSAFE=true disables ALL authentication on the UI. ║
# ║ Anyone who discovers your URL can: ║
# ║ • Read/modify your tasks and settings ║
# ║ • Send commands to agents that execute code on YOUR machine ║
# ║ • Access secrets, API keys, and environment variables ║
# ║ ║
# ║ Combined with TELEGRAM_UI_TUNNEL=named (Cloudflare tunnel), your UI ║
# ║ gets a PUBLIC internet URL — meaning ANYONE ON THE INTERNET can ║
# ║ find and control your machine. ║
# ║ ║
# ║ ONLY enable this for localhost-only debugging with tunnel DISABLED. ║
# ╚══════════════════════════════════════════════════════════════════════╝
# TELEGRAM_UI_ALLOW_UNSAFE=false
# Max age in seconds for initData auth tokens (default: 86400 = 24h)
# TELEGRAM_UI_AUTH_MAX_AGE_SEC=86400
# Presence heartbeat TTL in seconds (default: 180)
# TELEGRAM_PRESENCE_TTL_SEC=180
#
# ── Cloudflare Tunnel (for persistent HTTPS) ────────────────────────────────
# Telegram Mini App requires HTTPS with a valid cert. Cloudflare tunnels provide this.
#
# Default mode is **named** (permanent hostname, zero tunnel traffic cost):
# 1. Create tunnel: `cloudflared tunnel create <name>`
# 2. Save credentials json path
# 3. Set base domain + Cloudflare DNS API token/zone id
# Bosun will resolve deterministic per-user hostnames and create/verify the CNAME idempotently.
#
# Named tunnel required env:
# CLOUDFLARE_TUNNEL_NAME=my-tunnel
# CLOUDFLARE_TUNNEL_CREDENTIALS=/home/user/.cloudflared/<tunnel-id>.json
# CLOUDFLARE_BASE_DOMAIN=bosun.det.io
# CLOUDFLARE_ZONE_ID=<cloudflare-zone-id>
# CLOUDFLARE_API_TOKEN=<token-with-zone-dns-edit-scope>
#
# Optional overrides:
# CLOUDFLARE_TUNNEL_HOSTNAME=jon.bosun.det.io
# CLOUDFLARE_USERNAME_HOSTNAME_POLICY=per-user-fixed # per-user-fixed | fixed
# CLOUDFLARE_DNS_SYNC_ENABLED=true
# CLOUDFLARE_DNS_MAX_RETRIES=3
# CLOUDFLARE_DNS_RETRY_BASE_MS=750
#
# Tunnel mode control: named | quick | auto | cloudflared | disabled
# TELEGRAM_UI_TUNNEL=named
# TELEGRAM_UI_ALLOW_QUICK_TUNNEL_FALLBACK=false
# Quick tunnel restart controls (used when TELEGRAM_UI_TUNNEL=quick or named fallback):
# TELEGRAM_UI_QUICK_TUNNEL_RESTART_MAX_ATTEMPTS=6
# TELEGRAM_UI_QUICK_TUNNEL_RESTART_BASE_DELAY_MS=5000
# TELEGRAM_UI_QUICK_TUNNEL_RESTART_MAX_DELAY_MS=120000
# TELEGRAM_UI_QUICK_TUNNEL_RESTART_FOREVER=true
# TELEGRAM_UI_QUICK_TUNNEL_RESTART_COOLDOWN_MS=900000
#
# Fallback admin auth (secondary path; never stores plaintext credentials):
# Use API to set/reset credential after startup:
# POST /api/auth/fallback/set { "secret": "..." }
# POST /api/auth/fallback/rotate { "secret": "..." }
# POST /api/auth/fallback/reset
# POST /api/auth/fallback/login { "secret": "..." }
# TELEGRAM_UI_FALLBACK_AUTH_ENABLED=true
# TELEGRAM_UI_FALLBACK_AUTH_RATE_LIMIT_IP_PER_MIN=10
# TELEGRAM_UI_FALLBACK_AUTH_RATE_LIMIT_GLOBAL_PER_MIN=60
# TELEGRAM_UI_FALLBACK_AUTH_MAX_FAILURES=5
# TELEGRAM_UI_FALLBACK_AUTH_LOCKOUT_MS=600000
# TELEGRAM_UI_FALLBACK_AUTH_ROTATE_DAYS=30
# TELEGRAM_UI_FALLBACK_AUTH_TRANSIENT_COOLDOWN_MS=5000
# ─── Voice Assistant (v0.36+) ───────────────────────────────────────────────
# Enable real-time voice mode in the UI.
VOICE_ENABLED=true
# auto | openai | azure | claude | gemini | fallback
VOICE_PROVIDER=auto
# Realtime model (used by openai/azure Tier 1, or as provider-specific default override)
VOICE_MODEL=gpt-4o-realtime-preview-2024-12-17
# Vision model for live screen/camera frame understanding
VOICE_VISION_MODEL=gpt-4.1-mini
# Optional dedicated key for realtime sessions (falls back to OPENAI_API_KEY)
# OPENAI_REALTIME_API_KEY=
# Azure Realtime settings (used when VOICE_PROVIDER=azure, or auto with Azure vars)
# AZURE_OPENAI_REALTIME_ENDPOINT=https://<resource>.openai.azure.com
# AZURE_OPENAI_REALTIME_API_KEY=
# AZURE_OPENAI_REALTIME_DEPLOYMENT=gpt-4o-realtime-preview
# Claude provider mode (Tier 2 voice fallback + Claude vision)
# ANTHROPIC_API_KEY=
# Gemini provider mode (Tier 2 voice fallback + Gemini vision)
# GEMINI_API_KEY=
# GOOGLE_API_KEY=
# Transcription model used for audio-to-text (default: gpt-4o-transcribe)
# VOICE_TRANSCRIPTION_MODEL=gpt-4o-mini-transcribe
# Enable/disable input audio transcription in realtime sessions (default: true)
# VOICE_TRANSCRIPTION_ENABLED=true
# Voice output persona
VOICE_ID=alloy
# server_vad | semantic_vad | none
VOICE_TURN_DETECTION=server_vad
# browser | disabled (used when Tier 1 realtime is unavailable)
VOICE_FALLBACK_MODE=browser
# Executor used by voice tool delegations for complex requests
VOICE_DELEGATE_EXECUTOR=codex-sdk
# ─── Context Shredding / Live Tool Compaction ───────────────────────────────
# Traditional shredding trims older context turns. Live tool compaction runs
# earlier: it summarizes large, noisy command outputs before they ever land in
# the active turn, while preserving a `bosun --tool-log <id>` retrieval path.
# CONTEXT_SHREDDING_ENABLED=true
# CONTEXT_SHREDDING_LIVE_TOOL_COMPACTION_ENABLED=true
# CONTEXT_SHREDDING_LIVE_TOOL_COMPACTION_MODE=auto
# CONTEXT_SHREDDING_LIVE_TOOL_COMPACTION_MIN_CHARS=4000
# CONTEXT_SHREDDING_LIVE_TOOL_COMPACTION_TARGET_CHARS=1800
# CONTEXT_SHREDDING_LIVE_TOOL_COMPACTION_MIN_SAVINGS_PCT=15
# CONTEXT_SHREDDING_LIVE_TOOL_COMPACTION_MIN_RUNTIME_MS=2000
# CONTEXT_SHREDDING_LIVE_TOOL_COMPACTION_BLOCK_STRUCTURED_OUTPUT=true
# CONTEXT_SHREDDING_LIVE_TOOL_COMPACTION_ALLOW_COMMANDS=grep,rg,find,findstr,select-string,ag,ack,sift,fd,where,which,ls,dir,tree,git,go,npm,pnpm,yarn,npx,bun,node,python,python3,pytest,pip,pip3,poetry,docker,kubectl,helm,terraform,ansible,ansible-playbook,journalctl,tail,get-content,cargo,gradle,maven,mvn,javac,tsc,jest,vitest,deno,make,cmake,bazel,buck,nx,turbo,rush,composer,bundle
# ─── Desktop Portal ────────────────────────────────────────────────────────
# Auto-start bosun daemon when the desktop portal launches (default: true)
# BOSUN_DESKTOP_AUTO_START_DAEMON=true
# Enable auto-updates for packaged desktop builds (default: false)
# BOSUN_DESKTOP_AUTO_UPDATE=false
# Optional auto-update feed URL override
# BOSUN_DESKTOP_UPDATE_URL=https://updates.example.com/bosun
# ─── Telegram Sentinel (independent watchdog) ──────────────────────────────
# Keep Telegram command availability even when bosun is down.
# Sentinel can auto-restart monitor, detect crash loops, and run repair-agent.
# Auto-start sentinel whenever bosun starts (default: disabled)
# BOSUN_SENTINEL_AUTO_START=true
# Auto-restart monitor when sentinel detects monitor down/crash (default: 1)
# SENTINEL_AUTO_RESTART_MONITOR=true
# Crash-loop threshold within rolling window (default: 3)
# SENTINEL_CRASH_LOOP_THRESHOLD=3
# Crash-loop window in minutes (default: 10)
# SENTINEL_CRASH_LOOP_WINDOW_MIN=10
# Treat monitor deaths shortly after startup as rapid crashes (default: 45s)
# SENTINEL_MONITOR_START_GRACE_SEC=45
# Enable autonomous repair-agent when crash-loop is detected (default: 1)
# SENTINEL_REPAIR_AGENT_ENABLED=true
# Cooldown between repair-agent runs in minutes (default: 15)
# SENTINEL_REPAIR_COOLDOWN_MIN=15
# Repair-agent timeout in minutes (default: 20)
# SENTINEL_REPAIR_TIMEOUT_MIN=20
# Enable direct primary-agent fallback for commands while monitor is down (default: 1)
# SENTINEL_PRIMARY_AGENT_FALLBACK_ENABLED=true
# Fallback agent timeout in minutes (default: 15)
# SENTINEL_PRIMARY_AGENT_TIMEOUT_MIN=15
# Backoff before monitor restart attempts in seconds (default: 5)
# SENTINEL_RESTART_BACKOFF_SEC=5
# After manual /stop, suppress auto-restart for this many minutes (default: 10)
# SENTINEL_MANUAL_STOP_HOLD_MIN=10
# ─── Notification Batching (RECOMMENDED) ─────────────────────────────────────
# Batch notifications into periodic summaries instead of spamming individual messages
# TELEGRAM_BATCH_NOTIFICATIONS=true
# Batch interval in seconds - send summary every N seconds (default: 300 = 5 min)
# TELEGRAM_BATCH_INTERVAL_SEC=300
# Max messages before forcing a flush (default: 50)
# TELEGRAM_BATCH_MAX_SIZE=50
# Priority threshold for immediate delivery: 1=critical only, 2=critical+errors (default: 1)
# TELEGRAM_IMMEDIATE_PRIORITY=1
# ─── Auto-Delete Old Messages ──────────────────────────────────────────────────────────
# Automatically delete bot messages older than N days to keep chat tidy.
# Set to 0 to disable. Default: 3 days.
# Note: Telegram’s API may silently skip messages older than 48 h in private
# chats — those will just remain; no error is raised.
# TELEGRAM_HISTORY_RETENTION_DAYS=3
# ─── Presence & Multi-Instance Coordination ──────────────────────────────────
# Presence heartbeat allows discovering multiple bosun instances.
# Heartbeat interval in seconds (default: 60)
# TELEGRAM_PRESENCE_INTERVAL_SEC=60
# Consider instances offline after this many seconds (default: 180)
# TELEGRAM_PRESENCE_TTL_SEC=180
# Disable presence heartbeats entirely (default: false)
# TELEGRAM_PRESENCE_DISABLED=false
# Send presence messages silently without notification sound (default: false)
# TELEGRAM_PRESENCE_SILENT=false
# Only send when state changes, not on every heartbeat (default: true)
# TELEGRAM_PRESENCE_ONLY_ON_CHANGE=true
# Chat/channel for presence messages (required to enable presence announcements)
# TELEGRAM_PRESENCE_CHAT_ID=
# Instance ID (auto-generated stable ID across restarts if not set)
# VE_INSTANCE_ID=
# Human-friendly instance label shown in /presence (default: workspace name)
# VE_INSTANCE_LABEL=
# Coordinator election priority - lower wins (default: 10 for coordinators, 100 for workspaces)
# VE_COORDINATOR_PRIORITY=
# Opt out of coordinator election (default: true)
# VE_COORDINATOR_ELIGIBLE=true
# ─── WhatsApp Channel (Optional) ──────────────────────────────────────────────
# Optional WhatsApp channel for receiving commands and notifications.
# Uses @whiskeysockets/baileys for WhatsApp Web multi-device API.
# Install baileys: npm install @whiskeysockets/baileys qrcode-terminal
# Then authenticate: bosun --whatsapp-auth
# Enable WhatsApp channel (default: disabled)
# WHATSAPP_ENABLED=false
# Restrict to a specific chat JID (recommended for security)
# WHATSAPP_CHAT_ID=1234567890@s.whatsapp.net
# Bot name prefix for outbound messages (default: project name)
# WHATSAPP_ASSISTANT_NAME=VirtEngine
# Auth/session data directory (default: .cache/whatsapp-store)
# WHATSAPP_STORE_DIR=.cache/whatsapp-store
# Phone number for pairing code auth (digits only, with country code)
# WHATSAPP_PHONE_NUMBER=12025551234
# ─── Container Isolation (Optional) ──────────────────────────────────────────
# Run agent tasks inside containers for security isolation.
# Supports Docker, Podman, or Apple Container (macOS).
# Enable container isolation (default: disabled)
# CONTAINER_ENABLED=false
# Container runtime: docker | podman | container (macOS Apple Container)
# CONTAINER_RUNTIME=docker
# Container image for agent execution
# CONTAINER_IMAGE=node:22-slim
# Agent execution timeout in ms (default: 1800000 = 30 min)
# CONTAINER_TIMEOUT_MS=1800000
# Max output size per container in bytes (default: 10485760 = 10MB)
# CONTAINER_MAX_OUTPUT_SIZE=10485760
# Max concurrent containers (default: 3)
# MAX_CONCURRENT_CONTAINERS=3
# Resource limits (Docker/Podman only)
# CONTAINER_MEMORY_LIMIT=4g
# CONTAINER_CPU_LIMIT=2
# ─── Orchestrator Script ──────────────────────────────────────────────────────
# Path to the orchestrator script (Bash, PowerShell, or any CLI).
# Auto-detected from common locations if not set.
# ORCHESTRATOR_SCRIPT=./orchestrator.sh
# Arguments passed to the orchestrator script (space-separated).
# ORCHESTRATOR_ARGS=-MaxParallel 6 -WaitForMutex
# ─── Executor Configuration ──────────────────────────────────────────────────
# Define AI executors that work on tasks.
# Format: EXECUTOR_TYPE:VARIANT:WEIGHT[:MODEL|MODEL],EXECUTOR_TYPE:VARIANT:WEIGHT[:MODEL|MODEL]
# Example: COPILOT:CLAUDE_OPUS_4_6:50:claude-opus-4.6,CODEX:DEFAULT:50:gpt-5.2-codex|gpt-5.1-codex-mini
# For full config, use bosun.config.json instead.
# EXECUTORS=CODEX:DEFAULT:100
# Task distribution mode: "weighted" | "round-robin" | "primary-only"
# EXECUTOR_DISTRIBUTION=weighted
# ─── Failover Configuration ──────────────────────────────────────────────────
# What happens when an executor fails repeatedly.
# Strategy: "next-in-line" | "weighted-random" | "round-robin"
# FAILOVER_STRATEGY=next-in-line
# Max retries before switching executor
# FAILOVER_MAX_RETRIES=3
# Minutes to disable an executor after consecutive failures
# FAILOVER_COOLDOWN_MIN=5
# Disable executor after N consecutive failures
# FAILOVER_DISABLE_AFTER=3
# ─── Internal Executor ───────────────────────────────────────────────────────
# Controls whether tasks are executed locally via agent-pool.
# EXECUTOR_MODE=internal
# Max concurrent agent slots for internal executor (default: 3)
# INTERNAL_EXECUTOR_PARALLEL=3
# INTERNAL_EXECUTOR_BASE_BRANCH_PARALLEL=0
# How often to poll kanban for new tasks in ms (default: 30000)
# INTERNAL_EXECUTOR_POLL_MS=30000
# Fail-fast policy for workflow start guards when a task appears missing in task-store.
# false (default): allow dispatch and emit start_guard_bypass audit event
# true: block dispatch and emit start_guard_blocked audit event
# BOSUN_STRICT_START_GUARD_MISSING_TASK=false
# SDK to use: "auto" | "codex" | "copilot" | "claude" | "gemini" | "opencode" (default: auto)
# INTERNAL_EXECUTOR_SDK=auto
# Timeout per task execution in ms (default: 5400000 = 90 min)
# INTERNAL_EXECUTOR_TIMEOUT_MS=5400000
# Max retries per task (default: 2)
# INTERNAL_EXECUTOR_MAX_RETRIES=2
# Override project ID for polling (auto-detected by default)
# INTERNAL_EXECUTOR_PROJECT_ID=
# Enable/disable review handoff agent for completed task PRs (default: enabled)
# INTERNAL_EXECUTOR_REVIEW_AGENT_ENABLED=true
# Review agent max concurrent reviews (default: 2)
# INTERNAL_EXECUTOR_REVIEW_MAX_CONCURRENT=2
# Review agent timeout per review run in ms (default: 300000)
# INTERNAL_EXECUTOR_REVIEW_TIMEOUT_MS=300000
# Experimental autonomous backlog replenishment (disabled by default)
# INTERNAL_EXECUTOR_REPLENISH_ENABLED=false
# Enable deterministic internal harness compile/activate control-plane support
# BOSUN_HARNESS_ENABLED=false
# Path to harness profile source (JSON or markdown fenced JSON)
# BOSUN_HARNESS_SOURCE=.bosun/harness/internal-harness.md
# Validation mode: off | report | enforce
# BOSUN_HARNESS_VALIDATION_MODE=report
# Minimum follow-up tasks to generate per completed task (1-2)
# INTERNAL_EXECUTOR_REPLENISH_MIN_NEW_TASKS=1
# Maximum follow-up tasks to generate per completed task (1-3)
# INTERNAL_EXECUTOR_REPLENISH_MAX_NEW_TASKS=2
# Require explicit priority for generated tasks (default: true)
# INTERNAL_EXECUTOR_REPLENISH_REQUIRE_PRIORITY=true
# Stream retry ceiling for transient stream disconnects (default: 5)
# INTERNAL_EXECUTOR_STREAM_MAX_RETRIES=5
# Stream retry backoff base delay in ms (default: 2000)
# INTERNAL_EXECUTOR_STREAM_RETRY_BASE_MS=2000
# Stream retry backoff max delay in ms (default: 32000)
# INTERNAL_EXECUTOR_STREAM_RETRY_MAX_MS=32000
# Retry queue: route to review workflow once retry count reaches this threshold (default: 3)
# INTERNAL_EXECUTOR_RETRY_REVIEW_THRESHOLD=3
# Retry queue: default delay before next retry attempt in ms (default: 15000)
# INTERNAL_EXECUTOR_RETRY_DELAY_MS=15000
# Abort/retry turns that emit no stream events within this budget (default: 120000)
# INTERNAL_EXECUTOR_STREAM_FIRST_EVENT_TIMEOUT_MS=120000
# Cap number of completed stream items retained per turn (default: 600)
# INTERNAL_EXECUTOR_STREAM_MAX_ITEMS_PER_TURN=600
# Truncate oversized item payload strings to this char budget (default: 12000)
# INTERNAL_EXECUTOR_STREAM_MAX_ITEM_CHARS=12000
# Prompt cache anchoring mode:
# default = best-effort split between system/user prompt
# strict = fail fast if task-specific data leaks into system prompt
# BOSUN_CACHE_ANCHOR_MODE=default
# Project requirements profile used by planner/replenishment prompts
# Allowed: simple-feature | feature | large-feature | system | multi-system
# PROJECT_REQUIREMENTS_PROFILE=feature
# Optional free-form constraints/scoping notes
# PROJECT_REQUIREMENTS_NOTES=
# ─── Branch Strategy ──────────────────────────────────────────────────
# How agents work on branches for each task:
#
# worktree (default) — Each task gets an isolated ve/<id>-<slug> sub-branch
# that PRs back into the module/base branch.
# Best for: independent, high-parallelism work.
#
# direct — Agents push directly onto the module branch
# (no ve/ sub-branch). All work is sequential on that
# branch. Conflicts are resolved in real time.
# Best for: fast iteration on a well-scoped module.
#
# TASK_BRANCH_MODE=worktree
#
# Auto-detect origin/<module> as base_branch from conventional commit task titles
# e.g. "[m] feat(veid): add verification" → base_branch = origin/veid
# TASK_BRANCH_AUTO_MODULE=true
#
# Prefix used when building module branch refs (default: origin/)
# MODULE_BRANCH_PREFIX=origin/
#
# Default upstream target branch (main branch) for upstream sync and PRs
# DEFAULT_TARGET_BRANCH=main
#
# Merge origin/main into module branches before each push (keeps branches in
# sync with upstream continuously). Conflicts abort the merge and are resolved
# by the next agent working on that branch. Default: true
# TASK_UPSTREAM_SYNC_MAIN=true
# ─── GitHub App (Bosun[VE] Identity + Auth) ────────────────────────────
# App: https://github.com/apps/bosun-ve (slug: bosun-ve)
# Bot identity: bosun-ve[bot] (appears as contributor on every agent commit)
#
# Numeric App ID (shown on the App settings page under "About"):
# BOSUN_GITHUB_APP_ID=2911413
#
# OAuth Client ID (from App settings → Client ID):
# BOSUN_GITHUB_CLIENT_ID=Iv23liZpVhGePGka9gcL
#
# OAuth Client Secret (only needed for callback-based OAuth, not for Device Flow):
# BOSUN_GITHUB_CLIENT_SECRET=
#
# Webhook secret (VirtEngine relay signs forwarded events with this — leave blank
# until VirtEngine’s relay server is live; Bosun polls GitHub API in the meantime):
# BOSUN_GITHUB_WEBHOOK_SECRET=
#
# Path to the PEM private key downloaded from App settings → Generate a private key:
# BOSUN_GITHUB_PRIVATE_KEY_PATH=/path/to/bosun-ve.pem
#
# ─── GitHub App Settings (enable all three in https://github.com/settings/apps/bosun-ve) ────
# ✅ Callback URL → http://127.0.0.1:54317/github/callback (set this FIRST, then Save)
# ✅ "Request user authorization (OAuth) during installation" → ON
# GitHub does OAuth at install time, redirecting to the Callback URL with
# installation_id + setup_action=install. Setup URL is DISABLED — that's fine.
# ✅ "Enable Device Flow" → ON (only available AFTER Callback URL is saved)
# Allows CLI/terminal auth without a public URL (like VS Code / Roo Code)
# ✕ Setup URL → leave BLANK (GitHub disables this field when OAuth-at-install is ON)
# ✕ "Redirect on update" → leave OFF (disabled alongside Setup URL)
#
# ─── Authentication Method ───────────────────────────────────────────────
# RECOMMENDED: Device Flow (like VS Code / Roo Code — no public URL needed!)
# 1. Set BOSUN_GITHUB_CLIENT_ID above
# 2. Enable “Device Flow” in GitHub App settings (only clickable after Callback URL is saved)
# 3. Go to Settings → GitHub in the Bosun UI and click “Sign in with GitHub”
# 4. That’s it — no webhook URL, no tunnel, no public server needed
#
# ALTERNATIVE: OAuth Callback
# Set BOSUN_GITHUB_CLIENT_ID + BOSUN_GITHUB_CLIENT_SECRET
# Register callback URL: http://127.0.0.1:54317/github/callback
#
# NOTE on webhooks:
# Real-time GitHub events (PR comments, issue mentions) are received via
# VirtEngine’s relay server and forwarded to your Bosun instance.
# Until the relay is live, Bosun polls the GitHub API every few minutes instead.
# Users do NOT need to configure a webhook URL or run any tunnel.
#
# Leave BOSUN_GITHUB_APP_ID unset to disable co-author trailer injection.
# (App ID and Client ID are already filled in above — no need to set them again.)
# ─── Kanban Backend ──────────────────────────────────────────────────────────
# Task-board backend:
# internal - local task-store source of truth (recommended primary)
# github - GitHub Issues
# jira - Jira Issues
# gnap - GNAP projection backend (off by default)
# KANBAN_BACKEND=internal
# Sync behavior:
# internal-primary - internal task-store remains source-of-truth (recommended)
# bidirectional - external status updates can mutate internal task status
# KANBAN_SYNC_POLICY=internal-primary
# Optional explicit kanban project ID (overrides backend auto-detection)
# KANBAN_PROJECT_ID=
# For GitHub Issues backend, set owner/repo (or GITHUB_REPOSITORY)
# GITHUB_REPO_OWNER=your-org
# GITHUB_REPO_NAME=your-repo
# GITHUB_REPOSITORY=your-org/your-repo or GITHUB_REPO=your-org/your-repo
# GitHub task source mode:
# issues - only create/list issues
# kanban - create/list issues and auto-link them into a GitHub Project
# GITHUB_PROJECT_MODE=issues
# GitHub Project owner/title/number used when GITHUB_PROJECT_MODE=kanban
# GITHUB_PROJECT_OWNER=your-org
# GITHUB_PROJECT_TITLE=Bosun
# GITHUB_PROJECT_NUMBER=3
# GitHub Project v2 status field name mapping (customize to match your board columns)
# GITHUB_PROJECT_STATUS_TODO=Todo
# GITHUB_PROJECT_STATUS_INPROGRESS=In Progress
# GITHUB_PROJECT_STATUS_INREVIEW=In Review
# GITHUB_PROJECT_STATUS_DONE=Done
# GITHUB_PROJECT_STATUS_CANCELLED=Cancelled
# Auto-sync task status to project board when updating via bosun (default: true)
# GITHUB_PROJECT_AUTO_SYNC=true
# GitHub webhook endpoint (served by ui-server.mjs) for project item updates
# GITHUB_PROJECT_WEBHOOK_PATH=/api/webhooks/github/project-sync
# Shared secret used to validate X-Hub-Signature-256 (recommended in production)
# GITHUB_PROJECT_WEBHOOK_SECRET=
# Require webhook signature validation (default: true if secret is set)
# GITHUB_PROJECT_WEBHOOK_REQUIRE_SIGNATURE=true
# Alert threshold for consecutive webhook/sync failures
# GITHUB_PROJECT_SYNC_ALERT_FAILURE_THRESHOLD=3
# Alert threshold for accumulated sync rate-limit events
# GITHUB_PROJECT_SYNC_RATE_LIMIT_ALERT_THRESHOLD=3
# Default assignee for newly created tasks (defaults to authenticated gh user)
# GITHUB_DEFAULT_ASSIGNEE=
# Auto-assign task creator/login when creating issues (default: true)
# GITHUB_AUTO_ASSIGN_CREATOR=true
# Codex task scoping label policy (only matching labels are picked by bosun)
# BOSUN_TASK_LABEL=bosun
# BOSUN_TASK_LABELS=bosun,codex-mointor
# BOSUN_ENFORCE_TASK_LABEL=true
# Optional issue fetch cap per sync/poll cycle (default: 1000)
# GITHUB_ISSUES_LIST_LIMIT=1000
# Task context limits (comments + attachments)
# BOSUN_TASK_CONTEXT_MAX_COMMENTS=8
# BOSUN_TASK_CONTEXT_MAX_COMMENT_CHARS=1200
# BOSUN_TASK_CONTEXT_MAX_ATTACHMENTS=20
# Immediate cap for known high-volume git outputs in context cache.
# Set to 0 to disable the cap entirely (default: 8000).
# BOSUN_GIT_OUTPUT_MAX_CHARS=8000
# Max upload size for task/chat attachments (MB)
# BOSUN_ATTACHMENT_MAX_MB=25
# Jira backend (KANBAN_BACKEND=jira)
# Jira Cloud site URL (no trailing slash)
# JIRA_BASE_URL=https://your-domain.atlassian.net
# Jira user email + API token (Basic auth: email:token)
# JIRA_EMAIL=you@example.com
# JIRA_API_TOKEN=
# Default Jira project key and issue type used for task creation/listing
# JIRA_PROJECT_KEY=ENG
# JIRA_ISSUE_TYPE=Task
# Optional parent issue key when using sub-task issue type
# JIRA_SUBTASK_PARENT_KEY=ENG-1
# Default assignee account ID for new Jira tasks
# JIRA_DEFAULT_ASSIGNEE=5b10a2844c20165700ede21g
# Jira workflow status mapping (bosun status -> Jira status name)
# JIRA_STATUS_TODO=To Do
# JIRA_STATUS_INPROGRESS=In Progress
# JIRA_STATUS_INREVIEW=In Review
# JIRA_STATUS_DONE=Done
# JIRA_STATUS_CANCELLED=Cancelled
# Jira labels used for shared-state lifecycle flags
# JIRA_LABEL_CLAIMED=codex:claimed
# JIRA_LABEL_WORKING=codex:working
# JIRA_LABEL_STALE=codex:stale
# JIRA_LABEL_IGNORE=codex:ignore
# Jira task scoping labels (only tasks with these labels are picked up)
# JIRA_TASK_LABELS=bosun,codex-mointor
# JIRA_ENFORCE_TASK_LABEL=true
# Jira issue fetch cap per sync/poll cycle (default: 250)
# JIRA_ISSUES_LIST_LIMIT=250
# Use Atlassian Document Format when writing comments (default: true)
# JIRA_USE_ADF_COMMENTS=true
# Jira custom fields used for shared-state persistence
# (leave unset if using structured comment fallback)
# JIRA_CUSTOM_FIELD_OWNER_ID=customfield_10042
# JIRA_CUSTOM_FIELD_ATTEMPT_TOKEN=customfield_10043
# JIRA_CUSTOM_FIELD_ATTEMPT_STARTED=customfield_10044
# JIRA_CUSTOM_FIELD_HEARTBEAT=customfield_10045
# JIRA_CUSTOM_FIELD_RETRY_COUNT=customfield_10046
# JIRA_CUSTOM_FIELD_IGNORE_REASON=customfield_10047
# JIRA_CUSTOM_FIELD_BASE_BRANCH=customfield_10049
# Optional JSON custom field to store full shared state payload
# JIRA_CUSTOM_FIELD_SHARED_STATE=customfield_10048
# GNAP backend (KANBAN_BACKEND=gnap)
# Master toggle for GNAP integration. Must be enabled before selecting gnap.
# GNAP_ENABLED=false
# Path to the repo or clone that will host GNAP projection data
# GNAP_REPO_PATH=
# Synchronization mode. Bosun currently supports projection-only GNAP wiring.
# GNAP_SYNC_MODE=projection
# Where to store GNAP run metadata: git|local
# GNAP_RUN_STORAGE=git
# Where to store GNAP message projections: off|git|local
# GNAP_MESSAGE_STORAGE=off
# Optional sanitized roadmap export for shared visibility
# GNAP_PUBLIC_ROADMAP_ENABLED=false
# ─── Sandbox Policy ──────────────────────────────────────────────────────────
# Controls agent sandbox isolation when using Codex SDK.
# Options:
# "workspace-write" — Permissive writes within workspace/worktree (recommended default)
# "danger-full-access" — Full host filesystem access (use only when required)
# "read-only" — Agent cannot write to any files
# CODEX_SANDBOX=workspace-write
# ─── Codex Feature Flags ─────────────────────────────────────────────────────
# Controls which Codex CLI features are enabled in config.toml during setup.
# All default to "true" (enabled). Set to "false" to disable a specific feature.
# CODEX_FEATURES_CHILD_AGENTS_MD=true # Sub-agent discovery via CODEX.md (KEY for sub-agents)
# CODEX_FEATURES_MEMORIES=true # Persistent memory across sessions
# CODEX_FEATURES_UNDO=true # Undo/rollback support
# CODEX_FEATURES_MULTI_AGENT=true # Multi Agent mode
# CODEX_FEATURES_COLLABORATION_MODES=true # Mode selection for collaboration
# CODEX_FEATURES_STEER=true # Steering/guidance
# CODEX_FEATURES_APPS=true # ChatGPT Apps integration
# CODEX_FEATURES_BWRAP=true # Bubblewrap sandbox (disable if bwrap userns is blocked)
# CODEX_FEATURES_SHELL_TOOL=true # Shell tool access
# ─── Codex Sandbox Permissions ───────────────────────────────────────────────
# Comma-separated list of sandbox permission entries for config.toml.
# Default: "disk-full-write-access"
# CODEX_SANDBOX_PERMISSIONS=disk-full-write-access
# Workspace-write sandbox roots (comma-separated). Defaults to repo parent/root.
# Include your repo and its .git directory if git operations fail.
# CODEX_SANDBOX_WRITABLE_ROOTS=/home/jon/repos,/home/jon/repos/virtengine/.git
# ─── Codex Shell Environment Policy ─────────────────────────────────────────
# Controls which env vars are inherited by Codex sandbox.
# Options: "all" (inherit everything), "none", or custom policy
# CODEX_SHELL_ENV_POLICY=all
# ─── Codex Agent Limits ──────────────────────────────────────────────────────
# Max concurrent agent threads per Codex session (overrides default 6).
# CODEX_AGENT_MAX_THREADS=12
# ─── Copilot Sub-Agent / Parallel ────────────────────────────────────────────
# Disable parallel tool execution (sub-agent-like concurrency) in Copilot CLI.
# Default: parallel is ENABLED. Set to "true" to disable.
# COPILOT_DISABLE_PARALLEL_TOOLS=false
# Additional MCP config path for fleet/task sub-agent MCP servers
# COPILOT_ADDITIONAL_MCP_CONFIG=
# ─── Daemon Mode ──────────────────────────────────────────────────────────────
# Run bosun as a background daemon:
# bosun --daemon Start detached daemon
# bosun --stop-daemon Stop running daemon
# bosun --daemon-status Check if daemon is running
# Optional: keep sentinel always-on alongside monitor
# bosun --daemon --sentinel
# PID file: .cache/bosun.pid
# Logs: logs/daemon.log
# Daemon crash supervision (monitor child):
# BOSUN_DAEMON_RESTART_DELAY_MS=5000
# BOSUN_DAEMON_MAX_RESTARTS=0 # 0 = unlimited
# Consider any crash within this window as an instant startup failure (default: 15000)
# BOSUN_DAEMON_INSTANT_CRASH_WINDOW_MS=15000
# Stop auto-restarts after this many instant failures in a row (default: 3)
# BOSUN_DAEMON_MAX_INSTANT_RESTARTS=3
# ─── Shared Workspace Registry ───────────────────────────────────────────────
# Optional registry path for shared workspace leasing
# VE_SHARED_WORKSPACE_REGISTRY=.cache/bosun/shared-workspaces.json
# Optional audit log path for shared workspace leasing
# VE_SHARED_WORKSPACE_AUDIT_LOG=.cache/bosun/shared-workspace-audit.jsonl
# Default lease TTL in minutes (Telegram claims); can override with seconds below
# VE_WORKSPACE_LEASE_TTL_MIN=120
# Default lease TTL in seconds (converted to minutes if set)
# VE_WORKSPACE_LEASE_TTL_SEC=7200
# Default owner name for CLI/Telegram claims (falls back to USER/USERNAME)
# VE_WORKSPACE_OWNER=your-name
# ─── GitHub ───────────────────────────────────────────────────────────────────
# Repository slug for PR links (default: auto-detected from git remote)
# GITHUB_REPO=your-org/your-repo
# Custom GitHub URL base for links
# GITHUB_REPO_URL=https://github.com/your-org/your-repo
# GitHub API token for PR lookups when gh is unavailable (any of these work)
# GITHUB_TOKEN=
# GH_TOKEN=
# GITHUB_PAT=
# Target branch for PR checks/merge (default: origin/main)
# BOSUN_TASK_UPSTREAM=origin/main
# ─── Codex / AI Provider ─────────────────────────────────────────────────────
# The Codex SDK uses OpenAI-compatible configuration that has been setup in ~/.codex/config.toml -
# you do not need to set env variables here if config is already setup.
# Set these to use a different model or provider.
# OPENAI_API_KEY=
# AZURE_OPENAI_API_KEY=
# OPENAI_BASE_URL=https://api.openai.com/v1
# CODEX_MODEL=gpt-4o
#
# Optional profile-based model/provider switching (single Codex config, multiple presets):
# CODEX_MODEL_PROFILE=xl
# CODEX_MODEL_PROFILE_SUBAGENT=m
# CODEX_MODEL_PROFILE_XL_PROVIDER=openai
# CODEX_MODEL_PROFILE_XL_MODEL=gpt-5.3-codex
# CODEX_MODEL_PROFILE_XL_BASE_URL=
# CODEX_MODEL_PROFILE_XL_API_KEY=
# CODEX_MODEL_PROFILE_M_PROVIDER=openai
# CODEX_MODEL_PROFILE_M_MODEL=gpt-5.1-codex-mini
# CODEX_MODEL_PROFILE_M_BASE_URL=
# CODEX_MODEL_PROFILE_M_API_KEY=
# CODEX_SUBAGENT_MODEL=gpt-5.1-codex-mini
# Agent transport selector: auto | sdk | cli
# CODEX_TRANSPORT=sdk
# Set to true to disable all Codex/AI features (analysis, autofix, shell)
# CODEX_SDK_DISABLED=false
# Primary agent adapter: codex-sdk | copilot-sdk | claude-sdk | gemini-sdk | opencode-sdk
# PRIMARY_AGENT=codex-sdk
# Set to true to disable the primary agent adapter
# PRIMARY_AGENT_DISABLED=false
# ─── Agent Pool ──────────────────────────────────────────────────────────────
# Which SDK the ephemeral agent pool uses for concurrent operations.
# Defaults to PRIMARY_AGENT value, then falls back through available SDKs.
# IMPORTANT: single value only (codex | copilot | claude).
# Do NOT use separators like "|" or "," (unsupported).
# AGENT_POOL_SDK=copilot
# Default model for agent pool threads (empty = use SDK default).
# Note: agent-pool currently resolves model primarily from SDK-specific env vars
# (for example CODEX_MODEL / COPILOT_MODEL / CLAUDE_MODEL), not a multi-value list.
# AGENT_POOL_MODEL=
# ─── Agent Hooks (Codex / Claude / Copilot) ─────────────────────────────────
# Setup can scaffold shared hook configs in:
# .codex/hooks.json
# .claude/settings.local.json
# .github/hooks/bosun.hooks.json
#
# Hook profile for setup/non-interactive runs:
# strict | balanced | lightweight | none
# BOSUN_HOOK_PROFILE=strict
#
# Which agents should receive generated hook files (comma-separated):
# codex,claude,copilot
# BOSUN_HOOK_TARGETS=codex,claude,copilot
#
# Set to false to skip hook scaffolding during setup.
# BOSUN_HOOKS_ENABLED=true
# Set to true to overwrite existing generated hook files.
# BOSUN_HOOKS_OVERWRITE=false
# Optional overrides for generated bridge command tokens.
# Defaults are portable across workstations:
# node scripts/bosun/agent-hook-bridge.mjs
# BOSUN_HOOK_NODE_BIN=node
# BOSUN_HOOK_BRIDGE_PATH=scripts/bosun/agent-hook-bridge.mjs
#
# Optional per-event command overrides (separate multiple commands with ';;').
# Use value 'none' to disable that event in generated .codex/hooks.json.
# BOSUN_HOOK_PREPUSH=go vet ./...;;go build ./...
# BOSUN_HOOK_PRECOMMIT=gofmt -l .
# BOSUN_HOOK_TASK_COMPLETE=echo \"task completed\"
# BOSUN_HOOK_SESSION_START=echo \"session start\"
# BOSUN_HOOK_SESSION_STOP=echo \"session stop\"
#
# Built-in hook behavior inside bosun runtime:
# force (default), auto, off
# BOSUN_HOOKS_BUILTINS_MODE=force
# BOSUN_HOOKS_DISABLE_PREPUSH=false
# BOSUN_HOOKS_DISABLE_TASK_COMPLETE=false
# BOSUN_HOOKS_DISABLE_HEALTH_CHECK=false
# ── OpenTelemetry Tracing & Metrics ───────────────────────────────────────────
# External orchestration-layer observability only; never affects agent context.
# BOSUN_OTEL_ENDPOINT=http://localhost:4318/v1/traces
# Configure tracing.sampleRate in bosun.config.json to tune sampling.
# Force hooks to fire even for non-managed sessions (debug only):
# BOSUN_HOOKS_FORCE=false
# VE_MANAGED is auto-set by bosun at startup. Agent hook bridge
# scripts check for this and exit silently if not present, preventing
# hooks from firing in standalone Copilot/Codex/Claude sessions.
# ─── Copilot SDK (Primary Agent) ─────────────────────────────────────────────
# Requires GitHub Copilot CLI installed and authenticated.
# Set to true to disable Copilot SDK (primary agent) usage.
# COPILOT_SDK_DISABLED=false
# Override model (used by Copilot shell + background task-executor agent-pool sessions)
# COPILOT_MODEL=gpt-5
# Optional: profile-based overrides (model, reasoning effort, MCP config)
# COPILOT_PROFILE=default
# COPILOT_PROFILE_DEFAULT_MODEL=gpt-5
# COPILOT_PROFILE_DEFAULT_REASONING_EFFORT=high
# COPILOT_PROFILE_DEFAULT_MCP_CONFIG=.vscode/mcp.json
# COPILOT_PROFILE_DEFAULT_MCP_SERVERS={"context7":{"command":"npx","args":["-y","@upstash/context7-mcp"]}}
# Transport selector: auto | sdk | cli | url
# COPILOT_TRANSPORT=sdk
#
# Session mode: local | remote | auto
# "local" (default): CLI runs as local subprocess via stdio — FULL model access
# (gpt-5.3-codex, claude-sonnet-4.5, etc.), MCP tools, sub-agents.
# "remote": Connect to external server via cliUrl (may have restricted models/tools).
# "auto": Let the SDK decide (falls back to local when no cliUrl is set).
# COPILOT_SESSION_MODE=local
# Auto-approve Copilot SDK permission requests in automated runs (default: true)
# Set to false to require explicit approval callbacks.
# COPILOT_AUTO_APPROVE_PERMISSIONS=true
# Force spawned Copilot CLI sessions to allow all tools/paths/urls.
# Default behavior enables this automatically when auto-approve is enabled.
# COPILOT_ALLOW_ALL=true
# Optional: point to Copilot CLI binary or server
# COPILOT_CLI_PATH=copilot
# COPILOT_CLI_URL=http://127.0.0.1:8888
# Optional: pass MCP server config (JSON string or path)
# COPILOT_MCP_SERVERS={"github":{"type":"http","url":"https://api.githubcopilot.com/mcp/"}}
# COPILOT_MCP_CONFIG=.vscode/mcp.json
#
# ── Copilot Experimental & Autonomy ─────────────────────────────────────────
# Experimental mode is ON by default in SDK sessions. This enables:
# - /fleet command (parallel sub-agent dispatch for large tasks)
# - Autopilot mode (autonomous agent operation)
# - Persisted permissions across sessions
# - Subagent compaction (context management)
# - Session cleanup commands
# Set to true to DISABLE experimental features:
# COPILOT_NO_EXPERIMENTAL=false
#
# Auto-approve all permissions (tools, paths, URLs) — equivalent to --allow-all / --yolo.
# ON by default for autonomous operation. Set to true to DISABLE:
# COPILOT_NO_ALLOW_ALL=false
#
# Re-enable the ask_user tool (agent can ask questions and block for input).
# OFF by default for full autonomy (--no-ask-user). Set to true to ENABLE:
# COPILOT_ENABLE_ASK_USER=false
#
# Reasoning effort for models that support it: low | medium | high | xhigh
# COPILOT_REASONING_EFFORT=high
# Max requests per Copilot agent session (used for generated workspace settings)
# COPILOT_AGENT_MAX_REQUESTS=500
#
# Enable ALL GitHub MCP tools (extended toolset beyond defaults):
# COPILOT_ENABLE_ALL_GITHUB_MCP_TOOLS=true
#
# Disable built-in MCP servers (use only custom-configured ones):
# COPILOT_DISABLE_BUILTIN_MCPS=false
# ── Auth Passthrough (Copilot) ──────────────────────────────────────────────
# The shell automatically detects authentication from multiple sources:
# 1. COPILOT_CLI_TOKEN / GITHUB_TOKEN / GH_TOKEN / GITHUB_PAT (highest priority)
# 2. gh CLI authentication (gh auth status)
# 3. SDK default auth flow
# Provide a token to skip interactive login:
# COPILOT_CLI_TOKEN=gho_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# GH_TOKEN=your-github-personal-access-token
# GITHUB_PAT=your-github-personal-access-token
# ─── Claude Agent SDK (Claude Code) ─────────────────────────────────────────
# Set to true to disable Claude SDK features
# CLAUDE_SDK_DISABLED=false
# CLAUDE_MODEL=claude-opus-4-6
# Transport selector: auto | sdk | cli
# CLAUDE_TRANSPORT=sdk
# CLAUDE_PERMISSION_MODE=bypassPermissions
# CLAUDE_MAX_TURNS=0
# CLAUDE_INCLUDE_PARTIAL=false
# CLAUDE_ALLOWED_TOOLS=Read,Write,Edit,Grep,Glob,Bash,WebSearch,Task,Skill
# ── Auth Passthrough (Claude) ───────────────────────────────────────────────
# The shell automatically detects authentication from multiple sources:
# 1. ANTHROPIC_API_KEY / CLAUDE_API_KEY / CLAUDE_KEY (highest priority)
# 2. ~/.config/claude/config.json
# 3. SDK prompt (if no auth found)
# Provide an API key to skip interactive prompts:
# ANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# CLAUDE_API_KEY=your-anthropic-api-key
# CLAUDE_KEY=your-anthropic-api-key
# ─── Gemini SDK ──────────────────────────────────────────────────────────────
# Set to true to disable Gemini SDK features
# GEMINI_SDK_DISABLED=false
# Transport selector: auto | sdk | cli
# GEMINI_TRANSPORT=auto
# Gemini model (default: gemini-2.5-pro)
# GEMINI_MODEL=gemini-2.5-pro
# API key (either variable works)
# GEMINI_API_KEY=
# GOOGLE_API_KEY=
# Optional Gemini API base URL override
# GEMINI_BASE_URL=
# ─── OpenCode SDK ────────────────────────────────────────────────────────────
# Set to true to disable OpenCode SDK features
# OPENCODE_SDK_DISABLED=false
# Local OpenCode server port
# OPENCODE_PORT=4096
# Optional model override passed to OpenCode
# OPENCODE_MODEL=gpt-5.2-codex
# ─── Merge Strategy (Codex-powered PR decision engine) ───────────────────────
# When a task completes, analyze the agent's output via Codex SDK to decide:
# merge_after_ci_pass, prompt (agent), close_pr, re_attempt, manual_review, wait
# Set to "false" to disable (default: enabled when Codex is enabled)
# CODEX_ANALYZE_MERGE_STRATEGY=true
# Timeout for merge strategy analysis in milliseconds (default: 600000 = 10 min)
# MERGE_STRATEGY_TIMEOUT_MS=600000
# ─── Autofix Mode ────────────────────────────────────────────────────────────
# How autofix behaves when errors are detected:
# "auto" - (default) detect from environment (dev source = execute, npm = analyze)
# "execute" - force execute mode: actually applies fixes to disk
# "analyze" - force analyze mode: only sends suggestions, never modifies files
# AUTOFIX_MODE=auto
# ─── Task Planner ────────────────────────────────────────────────────────────
# Auto-trigger task planner when backlog-per-slot drops below threshold
TASK_PLANNER_PER_CAPITA_THRESHOLD=1
# Auto-trigger when idle slots meet/exceed threshold
TASK_PLANNER_IDLE_SLOT_THRESHOLD=1
# De-duplication window in hours
TASK_PLANNER_DEDUP_HOURS=6
# ─── Task Complexity Routing ─────────────────────────────────────────────────
# Automatically select AI models based on task size labels [xs]/[s]/[m]/[l]/[xl]/[xxl].
# Enabled by default. Set to false/0 to disable and use the profile's default model.
COMPLEXITY_ROUTING_ENABLED=true
#
# Override specific tier models (format: COMPLEXITY_ROUTING_{EXECUTOR}_{TIER}_{FIELD}):
# COMPLEXITY_ROUTING_CODEX_LOW_MODEL=gpt-5.1-codex-mini
# COMPLEXITY_ROUTING_CODEX_LOW_VARIANT=GPT51_CODEX_MINI
# COMPLEXITY_ROUTING_CODEX_LOW_REASONING=low
# COMPLEXITY_ROUTING_CODEX_MEDIUM_MODEL=gpt-5.2-codex
# COMPLEXITY_ROUTING_CODEX_MEDIUM_VARIANT=DEFAULT
# COMPLEXITY_ROUTING_CODEX_MEDIUM_REASONING=medium
# COMPLEXITY_ROUTING_CODEX_HIGH_MODEL=gpt-5.1-codex-max
# COMPLEXITY_ROUTING_CODEX_HIGH_VARIANT=GPT51_CODEX_MAX
# COMPLEXITY_ROUTING_CODEX_HIGH_REASONING=high
# COMPLEXITY_ROUTING_COPILOT_LOW_MODEL=claude-haiku-4.5
# COMPLEXITY_ROUTING_COPILOT_MEDIUM_MODEL=claude-sonnet-4.5
# COMPLEXITY_ROUTING_COPILOT_MEDIUM_REASONING=medium
# COMPLEXITY_ROUTING_COPILOT_HIGH_MODEL=claude-opus-4.6
# COMPLEXITY_ROUTING_COPILOT_HIGH_REASONING=high
# ─── Shared Cloud Workspaces ────────────────────────────────────────────────
# Registry file for shared workspace leasing (default: .cache/bosun/shared-workspaces.json)
# VE_SHARED_WORKSPACE_REGISTRY=
# Audit log file for claim/release events (default: .cache/bosun/shared-workspace-audit.jsonl)
# VE_SHARED_WORKSPACE_AUDIT_LOG=
# ─── CI Sweep (Orchestrator) ─────────────────────────────────────────────────
# Trigger CI sweep after N completed tasks (0 disables)
# VE_CI_SWEEP_EVERY=15
# Backup trigger after N merged PRs on main (0 disables)
# VE_CI_SWEEP_PR_EVERY=15
# Enable PR-based backup trigger
# VE_CI_SWEEP_PR_BACKUP=true
# Disable Copilot cloud triggers when rate-limited
# COPILOT_CLOUD_DISABLE_ON_RATE_LIMIT=true
# COPILOT_CLOUD_COOLDOWN_MIN=60
# Cooldown duration (minutes) when Copilot rate limit is detected in PR comments
# COPILOT_RATE_LIMIT_COOLDOWN_MIN=120
# Force-disable Copilot cloud triggers (PR comments/issues)
# Set to true to prevent @copilot PR comments, issue assignments, and CI sweeps via cloud.
# Default: true (disabled) — enable explicitly by setting to false.
COPILOT_CLOUD_DISABLED=true
# COPILOT_CLOUD_DISABLED_UNTIL=2026-02-07T12:00:00Z
# Local resolution strategy when Copilot cloud is disabled: "agent" or "codex"
# COPILOT_LOCAL_RESOLUTION=agent
# Wait for orchestrator mutex instead of exiting when another instance runs
# VE_ORCHESTRATOR_WAIT_FOR_MUTEX=true
# ─── Completed Task Archive ────────────────────────────────────────────────
# Enable/disable automatic completed task archival (default: true)
# VE_COMPLETED_TASK_ARCHIVE_ENABLED=true
# Only archive tasks completed more than N hours ago (default: 24)
# VE_COMPLETED_TASK_ARCHIVE_AGE_HOURS=24
# Minimum minutes between archive runs (default: 30)
# VE_COMPLETED_TASK_ARCHIVE_INTERVAL_MIN=30
# Max tasks to archive per run (default: 200)
# VE_COMPLETED_TASK_ARCHIVE_MAX=200
# Dry run (no deletes/writes) for validation
# VE_COMPLETED_TASK_ARCHIVE_DRY_RUN=false
# Allow smartPR to recreate PRs even if a closed PR already exists for the branch
# VE_SMARTPR_ALLOW_RECREATE_CLOSED=0
# Run a task-assessment gate before auto-creating PRs (default: enabled)
# When enabled, smartPR will defer PR creation if assessment action is not merge/noop.