loki-mode 6.4.0 → 6.6.0

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/autonomy/loki CHANGED
@@ -433,7 +433,7 @@ show_help() {
433
433
  echo " help Show this help"
434
434
  echo ""
435
435
  echo "Options for 'start':"
436
- echo " --provider NAME AI provider: claude (default), codex, gemini"
436
+ echo " --provider NAME AI provider: claude (default), codex, gemini, cline, aider"
437
437
  echo " --parallel Enable parallel mode with git worktrees"
438
438
  echo " --bg, --background Run in background mode"
439
439
  echo " --simple Force simple complexity tier (3 phases)"
@@ -450,7 +450,7 @@ show_help() {
450
450
  echo " --dry-run Preview generated PRD without starting"
451
451
  echo " --no-start Generate PRD but don't start execution"
452
452
  echo " --output FILE Save PRD to custom path"
453
- echo " --provider NAME AI provider: claude (default), codex, gemini"
453
+ echo " --provider NAME AI provider: claude (default), codex, gemini, cline, aider"
454
454
  echo " --parallel Enable parallel mode with git worktrees"
455
455
  echo " --budget USD Set cost budget limit"
456
456
  echo ""
@@ -499,7 +499,7 @@ cmd_start() {
499
499
  echo " PRD Path to PRD file (optional)"
500
500
  echo ""
501
501
  echo "Options:"
502
- echo " --provider NAME AI provider: claude (default), codex, gemini"
502
+ echo " --provider NAME AI provider: claude (default), codex, gemini, cline, aider"
503
503
  echo " --parallel Enable parallel mode with git worktrees"
504
504
  echo " --bg, --background Run in background mode"
505
505
  echo " --simple Force simple complexity tier (3 phases)"
@@ -536,7 +536,7 @@ cmd_start() {
536
536
  args+=("--provider" "$provider")
537
537
  shift 2
538
538
  else
539
- echo -e "${RED}--provider requires a value (claude, codex, gemini)${NC}"
539
+ echo -e "${RED}--provider requires a value (claude, codex, gemini, cline, aider)${NC}"
540
540
  exit 1
541
541
  fi
542
542
  ;;
@@ -545,6 +545,45 @@ cmd_start() {
545
545
  args+=("--provider" "$provider")
546
546
  shift
547
547
  ;;
548
+ --aider-model)
549
+ if [[ -n "${2:-}" ]]; then
550
+ export LOKI_AIDER_MODEL="$2"
551
+ shift 2
552
+ else
553
+ echo -e "${RED}--aider-model requires a value${NC}"
554
+ exit 1
555
+ fi
556
+ ;;
557
+ --aider-model=*)
558
+ export LOKI_AIDER_MODEL="${1#*=}"
559
+ shift
560
+ ;;
561
+ --aider-flags)
562
+ if [[ -n "${2:-}" ]]; then
563
+ export LOKI_AIDER_FLAGS="$2"
564
+ shift 2
565
+ else
566
+ echo -e "${RED}--aider-flags requires a value${NC}"
567
+ exit 1
568
+ fi
569
+ ;;
570
+ --aider-flags=*)
571
+ export LOKI_AIDER_FLAGS="${1#*=}"
572
+ shift
573
+ ;;
574
+ --cline-model)
575
+ if [[ -n "${2:-}" ]]; then
576
+ export LOKI_CLINE_MODEL="$2"
577
+ shift 2
578
+ else
579
+ echo -e "${RED}--cline-model requires a value${NC}"
580
+ exit 1
581
+ fi
582
+ ;;
583
+ --cline-model=*)
584
+ export LOKI_CLINE_MODEL="${1#*=}"
585
+ shift
586
+ ;;
548
587
  --parallel)
549
588
  args+=("--parallel")
550
589
  shift
@@ -1342,12 +1381,15 @@ cmd_status() {
1342
1381
  # Show provider with capability
1343
1382
  local capability="full features"
1344
1383
  case "$current_provider" in
1345
- codex|gemini)
1384
+ codex|gemini|aider)
1346
1385
  capability="degraded mode"
