loki-mode 6.32.0 → 6.32.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/SKILL.md CHANGED
@@ -3,7 +3,7 @@ name: loki-mode
3
3
  description: Multi-agent autonomous startup system. Triggers on "Loki Mode". Takes PRD to deployed product with minimal human intervention. Requires --dangerously-skip-permissions flag.
4
4
  ---
5
5
 
6
- # Loki Mode v6.32.0
6
+ # Loki Mode v6.32.1
7
7
 
8
8
  **You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
9
9
 
@@ -267,4 +267,4 @@ The following features are documented in skill modules but not yet fully automat
267
267
  | Quality gates 3-reviewer system | Implemented (v5.35.0) | 5 specialist reviewers in `skills/quality-gates.md`; execution in run.sh |
268
268
  | Benchmarks (HumanEval, SWE-bench) | Infrastructure only | Runner scripts and datasets exist in `benchmarks/`; no published results |
269
269
 
270
- **v6.32.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
270
+ **v6.32.1 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 6.32.0
1
+ 6.32.1
package/autonomy/loki CHANGED
@@ -394,7 +394,7 @@ show_help() {
394
394
  echo " demo Run interactive demo (~60s simulated session)"
395
395
  echo " init [name] Project scaffolding with 22 PRD templates"
396
396
  echo " issue <url|num> [DEPRECATED] Use 'loki run' instead"
397
- echo " watch [sec] Live TUI session monitor (v6.0.0)"
397
+ echo " watch [prd] Auto-rerun on PRD file changes (v6.33.0)"
398
398
  echo " export <format> Export session data: json|markdown|csv|timeline (v6.0.0)"
399
399
  echo " stop Stop execution immediately"
400
400
  echo " cleanup Kill orphaned processes from crashed sessions"
@@ -487,7 +487,7 @@ show_help() {
487
487
  echo " loki start ./prd.md # Start with PRD file"
488
488
  echo " loki start --bg # Start in background"
489
489
  echo " loki start --parallel # Start in parallel mode"
490
- echo " loki watch # Live session monitor"
490
+ echo " loki watch # Watch PRD for changes, auto-rerun"
491
491
  echo " loki export json # Export session data"
492
492
  echo " loki config set maxTier sonnet # Cap model cost"
493
493
  echo " loki status # Check current status"
@@ -4312,126 +4312,252 @@ EOF
4312
4312
 
4313
4313
  # Show configuration
4314
4314
  #===============================================================================
4315
- # loki watch - Live TUI session monitor (v6.0.0)
4315
+ # loki watch - Auto-rerun on PRD file changes (v6.33.0)
4316
4316
  #===============================================================================
4317
4317
 
4318
4318
  cmd_watch() {
4319
- local interval="${1:-2}"
4319
+ local prd_path=""
4320
+ local run_once=false
4321
+ local poll_interval=2
4322
+ local no_auto_start=false
4323
+ local debounce=3
4324
+ local _watch_child_pid=""
4320
4325
 
4321
- # Handle --help
4322
- if [[ "$interval" == "--help" || "$interval" == "-h" ]]; then
4323
- # fall through to help block
4324
- :
4325
- elif ! [[ "$interval" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
4326
- echo -e "${RED}Invalid interval: $interval (expected positive number)${NC}"
4327
- return 1
4328
- elif [[ "$interval" =~ ^0+(\.0+)?$ ]]; then
4329
- echo -e "${RED}Invalid interval: $interval (must be greater than 0)${NC}"
4326
+ while [[ $# -gt 0 ]]; do
4327
+ case "$1" in
4328
+ --help|-h)
4329
+ echo -e "${BOLD}loki watch${NC} - Auto-rerun on PRD file changes (v6.33.0)"
4330
+ echo ""
4331
+ echo "Usage: loki watch [prd-path] [options]"
4332
+ echo ""
4333
+ echo "Monitors a PRD file for changes and automatically re-runs Loki Mode"
4334
+ echo "when the file is saved. Enables a tight edit-PRD-see-results loop."
4335
+ echo ""
4336
+ echo "Arguments:"
4337
+ echo " prd-path Path to PRD file (default: auto-detect prd.md, PRD.md, or first *.md)"
4338
+ echo ""
4339
+ echo "Options:"
4340
+ echo " --once Run once immediately then exit"
4341
+ echo " --interval N Poll interval in seconds for fallback watcher (default: 2)"
4342
+ echo " --no-auto-start Watch but do not auto-start, just print change timestamps"
4343
+ echo " --debounce N Wait N seconds after change before triggering (default: 3)"
4344
+ echo " --help, -h Show this help"
4345
+ echo ""
4346
+ echo "File watcher priority:"
4347
+ echo " 1. fswatch (macOS) -- native filesystem events"
4348
+ echo " 2. inotifywait (Linux) -- inotify-based"
4349
+ echo " 3. stat polling -- universal fallback"
4350
+ echo ""
4351
+ echo "Examples:"
4352
+ echo " loki watch # Auto-detect PRD and watch"
4353
+ echo " loki watch ./my-prd.md # Watch specific file"
4354
+ echo " loki watch --once # Run once immediately then exit"
4355
+ echo " loki watch --no-auto-start # Just report changes, don't run"
4356
+ echo " loki watch --debounce 5 # Wait 5s after change before triggering"
4357
+ echo " loki watch --interval 1 # Poll every 1s (fallback mode)"
4358
+ return 0
4359
+ ;;
4360
+ --once) run_once=true; shift ;;
4361
+ --interval) poll_interval="${2:-2}"; shift 2 ;;
4362
+ --interval=*) poll_interval="${1#*=}"; shift ;;
4363
+ --no-auto-start) no_auto_start=true; shift ;;
4364
+ --debounce) debounce="${2:-3}"; shift 2 ;;
4365
+ --debounce=*) debounce="${1#*=}"; shift ;;
4366
+ -*)
4367
+ echo -e "${RED}Unknown option: $1${NC}"
4368
+ echo "Run 'loki watch --help' for usage."
4369
+ return 1
4370
+ ;;
4371
+ *)
4372
+ if [ -z "$prd_path" ]; then
4373
+ prd_path="$1"
4374
+ else
4375
+ echo -e "${RED}Unexpected argument: $1${NC}"
4376
+ return 1
4377
+ fi
4378
+ shift
4379
+ ;;
4380
+ esac
4381
+ done
4382
+
4383
+ # Validate numeric arguments
4384
+ if ! [[ "$poll_interval" =~ ^[0-9]+$ ]] || [ "$poll_interval" -lt 1 ]; then
4385
+ echo -e "${RED}Invalid --interval: $poll_interval (expected positive integer)${NC}"
4330
4386
  return 1
