loki-mode 5.28.1 → 5.29.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/README.md +40 -1
- package/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/loki +5 -44
- package/autonomy/sandbox.sh +296 -21
- package/dashboard/__init__.py +1 -1
- package/docs/INSTALLATION.md +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
[](https://www.npmjs.com/package/loki-mode)
|
|
7
7
|
[](https://github.com/asklokesh/loki-mode)
|
|
8
8
|
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
[](https://github.com/marketplace/actions/loki-mode-code-review)
|
|
9
10
|
[](https://claude.ai)
|
|
10
11
|
[]()
|
|
11
12
|
[](benchmarks/results/)
|
|
@@ -55,7 +56,45 @@ claude --dangerously-skip-permissions
|
|
|
55
56
|
# Then say: Loki Mode with PRD at ./my-prd.md
|
|
56
57
|
```
|
|
57
58
|
|
|
58
|
-
|
|
59
|
+
### Option 3: GitHub Action
|
|
60
|
+
|
|
61
|
+
Add automated AI code review to your pull requests:
|
|
62
|
+
|
|
63
|
+
```yaml
|
|
64
|
+
# .github/workflows/loki-review.yml
|
|
65
|
+
name: Loki Code Review
|
|
66
|
+
|
|
67
|
+
on:
|
|
68
|
+
pull_request:
|
|
69
|
+
types: [opened, synchronize]
|
|
70
|
+
|
|
71
|
+
permissions:
|
|
72
|
+
contents: read
|
|
73
|
+
pull-requests: write
|
|
74
|
+
|
|
75
|
+
jobs:
|
|
76
|
+
review:
|
|
77
|
+
runs-on: ubuntu-latest
|
|
78
|
+
steps:
|
|
79
|
+
- uses: actions/checkout@v4
|
|
80
|
+
- uses: asklokesh/loki-mode@v5
|
|
81
|
+
with:
|
|
82
|
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
83
|
+
mode: review # review, fix, or test
|
|
84
|
+
provider: claude # claude, codex, or gemini
|
|
85
|
+
max_iterations: 3 # higher = more thorough
|
|
86
|
+
budget_limit: '5.00' # max cost in USD
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Modes:**
|
|
90
|
+
|
|
91
|
+
| Mode | Description |
|
|
92
|
+
|------|-------------|
|
|
93
|
+
| `review` | Analyze PR diff, post structured review as PR comment |
|
|
94
|
+
| `fix` | Automatically fix issues found in the codebase |
|
|
95
|
+
| `test` | Run autonomous test generation and validation |
|
|
96
|
+
|
|
97
|
+
Also available via **Homebrew**, **Docker**, **VS Code Extension**, and **direct shell script**. See the [Installation Guide](docs/INSTALLATION.md) for all 7 installation methods and detailed instructions.
|
|
59
98
|
|
|
60
99
|
### Multi-Provider Support (v5.0.0)
|
|
61
100
|
|
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 zero human intervention. Requires --dangerously-skip-permissions flag.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Loki Mode v5.
|
|
6
|
+
# Loki Mode v5.29.0
|
|
7
7
|
|
|
8
8
|
**You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
|
|
9
9
|
|
|
@@ -260,4 +260,4 @@ Auto-detected or force with `LOKI_COMPLEXITY`:
|
|
|
260
260
|
|
|
261
261
|
---
|
|
262
262
|
|
|
263
|
-
**v5.
|
|
263
|
+
**v5.29.0 | Demo, quick mode, init, cost dashboard, 12 templates, GitHub Action | ~270 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
5.
|
|
1
|
+
5.29.0
|
package/autonomy/loki
CHANGED
|
@@ -506,33 +506,14 @@ cmd_start() {
|
|
|
506
506
|
local effective_provider="${provider:-${LOKI_PROVIDER:-claude}}"
|
|
507
507
|
|
|
508
508
|
# Handle sandbox mode - delegate to sandbox.sh
|
|
509
|
-
# Skip if we're already inside a
|
|
510
|
-
if [[ "${LOKI_SANDBOX_MODE:-}" == "true" ]] && [[ ! -f /.dockerenv ]]; then
|
|
509
|
+
# Skip if we're already inside a sandbox (IS_SANDBOX=1 or /.dockerenv exists)
|
|
510
|
+
if [[ "${LOKI_SANDBOX_MODE:-}" == "true" ]] && [[ "${IS_SANDBOX:-}" != "1" ]] && [[ ! -f /.dockerenv ]]; then
|
|
511
511
|
if [ ! -f "$SANDBOX_SH" ]; then
|
|
512
512
|
echo -e "${RED}Error: sandbox.sh not found at $SANDBOX_SH${NC}"
|
|
513
513
|
exit 1
|
|
514
514
|
fi
|
|
515
515
|
|
|
516
|
-
|
|
517
|
-
if ! command -v docker &> /dev/null; then
|
|
518
|
-
echo -e "${RED}Error: Docker not found${NC}"
|
|
519
|
-
echo ""
|
|
520
|
-
echo "Docker is required for sandbox mode. Install it:"
|
|
521
|
-
echo " macOS: brew install --cask docker"
|
|
522
|
-
echo " Linux: curl -fsSL https://get.docker.com | sh"
|
|
523
|
-
exit 1
|
|
524
|
-
fi
|
|
525
|
-
|
|
526
|
-
if ! docker info &> /dev/null 2>&1; then
|
|
527
|
-
echo -e "${RED}Error: Docker daemon not running${NC}"
|
|
528
|
-
echo ""
|
|
529
|
-
echo "Start Docker:"
|
|
530
|
-
echo " macOS: Open Docker Desktop app"
|
|
531
|
-
echo " Linux: sudo systemctl start docker"
|
|
532
|
-
exit 1
|
|
533
|
-
fi
|
|
534
|
-
|
|
535
|
-
echo -e "${GREEN}Starting Loki Mode in Docker sandbox...${NC}"
|
|
516
|
+
echo -e "${GREEN}Starting Loki Mode in sandbox...${NC}"
|
|
536
517
|
# Load memory context before sandbox start (errors don't block startup)
|
|
537
518
|
load_memory_context "$prd_file" || true
|
|
538
519
|
emit_event session cli start "provider=$effective_provider" "sandbox=true" "prd_path=${prd_file:-}"
|
|
@@ -2795,6 +2776,7 @@ broadcast_notification() {
|
|
|
2795
2776
|
}
|
|
2796
2777
|
|
|
2797
2778
|
# Sandbox management (delegates to sandbox.sh)
|
|
2779
|
+
# sandbox.sh handles detection: Docker Desktop Sandbox > Docker Container > Worktree
|
|
2798
2780
|
cmd_sandbox() {
|
|
2799
2781
|
local subcommand="${1:-help}"
|
|
2800
2782
|
shift || true
|
|
@@ -2805,28 +2787,7 @@ cmd_sandbox() {
|
|
|
2805
2787
|
exit 1
|
|
2806
2788
|
fi
|
|
2807
2789
|
|
|
2808
|
-
#
|
|
2809
|
-
if ! command -v docker &> /dev/null; then
|
|
2810
|
-
echo -e "${RED}Error: Docker not found${NC}"
|
|
2811
|
-
echo ""
|
|
2812
|
-
echo "Docker is required for sandbox mode. Install it:"
|
|
2813
|
-
echo " macOS: brew install --cask docker"
|
|
2814
|
-
echo " Linux: curl -fsSL https://get.docker.com | sh"
|
|
2815
|
-
echo ""
|
|
2816
|
-
echo "After installation, start Docker Desktop or the Docker daemon."
|
|
2817
|
-
exit 1
|
|
2818
|
-
fi
|
|
2819
|
-
|
|
2820
|
-
if ! docker info &> /dev/null 2>&1; then
|
|
2821
|
-
echo -e "${RED}Error: Docker daemon not running${NC}"
|
|
2822
|
-
echo ""
|
|
2823
|
-
echo "Start Docker:"
|
|
2824
|
-
echo " macOS: Open Docker Desktop app"
|
|
2825
|
-
echo " Linux: sudo systemctl start docker"
|
|
2826
|
-
exit 1
|
|
2827
|
-
fi
|
|
2828
|
-
|
|
2829
|
-
# Delegate to sandbox.sh
|
|
2790
|
+
# Delegate to sandbox.sh (it handles Docker/worktree detection internally)
|
|
2830
2791
|
exec "$SANDBOX_SH" "$subcommand" "$@"
|
|
2831
2792
|
}
|
|
2832
2793
|
|
package/autonomy/sandbox.sh
CHANGED
|
@@ -184,6 +184,11 @@ WORKTREE_PREFIX="loki-sandbox"
|
|
|
184
184
|
WORKTREE_BASE="${LOKI_WORKTREE_BASE:-${TMPDIR:-/tmp}}"
|
|
185
185
|
WORKTREE_STATE_FILE="${PROJECT_DIR}/.loki/sandbox/worktree-state.json"
|
|
186
186
|
|
|
187
|
+
# Check if Docker Desktop Sandbox is available (microVM-based isolation)
|
|
188
|
+
is_docker_desktop_sandbox_available() {
|
|
189
|
+
command -v docker &>/dev/null && docker sandbox version &>/dev/null 2>&1
|
|
190
|
+
}
|
|
191
|
+
|
|
187
192
|
# Check if Docker is available (non-fatal version)
|
|
188
193
|
is_docker_available() {
|
|
189
194
|
command -v docker &>/dev/null && docker info &>/dev/null 2>&1
|
|
@@ -195,10 +200,19 @@ is_git_available() {
|
|
|
195
200
|
}
|
|
196
201
|
|
|
197
202
|
# Detect which sandbox mode to use
|
|
203
|
+
# Priority: docker-desktop > docker > worktree
|
|
198
204
|
detect_sandbox_mode() {
|
|
199
205
|
local requested="${1:-auto}"
|
|
200
206
|
|
|
201
207
|
case "$requested" in
|
|
208
|
+
docker-desktop)
|
|
209
|
+
if is_docker_desktop_sandbox_available; then
|
|
210
|
+
echo "docker-desktop"
|
|
211
|
+
else
|
|
212
|
+
log_error "Docker Desktop Sandbox not available (requires Docker Desktop 4.58+)"
|
|
213
|
+
return 1
|
|
214
|
+
fi
|
|
215
|
+
;;
|
|
202
216
|
docker)
|
|
203
217
|
if is_docker_available; then
|
|
204
218
|
echo "docker"
|
|
@@ -216,7 +230,9 @@ detect_sandbox_mode() {
|
|
|
216
230
|
fi
|
|
217
231
|
;;
|
|
218
232
|
auto|*)
|
|
219
|
-
if
|
|
233
|
+
if is_docker_desktop_sandbox_available; then
|
|
234
|
+
echo "docker-desktop"
|
|
235
|
+
elif is_docker_available; then
|
|
220
236
|
echo "docker"
|
|
221
237
|
elif is_git_available; then
|
|
222
238
|
log_warn "Docker not available - using worktree sandbox (soft isolation)"
|
|
@@ -514,7 +530,229 @@ cleanup_worktrees() {
|
|
|
514
530
|
}
|
|
515
531
|
|
|
516
532
|
#===============================================================================
|
|
517
|
-
#
|
|
533
|
+
# Docker Desktop Sandbox (microVM-based isolation via Docker Desktop 4.58+)
|
|
534
|
+
#===============================================================================
|
|
535
|
+
|
|
536
|
+
# Desktop sandbox name follows same pattern as container name
|
|
537
|
+
DESKTOP_SANDBOX_NAME="$CONTAINER_NAME"
|
|
538
|
+
|
|
539
|
+
# Install provider CLI inside sandbox if not pre-installed
|
|
540
|
+
_desktop_install_provider_cli() {
|
|
541
|
+
local sandbox_name="$1" provider="$2"
|
|
542
|
+
case "$provider" in
|
|
543
|
+
codex)
|
|
544
|
+
if ! docker sandbox exec "$sandbox_name" which codex &>/dev/null 2>&1; then
|
|
545
|
+
log_info "Installing Codex CLI in sandbox (one-time)..."
|
|
546
|
+
docker sandbox exec "$sandbox_name" npm install -g @openai/codex 2>&1 | tail -1
|
|
547
|
+
fi
|
|
548
|
+
;;
|
|
549
|
+
gemini)
|
|
550
|
+
if ! docker sandbox exec "$sandbox_name" which gemini &>/dev/null 2>&1; then
|
|
551
|
+
log_info "Installing Gemini CLI in sandbox (one-time)..."
|
|
552
|
+
docker sandbox exec "$sandbox_name" npm install -g @google/gemini-cli 2>&1 | tail -1
|
|
553
|
+
fi
|
|
554
|
+
;;
|
|
555
|
+
# claude is pre-installed in the sandbox template
|
|
556
|
+
esac
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
# Build environment variable args for docker sandbox exec
|
|
560
|
+
_desktop_build_env_args() {
|
|
561
|
+
DESKTOP_ENV_ARGS=()
|
|
562
|
+
[[ -n "${ANTHROPIC_API_KEY:-}" ]] && DESKTOP_ENV_ARGS+=("-e" "ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY")
|
|
563
|
+
[[ -n "${OPENAI_API_KEY:-}" ]] && DESKTOP_ENV_ARGS+=("-e" "OPENAI_API_KEY=$OPENAI_API_KEY")
|
|
564
|
+
[[ -n "${GOOGLE_API_KEY:-}" ]] && DESKTOP_ENV_ARGS+=("-e" "GOOGLE_API_KEY=$GOOGLE_API_KEY")
|
|
565
|
+
[[ -n "${GITHUB_TOKEN:-}" ]] && DESKTOP_ENV_ARGS+=("-e" "GITHUB_TOKEN=$GITHUB_TOKEN")
|
|
566
|
+
[[ -n "${GH_TOKEN:-}" ]] && DESKTOP_ENV_ARGS+=("-e" "GH_TOKEN=$GH_TOKEN")
|
|
567
|
+
# Forward all LOKI_* env vars
|
|
568
|
+
local var
|
|
569
|
+
while IFS= read -r var; do
|
|
570
|
+
[[ -n "$var" ]] && DESKTOP_ENV_ARGS+=("-e" "$var=${!var}")
|
|
571
|
+
done < <(compgen -v LOKI_ 2>/dev/null || true)
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
start_docker_desktop_sandbox() {
|
|
575
|
+
local prd_path="${1:-}"
|
|
576
|
+
local provider="${LOKI_PROVIDER:-claude}"
|
|
577
|
+
|
|
578
|
+
validate_project_dir || return 1
|
|
579
|
+
warn_missing_api_keys "$provider"
|
|
580
|
+
|
|
581
|
+
# Check if sandbox already exists
|
|
582
|
+
local sandbox_exists=false
|
|
583
|
+
if docker sandbox ls 2>/dev/null | grep -q "$DESKTOP_SANDBOX_NAME"; then
|
|
584
|
+
sandbox_exists=true
|
|
585
|
+
fi
|
|
586
|
+
|
|
587
|
+
if [[ "$sandbox_exists" == "false" ]]; then
|
|
588
|
+
log_info "Creating Docker Desktop Sandbox (microVM)..."
|
|
589
|
+
log_info " Workspace: $PROJECT_DIR"
|
|
590
|
+
log_info " Agent: claude (provider: $provider)"
|
|
591
|
+
docker sandbox create --name "$DESKTOP_SANDBOX_NAME" claude "$PROJECT_DIR" || {
|
|
592
|
+
log_error "Failed to create Docker Desktop Sandbox"
|
|
593
|
+
log_info "Falling back to Docker container sandbox..."
|
|
594
|
+
start_sandbox "$@"
|
|
595
|
+
return $?
|
|
596
|
+
}
|
|
597
|
+
log_success "Sandbox created: $DESKTOP_SANDBOX_NAME"
|
|
598
|
+
else
|
|
599
|
+
log_info "Using existing sandbox: $DESKTOP_SANDBOX_NAME"
|
|
600
|
+
fi
|
|
601
|
+
|
|
602
|
+
# Install provider CLI if needed (codex/gemini not pre-installed)
|
|
603
|
+
_desktop_install_provider_cli "$DESKTOP_SANDBOX_NAME" "$provider"
|
|
604
|
+
|
|
605
|
+
# Build environment variable args
|
|
606
|
+
_desktop_build_env_args
|
|
607
|
+
|
|
608
|
+
# Build loki command
|
|
609
|
+
local loki_cmd="bash ${PROJECT_DIR}/autonomy/run.sh"
|
|
610
|
+
if [[ -n "$prd_path" ]]; then
|
|
611
|
+
local abs_prd
|
|
612
|
+
abs_prd=$(cd "$(dirname "$prd_path")" && pwd)/$(basename "$prd_path")
|
|
613
|
+
loki_cmd="$loki_cmd $abs_prd"
|
|
614
|
+
fi
|
|
615
|
+
loki_cmd="LOKI_PROVIDER=$provider LOKI_SANDBOX_MODE=true LOKI_DASHBOARD=false $loki_cmd"
|
|
616
|
+
|
|
617
|
+
log_info ""
|
|
618
|
+
log_info "Starting Loki Mode in Docker Desktop Sandbox..."
|
|
619
|
+
log_info " Isolation: microVM (hypervisor-based)"
|
|
620
|
+
log_info " Provider: $provider"
|
|
621
|
+
log_info " Sandbox: $DESKTOP_SANDBOX_NAME"
|
|
622
|
+
log_info " Workspace: $PROJECT_DIR (synced at same path)"
|
|
623
|
+
log_info ""
|
|
624
|
+
log_info " Private Docker daemon available inside sandbox"
|
|
625
|
+
log_info " Dashboard: run 'loki dashboard' on host (reads synced .loki/ files)"
|
|
626
|
+
log_info ""
|
|
627
|
+
log_info "Commands:"
|
|
628
|
+
log_info " loki sandbox status - Check sandbox status"
|
|
629
|
+
log_info " loki sandbox shell - Open shell in sandbox"
|
|
630
|
+
log_info " loki sandbox stop - Stop sandbox"
|
|
631
|
+
log_info ""
|
|
632
|
+
|
|
633
|
+
# Execute loki inside sandbox (use -it only when stdin is a terminal)
|
|
634
|
+
local tty_args="-i"
|
|
635
|
+
if [ -t 0 ]; then
|
|
636
|
+
tty_args="-it"
|
|
637
|
+
fi
|
|
638
|
+
docker sandbox exec $tty_args \
|
|
639
|
+
-w "$PROJECT_DIR" \
|
|
640
|
+
${DESKTOP_ENV_ARGS[@]+"${DESKTOP_ENV_ARGS[@]}"} \
|
|
641
|
+
"$DESKTOP_SANDBOX_NAME" \
|
|
642
|
+
bash -c "$loki_cmd"
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
stop_docker_desktop_sandbox() {
|
|
646
|
+
local remove="${1:-false}"
|
|
647
|
+
|
|
648
|
+
if ! docker sandbox ls 2>/dev/null | grep -q "$DESKTOP_SANDBOX_NAME"; then
|
|
649
|
+
log_error "Sandbox not found: $DESKTOP_SANDBOX_NAME"
|
|
650
|
+
return 1
|
|
651
|
+
fi
|
|
652
|
+
|
|
653
|
+
# Signal loki to stop gracefully
|
|
654
|
+
docker sandbox exec "$DESKTOP_SANDBOX_NAME" \
|
|
655
|
+
bash -c "touch ${PROJECT_DIR}/.loki/STOP 2>/dev/null" 2>/dev/null || true
|
|
656
|
+
|
|
657
|
+
log_info "Stopping sandbox: $DESKTOP_SANDBOX_NAME"
|
|
658
|
+
docker sandbox stop "$DESKTOP_SANDBOX_NAME" 2>/dev/null || true
|
|
659
|
+
|
|
660
|
+
if [[ "$remove" == "true" ]]; then
|
|
661
|
+
log_info "Removing sandbox: $DESKTOP_SANDBOX_NAME"
|
|
662
|
+
docker sandbox rm "$DESKTOP_SANDBOX_NAME" 2>/dev/null || true
|
|
663
|
+
fi
|
|
664
|
+
|
|
665
|
+
log_success "Sandbox stopped"
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
docker_desktop_sandbox_status() {
|
|
669
|
+
local found=false
|
|
670
|
+
while IFS= read -r line; do
|
|
671
|
+
if echo "$line" | grep -q "$DESKTOP_SANDBOX_NAME"; then
|
|
672
|
+
found=true
|
|
673
|
+
echo "$line"
|
|
674
|
+
fi
|
|
675
|
+
done < <(docker sandbox ls 2>/dev/null)
|
|
676
|
+
|
|
677
|
+
if [[ "$found" == "false" ]]; then
|
|
678
|
+
log_info "No Docker Desktop Sandbox found for this project"
|
|
679
|
+
log_info "Expected name: $DESKTOP_SANDBOX_NAME"
|
|
680
|
+
return 1
|
|
681
|
+
fi
|
|
682
|
+
|
|
683
|
+
# If sandbox is running, get loki status
|
|
684
|
+
if docker sandbox ls 2>/dev/null | grep "$DESKTOP_SANDBOX_NAME" | grep -q "running"; then
|
|
685
|
+
echo ""
|
|
686
|
+
docker sandbox exec -w "$PROJECT_DIR" "$DESKTOP_SANDBOX_NAME" \
|
|
687
|
+
bash -c "bash ${PROJECT_DIR}/autonomy/loki status" 2>/dev/null || true
|
|
688
|
+
fi
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
docker_desktop_sandbox_shell() {
|
|
692
|
+
if ! docker sandbox ls 2>/dev/null | grep "$DESKTOP_SANDBOX_NAME" | grep -q "running"; then
|
|
693
|
+
log_error "Sandbox is not running: $DESKTOP_SANDBOX_NAME"
|
|
694
|
+
log_info "Start it with: loki sandbox start"
|
|
695
|
+
return 1
|
|
696
|
+
fi
|
|
697
|
+
|
|
698
|
+
log_info "Opening shell in Docker Desktop Sandbox..."
|
|
699
|
+
docker sandbox exec -it -w "$PROJECT_DIR" "$DESKTOP_SANDBOX_NAME" bash
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
docker_desktop_sandbox_logs() {
|
|
703
|
+
local lines="${1:-100}"
|
|
704
|
+
if ! docker sandbox ls 2>/dev/null | grep -q "$DESKTOP_SANDBOX_NAME"; then
|
|
705
|
+
log_error "Sandbox not found: $DESKTOP_SANDBOX_NAME"
|
|
706
|
+
return 1
|
|
707
|
+
fi
|
|
708
|
+
|
|
709
|
+
docker sandbox exec -w "$PROJECT_DIR" "$DESKTOP_SANDBOX_NAME" \
|
|
710
|
+
bash -c "cat .loki/logs/*.log 2>/dev/null | tail -${lines}" || \
|
|
711
|
+
log_warn "No logs found in .loki/logs/"
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
docker_desktop_sandbox_prompt() {
|
|
715
|
+
local message="${1:-}"
|
|
716
|
+
if [[ -z "$message" ]]; then
|
|
717
|
+
log_error "Usage: loki sandbox prompt <message>"
|
|
718
|
+
return 1
|
|
719
|
+
fi
|
|
720
|
+
|
|
721
|
+
if ! docker sandbox ls 2>/dev/null | grep "$DESKTOP_SANDBOX_NAME" | grep -q "running"; then
|
|
722
|
+
log_error "Sandbox is not running"
|
|
723
|
+
return 1
|
|
724
|
+
fi
|
|
725
|
+
|
|
726
|
+
_desktop_build_env_args
|
|
727
|
+
docker sandbox exec -w "$PROJECT_DIR" \
|
|
728
|
+
${DESKTOP_ENV_ARGS[@]+"${DESKTOP_ENV_ARGS[@]}"} \
|
|
729
|
+
"$DESKTOP_SANDBOX_NAME" \
|
|
730
|
+
bash -c "echo '$message' > ${PROJECT_DIR}/.loki/HUMAN_INPUT.md"
|
|
731
|
+
|
|
732
|
+
log_success "Prompt sent to sandbox"
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
docker_desktop_sandbox_run() {
|
|
736
|
+
local cmd="${*}"
|
|
737
|
+
if [[ -z "$cmd" ]]; then
|
|
738
|
+
log_error "Usage: loki sandbox run <command>"
|
|
739
|
+
return 1
|
|
740
|
+
fi
|
|
741
|
+
|
|
742
|
+
if ! docker sandbox ls 2>/dev/null | grep "$DESKTOP_SANDBOX_NAME" | grep -q "running"; then
|
|
743
|
+
log_error "Sandbox is not running"
|
|
744
|
+
return 1
|
|
745
|
+
fi
|
|
746
|
+
|
|
747
|
+
_desktop_build_env_args
|
|
748
|
+
docker sandbox exec -w "$PROJECT_DIR" \
|
|
749
|
+
${DESKTOP_ENV_ARGS[@]+"${DESKTOP_ENV_ARGS[@]}"} \
|
|
750
|
+
"$DESKTOP_SANDBOX_NAME" \
|
|
751
|
+
bash -c "$cmd"
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
#===============================================================================
|
|
755
|
+
# Docker Container Sandbox (standard Docker - fallback from Docker Desktop)
|
|
518
756
|
#===============================================================================
|
|
519
757
|
|
|
520
758
|
start_sandbox() {
|
|
@@ -1121,15 +1359,18 @@ show_help() {
|
|
|
1121
1359
|
echo " expose <port> Show how to expose additional ports"
|
|
1122
1360
|
echo ""
|
|
1123
1361
|
echo "Mode Options:"
|
|
1124
|
-
echo " --docker
|
|
1362
|
+
echo " --docker-desktop Force Docker Desktop Sandbox (microVM isolation)"
|
|
1363
|
+
echo " --docker Force Docker container sandbox (seccomp isolation)"
|
|
1125
1364
|
echo " --worktree Force git worktree sandbox (soft isolation)"
|
|
1126
1365
|
echo " --auto Auto-detect best mode (default)"
|
|
1127
1366
|
echo ""
|
|
1128
|
-
echo "Sandbox Modes:"
|
|
1129
|
-
echo " Docker
|
|
1130
|
-
echo "
|
|
1131
|
-
echo "
|
|
1132
|
-
echo "
|
|
1367
|
+
echo "Sandbox Modes (priority order):"
|
|
1368
|
+
echo " Docker Desktop - microVM isolation via 'docker sandbox' (Docker Desktop 4.58+)"
|
|
1369
|
+
echo " (default) Hypervisor-based VM, private Docker daemon, pre-installed CLIs"
|
|
1370
|
+
echo " Docker Container - Container isolation with seccomp, dropped capabilities,"
|
|
1371
|
+
echo " (fallback) resource limits, network control (Dockerfile.sandbox)"
|
|
1372
|
+
echo " Worktree - Git worktree isolation (last resort if no Docker)"
|
|
1373
|
+
echo " (last resort) Warning: No filesystem/network/process isolation"
|
|
1133
1374
|
echo ""
|
|
1134
1375
|
echo "Environment Variables:"
|
|
1135
1376
|
echo " LOKI_SANDBOX_IMAGE Docker image (default: loki-mode:sandbox)"
|
|
@@ -1150,8 +1391,9 @@ show_help() {
|
|
|
1150
1391
|
echo " - Prompt injection DISABLED by default (enterprise security)"
|
|
1151
1392
|
echo ""
|
|
1152
1393
|
echo "Examples:"
|
|
1153
|
-
echo " loki sandbox start # Start (auto-detect
|
|
1154
|
-
echo " loki sandbox start --docker ./prd.md
|
|
1394
|
+
echo " loki sandbox start # Start (auto-detect: Desktop > Docker > Worktree)"
|
|
1395
|
+
echo " loki sandbox start --docker-desktop ./prd.md # Force Docker Desktop microVM"
|
|
1396
|
+
echo " loki sandbox start --docker ./prd.md # Force Docker container mode"
|
|
1155
1397
|
echo " loki sandbox start --worktree # Force worktree mode"
|
|
1156
1398
|
echo " loki sandbox prompt 'start the app and show URL' # Send prompt"
|
|
1157
1399
|
echo " loki sandbox serve # Start dev server"
|
|
@@ -1175,6 +1417,7 @@ main() {
|
|
|
1175
1417
|
local args=()
|
|
1176
1418
|
while [[ $# -gt 0 ]]; do
|
|
1177
1419
|
case "$1" in
|
|
1420
|
+
--docker-desktop) mode="docker-desktop"; shift ;;
|
|
1178
1421
|
--docker) mode="docker"; shift ;;
|
|
1179
1422
|
--worktree) mode="worktree"; shift ;;
|
|
1180
1423
|
--auto) mode="auto"; shift ;;
|
|
@@ -1185,63 +1428,95 @@ main() {
|
|
|
1185
1428
|
# Detect sandbox mode for commands that need it
|
|
1186
1429
|
local sandbox_mode=""
|
|
1187
1430
|
case "$command" in
|
|
1188
|
-
start|stop|status|prompt)
|
|
1431
|
+
start|stop|status|prompt|shell|logs|run|serve|test|phase)
|
|
1189
1432
|
sandbox_mode=$(detect_sandbox_mode "$mode") || exit 1
|
|
1190
1433
|
;;
|
|
1191
1434
|
esac
|
|
1192
1435
|
|
|
1193
1436
|
case "$command" in
|
|
1194
1437
|
start)
|
|
1195
|
-
if [[ "$sandbox_mode" == "docker" ]]; then
|
|
1438
|
+
if [[ "$sandbox_mode" == "docker-desktop" ]]; then
|
|
1439
|
+
start_docker_desktop_sandbox ${args[@]+"${args[@]}"}
|
|
1440
|
+
elif [[ "$sandbox_mode" == "docker" ]]; then
|
|
1196
1441
|
start_sandbox ${args[@]+"${args[@]}"}
|
|
1197
1442
|
else
|
|
1198
1443
|
start_worktree_sandbox ${args[@]+"${args[@]}"}
|
|
1199
1444
|
fi
|
|
1200
1445
|
;;
|
|
1201
1446
|
stop)
|
|
1202
|
-
if [[ "$sandbox_mode" == "docker" ]]; then
|
|
1447
|
+
if [[ "$sandbox_mode" == "docker-desktop" ]]; then
|
|
1448
|
+
stop_docker_desktop_sandbox
|
|
1449
|
+
elif [[ "$sandbox_mode" == "docker" ]]; then
|
|
1203
1450
|
stop_sandbox
|
|
1204
1451
|
else
|
|
1205
1452
|
stop_worktree_sandbox
|
|
1206
1453
|
fi
|
|
1207
1454
|
;;
|
|
1208
1455
|
status)
|
|
1209
|
-
if [[ "$sandbox_mode" == "docker" ]]; then
|
|
1456
|
+
if [[ "$sandbox_mode" == "docker-desktop" ]]; then
|
|
1457
|
+
docker_desktop_sandbox_status
|
|
1458
|
+
elif [[ "$sandbox_mode" == "docker" ]]; then
|
|
1210
1459
|
sandbox_status
|
|
1211
1460
|
else
|
|
1212
1461
|
worktree_sandbox_status
|
|
1213
1462
|
fi
|
|
1214
1463
|
;;
|
|
1215
1464
|
logs)
|
|
1216
|
-
|
|
1465
|
+
if [[ "$sandbox_mode" == "docker-desktop" ]]; then
|
|
1466
|
+
docker_desktop_sandbox_logs ${args[@]+"${args[@]}"}
|
|
1467
|
+
else
|
|
1468
|
+
sandbox_logs ${args[@]+"${args[@]}"}
|
|
1469
|
+
fi
|
|
1217
1470
|
;;
|
|
1218
1471
|
shell)
|
|
1219
|
-
|
|
1472
|
+
if [[ "$sandbox_mode" == "docker-desktop" ]]; then
|
|
1473
|
+
docker_desktop_sandbox_shell
|
|
1474
|
+
else
|
|
1475
|
+
sandbox_shell
|
|
1476
|
+
fi
|
|
1220
1477
|
;;
|
|
1221
1478
|
build)
|
|
1222
1479
|
sandbox_build
|
|
1223
1480
|
;;
|
|
1224
1481
|
prompt)
|
|
1225
|
-
if [[ "$sandbox_mode" == "docker" ]]; then
|
|
1482
|
+
if [[ "$sandbox_mode" == "docker-desktop" ]]; then
|
|
1483
|
+
docker_desktop_sandbox_prompt ${args[@]+"${args[@]}"}
|
|
1484
|
+
elif [[ "$sandbox_mode" == "docker" ]]; then
|
|
1226
1485
|
sandbox_prompt ${args[@]+"${args[@]}"}
|
|
1227
1486
|
else
|
|
1228
1487
|
worktree_sandbox_prompt ${args[@]+"${args[@]}"}
|
|
1229
1488
|
fi
|
|
1230
1489
|
;;
|
|
1231
1490
|
run)
|
|
1232
|
-
|
|
1491
|
+
if [[ "$sandbox_mode" == "docker-desktop" ]]; then
|
|
1492
|
+
docker_desktop_sandbox_run ${args[@]+"${args[@]}"}
|
|
1493
|
+
else
|
|
1494
|
+
sandbox_run ${args[@]+"${args[@]}"}
|
|
1495
|
+
fi
|
|
1233
1496
|
;;
|
|
1234
1497
|
cleanup)
|
|
1235
1498
|
cleanup_worktrees
|
|
1236
1499
|
;;
|
|
1237
1500
|
serve)
|
|
1238
|
-
|
|
1501
|
+
if [[ "$sandbox_mode" == "docker-desktop" ]]; then
|
|
1502
|
+
docker_desktop_sandbox_run "npm start 2>/dev/null || python3 -m http.server ${args[0]:-3000}"
|
|
1503
|
+
else
|
|
1504
|
+
sandbox_serve ${args[@]+"${args[@]}"}
|
|
1505
|
+
fi
|
|
1239
1506
|
;;
|
|
1240
1507
|
test)
|
|
1241
|
-
|
|
1508
|
+
if [[ "$sandbox_mode" == "docker-desktop" ]]; then
|
|
1509
|
+
docker_desktop_sandbox_run "npm test 2>/dev/null || python3 -m pytest 2>/dev/null || echo 'No test runner found'"
|
|
1510
|
+
else
|
|
1511
|
+
sandbox_test ${args[@]+"${args[@]}"}
|
|
1512
|
+
fi
|
|
1242
1513
|
;;
|
|
1243
1514
|
phase)
|
|
1244
|
-
|
|
1515
|
+
if [[ "$sandbox_mode" == "docker-desktop" ]]; then
|
|
1516
|
+
docker_desktop_sandbox_run "bash ${PROJECT_DIR}/autonomy/loki status"
|
|
1517
|
+
else
|
|
1518
|
+
sandbox_phase
|
|
1519
|
+
fi
|
|
1245
1520
|
;;
|
|
1246
1521
|
expose)
|
|
1247
1522
|
sandbox_expose ${args[@]+"${args[@]}"}
|
package/dashboard/__init__.py
CHANGED
package/docs/INSTALLATION.md
CHANGED