1347
1386
  ;;
1387
+ cline)
1388
+ capability="near-full mode"
1389
+ ;;
1348
1390
  esac
1349
1391
  echo -e "${CYAN}Provider:${NC} $current_provider ($capability)"
1350
- echo -e "${DIM} Switch with: loki provider set <claude|codex|gemini>${NC}"
1392
+ echo -e "${DIM} Switch with: loki provider set <claude|codex|gemini|cline|aider>${NC}"
1351
1393
  echo ""
1352
1394
 
1353
1395
  # Show running sessions (v6.4.0 - concurrent session support)
@@ -1356,7 +1398,7 @@ cmd_status() {
1356
1398
  [ -n "$line" ] && running_sessions+=("$line")
1357
1399
  done < <(list_running_sessions 2>/dev/null)
1358
1400
 
1359
- if [ ${#running_sessions[@]} -gt 1 ]; then
1401
+ if [ ${#running_sessions[@]} -gt 0 ]; then
1360
1402
  echo -e "${GREEN}Active Sessions: ${#running_sessions[@]}${NC}"
1361
1403
  for entry in "${running_sessions[@]}"; do
1362
1404
  local sid="${entry%%:*}"
@@ -1624,12 +1666,14 @@ cmd_provider() {
1624
1666
  }
1625
1667
 
1626
1668
  cmd_provider_show() {
1669
+ local positional_arg="${1:-}"
1670
+
1627
1671
  local saved_provider=""
1628
1672
  if [ -f "$LOKI_DIR/state/provider" ]; then
1629
1673
  saved_provider=$(cat "$LOKI_DIR/state/provider" 2>/dev/null)
1630
1674
  fi
1631
1675
 
1632
- local current="${saved_provider:-${LOKI_PROVIDER:-claude}}"
1676
+ local current="${positional_arg:-${saved_provider:-${LOKI_PROVIDER:-claude}}}"
1633
1677
 
1634
1678
  echo -e "${BOLD}Current Provider${NC}"
1635
1679
  echo ""
@@ -1640,7 +1684,10 @@ cmd_provider_show() {
1640
1684
  claude)
1641
1685
  echo -e "${GREEN}Status:${NC} Full features (subagents, parallel, MCP)"
1642
1686
  ;;
1643
- codex|gemini)
1687
+ cline)
1688
+ echo -e "${GREEN}Status:${NC} Near-full mode (subagents, MCP, 12+ providers)"
1689
+ ;;
1690
+ codex|gemini|aider)
1644
1691
  echo -e "${YELLOW}Status:${NC} Degraded mode (sequential only)"
1645
1692
  ;;
1646
1693
  esac
@@ -1661,17 +1708,17 @@ cmd_provider_set() {
1661
1708
 
1662
1709
  if [ -z "$new_provider" ]; then
1663
1710
  echo -e "${RED}Error: Provider name required${NC}"
1664
- echo "Usage: loki provider set <claude|codex|gemini>"
1711
+ echo "Usage: loki provider set <claude|codex|gemini|cline|aider>"
1665
1712
  exit 1
1666
1713
  fi
1667
1714
 
1668
1715
  # Validate provider
1669
1716
  case "$new_provider" in
1670
- claude|codex|gemini)
1717
+ claude|codex|gemini|cline|aider)
1671
1718
  ;;
1672
1719
  *)
1673
1720
  echo -e "${RED}Error: Invalid provider '$new_provider'${NC}"
1674
- echo "Valid providers: claude, codex, gemini"
1721
+ echo "Valid providers: claude, codex, gemini, cline, aider"
1675
1722
  exit 1
1676
1723
  ;;
1677
1724
  esac
@@ -1690,6 +1737,12 @@ cmd_provider_set() {
1690
1737
  gemini)
1691
1738
  echo "Install: npm install -g @google/gemini-cli"
1692
1739
  ;;
1740
+ cline)
1741
+ echo "Install: npm install -g cline"
1742
+ ;;
1743
+ aider)
1744
+ echo "Install: pip install aider-chat"
1745
+ ;;
1693
1746
  esac