4331
4387
  fi
4332
- if [[ "$interval" == "--help" || "$interval" == "-h" ]]; then
4333
- echo -e "${BOLD}loki watch${NC} - Live session monitor (v6.0.0)"
4334
- echo ""
4335
- echo "Usage: loki watch [interval]"
4336
- echo ""
4337
- echo "Options:"
4338
- echo " interval Refresh interval in seconds (default: 2)"
4339
- echo ""
4340
- echo "Displays:"
4341
- echo " - Current iteration and RARV phase"
4342
- echo " - Provider and model tier"
4343
- echo " - Task queue status"
4344
- echo " - Recent log lines"
4345
- echo " - Cost tracking"
4346
- echo ""
4347
- echo "Press Ctrl+C to exit."
4348
- exit 0
4388
+ if ! [[ "$debounce" =~ ^[0-9]+$ ]] || [ "$debounce" -lt 0 ]; then
4389
+ echo -e "${RED}Invalid --debounce: $debounce (expected non-negative integer)${NC}"
4390
+ return 1
4349
4391
  fi
4350
4392
 
4351
- if [ ! -d "$LOKI_DIR" ]; then
4352
- echo -e "${RED}No active session found.${NC}"
4353
- echo "Start a session with: loki start <prd>"
4354
- exit 1
4393
+ # Auto-detect PRD file if not specified
4394
+ if [ -z "$prd_path" ]; then
4395
+ if [ -f "prd.md" ]; then
4396
+ prd_path="prd.md"
4397
+ elif [ -f "PRD.md" ]; then
4398
+ prd_path="PRD.md"
4399
+ else
4400
+ # Find first .md file in current directory
4401
+ local first_md
4402
+ first_md=$(ls -1 *.md 2>/dev/null | head -1 || true)
4403
+ if [ -n "$first_md" ]; then
4404
+ prd_path="$first_md"
4405
+ else
4406
+ echo -e "${RED}No PRD file found.${NC}"
4407
+ echo "Specify a file: loki watch ./my-prd.md"
4408
+ echo "Or create one: prd.md, PRD.md, or any .md file in current directory."
4409
+ return 1
4410
+ fi
4411
+ fi
4355
4412
  fi