1694
1747
  echo ""
1695
1748
  echo -e "${DIM}Setting provider anyway...${NC}"
@@ -1719,6 +1772,8 @@ cmd_provider_list() {
1719
1772
  local claude_status="${RED}not installed${NC}"
1720
1773
  local codex_status="${RED}not installed${NC}"
1721
1774
  local gemini_status="${RED}not installed${NC}"
1775
+ local cline_status="${RED}not installed${NC}"
1776
+ local aider_status="${RED}not installed${NC}"
1722
1777
 
1723
1778
  if command -v claude &> /dev/null; then
1724
1779
  claude_status="${GREEN}installed${NC}"
@@ -1729,6 +1784,12 @@ cmd_provider_list() {
1729
1784
  if command -v gemini &> /dev/null; then
1730
1785
  gemini_status="${GREEN}installed${NC}"
1731
1786
  fi
1787
+ if command -v cline &> /dev/null; then
1788
+ cline_status="${GREEN}installed${NC}"
1789
+ fi
1790
+ if command -v aider &> /dev/null; then
1791
+ aider_status="${GREEN}installed${NC}"
1792
+ fi
1732
1793
 
1733
1794
  # Display providers
1734
1795
  local marker=""
@@ -1743,6 +1804,14 @@ cmd_provider_list() {
1743
1804
  [ "$current" = "gemini" ] && marker=" ${CYAN}(current)${NC}"
1744
1805
  echo -e " gemini - Gemini CLI (Google) $gemini_status$marker"
1745
1806
 
1807
+ marker=""
1808
+ [ "$current" = "cline" ] && marker=" ${CYAN}(current)${NC}"
1809
+ echo -e " cline - Cline (multi-provider) $cline_status$marker"
1810
+
1811
+ marker=""
1812
+ [ "$current" = "aider" ] && marker=" ${CYAN}(current)${NC}"
1813
+ echo -e " aider - Aider (terminal pair prog) $aider_status$marker"
1814
+
1746
1815
  echo ""
1747
1816
  echo -e "Set provider: ${CYAN}loki provider set <name>${NC}"
1748
1817
  }
@@ -1792,6 +1861,34 @@ cmd_provider_info() {
1792
1861
  echo ""
1793
1862
  echo "Status: Degraded mode"
1794
1863
  ;;
1864
+ cline)
1865
+ echo "Name: Cline CLI (Multi-Provider)"
1866
+ echo "Vendor: Cline (supports 12+ providers)"
1867
+ echo "CLI: cline"
1868
+ echo "Flag: -y (YOLO mode)"
1869
+ echo ""
1870
+ echo "Features:"
1871
+ echo " - Autonomous mode"
1872
+ echo " - Subagent support"
1873
+ echo " - MCP server support"
1874
+ echo " - 12+ model providers"
1875
+ echo ""
1876
+ echo "Status: Near-full mode (Tier 2)"
1877
+ ;;
1878
+ aider)
1879
+ echo "Name: Aider (18+ Providers)"
1880
+ echo "Vendor: Aider (supports 18+ providers)"
1881
+ echo "CLI: aider"
1882
+ echo "Flag: --yes-always"
1883
+ echo ""
1884
+ echo "Features:"
1885
+ echo " - Autonomous mode"
1886
+ echo " - 18+ model providers"
1887
+ echo " - Architect mode (dual model)"
1888
+ echo " - Built-in lint/test integration"
1889
+ echo ""
1890
+ echo "Status: Degraded mode (Tier 3)"
1891
+ ;;
1795
1892
  *)
1796
1893
  echo -e "${RED}Unknown provider: $provider${NC}"
1797
1894
  exit 1