4356
4413
 
4357
- echo -e "${BOLD}Loki Mode Watch${NC} (refresh: ${interval}s, Ctrl+C to exit)"
4358
- echo ""
4359
-
4360
- trap 'echo ""; echo "Watch stopped."; return 0' INT TERM
4414
+ if [ ! -f "$prd_path" ]; then
4415
+ echo -e "${RED}PRD file not found: $prd_path${NC}"
4416
+ return 1
4417
+ fi
4361
4418
 
4362
- while true; do
4363
- clear
4364
- echo -e "${BOLD}Loki Mode Watch${NC} $(date '+%H:%M:%S') (refresh: ${interval}s)"
4365
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
4419
+ # Resolve to absolute path
4420
+ prd_path="$(cd "$(dirname "$prd_path")" && pwd)/$(basename "$prd_path")"
4421
+ local prd_basename
4422
+ prd_basename="$(basename "$prd_path")"
4423
+
4424
+ # --once mode: run immediately and exit
4425
+ if [ "$run_once" = true ]; then
4426
+ echo -e "${BOLD}loki watch${NC} --once: running loki start ${prd_basename}"
4427
+ "$0" start "$prd_path"
4428
+ return $?
4429
+ fi
4366
4430
 
4367
- # Session status
4368
- if [ -f "$LOKI_DIR/PAUSE" ]; then
4369
- echo -e "Status: ${YELLOW}PAUSED${NC}"
4370
- elif [ -f "$LOKI_DIR/STOP" ]; then
4371
- echo -e "Status: ${RED}STOPPED${NC}"
4372
- elif [ -f "$LOKI_DIR/loki.pid" ] && kill -0 "$(cat "$LOKI_DIR/loki.pid" 2>/dev/null)" 2>/dev/null; then
4373
- echo -e "Status: ${GREEN}RUNNING${NC}"
4374
- else
4375
- echo -e "Status: ${DIM}IDLE${NC}"
4431
+ # Graceful shutdown handler
4432
+ _watch_cleanup() {
4433
+ echo ""
4434
+ echo "Watch stopped."
4435
+ if [ -n "$_watch_child_pid" ] && kill -0 "$_watch_child_pid" 2>/dev/null; then
4436
+ echo "Stopping running loki session (PID $_watch_child_pid)..."
4437
+ kill "$_watch_child_pid" 2>/dev/null
4438
+ wait "$_watch_child_pid" 2>/dev/null || true
4376
4439
  fi
4377
-
4378
- # Iteration and phase
4379
- if [ -f "$LOKI_DIR/state/iteration" ]; then
4380
- local iter
4381
- iter=$(cat "$LOKI_DIR/state/iteration" 2>/dev/null || echo "?")
4382
- echo -e "Iteration: $iter"
4440
+ # Kill any background watcher process
4441
+ if [ -n "${_watch_bg_pid:-}" ] && kill -0 "$_watch_bg_pid" 2>/dev/null; then
4442
+ kill "$_watch_bg_pid" 2>/dev/null
4443
+ wait "$_watch_bg_pid" 2>/dev/null || true
4383
4444
  fi
4445
+ exit 0
4446
+ }
4447
+ trap '_watch_cleanup' INT TERM
4384
4448
 