@@ -2092,7 +2189,7 @@ cmd_dashboard_stop() {
2092
2189
  local wait_count=0
2093
2190
  while kill -0 "$pid" 2>/dev/null && [ $wait_count -lt 10 ]; do
2094
2191
  sleep 0.5
2095
- ((wait_count++))
2192
+ wait_count=$((wait_count + 1))
2096
2193
  done
2097
2194
 
2098
2195
  # Force kill if still running
@@ -2770,7 +2867,7 @@ cmd_run() {
2770
2867
  echo " --dry-run Preview generated PRD without starting"
2771
2868
  echo " --no-start Generate PRD but don't start execution"
2772
2869
  echo " --output FILE Save PRD to custom path"
2773
- echo " --provider NAME AI provider: claude (default), codex, gemini"
2870
+ echo " --provider NAME AI provider: claude (default), codex, gemini, cline, aider"
2774
2871
  echo " --parallel Enable parallel mode with git worktrees"
2775
2872
  echo " --bg, --background Run in background mode"
2776
2873
  echo " --simple Force simple complexity tier"
@@ -2867,27 +2964,23 @@ cmd_run() {
2867
2964
  shift
2868
2965
  ;;
2869
2966
  --worktree|-w)
2870
- start_args+=("--parallel")
2871
2967
  use_worktree=true
2872
2968
  shift
2873
2969
  ;;
2874
2970
  --pr)
2875
2971
  use_worktree=true
2876
2972
  create_pr=true
2877
- start_args+=("--parallel")
2878
2973
  shift
2879
2974
  ;;
2880
2975
  --ship)
2881
2976
  use_worktree=true
2882
2977
  create_pr=true
2883
2978
  auto_merge=true
2884
- start_args+=("--parallel")
2885
2979
  shift
2886
2980
  ;;
2887
2981
  --detach|-d)
2888
2982
  use_worktree=true
2889
2983
  run_detached=true
2890
- start_args+=("--parallel")
2891
2984
  shift
2892
2985
  ;;
2893
2986
  -*)