4385
- # Provider info
4386
- local prov="${LOKI_PROVIDER:-claude}"
4387
- if [ -f "$LOKI_DIR/state/provider" ]; then
4388
- prov=$(cat "$LOKI_DIR/state/provider" 2>/dev/null || echo "$prov")
4389
- fi
4390
- echo -e "Provider: $prov"
4449
+ local last_run="never"
4391
4450
 
4392
- # Queue status
4393
- echo ""
4394
- echo -e "${CYAN}Task Queue:${NC}"
4395
- for queue in pending in-progress completed failed; do
4396
- local queue_file="$LOKI_DIR/queue/${queue}.json"
4397
- if [ -f "$queue_file" ]; then
4398
- local count
4399
- count=$(_QUEUE_FILE="$queue_file" python3 -c "import json, os; print(len(json.load(open(os.environ['_QUEUE_FILE']))))" 2>/dev/null || echo "0")
4400
- echo " $queue: $count"
4401
- fi
4402
- done
4451
+ echo -e "${BOLD}loki watch${NC} -- monitoring ${prd_basename} for changes"
4452
+ echo "Watching: $prd_path"
4453
+ echo "Debounce: ${debounce}s | Ctrl+C to exit"
4454
+ if [ "$no_auto_start" = true ]; then
4455
+ echo "Mode: observe only (--no-auto-start)"
4456
+ fi
4457
+ echo ""
4403
4458
 