@@ -2904,6 +2997,11 @@ cmd_run() {
2904
2997
  esac
2905
2998
  done
2906
2999
 
3000
+ # Add --parallel once if worktree mode is enabled (not per-flag)
3001
+ if $use_worktree; then
3002
+ start_args+=("--parallel")
3003
+ fi
3004
+
2907
3005
  if [[ -z "$issue_ref" ]]; then
2908
3006
  echo -e "${RED}Error: Issue reference required${NC}"
2909
3007
  echo ""
@@ -2971,6 +3069,13 @@ cmd_run() {
2971
3069
 
2972
3070
  # Detached mode: fork to background
2973
3071
  if $run_detached; then
3072
+ # Guard: prevent launching duplicate session
3073
+ if is_session_running "$session_id"; then
3074
+ echo -e "${RED}Error: Session '$session_id' is already running.${NC}"
3075
+ echo -e "Stop it first with: ${CYAN}loki stop $session_id${NC}"
3076
+ exit 1
3077
+ fi
3078
+
2974
3079
  local log_file="$LOKI_DIR/logs/run-${number:-$(date +%s)}.log"
2975
3080
  mkdir -p "$(dirname "$log_file")"
2976
3081
  echo -e "${GREEN}Running detached. Logs: $log_file${NC}"
@@ -2985,32 +3090,51 @@ cmd_run() {
2985
3090
  branch_name="issue/detach-$(date +%s)"
2986
3091
  fi
2987
3092
 
2988
- nohup bash -c "
2989
- cd $(pwd)
2990
- export LOKI_DETACHED=true
2991
- export LOKI_PARALLEL_MODE=true
2992
- export LOKI_SESSION_ID=\"$session_id\"
2993
- export LOKI_WORKTREE_BRANCH=\"$branch_name\"
2994
- $(command -v loki || echo "$0") start \"$detach_prd\" --parallel ${start_args[*]+"${start_args[*]}"}
2995
-
2996
- # Post-completion: create PR if requested
2997
- if [[ \"$create_pr\" == \"true\" ]]; then
2998
- branch_current=\$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo \"\")
2999
- if [[ -n \"\$branch_current\" && \"\$branch_current\" != \"main\" && \"\$branch_current\" != \"master\" ]]; then
3000
- git push origin \"\$branch_current\" 2>/dev/null || true
3001
- gh pr create --title \"${title:-Implementation for issue ${issue_ref}}\" --body \"Implemented by Loki Mode\" --head \"\$branch_current\" 2>/dev/null || true
3002
- fi
3003
- fi
3004
- # Post-completion: auto-merge if requested
3005
- if [[ \"$auto_merge\" == \"true\" ]]; then
3006
- branch_current=\$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo \"\")
3007
- if gh pr merge \"\$branch_current\" --squash --delete-branch 2>/dev/null; then
3008
- if [[ -n \"${number:-}\" ]]; then
3009
- gh issue close \"$number\" --comment \"Resolved by Loki Mode\" 2>/dev/null || true
3010
- fi
3011
- fi
3012
- fi
3013
- " > "$log_file" 2>&1 &
3093
+ # Write a temp script to avoid shell injection via variable interpolation
3094
+ local run_script="$LOKI_DIR/scripts/run-${number:-detached}.sh"
3095
+ mkdir -p "$LOKI_DIR/scripts"
3096
+ local loki_cmd
3097
+ loki_cmd="$(command -v loki || echo "$0")"
3098
+ cat > "$run_script" << 'INNER_SCRIPT_EOF'
3099
+ #!/usr/bin/env bash
3100
+ set -euo pipefail
3101
+ cd "$LOKI_RUN_DIR"
3102
+ export LOKI_DETACHED=true
3103
+ export LOKI_PARALLEL_MODE=true
3104
+ "$LOKI_CMD" start "$LOKI_PRD_PATH" ${LOKI_START_ARGS:-}
3105
+
3106
+ # Post-completion: create PR if requested
3107
+ if [[ "$LOKI_CREATE_PR" == "true" ]]; then
3108
+ branch_current=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")
3109
+ if [[ -n "$branch_current" && "$branch_current" != "main" && "$branch_current" != "master" ]]; then
3110
+ git push origin "$branch_current" 2>/dev/null || true
3111
+ gh pr create --title "$LOKI_PR_TITLE" --body "Implemented by Loki Mode" --head "$branch_current" 2>/dev/null || true
3112
+ fi
3113
+ fi
3114
+ # Post-completion: auto-merge if requested
3115
+ if [[ "$LOKI_AUTO_MERGE" == "true" ]]; then
3116
+ branch_current=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")
3117
+ if gh pr merge "$branch_current" --squash --delete-branch 2>/dev/null; then
3118
+ if [[ -n "${LOKI_ISSUE_NUMBER:-}" ]]; then
3119
+ gh issue close "$LOKI_ISSUE_NUMBER" --comment "Resolved by Loki Mode" 2>/dev/null || true
3120
+ fi
3121
+ fi
3122
+ fi
3123
+ INNER_SCRIPT_EOF
3124
+ chmod +x "$run_script"
3125
+
3126
+ # Pass all variables safely via environment
3127
+ LOKI_RUN_DIR="$(pwd)" \
3128
+ LOKI_CMD="$loki_cmd" \
3129
+ LOKI_SESSION_ID="$session_id" \
3130
+ LOKI_WORKTREE_BRANCH="$branch_name" \
3131
+ LOKI_PRD_PATH="$detach_prd" \
3132
+ LOKI_START_ARGS="${start_args[*]+"${start_args[*]}"}" \
3133
+ LOKI_CREATE_PR="$create_pr" \
3134
+ LOKI_AUTO_MERGE="$auto_merge" \
3135
+ LOKI_PR_TITLE="${title:-Implementation for issue ${issue_ref}}" \
3136
+ LOKI_ISSUE_NUMBER="${number:-}" \
3137
+ nohup bash "$run_script" > "$log_file" 2>&1 &
3014
3138
 
3015
3139
  local bg_pid=$!
3016
3140
  echo "$bg_pid" > "$LOKI_DIR/run-${number:-detached}.pid"
@@ -3191,7 +3315,7 @@ cmd_issue() {
3191
3315
  echo " --output FILE Save PRD to custom path (default: .loki/prd-issue-N.md)"
3192
3316
  echo ""
3193
3317
  echo "Options passed to 'start' (when --start is used):"
3194
- echo " --provider NAME AI provider: claude (default), codex, gemini"
3318
+ echo " --provider NAME AI provider: claude (default), codex, gemini, cline, aider"
3195
3319
  echo " --parallel Enable parallel mode with git worktrees"
3196
3320
  echo " --bg, --background Run in background mode"
3197
3321
  echo ""
@@ -3904,7 +4028,7 @@ cmd_config() {
3904
4028
  echo " model.planning Model for planning tier"
3905
4029
  echo " model.development Model for development tier"
3906
4030
  echo " model.fast Model for fast tier"
3907
- echo " provider Default AI provider: claude, codex, gemini"
4031
+ echo " provider Default AI provider: claude, codex, gemini, cline, aider"
3908
4032
  echo " issue.provider Default issue provider: github, gitlab, jira, azure_devops"
3909
4033
  echo " blind_validation Blind validation mode: true, false (default: true)"
3910
4034
  echo " adversarial_testing Adversarial testing: true, false (default: true)"
@@ -3947,8 +4071,8 @@ cmd_config_set() {
3947
4071
  ;;
3948
4072
  provider)
3949
4073
  case "$value" in
3950
- claude|codex|gemini) ;;
3951
- *) echo -e "${RED}Invalid provider: $value (expected: claude, codex, gemini)${NC}"; return 1 ;;
4074
+ claude|codex|gemini|cline|aider) ;;
4075
+ *) echo -e "${RED}Invalid provider: $value (expected: claude, codex, gemini, cline, aider)${NC}"; return 1 ;;
3952
4076
  esac
3953
4077
  ;;
3954
4078
  issue.provider)
@@ -4244,6 +4368,8 @@ cmd_setup_skill() {
4244
4368
  "$HOME/.claude/skills/loki-mode:Claude Code"
4245
4369
  "$HOME/.codex/skills/loki-mode:Codex CLI"
4246
4370
  "$HOME/.gemini/skills/loki-mode:Gemini CLI"
4371
+ "$HOME/.cline/skills/loki-mode:Cline CLI"
4372
+ "$HOME/.aider/skills/loki-mode:Aider CLI"
4247
4373
  )
4248
4374
 
4249
4375
  local created=0
@@ -4392,6 +4518,12 @@ cmd_doctor() {
4392
4518
  gemini)
4393
4519
  version=$(gemini --version 2>/dev/null | head -1 | sed 's/[^0-9.]//g' | head -1)
4394
4520
  ;;
4521
+ cline)
4522
+ version=$(cline --version 2>/dev/null | head -1 | sed 's/[^0-9.]//g' | head -1)
4523
+ ;;
4524
+ aider)
4525
+ version=$(aider --version 2>/dev/null | head -1 | sed 's/[^0-9.]//g' | head -1)
4526
+ ;;
4395
4527
  esac
4396
4528
 
4397
4529
  local version_display=""
@@ -4426,17 +4558,19 @@ cmd_doctor() {
4426
4558
  }
4427
4559
 
4428
4560
  echo -e "${CYAN}Required:${NC}"
4429
- doctor_check "Node.js (>= 18)" node required 18.0
4430
- doctor_check "Python 3 (>= 3.8)" python3 required 3.8
4431
- doctor_check "jq" jq required
4432
- doctor_check "git" git required
4433
- doctor_check "curl" curl required
4561
+ doctor_check "Node.js (>= 18)" node required 18.0 || true
4562
+ doctor_check "Python 3 (>= 3.8)" python3 required 3.8 || true
4563
+ doctor_check "jq" jq required || true
4564
+ doctor_check "git" git required || true
4565
+ doctor_check "curl" curl required || true
4434
4566
  echo ""
4435
4567
 
4436
4568
  echo -e "${CYAN}AI Providers:${NC}"
4437
- doctor_check "Claude CLI" claude optional
4438
- doctor_check "Codex CLI" codex optional
4439
- doctor_check "Gemini CLI" gemini optional
4569
+ doctor_check "Claude CLI" claude optional || true
4570
+ doctor_check "Codex CLI" codex optional || true
4571
+ doctor_check "Gemini CLI" gemini optional || true
4572
+ doctor_check "Cline CLI" cline optional || true
4573
+ doctor_check "Aider CLI" aider optional || true
4440
4574
  echo ""
4441
4575
 
4442
4576
  echo -e "${CYAN}Skills:${NC}"
@@ -4444,6 +4578,8 @@ cmd_doctor() {
4444
4578
  "$HOME/.claude/skills/loki-mode:Claude Code"
4445
4579
  "$HOME/.codex/skills/loki-mode:Codex CLI"
4446
4580
  "$HOME/.gemini/skills/loki-mode:Gemini CLI"
4581
+ "$HOME/.cline/skills/loki-mode:Cline CLI"
4582
+ "$HOME/.aider/skills/loki-mode:Aider CLI"
4447
4583
  )
4448
4584
  for entry in "${skill_dirs[@]}"; do
4449
4585
  local sdir="${entry%%:*}"
@@ -4463,7 +4599,7 @@ cmd_doctor() {
4463
4599
  echo ""
4464
4600
 
4465
4601
  echo -e "${CYAN}System:${NC}"
4466
- doctor_check "bash (>= 4.0)" bash recommended 4.0
4602
+ doctor_check "bash (>= 4.0)" bash recommended 4.0 || true
4467
4603
 
4468
4604
  # Disk space check
4469
4605
  local disk_avail
@@ -4563,6 +4699,8 @@ checks.append(check_tool('bash', 'bash', 'recommended', '4.0'))
4563
4699
  checks.append(check_tool('Claude CLI', 'claude', 'optional'))
4564
4700
  checks.append(check_tool('Codex CLI', 'codex', 'optional'))
4565
4701
  checks.append(check_tool('Gemini CLI', 'gemini', 'optional'))
4702
+ checks.append(check_tool('Cline CLI', 'cline', 'optional'))
4703
+ checks.append(check_tool('Aider CLI', 'aider', 'optional'))
4566
4704
 
4567
4705
  # Disk space
4568
4706
  disk_gb = None
@@ -4946,7 +5084,7 @@ cmd_notify_test() {
4946
5084
  echo -n " Slack... "
4947
5085
  if send_slack_notification "$message" "Test"; then
4948
5086
  echo -e "${GREEN}OK${NC}"
4949
- ((channels_notified++))
5087
+ channels_notified=$((channels_notified + 1))
4950
5088
  else
4951
5089
  echo -e "${RED}FAILED${NC}"
4952
5090
  fi
@@ -4959,7 +5097,7 @@ cmd_notify_test() {
4959
5097
  echo -n " Discord... "
4960
5098
  if send_discord_notification "$message" "Test"; then
4961
5099
  echo -e "${GREEN}OK${NC}"
4962
- ((channels_notified++))
5100
+ channels_notified=$((channels_notified + 1))
4963
5101
  else
4964
5102
  echo -e "${RED}FAILED${NC}"
4965
5103
  fi
@@ -4972,7 +5110,7 @@ cmd_notify_test() {
4972
5110
  echo -n " Webhook... "
4973
5111
  if send_webhook_notification "$message" "Test"; then
4974
5112
  echo -e "${GREEN}OK${NC}"
4975
- ((channels_notified++))
5113
+ channels_notified=$((channels_notified + 1))
4976
5114
  else
4977
5115
  echo -e "${RED}FAILED${NC}"
4978
5116
  fi
@@ -6691,7 +6829,7 @@ Tasks:
6691
6829
  local provider_name="${LOKI_PROVIDER:-claude}"
6692
6830
  case "$provider_name" in
6693
6831
  claude)
6694
- (cd "$codebase_path" && claude --dangerously-skip-permissions -p "$phase_prompt" --output-format stream-json --verbose 2>&1) | \
6832
+ { (cd "$codebase_path" && claude --dangerously-skip-permissions -p "$phase_prompt" --output-format stream-json --verbose 2>&1) | \
6695
6833
  while IFS= read -r line; do
6696
6834
  # Extract text from stream-json
6697
6835
  if echo "$line" | python3 -c "
@@ -6706,8 +6844,7 @@ except Exception: pass
6706
6844
  " 2>/dev/null; then
6707
6845
  true
6708
6846
  fi
6709
- done
6710
- phase_exit=${PIPESTATUS[0]}
6847
+ done; } && phase_exit=0 || phase_exit=$?
6711
6848
  ;;
6712
6849
  codex)
6713
6850
  (cd "$codebase_path" && codex exec --full-auto "$phase_prompt" 2>&1) || phase_exit=$?
@@ -6715,8 +6852,17 @@ except Exception: pass
6715
6852
  gemini)
6716
6853
  (cd "$codebase_path" && gemini --approval-mode=yolo "$phase_prompt" 2>&1) || phase_exit=$?
6717
6854
  ;;
6855
+ cline)
6856
+ (cd "$codebase_path" && cline -y "$phase_prompt" 2>&1) || phase_exit=$?
6857
+ ;;
6858
+ aider)
6859
+ local aider_model="${LOKI_AIDER_MODEL:-claude-3.7-sonnet}"
6860
+ local aider_flags="${LOKI_AIDER_FLAGS:-}"
6861
+ # shellcheck disable=SC2086
6862
+ (cd "$codebase_path" && aider --message "$phase_prompt" --yes-always --no-auto-commits --model "$aider_model" $aider_flags 2>&1) || phase_exit=$?
6863
+ ;;
6718
6864
  *)
6719
- echo -e "${RED}Error: Unknown provider '${provider_name}'. Supported: claude, codex, gemini${NC}"
6865
+ echo -e "${RED}Error: Unknown provider '${provider_name}'. Supported: claude, codex, gemini, cline, aider${NC}"
6720
6866
  phase_exit=1
6721
6867
  ;;
6722
6868
  esac
@@ -6854,7 +7000,7 @@ IMPORTANT RULES:
6854
7000
  local provider_name="${LOKI_PROVIDER:-claude}"
6855
7001
  case "$provider_name" in
6856
7002
  claude)
6857
- (cd "$codebase_path" && claude --dangerously-skip-permissions -p "$doc_prompt" --output-format stream-json --verbose 2>&1) | \
7003
+ { (cd "$codebase_path" && claude --dangerously-skip-permissions -p "$doc_prompt" --output-format stream-json --verbose 2>&1) | \
6858
7004
  while IFS= read -r line; do
6859
7005
  if echo "$line" | python3 -c "
6860
7006
  import sys, json
@@ -6868,8 +7014,7 @@ except Exception: pass
6868
7014
  " 2>/dev/null; then
6869
7015
  true
6870
7016
  fi
6871
- done
6872
- doc_exit=${PIPESTATUS[0]}
7017
+ done; } && doc_exit=0 || doc_exit=$?
6873
7018
  ;;
6874
7019
  codex)
6875
7020
  (cd "$codebase_path" && codex exec --full-auto "$doc_prompt" 2>&1) || doc_exit=$?
@@ -6877,6 +7022,15 @@ except Exception: pass
6877
7022
  gemini)
6878
7023
  (cd "$codebase_path" && gemini --approval-mode=yolo "$doc_prompt" 2>&1) || doc_exit=$?
6879
7024
  ;;
7025
+ cline)
7026
+ (cd "$codebase_path" && cline -y "$doc_prompt" 2>&1) || doc_exit=$?
7027
+ ;;
7028
+ aider)
7029
+ local aider_model="${LOKI_AIDER_MODEL:-claude-3.7-sonnet}"
7030
+ local aider_flags="${LOKI_AIDER_FLAGS:-}"
7031
+ # shellcheck disable=SC2086
7032
+ (cd "$codebase_path" && aider --message "$doc_prompt" --yes-always --no-auto-commits --model "$aider_model" $aider_flags 2>&1) || doc_exit=$?
7033
+ ;;
6880
7034
  esac
6881
7035
 
6882
7036
  if [ "$doc_exit" -eq 0 ] && [ -d "${codebase_path}/migration_docs" ]; then