4404
- # Cost tracking
4405
- if [ -f "$LOKI_DIR/state/cost-tracker.json" ]; then
4406
- echo ""
4407
- echo -e "${CYAN}Cost:${NC}"
4408
- _LOKI_COST_FILE="$LOKI_DIR/state/cost-tracker.json" python3 -c "
4409
- import json, os
4410
- with open(os.environ['_LOKI_COST_FILE']) as f:
4411
- data = json.load(f)
4412
- total = data.get('total_cost_usd', 0)
4413
- budget = data.get('budget_limit', 0)
4414
- print(f' Total: \${total:.4f}')
4415
- if budget > 0:
4416
- print(f' Budget: \${budget:.2f} ({total/budget*100:.1f}% used)')
4417
- " 2>/dev/null || true
4459
+ _watch_status_line() {
4460
+ echo -e "\rWatching ${prd_basename} -- last run: ${last_run} -- next: on change"
4461
+ }
4462
+
4463
+ _watch_trigger() {
4464
+ local change_time
4465
+ change_time="$(date '+%H:%M:%S')"
4466
+
4467
+ if [ "$no_auto_start" = true ]; then
4468
+ echo "PRD changed: ${change_time}"
4469
+ return 0
4418
4470
  fi
4419
4471
 
4420
- # Recent log
4421
- echo ""
4422
- echo -e "${CYAN}Recent Activity:${NC}"
4423
- local log_file="$LOKI_DIR/logs/loki-run.log"
4424
- if [ -f "$log_file" ]; then
4425
- tail -5 "$log_file" 2>/dev/null | sed 's/^/ /'
4426
- else
4427
- echo " (no log file)"
4472
+ # Kill any currently running loki session
4473
+ if [ -n "$_watch_child_pid" ] && kill -0 "$_watch_child_pid" 2>/dev/null; then
4474
+ echo "Stopping previous loki session (PID $_watch_child_pid)..."
4475
+ kill "$_watch_child_pid" 2>/dev/null
4476
+ wait "$_watch_child_pid" 2>/dev/null || true
4477
+ _watch_child_pid=""
4428
4478
  fi
4429
4479
 
4430
4480
  echo ""
4431
4481
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
4482
+ echo "PRD changed -- starting loki... (${change_time})"
4483
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
4484
+ echo ""
4432
4485
 
4433
- sleep "$interval"
4434
- done
4486
+ "$0" start "$prd_path" &
4487
+ _watch_child_pid=$!
4488
+ last_run="$change_time"
4489
+ }
4490
+
4491
+ # Determine watcher backend
4492
+ local watcher="poll"
4493
+ if command -v fswatch &>/dev/null; then
4494
+ watcher="fswatch"
4495
+ elif command -v inotifywait &>/dev/null; then
4496
+ watcher="inotifywait"
4497
+ fi
4498
+
4499
+ echo "Watcher: $watcher"
4500
+ _watch_status_line
4501
+
4502
+ case "$watcher" in
4503
+ fswatch)
4504
+ # Use fswatch for native macOS filesystem events
4505
+ fswatch -1 --latency "$debounce" "$prd_path" | while read -r _event; do
4506
+ _watch_trigger
4507
+ _watch_status_line
4508
+ # Re-attach fswatch for next change
4509
+ fswatch -1 --latency "$debounce" "$prd_path" > /dev/null 2>&1 || true
4510
+ done
4511
+ # Fallback: loop-based fswatch for continuous watching
4512
+ while true; do
4513
+ fswatch -1 --latency "$debounce" "$prd_path" > /dev/null 2>&1
4514
+ _watch_trigger
4515
+ _watch_status_line
4516
+ done
4517
+ ;;
4518
+ inotifywait)
4519
+ while true; do
4520
+ inotifywait -qq -e modify "$prd_path" 2>/dev/null
4521
+ if [ "$debounce" -gt 0 ]; then
4522
+ sleep "$debounce"
4523
+ fi
4524
+ _watch_trigger
4525
+ _watch_status_line
4526
+ done
4527
+ ;;
4528
+ poll)
4529
+ # Universal fallback: stat-based polling
4530
+ local last_mtime
4531
+ last_mtime=$(stat -f '%m' "$prd_path" 2>/dev/null || stat -c '%Y' "$prd_path" 2>/dev/null || echo "0")
4532
+ local debounce_pending=false
4533
+ local debounce_deadline=0
4534
+
4535
+ while true; do
4536
+ sleep "$poll_interval"
4537
+ local current_mtime
4538
+ current_mtime=$(stat -f '%m' "$prd_path" 2>/dev/null || stat -c '%Y' "$prd_path" 2>/dev/null || echo "0")
4539
+
4540
+ if [ "$current_mtime" != "$last_mtime" ]; then
4541
+ last_mtime="$current_mtime"
4542
+ if [ "$debounce" -gt 0 ]; then
4543
+ # Start debounce window
4544
+ debounce_pending=true
4545
+ debounce_deadline=$(( $(date +%s) + debounce ))
4546
+ else
4547
+ _watch_trigger
4548
+ _watch_status_line
4549
+ fi
4550
+ fi
4551
+
4552
+ # Check debounce deadline
4553
+ if [ "$debounce_pending" = true ] && [ "$(date +%s)" -ge "$debounce_deadline" ]; then
4554
+ debounce_pending=false
4555
+ _watch_trigger
4556
+ _watch_status_line
4557
+ fi
4558
+ done
4559
+ ;;
4560
+ esac
4435
4561
  }
4436
4562
 
4437
4563
  #===============================================================================
@@ -85,6 +85,30 @@ if (results.some(r => !r.ok)) {
85
85
  console.log(` loki setup-skill`);
86
86
  }
87
87
 
88
+ // PATH check: warn if npm global bin is not in PATH
89
+ try {
90
+ const { execSync } = require('child_process');
91
+ const npmBin = execSync('npm bin -g 2>/dev/null || npm prefix -g', { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
92
+ const npmBinDir = npmBin.endsWith('/bin') ? npmBin : npmBin + '/bin';
93
+ const pathDirs = (process.env.PATH || '').split(':');
94
+ const lokiBinInPath = pathDirs.some(d => d === npmBinDir || d === npmBin);
95
+ if (!lokiBinInPath) {
96
+ console.log('');
97
+ console.log('[IMPORTANT] The `loki` command may not be in your PATH.');
98
+ console.log('');
99
+ console.log('Add the npm global bin directory to your PATH:');
100
+ console.log(` export PATH="${npmBinDir}:$PATH"`);
101
+ console.log('');
102
+ console.log('To make this permanent, add it to your shell config (~/.zshrc or ~/.bashrc):');
103
+ console.log(` echo 'export PATH="${npmBinDir}:$PATH"' >> ~/.zshrc && source ~/.zshrc`);
104
+ console.log('');
105
+ console.log('Or use the Homebrew tap (sets PATH automatically):');
106
+ console.log(' brew tap asklokesh/tap && brew install loki-mode');
107
+ }
108
+ } catch {
109
+ // If npm bin check fails, skip PATH warning silently
110
+ }
111
+
88
112
  console.log('');
89
113
  console.log('CLI commands:');
90
114
  console.log(' loki start ./prd.md Start with Claude (default)');
@@ -5,7 +5,7 @@ _loki_completion() {
5
5
  _init_completion || return
6
6
 
7
7
  # Main subcommands (must match autonomy/loki main case statement)
8
- local main_commands="start quick demo init stop pause resume status dashboard logs serve api sandbox notify import github issue config provider reset memory compound checkpoint council dogfood projects enterprise voice secrets doctor watchdog audit metrics syslog onboard share explain plan report test ci version completions help"
8
+ local main_commands="start quick demo init stop pause resume status dashboard logs serve api sandbox notify import github issue config provider reset memory compound checkpoint council dogfood projects enterprise voice secrets doctor watchdog audit metrics syslog onboard share explain plan report test ci watch version completions help"
9
9
 
10
10
  # 1. If we are on the first argument (subcommand)
11
11
  if [[ $cword -eq 1 ]]; then
@@ -153,6 +153,15 @@ _loki_completion() {
153
153
  COMPREPLY=( $(compgen -W "${metrics_cmds}" -- "$cur") )
154
154
  ;;
155
155
 
156
+ watch)
157
+ if [[ "$cur" == -* ]]; then
158
+ COMPREPLY=( $(compgen -W "--once --interval --no-auto-start --debounce --help" -- "$cur") )
159
+ return 0
160
+ fi
161
+ # Default to file completion for PRD files
162
+ COMPREPLY=( $(compgen -f -- "$cur") )
163
+ ;;
164
+
156
165
  share)
157
166
  if [[ "$cur" == -* ]]; then
158
167
  COMPREPLY=( $(compgen -W "--private --format --help" -- "$cur") )
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "6.32.0"
10
+ __version__ = "6.32.1"
11
11
 
12
12
  # Expose the control app for easy import
13
13
  try:
@@ -2,7 +2,7 @@
2
2
 
3
3
  The flagship product of [Autonomi](https://www.autonomi.dev/). Complete installation instructions for all platforms and use cases.
4
4
 
5
- **Version:** v6.32.0
5
+ **Version:** v6.32.1
6
6
 
7
7
  ---
8
8
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loki-mode",
3
- "version": "6.32.0",
3
+ "version": "6.32.1",
4
4
  "description": "Loki Mode by Autonomi - Multi-agent autonomous startup system for Claude Code, Codex CLI, and Gemini CLI",
5
5
  "keywords": [
6
6
  "agent",