@kokorolx/ai-sandbox-wrapper 3.1.2 → 3.3.0-beta.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/bin/ai-run +222 -106
- package/dockerfiles/base/Dockerfile +1 -1
- package/dockerfiles/sandbox/Dockerfile +9 -1
- package/lib/install-base.sh +14 -1
- package/lib/playwright-mcp-config.sh +118 -0
- package/package.json +1 -1
- package/setup.sh +41 -34
- package/dockerfiles/base/skills/rtk/SKILL.md +0 -103
- package/dockerfiles/base/skills/rtk-setup/SKILL.md +0 -118
- package/dockerfiles/opencode/Dockerfile +0 -9
- package/dockerfiles/sandbox/skills/rtk/SKILL.md +0 -103
- package/dockerfiles/sandbox/skills/rtk-setup/SKILL.md +0 -118
package/bin/ai-run
CHANGED
|
@@ -43,7 +43,7 @@ Examples:
|
|
|
43
43
|
ai-run opencode web -e 4096 # Run OpenCode web with port exposed
|
|
44
44
|
ai-run opencode web -p secret # Run with password
|
|
45
45
|
ai-run opencode --shell # Start shell, run tool manually
|
|
46
|
-
|
|
46
|
+
ai-run aider -n mynetwork # Connect to Docker network
|
|
47
47
|
ai-run opencode --git-fetch # Git fetch only (no push)
|
|
48
48
|
|
|
49
49
|
Documentation: https://github.com/kokorolx/ai-sandbox-wrapper
|
|
@@ -663,26 +663,26 @@ done < "$WORKSPACES_FILE"
|
|
|
663
663
|
# Maps tool name to space-separated config paths (relative to $HOME)
|
|
664
664
|
get_tool_configs() {
|
|
665
665
|
case "$1" in
|
|
666
|
-
|
|
666
|
+
amp) echo ".config/amp .local/share/amp" ;;
|
|
667
667
|
opencode) echo ".config/opencode .local/share/opencode" ;;
|
|
668
668
|
claude) echo ".claude" ;;
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
669
|
+
openclaw) echo ".openclaw" ;;
|
|
670
|
+
droid) echo ".config/droid" ;;
|
|
671
|
+
qoder) echo ".config/qoder" ;;
|
|
672
|
+
auggie) echo ".config/auggie" ;;
|
|
673
|
+
codebuddy) echo ".config/codebuddy" ;;
|
|
674
|
+
jules) echo ".config/jules" ;;
|
|
675
|
+
shai) echo ".config/shai" ;;
|
|
676
|
+
gemini) echo ".config/gemini" ;;
|
|
677
|
+
aider) echo ".config/aider .aider" ;;
|
|
678
|
+
kilo) echo ".config/kilo" ;;
|
|
679
679
|
codex) echo ".config/codex" ;;
|
|
680
|
-
|
|
680
|
+
qwen) echo ".config/qwen" ;;
|
|
681
681
|
esac
|
|
682
682
|
}
|
|
683
683
|
|
|
684
684
|
# All known tools (for fallback)
|
|
685
|
-
ALL_KNOWN_TOOLS="opencode claude codex"
|
|
685
|
+
ALL_KNOWN_TOOLS="amp opencode claude openclaw droid qoder auggie codebuddy jules shai gemini aider kilo codex qwen"
|
|
686
686
|
|
|
687
687
|
# Get list of installed tools from config.json, fallback to all known tools
|
|
688
688
|
get_installed_tools() {
|
|
@@ -783,6 +783,83 @@ if [[ -d "$HOST_SKILLS_DIR" ]]; then
|
|
|
783
783
|
SHARED_CACHE_MOUNTS="$SHARED_CACHE_MOUNTS -v $HOST_SKILLS_DIR:/home/agent/.config/opencode/skills:ro"
|
|
784
784
|
fi
|
|
785
785
|
|
|
786
|
+
# Host Chrome for Playwright MCP (via CDP - Chrome DevTools Protocol)
|
|
787
|
+
# NOTE: macOS Chrome binary (Mach-O) cannot run inside a Linux container.
|
|
788
|
+
# Instead, we launch Chrome on the host with --remote-debugging-port and
|
|
789
|
+
# connect from the container via CDP. Each container gets its own port and
|
|
790
|
+
# its own MCP entry; entries are sweep-cleaned on every start.
|
|
791
|
+
HOST_CHROME_CDP=false
|
|
792
|
+
HOST_CHROME_CDP_PORT=19222
|
|
793
|
+
PLAYWRIGHT_MCP_NAME=""
|
|
794
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
795
|
+
# shellcheck source=lib/playwright-mcp-config.sh
|
|
796
|
+
[[ -f "$SCRIPT_DIR/lib/playwright-mcp-config.sh" ]] && source "$SCRIPT_DIR/lib/playwright-mcp-config.sh"
|
|
797
|
+
|
|
798
|
+
if [[ "$TOOL" == "opencode" ]] && command -v jq &>/dev/null && [[ -f "$AI_SANDBOX_CONFIG" ]] && declare -f pmcp::sanitize_name >/dev/null; then
|
|
799
|
+
PLAYWRIGHT_HOST_CHROME=$(jq -r '.mcp.chromePath // empty' "$AI_SANDBOX_CONFIG" 2>/dev/null)
|
|
800
|
+
if [[ -n "$PLAYWRIGHT_HOST_CHROME" ]] && [[ -f "$PLAYWRIGHT_HOST_CHROME" ]]; then
|
|
801
|
+
HOST_CHROME_CDP=true
|
|
802
|
+
echo "🌐 Host Chrome CDP mode: $PLAYWRIGHT_HOST_CHROME"
|
|
803
|
+
|
|
804
|
+
# CONTAINER_NAME has the form "--name foo" or is empty. Extract the value
|
|
805
|
+
# for hashing only — the MCP key uses just the port (containers that
|
|
806
|
+
# collide on a port intentionally share the same Chrome / MCP entry).
|
|
807
|
+
CONTAINER_NAME_VALUE="${CONTAINER_NAME#--name }"
|
|
808
|
+
[[ "$CONTAINER_NAME_VALUE" == "$CONTAINER_NAME" ]] && CONTAINER_NAME_VALUE="anon-$$"
|
|
809
|
+
|
|
810
|
+
# Deterministic port per container name
|
|
811
|
+
CONTAINER_HASH=$(echo "$CONTAINER_NAME_VALUE" | md5sum | cut -c1-4)
|
|
812
|
+
HOST_CHROME_CDP_PORT=$((19222 + 0x$CONTAINER_HASH % 100))
|
|
813
|
+
PLAYWRIGHT_MCP_NAME="playwright_port_${HOST_CHROME_CDP_PORT}"
|
|
814
|
+
|
|
815
|
+
# Reuse-if-alive: probe before launching
|
|
816
|
+
if pmcp::probe_chrome "$HOST_CHROME_CDP_PORT"; then
|
|
817
|
+
echo " ✅ Chrome already running on port $HOST_CHROME_CDP_PORT (reusing)"
|
|
818
|
+
else
|
|
819
|
+
echo " 🚀 Launching Chrome with remote debugging on port $HOST_CHROME_CDP_PORT..."
|
|
820
|
+
mkdir -p "$SANDBOX_DIR/chrome-profile-$HOST_CHROME_CDP_PORT"
|
|
821
|
+
"$PLAYWRIGHT_HOST_CHROME" \
|
|
822
|
+
--remote-debugging-port="$HOST_CHROME_CDP_PORT" \
|
|
823
|
+
--user-data-dir="$SANDBOX_DIR/chrome-profile-$HOST_CHROME_CDP_PORT" \
|
|
824
|
+
--no-first-run \
|
|
825
|
+
--no-default-browser-check \
|
|
826
|
+
&>/dev/null &
|
|
827
|
+
CHROME_PID=$!
|
|
828
|
+
for i in {1..20}; do
|
|
829
|
+
if pmcp::probe_chrome "$HOST_CHROME_CDP_PORT"; then
|
|
830
|
+
echo " ✅ Chrome ready (PID: $CHROME_PID, port: $HOST_CHROME_CDP_PORT)"
|
|
831
|
+
echo " 👀 You can watch the browser window to see what the AI is doing"
|
|
832
|
+
break
|
|
833
|
+
fi
|
|
834
|
+
sleep 0.25
|
|
835
|
+
done
|
|
836
|
+
if ! pmcp::probe_chrome "$HOST_CHROME_CDP_PORT"; then
|
|
837
|
+
echo " ⚠️ Chrome failed to start. Falling back to container Chromium."
|
|
838
|
+
HOST_CHROME_CDP=false
|
|
839
|
+
kill "$CHROME_PID" 2>/dev/null || true
|
|
840
|
+
PLAYWRIGHT_MCP_NAME=""
|
|
841
|
+
fi
|
|
842
|
+
fi
|
|
843
|
+
|
|
844
|
+
# Locked sweep+append on the shared OpenCode config
|
|
845
|
+
if [[ "$HOST_CHROME_CDP" == "true" ]]; then
|
|
846
|
+
OPENCODE_CONFIG_FILE="$HOME/.config/opencode/opencode.json"
|
|
847
|
+
LOCK_FILE="$HOME/.config/opencode/.playwright.lock"
|
|
848
|
+
mkdir -p "$(dirname "$OPENCODE_CONFIG_FILE")"
|
|
849
|
+
[[ -f "$OPENCODE_CONFIG_FILE" ]] || echo '{}' > "$OPENCODE_CONFIG_FILE"
|
|
850
|
+
pmcp::with_lock "$LOCK_FILE" pmcp::sweep_and_append "$OPENCODE_CONFIG_FILE" "$PLAYWRIGHT_MCP_NAME" "$HOST_CHROME_CDP_PORT"
|
|
851
|
+
rc=$?
|
|
852
|
+
if [[ "$rc" == "99" ]]; then
|
|
853
|
+
echo " ⚠️ Could not acquire MCP config lock within 5s; skipping registration."
|
|
854
|
+
PLAYWRIGHT_MCP_NAME=""
|
|
855
|
+
elif [[ "$rc" != "0" ]]; then
|
|
856
|
+
echo " ⚠️ MCP config update failed (rc=$rc); skipping registration."
|
|
857
|
+
PLAYWRIGHT_MCP_NAME=""
|
|
858
|
+
fi
|
|
859
|
+
fi
|
|
860
|
+
fi
|
|
861
|
+
fi
|
|
862
|
+
|
|
786
863
|
# Nano-brain mount: writable so container can modify config, write memory, logs, etc.
|
|
787
864
|
NANO_BRAIN_MOUNT=""
|
|
788
865
|
if [[ -d "$HOME/.nano-brain" ]]; then
|
|
@@ -1921,6 +1998,12 @@ configure_opencode_mcp() {
|
|
|
1921
1998
|
is_mcp_configured "playwright" && playwright_configured=true
|
|
1922
1999
|
fi
|
|
1923
2000
|
|
|
2001
|
+
# Get host Chrome path if using playwright-host
|
|
2002
|
+
local PLAYWRIGHT_HOST_CHROME=""
|
|
2003
|
+
if command -v jq &>/dev/null && [[ -f "$AI_SANDBOX_CONFIG" ]]; then
|
|
2004
|
+
PLAYWRIGHT_HOST_CHROME=$(jq -r '.mcp.chromePath // empty' "$AI_SANDBOX_CONFIG" 2>/dev/null)
|
|
2005
|
+
fi
|
|
2006
|
+
|
|
1924
2007
|
# If no MCP tools installed in image, return
|
|
1925
2008
|
if [[ "$chrome_installed" == "false" && "$playwright_installed" == "false" ]]; then
|
|
1926
2009
|
return 0
|
|
@@ -1957,7 +2040,11 @@ configure_opencode_mcp() {
|
|
|
1957
2040
|
echo " ✓ Chrome DevTools MCP"
|
|
1958
2041
|
;;
|
|
1959
2042
|
playwright)
|
|
1960
|
-
|
|
2043
|
+
if [[ -n "$PLAYWRIGHT_HOST_CHROME" ]] && [[ -f "$PLAYWRIGHT_HOST_CHROME" ]]; then
|
|
2044
|
+
echo " ✓ Playwright MCP (host Chrome)"
|
|
2045
|
+
else
|
|
2046
|
+
echo " ✓ Playwright MCP"
|
|
2047
|
+
fi
|
|
1961
2048
|
;;
|
|
1962
2049
|
esac
|
|
1963
2050
|
done
|
|
@@ -1973,7 +2060,11 @@ configure_opencode_mcp() {
|
|
|
1973
2060
|
echo " • Chrome DevTools MCP - browser automation + performance profiling"
|
|
1974
2061
|
;;
|
|
1975
2062
|
playwright)
|
|
1976
|
-
|
|
2063
|
+
if [[ -n "$PLAYWRIGHT_HOST_CHROME" ]] && [[ -f "$PLAYWRIGHT_HOST_CHROME" ]]; then
|
|
2064
|
+
echo " • Playwright MCP (host Chrome) - use your installed Chrome browser"
|
|
2065
|
+
else
|
|
2066
|
+
echo " • Playwright MCP - multi-browser automation"
|
|
2067
|
+
fi
|
|
1977
2068
|
;;
|
|
1978
2069
|
esac
|
|
1979
2070
|
done
|
|
@@ -2006,9 +2097,16 @@ configure_opencode_mcp() {
|
|
|
2006
2097
|
fi
|
|
2007
2098
|
;;
|
|
2008
2099
|
playwright)
|
|
2009
|
-
|
|
2010
|
-
|
|
2100
|
+
# Check if using host Chrome via CDP
|
|
2101
|
+
if [[ -n "$PLAYWRIGHT_HOST_CHROME" ]] && [[ -f "$PLAYWRIGHT_HOST_CHROME" ]]; then
|
|
2102
|
+
echo " ℹ️ Playwright MCP entry will be registered per-container at runtime (host Chrome mode)."
|
|
2011
2103
|
configured_any=true
|
|
2104
|
+
else
|
|
2105
|
+
# Use container Chromium
|
|
2106
|
+
if add_mcp_config "playwright" '["playwright-mcp", "--headless", "--browser", "chromium"]'; then
|
|
2107
|
+
echo " ✓ Configured Playwright MCP"
|
|
2108
|
+
configured_any=true
|
|
2109
|
+
fi
|
|
2012
2110
|
fi
|
|
2013
2111
|
;;
|
|
2014
2112
|
esac
|
|
@@ -2042,9 +2140,16 @@ configure_opencode_mcp() {
|
|
|
2042
2140
|
fi
|
|
2043
2141
|
;;
|
|
2044
2142
|
playwright)
|
|
2045
|
-
|
|
2046
|
-
|
|
2143
|
+
# Check if using host Chrome via CDP
|
|
2144
|
+
if [[ -n "$PLAYWRIGHT_HOST_CHROME" ]] && [[ -f "$PLAYWRIGHT_HOST_CHROME" ]]; then
|
|
2145
|
+
echo " ℹ️ Playwright MCP entry will be registered per-container at runtime (host Chrome mode)."
|
|
2047
2146
|
configured_any=true
|
|
2147
|
+
else
|
|
2148
|
+
# Use container Chromium
|
|
2149
|
+
if add_mcp_config "playwright" '["playwright-mcp", "--headless", "--browser", "chromium"]'; then
|
|
2150
|
+
echo " ✓ Configured"
|
|
2151
|
+
configured_any=true
|
|
2152
|
+
fi
|
|
2048
2153
|
fi
|
|
2049
2154
|
;;
|
|
2050
2155
|
esac
|
|
@@ -2441,7 +2546,7 @@ elif [[ "$SHELL_MODE" == "true" || -z "$TOOL" ]]; then
|
|
|
2441
2546
|
# Shell mode without tool (ai-run with no args)
|
|
2442
2547
|
DOCKER_COMMAND=(
|
|
2443
2548
|
"-c"
|
|
2444
|
-
"echo ''; echo '🚀 AI Sandbox - Interactive Shell'; echo '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'; echo ''; echo 'Installed tools: ${INSTALLED_TOOLS_MSG:-unknown}'; echo ''; echo 'Run any tool by name: claude, opencode,
|
|
2549
|
+
"echo ''; echo '🚀 AI Sandbox - Interactive Shell'; echo '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'; echo ''; echo 'Installed tools: ${INSTALLED_TOOLS_MSG:-unknown}'; echo ''; echo 'Run any tool by name: claude, opencode, gemini, etc.'; echo 'Exit: exit or Ctrl+D'; echo ''; echo 'Enhancement tools: specify, uipro, openspec, rtk'; echo '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'; echo ''; exec bash"
|
|
2445
2550
|
)
|
|
2446
2551
|
fi
|
|
2447
2552
|
else
|
|
@@ -2479,7 +2584,7 @@ if [[ -z "$PLATFORM" ]]; then
|
|
|
2479
2584
|
esac
|
|
2480
2585
|
fi
|
|
2481
2586
|
|
|
2482
|
-
# Terminal size for TUI apps (important for opencode, etc.)
|
|
2587
|
+
# Terminal size for TUI apps (important for opencode, aider, etc.)
|
|
2483
2588
|
TERMINAL_SIZE=""
|
|
2484
2589
|
if [[ -n "$TTY_FLAGS" ]]; then
|
|
2485
2590
|
# Get current terminal size
|
|
@@ -2521,87 +2626,98 @@ DISPLAY_FLAGS=$(detect_display_config)
|
|
|
2521
2626
|
# ============================================================================
|
|
2522
2627
|
# OPENCLAW DOCKER-COMPOSE MODE
|
|
2523
2628
|
# ============================================================================
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
docker run
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2629
|
+
if [[ "$TOOL" == "openclaw" ]]; then
|
|
2630
|
+
OPENCLAW_REPO_DIR="$HOME/.ai-sandbox/tools/openclaw/repo"
|
|
2631
|
+
|
|
2632
|
+
if [[ ! -d "$OPENCLAW_REPO_DIR" ]]; then
|
|
2633
|
+
echo "❌ ERROR: OpenClaw repository not found at $OPENCLAW_REPO_DIR"
|
|
2634
|
+
echo " Run: npx @kokorolx/ai-sandbox-wrapper setup"
|
|
2635
|
+
exit 1
|
|
2636
|
+
fi
|
|
2637
|
+
|
|
2638
|
+
cd "$OPENCLAW_REPO_DIR"
|
|
2639
|
+
|
|
2640
|
+
OPENCLAW_COMPOSE_FILE="$OPENCLAW_REPO_DIR/docker-compose.yml"
|
|
2641
|
+
OPENCLAW_OVERRIDE_FILE="$OPENCLAW_REPO_DIR/docker-compose.override.yml"
|
|
2642
|
+
|
|
2643
|
+
echo "🔄 Generating OpenClaw docker-compose override..."
|
|
2644
|
+
|
|
2645
|
+
cat > "$OPENCLAW_OVERRIDE_FILE" <<EOF
|
|
2646
|
+
services:
|
|
2647
|
+
openclaw-gateway:
|
|
2648
|
+
environment:
|
|
2649
|
+
HOME: /home/node
|
|
2650
|
+
OPENCLAW_GATEWAY_TOKEN: \${OPENCLAW_GATEWAY_TOKEN:-}
|
|
2651
|
+
volumes:
|
|
2652
|
+
- $HOME/.openclaw:/home/node/.openclaw
|
|
2653
|
+
EOF
|
|
2654
|
+
|
|
2655
|
+
for workspace in "${WORKSPACES[@]}"; do
|
|
2656
|
+
echo " - $workspace:$workspace" >> "$OPENCLAW_OVERRIDE_FILE"
|
|
2657
|
+
done
|
|
2658
|
+
|
|
2659
|
+
cat >> "$OPENCLAW_OVERRIDE_FILE" <<EOF
|
|
2660
|
+
ports:
|
|
2661
|
+
- "18789:18789"
|
|
2662
|
+
- "18790:18790"
|
|
2663
|
+
working_dir: $CURRENT_DIR
|
|
2664
|
+
EOF
|
|
2665
|
+
|
|
2666
|
+
if [[ -n "$NETWORK_OPTIONS" ]]; then
|
|
2667
|
+
echo " networks:" >> "$OPENCLAW_OVERRIDE_FILE"
|
|
2668
|
+
for net in ${DOCKER_NETWORKS//,/ }; do
|
|
2669
|
+
echo " - $net" >> "$OPENCLAW_OVERRIDE_FILE"
|
|
2670
|
+
done
|
|
2671
|
+
echo "" >> "$OPENCLAW_OVERRIDE_FILE"
|
|
2672
|
+
echo "networks:" >> "$OPENCLAW_OVERRIDE_FILE"
|
|
2673
|
+
for net in ${DOCKER_NETWORKS//,/ }; do
|
|
2674
|
+
echo " $net:" >> "$OPENCLAW_OVERRIDE_FILE"
|
|
2675
|
+
echo " external: true" >> "$OPENCLAW_OVERRIDE_FILE"
|
|
2676
|
+
done
|
|
2677
|
+
fi
|
|
2678
|
+
|
|
2679
|
+
echo "🚀 Starting OpenClaw with docker-compose..."
|
|
2680
|
+
echo "🌐 Gateway: http://localhost:18789"
|
|
2681
|
+
echo "🌐 Bridge: http://localhost:18790"
|
|
2682
|
+
echo ""
|
|
2683
|
+
|
|
2684
|
+
exec docker compose -f "$OPENCLAW_COMPOSE_FILE" -f "$OPENCLAW_OVERRIDE_FILE" \
|
|
2685
|
+
--env-file "$ENV_FILE" \
|
|
2686
|
+
up --remove-orphans
|
|
2687
|
+
fi
|
|
2688
|
+
|
|
2689
|
+
# Build docker run arguments as an array (handles paths with spaces correctly)
|
|
2690
|
+
DOCKER_ARGS=()
|
|
2691
|
+
DOCKER_ARGS+=($CONTAINER_NAME --rm $TTY_FLAGS)
|
|
2692
|
+
DOCKER_ARGS+=(--init)
|
|
2693
|
+
DOCKER_ARGS+=(--platform "$PLATFORM")
|
|
2694
|
+
DOCKER_ARGS+=($ENTRYPOINT_OVERRIDE)
|
|
2695
|
+
DOCKER_ARGS+=($VOLUME_MOUNTS)
|
|
2696
|
+
DOCKER_ARGS+=($CONFIG_MOUNT)
|
|
2697
|
+
DOCKER_ARGS+=($TOOL_CONFIG_MOUNTS)
|
|
2698
|
+
DOCKER_ARGS+=($RG_COMPAT_MOUNT)
|
|
2699
|
+
DOCKER_ARGS+=($GIT_MOUNTS)
|
|
2700
|
+
DOCKER_ARGS+=($SSH_AGENT_ENV)
|
|
2701
|
+
DOCKER_ARGS+=($NETWORK_OPTIONS)
|
|
2702
|
+
DOCKER_ARGS+=($DISPLAY_FLAGS)
|
|
2703
|
+
DOCKER_ARGS+=($HOST_ACCESS_ARGS)
|
|
2704
|
+
DOCKER_ARGS+=($PORT_MAPPINGS)
|
|
2705
|
+
DOCKER_ARGS+=($OPENCODE_PASSWORD_ENV)
|
|
2706
|
+
DOCKER_ARGS+=(-v "$HOME_DIR":/home/agent)
|
|
2707
|
+
DOCKER_ARGS+=($SHARED_CACHE_MOUNTS)
|
|
2708
|
+
DOCKER_ARGS+=($NANO_BRAIN_MOUNT)
|
|
2709
|
+
DOCKER_ARGS+=(-w "$CURRENT_DIR")
|
|
2710
|
+
DOCKER_ARGS+=(--env-file "$ENV_FILE")
|
|
2711
|
+
DOCKER_ARGS+=(-e TERM="$TERM")
|
|
2712
|
+
DOCKER_ARGS+=(-e COLORTERM="$COLORTERM")
|
|
2713
|
+
if [[ -n "${PLAYWRIGHT_MCP_NAME:-}" ]]; then
|
|
2714
|
+
DOCKER_ARGS+=(-e "PLAYWRIGHT_MCP_NAME=$PLAYWRIGHT_MCP_NAME")
|
|
2715
|
+
DOCKER_ARGS+=(-e "PLAYWRIGHT_PORT=$HOST_CHROME_CDP_PORT")
|
|
2716
|
+
fi
|
|
2717
|
+
DOCKER_ARGS+=($TERMINAL_SIZE)
|
|
2718
|
+
|
|
2719
|
+
DOCKER_ARGS+=("$IMAGE")
|
|
2720
|
+
DOCKER_ARGS+=("${DOCKER_COMMAND[@]}")
|
|
2721
|
+
|
|
2722
|
+
# Execute docker run with proper argument handling
|
|
2723
|
+
docker run "${DOCKER_ARGS[@]}"
|
|
@@ -6,7 +6,7 @@ FROM node:22-bookworm-slim
|
|
|
6
6
|
|
|
7
7
|
ARG AGENT_UID=1001
|
|
8
8
|
|
|
9
|
-
RUN apt-get update && apt-get install -y --no-install-recommends git curl ssh ca-certificates jq python3 python3-pip python3-venv python3-dev python3-setuptools build-essential libopenblas-dev pipx unzip xclip wl-clipboard ripgrep tmux fd-find sqlite3
|
|
9
|
+
RUN apt-get update && apt-get install -y --no-install-recommends git curl ssh ca-certificates jq python3 python3-pip python3-venv python3-dev python3-setuptools build-essential libopenblas-dev pipx unzip xclip wl-clipboard ripgrep tmux vim-nox fd-find sqlite3 poppler-utils qpdf tesseract-ocr && curl -LsSf https://astral.sh/uv/install.sh | UV_INSTALL_DIR=/usr/local/bin sh && rm -rf /var/lib/apt/lists/* && pipx ensurepath
|
|
10
10
|
|
|
11
11
|
# Install Python PDF processing tools for PDF skill
|
|
12
12
|
RUN pip3 install --no-cache-dir --break-system-packages pypdf pdfplumber reportlab pytesseract pdf2image
|
|
@@ -6,7 +6,7 @@ FROM node:22-bookworm-slim
|
|
|
6
6
|
|
|
7
7
|
ARG AGENT_UID=1001
|
|
8
8
|
|
|
9
|
-
RUN apt-get update && apt-get install -y --no-install-recommends git curl ssh ca-certificates jq python3 python3-pip python3-venv python3-dev python3-setuptools build-essential libopenblas-dev pipx unzip xclip wl-clipboard ripgrep tmux fd-find sqlite3
|
|
9
|
+
RUN apt-get update && apt-get install -y --no-install-recommends git curl ssh ca-certificates jq python3 python3-pip python3-venv python3-dev python3-setuptools build-essential libopenblas-dev pipx unzip xclip wl-clipboard ripgrep tmux vim-nox fd-find sqlite3 poppler-utils qpdf tesseract-ocr && curl -LsSf https://astral.sh/uv/install.sh | UV_INSTALL_DIR=/usr/local/bin sh && rm -rf /var/lib/apt/lists/* && pipx ensurepath
|
|
10
10
|
|
|
11
11
|
# Install Python PDF processing tools for PDF skill
|
|
12
12
|
RUN pip3 install --no-cache-dir --break-system-packages pypdf pdfplumber reportlab pytesseract pdf2image
|
|
@@ -106,6 +106,14 @@ RUN curl -fsSL https://opencode.ai/install | bash && \
|
|
|
106
106
|
mv /root/.opencode/bin/opencode /usr/local/bin/opencode && \
|
|
107
107
|
rm -rf /root/.opencode
|
|
108
108
|
|
|
109
|
+
# === claude ===
|
|
110
|
+
USER root
|
|
111
|
+
RUN export HOME=/root && curl -fsSL https://claude.ai/install.sh | bash && \
|
|
112
|
+
mkdir -p /usr/local/share && \
|
|
113
|
+
mv /root/.local/share/claude /usr/local/share/claude && \
|
|
114
|
+
ln -sf /usr/local/share/claude/versions/$(ls /usr/local/share/claude/versions | head -1) /usr/local/bin/claude
|
|
115
|
+
USER agent
|
|
116
|
+
|
|
109
117
|
USER agent
|
|
110
118
|
ENV HOME=/home/agent
|
|
111
119
|
CMD ["bash"]
|
package/lib/install-base.sh
CHANGED
|
@@ -170,13 +170,25 @@ if [[ "${INSTALL_CHROME_DEVTOOLS_MCP:-0}" -eq 1 ]] || [[ "${INSTALL_PLAYWRIGHT_M
|
|
|
170
170
|
wget \
|
|
171
171
|
&& rm -rf /var/lib/apt/lists/*
|
|
172
172
|
ENV PLAYWRIGHT_BROWSERS_PATH=/opt/playwright-browsers
|
|
173
|
-
|
|
173
|
+
'
|
|
174
|
+
|
|
175
|
+
# Only install Chromium if not using host Chrome
|
|
176
|
+
if [[ "${INSTALL_PLAYWRIGHT_HOST:-0}" -eq 1 ]]; then
|
|
177
|
+
echo " 📦 Using host Chrome - skipping Chromium installation"
|
|
178
|
+
ADDITIONAL_TOOLS_INSTALL+='RUN mkdir -p /opt/playwright-browsers && \
|
|
179
|
+
npm install -g @playwright/mcp@latest && \
|
|
180
|
+
touch /opt/.mcp-playwright-installed
|
|
181
|
+
'
|
|
182
|
+
else
|
|
183
|
+
echo " 📦 Installing Chromium browser for MCP tools"
|
|
184
|
+
ADDITIONAL_TOOLS_INSTALL+='RUN mkdir -p /opt/playwright-browsers && \
|
|
174
185
|
npm install -g @playwright/mcp@latest && \
|
|
175
186
|
npx playwright-core install --no-shell chromium && \
|
|
176
187
|
npx playwright-core install-deps chromium && \
|
|
177
188
|
chmod -R 777 /opt/playwright-browsers && \
|
|
178
189
|
ln -sf $(ls -d /opt/playwright-browsers/chromium-*/chrome-linux/chrome | sort -V | tail -1) /opt/chromium
|
|
179
190
|
'
|
|
191
|
+
fi
|
|
180
192
|
fi
|
|
181
193
|
|
|
182
194
|
if [[ "${INSTALL_CHROME_DEVTOOLS_MCP:-0}" -eq 1 ]]; then
|
|
@@ -218,6 +230,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
|
218
230
|
wl-clipboard \
|
|
219
231
|
ripgrep \
|
|
220
232
|
tmux \
|
|
233
|
+
vim-nox \
|
|
221
234
|
fd-find \
|
|
222
235
|
sqlite3 \
|
|
223
236
|
poppler-utils \
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Helpers for managing per-container Playwright MCP entries in the shared
|
|
3
|
+
# OpenCode config (~/.config/opencode/opencode.json). All functions are pure
|
|
4
|
+
# except where noted. Callers are responsible for holding the flock around
|
|
5
|
+
# pmcp::sweep_and_append.
|
|
6
|
+
|
|
7
|
+
# Replace any character outside [A-Za-z0-9_-] with underscore. Empty input
|
|
8
|
+
# becomes "unnamed". Used to keep MCP keys jq-safe.
|
|
9
|
+
pmcp::sanitize_name() {
|
|
10
|
+
local input="${1:-}"
|
|
11
|
+
if [[ -z "$input" ]]; then
|
|
12
|
+
echo "unnamed"
|
|
13
|
+
return
|
|
14
|
+
fi
|
|
15
|
+
printf '%s' "$input" | tr -c 'A-Za-z0-9_-' '_'
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
# Probe a port for a valid Chrome CDP endpoint. Returns 0 if /json/version
|
|
19
|
+
# responds with JSON containing a "Browser" field within the timeout.
|
|
20
|
+
# Args: $1 = port
|
|
21
|
+
pmcp::probe_chrome() {
|
|
22
|
+
local port="$1"
|
|
23
|
+
local body
|
|
24
|
+
body=$(curl -fsS --max-time 0.5 "http://localhost:$port/json/version" 2>/dev/null) || return 1
|
|
25
|
+
[[ "$body" == *'"Browser"'* ]] || return 1
|
|
26
|
+
return 0
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
# Host address from container (Docker Desktop on Mac).
|
|
30
|
+
PMCP_DOCKER_HOST_IP="${PMCP_DOCKER_HOST_IP:-192.168.65.254}"
|
|
31
|
+
|
|
32
|
+
# Sweep dead playwright_* entries and append a new one. MUST be called inside
|
|
33
|
+
# a flock by the caller. Does not acquire the lock itself, by design — locking
|
|
34
|
+
# happens around a larger critical section in the caller.
|
|
35
|
+
# Args: $1 = config file path, $2 = full MCP key (e.g. playwright_foo_19223), $3 = port
|
|
36
|
+
pmcp::sweep_and_append() {
|
|
37
|
+
local cfg="$1" name="$2" port="$3"
|
|
38
|
+
|
|
39
|
+
if [[ ! -f "$cfg" ]]; then
|
|
40
|
+
echo " ⚠️ pmcp: config file not found: $cfg" >&2
|
|
41
|
+
return 1
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
# Collect dead keys
|
|
45
|
+
local keys dead_keys=()
|
|
46
|
+
keys=$(jq -r '(.mcp // {}) | keys[] | select(startswith("playwright_"))' "$cfg" 2>/dev/null || true)
|
|
47
|
+
while IFS= read -r key; do
|
|
48
|
+
[[ -z "$key" ]] && continue
|
|
49
|
+
local cmd_url
|
|
50
|
+
cmd_url=$(jq -r --arg k "$key" '.mcp[$k].command[]? | select(startswith("http://"))' "$cfg" 2>/dev/null | head -1)
|
|
51
|
+
[[ -z "$cmd_url" ]] && continue
|
|
52
|
+
local entry_port="${cmd_url##*:}"
|
|
53
|
+
if ! pmcp::probe_chrome "$entry_port"; then
|
|
54
|
+
dead_keys+=("$key")
|
|
55
|
+
fi
|
|
56
|
+
done <<< "$keys"
|
|
57
|
+
|
|
58
|
+
# Build --arg flags for each dead key, then run a single jq invocation
|
|
59
|
+
# that deletes them all and appends the new entry.
|
|
60
|
+
local tmp="$cfg.tmp.$$"
|
|
61
|
+
local args=()
|
|
62
|
+
local i=0
|
|
63
|
+
for k in "${dead_keys[@]+"${dead_keys[@]}"}"; do
|
|
64
|
+
args+=(--arg "k$i" "$k")
|
|
65
|
+
i=$((i + 1))
|
|
66
|
+
done
|
|
67
|
+
jq "${args[@]+"${args[@]}"}" --arg name "$name" --arg host "$PMCP_DOCKER_HOST_IP" --arg port "$port" \
|
|
68
|
+
'
|
|
69
|
+
def setup($args; $name; $host; $port):
|
|
70
|
+
.mcp = (.mcp // {})
|
|
71
|
+
| reduce ($args[]) as $k (.; del(.mcp[$k]))
|
|
72
|
+
| .mcp[$name] = {"type":"local","command":["playwright-mcp","--cdp-endpoint","http://" + $host + ":" + $port]};
|
|
73
|
+
setup([$ARGS.named | to_entries[] | select(.key|startswith("k")) | .value]; $name; $host; $port)
|
|
74
|
+
' "$cfg" > "$tmp"
|
|
75
|
+
|
|
76
|
+
mv "$tmp" "$cfg"
|
|
77
|
+
chmod 600 "$cfg"
|
|
78
|
+
|
|
79
|
+
if (( ${#dead_keys[@]} > 0 )); then
|
|
80
|
+
echo " 🧹 pmcp: removed ${#dead_keys[@]} stale entr$([ ${#dead_keys[@]} -eq 1 ] && echo y || echo ies): ${dead_keys[*]}"
|
|
81
|
+
fi
|
|
82
|
+
echo " ➕ pmcp: registered $name → http://$PMCP_DOCKER_HOST_IP:$port"
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
# Run a command while holding an exclusive lock on $1. Uses flock(1) if available,
|
|
86
|
+
# else falls back to a mkdir-based mutex (portable across macOS where flock is
|
|
87
|
+
# not built-in). Times out after 5 seconds; on timeout, returns 99 without
|
|
88
|
+
# running the command. Returns the command's exit status otherwise.
|
|
89
|
+
# Args: $1 = lockfile path, $2... = command + args
|
|
90
|
+
pmcp::with_lock() {
|
|
91
|
+
local lockfile="$1"; shift
|
|
92
|
+
local timeout=5
|
|
93
|
+
|
|
94
|
+
if command -v flock >/dev/null 2>&1; then
|
|
95
|
+
(
|
|
96
|
+
flock -w "$timeout" 9 || exit 99
|
|
97
|
+
"$@"
|
|
98
|
+
) 9>"$lockfile"
|
|
99
|
+
return $?
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
# mkdir-based fallback. mkdir is atomic on POSIX filesystems.
|
|
103
|
+
local mutex="${lockfile}.d"
|
|
104
|
+
local waited=0
|
|
105
|
+
while ! mkdir "$mutex" 2>/dev/null; do
|
|
106
|
+
if (( waited >= timeout * 10 )); then
|
|
107
|
+
return 99
|
|
108
|
+
fi
|
|
109
|
+
sleep 0.1
|
|
110
|
+
waited=$((waited + 1))
|
|
111
|
+
done
|
|
112
|
+
trap "rmdir '$mutex' 2>/dev/null || true" EXIT
|
|
113
|
+
"$@"
|
|
114
|
+
local rc=$?
|
|
115
|
+
rmdir "$mutex" 2>/dev/null || true
|
|
116
|
+
trap - EXIT
|
|
117
|
+
return $rc
|
|
118
|
+
}
|
package/package.json
CHANGED
package/setup.sh
CHANGED
|
@@ -281,9 +281,8 @@ echo "📁 Legacy workspaces file: $WORKSPACES_FILE"
|
|
|
281
281
|
WORKSPACE="${WORKSPACES[0]}"
|
|
282
282
|
|
|
283
283
|
# Tool definitions
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
TOOL_DESCS="Open-source coding tool from opencode-ai,Claude Code CLI from Anthropic,OpenAI Codex terminal agent"
|
|
284
|
+
TOOL_OPTIONS="amp,opencode,openclaw,droid,claude,gemini,kilo,qwen,codex,qoder,auggie,codebuddy,jules,shai"
|
|
285
|
+
TOOL_DESCS="AI coding assistant from @sourcegraph/amp,Open-source coding tool from opencode-ai,OpenClaw AI gateway (Docker Compose),Factory CLI from factory.ai,Claude Code CLI from Anthropic,Google Gemini CLI (free tier),AI pair programmer (Git-native),Kilo Code (500+ models),Alibaba Qwen CLI (1M context),OpenAI Codex terminal agent,Qoder AI CLI assistant,Augment Auggie CLI,Tencent CodeBuddy CLI,Google Jules CLI,OVHcloud SHAI agent"
|
|
287
286
|
|
|
288
287
|
# Pre-select previously installed tools
|
|
289
288
|
PRESELECTED_TOOLS=""
|
|
@@ -304,44 +303,52 @@ echo "Installing tools: ${TOOLS[*]}"
|
|
|
304
303
|
|
|
305
304
|
CONTAINERIZED_TOOLS=()
|
|
306
305
|
for tool in "${TOOLS[@]}"; do
|
|
307
|
-
if [[ "$tool" =~ ^(opencode|claude|codex)$ ]]; then
|
|
306
|
+
if [[ "$tool" =~ ^(amp|opencode|openclaw|claude|aider|droid|gemini|kilo|qwen|codex|qoder|auggie|codebuddy|jules|shai)$ ]]; then
|
|
308
307
|
CONTAINERIZED_TOOLS+=("$tool")
|
|
309
308
|
fi
|
|
310
309
|
done
|
|
311
310
|
|
|
312
311
|
echo ""
|
|
313
312
|
if [[ ${#CONTAINERIZED_TOOLS[@]} -gt 0 ]]; then
|
|
314
|
-
#
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
# # Category 1: AI Enhancement Tools (spec-driven development, UI/UX, browser automation)
|
|
318
|
-
# AI_TOOL_OPTIONS="spec-kit,ux-ui-promax,openspec,playwright,rtk"
|
|
319
|
-
# AI_TOOL_DESCS="Spec-driven development toolkit,UI/UX design intelligence tool,OpenSpec - spec-driven development,Browser automation + Chromium/Firefox/WebKit (~500MB),RTK token optimizer - reduces LLM token usage by 60-90% (~5MB)"
|
|
320
|
-
# multi_select "Select AI Enhancement Tools (installed in containers)" "$AI_TOOL_OPTIONS" "$AI_TOOL_DESCS"
|
|
321
|
-
# AI_ENHANCEMENT_TOOLS=("${SELECTED_ITEMS[@]}")
|
|
322
|
-
# if [[ ${#AI_ENHANCEMENT_TOOLS[@]} -gt 0 ]]; then
|
|
323
|
-
# echo "AI tools selected: ${AI_ENHANCEMENT_TOOLS[*]}"
|
|
324
|
-
# fi
|
|
325
|
-
|
|
326
|
-
# # Category 2: Language Runtimes (Ruby, etc.)
|
|
327
|
-
# LANG_OPTIONS="ruby"
|
|
328
|
-
# LANG_DESCS="Ruby 3.3.0 + Rails 8.0.2 via rbenv (~500MB)"
|
|
329
|
-
# multi_select "Select Additional Language Runtimes (installed in containers)" "$LANG_OPTIONS" "$LANG_DESCS"
|
|
330
|
-
# LANGUAGE_RUNTIMES=("${SELECTED_ITEMS[@]}")
|
|
331
|
-
# if [[ ${#LANGUAGE_RUNTIMES[@]} -gt 0 ]]; then
|
|
332
|
-
# echo "Language runtimes selected: ${LANGUAGE_RUNTIMES[*]}"
|
|
333
|
-
# fi
|
|
334
|
-
|
|
335
|
-
# # Category 3: MCP Tools (Browser automation for AI agents)
|
|
336
|
-
# MCP_OPTIONS="chrome-devtools-mcp,playwright-mcp"
|
|
337
|
-
# MCP_DESCS="Google Chrome DevTools MCP - performance profiling + debugging (~400MB),Microsoft Playwright MCP - multi-browser automation (~300MB)"
|
|
338
|
-
# multi_select "Select MCP Tools for AI Agent Browser Automation" "$MCP_OPTIONS" "$MCP_DESCS"
|
|
339
|
-
# MCP_TOOLS=("${SELECTED_ITEMS[@]}")
|
|
340
|
-
# if [[ ${#MCP_TOOLS[@]} -gt 0 ]]; then
|
|
341
|
-
# echo "MCP tools selected: ${MCP_TOOLS[*]}"
|
|
342
|
-
# fi
|
|
313
|
+
# Category 1: AI Enhancement Tools (spec-driven development, UI/UX, browser automation)
|
|
314
|
+
AI_TOOL_OPTIONS="spec-kit,ux-ui-promax,openspec,playwright,rtk"
|
|
315
|
+
AI_TOOL_DESCS="Spec-driven development toolkit,UI/UX design intelligence tool,OpenSpec - spec-driven development,Browser automation + Chromium/Firefox/WebKit (~500MB),RTK token optimizer - reduces LLM token usage by 60-90% (~5MB)"
|
|
343
316
|
|
|
344
|
-
|
|
317
|
+
multi_select "Select AI Enhancement Tools (installed in containers)" "$AI_TOOL_OPTIONS" "$AI_TOOL_DESCS"
|
|
318
|
+
AI_ENHANCEMENT_TOOLS=("${SELECTED_ITEMS[@]}")
|
|
319
|
+
|
|
320
|
+
if [[ ${#AI_ENHANCEMENT_TOOLS[@]} -gt 0 ]]; then
|
|
321
|
+
echo "AI tools selected: ${AI_ENHANCEMENT_TOOLS[*]}"
|
|
322
|
+
fi
|
|
323
|
+
|
|
324
|
+
echo ""
|
|
325
|
+
|
|
326
|
+
# Category 2: Language Runtimes (Ruby, etc.)
|
|
327
|
+
LANG_OPTIONS="ruby"
|
|
328
|
+
LANG_DESCS="Ruby 3.3.0 + Rails 8.0.2 via rbenv (~500MB)"
|
|
329
|
+
|
|
330
|
+
multi_select "Select Additional Language Runtimes (installed in containers)" "$LANG_OPTIONS" "$LANG_DESCS"
|
|
331
|
+
LANGUAGE_RUNTIMES=("${SELECTED_ITEMS[@]}")
|
|
332
|
+
|
|
333
|
+
if [[ ${#LANGUAGE_RUNTIMES[@]} -gt 0 ]]; then
|
|
334
|
+
echo "Language runtimes selected: ${LANGUAGE_RUNTIMES[*]}"
|
|
335
|
+
fi
|
|
336
|
+
|
|
337
|
+
echo ""
|
|
338
|
+
|
|
339
|
+
# Category 3: MCP Tools (Browser automation for AI agents)
|
|
340
|
+
MCP_OPTIONS="chrome-devtools-mcp,playwright-mcp"
|
|
341
|
+
MCP_DESCS="Google Chrome DevTools MCP - performance profiling + debugging (~400MB),Microsoft Playwright MCP - multi-browser automation (~300MB)"
|
|
342
|
+
|
|
343
|
+
multi_select "Select MCP Tools for AI Agent Browser Automation" "$MCP_OPTIONS" "$MCP_DESCS"
|
|
344
|
+
MCP_TOOLS=("${SELECTED_ITEMS[@]}")
|
|
345
|
+
|
|
346
|
+
if [[ ${#MCP_TOOLS[@]} -gt 0 ]]; then
|
|
347
|
+
echo "MCP tools selected: ${MCP_TOOLS[*]}"
|
|
348
|
+
fi
|
|
349
|
+
|
|
350
|
+
# Combine all categories for processing
|
|
351
|
+
ADDITIONAL_TOOLS=("${AI_ENHANCEMENT_TOOLS[@]}" "${LANGUAGE_RUNTIMES[@]}" "${MCP_TOOLS[@]}")
|
|
345
352
|
else
|
|
346
353
|
ADDITIONAL_TOOLS=()
|
|
347
354
|
echo "ℹ️ No containerized AI tools selected. Skipping additional tools."
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: rtk
|
|
3
|
-
description: "Token optimizer for AI coding agents. Wraps common CLI commands with rtk to reduce LLM token consumption by 60-90%."
|
|
4
|
-
compatibility: "OpenCode with RTK binary installed"
|
|
5
|
-
metadata:
|
|
6
|
-
author: Sisyphus
|
|
7
|
-
version: "1.0.0"
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# RTK — Rust Token Killer
|
|
11
|
-
|
|
12
|
-
**Purpose**: Reduce token consumption by 60-90% on shell commands. RTK filters and compresses command output before it reaches your context.
|
|
13
|
-
|
|
14
|
-
## When This Skill Activates
|
|
15
|
-
|
|
16
|
-
This skill is loaded automatically. Once active, **always** prefix supported commands with `rtk`.
|
|
17
|
-
|
|
18
|
-
## Command Mappings (MANDATORY)
|
|
19
|
-
|
|
20
|
-
When running shell commands via Bash tool, use `rtk` prefix for these commands:
|
|
21
|
-
|
|
22
|
-
| Instead of | Use | Savings |
|
|
23
|
-
|-----------|-----|---------|
|
|
24
|
-
| `git status` | `rtk git status` | ~80% |
|
|
25
|
-
| `git diff` | `rtk git diff` | ~75% |
|
|
26
|
-
| `git log` | `rtk git log` | ~80% |
|
|
27
|
-
| `git add/commit/push/pull` | `rtk git add/commit/push/pull` | ~90% |
|
|
28
|
-
| `ls` / `ls -la` | `rtk ls` | ~80% |
|
|
29
|
-
| `cat file` | `rtk read file` | ~70% |
|
|
30
|
-
| `grep pattern .` | `rtk grep pattern .` | ~80% |
|
|
31
|
-
| `rg pattern` | `rtk grep pattern .` | ~80% |
|
|
32
|
-
| `npm test` / `cargo test` / `pytest` | `rtk test <cmd>` | ~90% |
|
|
33
|
-
| `npm run build` / `cargo build` | `rtk err <cmd>` | ~80% |
|
|
34
|
-
| `gh pr list/view` | `rtk gh pr list/view` | ~70% |
|
|
35
|
-
| `docker ps` | `rtk docker ps` | ~80% |
|
|
36
|
-
| `eslint` / `tsc` | `rtk lint` / `rtk tsc` | ~80% |
|
|
37
|
-
|
|
38
|
-
## Searching Inside `node_modules` / Ignored Directories
|
|
39
|
-
|
|
40
|
-
By default, `rtk grep` respects `.gitignore` rules — meaning `node_modules`, `.nuxt`, `dist`, etc. are **excluded**. This is the right behavior 99% of the time.
|
|
41
|
-
|
|
42
|
-
When you **need** to search inside ignored directories (debugging a library, checking an API signature, tracing a dependency bug):
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
# Search all files including node_modules (--no-ignore bypasses .gitignore)
|
|
46
|
-
rtk grep "defineStore" . --no-ignore
|
|
47
|
-
|
|
48
|
-
# Search a specific package only (combine --no-ignore with --glob)
|
|
49
|
-
rtk grep "defineStore" . --no-ignore --glob 'node_modules/pinia/**'
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
**What does NOT work:**
|
|
53
|
-
- `rtk grep "pattern" node_modules/pinia/` — still excluded even with direct path
|
|
54
|
-
- `rtk grep "pattern" . --glob 'node_modules/**'` — glob alone doesn't override .gitignore
|
|
55
|
-
|
|
56
|
-
**Key flag: `--no-ignore`** — this is the ONLY way to search ignored directories with rtk grep.
|
|
57
|
-
|
|
58
|
-
### Other useful `rtk grep` flags
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
rtk grep "pattern" . -t ts # Filter by file type (ts, py, rust, etc.)
|
|
62
|
-
rtk grep "pattern" . -m 100 # Increase max results (default: 50)
|
|
63
|
-
rtk grep "pattern" . -u # Ultra-compact mode (even fewer tokens)
|
|
64
|
-
rtk grep "pattern" . -l 120 # Max line length before truncation (default: 80)
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
## Commands to NOT Wrap
|
|
68
|
-
|
|
69
|
-
Do NOT prefix these with `rtk` (unsupported or counterproductive):
|
|
70
|
-
|
|
71
|
-
- `npx`, `npm install`, `pip install` (package managers)
|
|
72
|
-
- `node`, `python3`, `ruby` (interpreters)
|
|
73
|
-
- `nano-brain`, `openspec`, `opencode` (custom tools)
|
|
74
|
-
- Heredocs (`<<EOF`)
|
|
75
|
-
- Piped commands (`cmd1 | cmd2`) — wrap only the first command if applicable
|
|
76
|
-
- Commands already prefixed with `rtk`
|
|
77
|
-
|
|
78
|
-
## How RTK Works
|
|
79
|
-
|
|
80
|
-
```
|
|
81
|
-
Without RTK: git status → 50 lines raw output → 2,000 tokens
|
|
82
|
-
With RTK: rtk git status → "3 modified, 1 untracked ✓" → 200 tokens
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
RTK runs the real command, then filters/compresses the output. The agent sees a compact summary instead of verbose raw output.
|
|
86
|
-
|
|
87
|
-
## Detection
|
|
88
|
-
|
|
89
|
-
Before using RTK commands, verify it's installed:
|
|
90
|
-
```bash
|
|
91
|
-
rtk --version
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
If `rtk` is not found, skip this skill — run commands normally without the `rtk` prefix.
|
|
95
|
-
|
|
96
|
-
## Token Savings Reference
|
|
97
|
-
|
|
98
|
-
Typical 30-min coding session:
|
|
99
|
-
- Without RTK: ~150,000 tokens
|
|
100
|
-
- With RTK: ~45,000 tokens
|
|
101
|
-
- **Savings: ~70%**
|
|
102
|
-
|
|
103
|
-
Biggest wins: test output (`rtk test` — 90%), git operations (`rtk git` — 80%), file reading (`rtk read` — 70%).
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: rtk-setup
|
|
3
|
-
description: "One-time setup + ongoing enforcement of RTK (Rust Token Killer) across sessions and subagents. Persists RTK instructions to AGENTS.md and propagates to delegated tasks."
|
|
4
|
-
compatibility: "OpenCode with RTK binary installed"
|
|
5
|
-
metadata:
|
|
6
|
-
author: Sisyphus
|
|
7
|
-
version: "1.0.0"
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# RTK Setup — Persistent RTK Enforcement
|
|
11
|
-
|
|
12
|
-
This skill performs **setup** (persist RTK instructions) and **ongoing enforcement** (use rtk, propagate to subagents).
|
|
13
|
-
|
|
14
|
-
## Phase 1: Detection (ALWAYS run first)
|
|
15
|
-
|
|
16
|
-
Run these checks before anything else:
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
rtk --version
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
- If `rtk` is NOT found → **STOP**. Tell the user: "RTK is not installed. Install it first: `cargo install --git https://github.com/rtk-ai/rtk --locked`". Do NOT proceed with setup.
|
|
23
|
-
- If `rtk` IS found → continue.
|
|
24
|
-
|
|
25
|
-
### Check oh-my-opencode
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
ls ~/.config/opencode/oh-my-opencode.json 2>/dev/null
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
- If found → omo is installed. Note this for Phase 2.
|
|
32
|
-
- If not found → skip omo-specific steps.
|
|
33
|
-
|
|
34
|
-
## Phase 2: Setup (persist to AGENTS.md)
|
|
35
|
-
|
|
36
|
-
Check BOTH of these files for the RTK managed block:
|
|
37
|
-
|
|
38
|
-
1. **User-level**: `~/.config/opencode/AGENTS.md`
|
|
39
|
-
2. **Project-level**: `./AGENTS.md` (current workspace)
|
|
40
|
-
|
|
41
|
-
For EACH file, check if `<!-- RTK:START -->` exists. If it does NOT exist, **append** the following managed block to the file (create the file if it doesn't exist). NEVER replace existing content — only append.
|
|
42
|
-
|
|
43
|
-
```markdown
|
|
44
|
-
<!-- RTK:START -->
|
|
45
|
-
<!-- Managed block - do not edit manually. Updated by: rtk-setup skill -->
|
|
46
|
-
|
|
47
|
-
## RTK Token Optimizer
|
|
48
|
-
|
|
49
|
-
This project uses **RTK** (Rust Token Killer) to reduce LLM token consumption by 60-90%.
|
|
50
|
-
|
|
51
|
-
### Rules for ALL agents (including subagents)
|
|
52
|
-
|
|
53
|
-
**ALWAYS** prefix these commands with `rtk`:
|
|
54
|
-
|
|
55
|
-
| Command | Use instead |
|
|
56
|
-
|---------|-------------|
|
|
57
|
-
| `git status/diff/log/add/commit/push/pull` | `rtk git ...` |
|
|
58
|
-
| `ls`, `ls -la` | `rtk ls` |
|
|
59
|
-
| `cat file` | `rtk read file` |
|
|
60
|
-
| `grep pattern .` / `rg pattern` | `rtk grep pattern .` |
|
|
61
|
-
| `npm test` / `cargo test` / `pytest` | `rtk test <cmd>` |
|
|
62
|
-
| `npm run build` / `cargo build` | `rtk err <cmd>` |
|
|
63
|
-
| `gh pr list/view` | `rtk gh pr list/view` |
|
|
64
|
-
| `docker ps` | `rtk docker ps` |
|
|
65
|
-
| `eslint` / `tsc` | `rtk lint` / `rtk tsc` |
|
|
66
|
-
|
|
67
|
-
**Do NOT** prefix: `npx`, `npm install`, `pip install`, `node`, `python3`, heredocs, piped commands.
|
|
68
|
-
|
|
69
|
-
<!-- RTK:END -->
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
### If oh-my-opencode is installed
|
|
73
|
-
|
|
74
|
-
After updating AGENTS.md files, check if the omo config at `~/.config/opencode/oh-my-opencode.json` has `prompt_append` fields on agents. If it does, inform the user:
|
|
75
|
-
|
|
76
|
-
> "omo is installed. For maximum coverage, you can add RTK instructions to agent `prompt_append` fields in `oh-my-opencode.json`. This ensures subagents always use rtk even when AGENTS.md is not loaded. Want me to do this?"
|
|
77
|
-
|
|
78
|
-
**Only modify `oh-my-opencode.json` if the user explicitly confirms.** If they confirm, append this line to the `prompt_append` of `sisyphus-junior` agent (the primary coder):
|
|
79
|
-
|
|
80
|
-
```
|
|
81
|
-
\n\nRTK: ALWAYS prefix shell commands with `rtk` when available (git, ls, grep, test, build). Example: `rtk git status` not `git status`.
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
Do NOT modify other agents' prompt_append unless asked.
|
|
85
|
-
|
|
86
|
-
## Phase 3: Ongoing Enforcement (EVERY time this skill is loaded)
|
|
87
|
-
|
|
88
|
-
### For the current agent
|
|
89
|
-
|
|
90
|
-
From this point forward in this session, **you MUST**:
|
|
91
|
-
|
|
92
|
-
1. **Use `rtk` prefix** for all supported shell commands (see table above)
|
|
93
|
-
2. **Verify rtk is available** before first use: `rtk --version`
|
|
94
|
-
3. If rtk is not available in the current environment, fall back to normal commands silently
|
|
95
|
-
|
|
96
|
-
### For subagent delegation
|
|
97
|
-
|
|
98
|
-
When delegating ANY task that involves shell commands (via `task()`, `delegate_task()`, or any delegation mechanism), **ALWAYS** add this to the `MUST DO` section of the delegation prompt:
|
|
99
|
-
|
|
100
|
-
```
|
|
101
|
-
- Use `rtk` prefix for shell commands when available (git, ls, grep, test, build). Run `rtk --version` first to check. If not installed, use normal commands. Examples: `rtk git status`, `rtk ls`, `rtk grep pattern .`, `rtk test npm test`.
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
This is NON-NEGOTIABLE. Subagents do not read AGENTS.md, so RTK instructions MUST be passed explicitly in every delegation prompt.
|
|
105
|
-
|
|
106
|
-
### Quick reference for subagent prompts
|
|
107
|
-
|
|
108
|
-
Copy-paste this one-liner into MUST DO sections:
|
|
109
|
-
|
|
110
|
-
> Use `rtk` prefix for all shell commands (git, ls, grep, test, build, docker). Example: `rtk git status` not `git status`. If `rtk` is not found, use normal commands.
|
|
111
|
-
|
|
112
|
-
## Summary
|
|
113
|
-
|
|
114
|
-
| Phase | When | What |
|
|
115
|
-
|-------|------|------|
|
|
116
|
-
| Detection | Always first | Check rtk installed, check omo |
|
|
117
|
-
| Setup | Once (idempotent) | Append RTK block to AGENTS.md (user + project) |
|
|
118
|
-
| Enforcement | Every session | Use rtk yourself, propagate to all subagents |
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: rtk
|
|
3
|
-
description: "Token optimizer for AI coding agents. Wraps common CLI commands with rtk to reduce LLM token consumption by 60-90%."
|
|
4
|
-
compatibility: "OpenCode with RTK binary installed"
|
|
5
|
-
metadata:
|
|
6
|
-
author: Sisyphus
|
|
7
|
-
version: "1.0.0"
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# RTK — Rust Token Killer
|
|
11
|
-
|
|
12
|
-
**Purpose**: Reduce token consumption by 60-90% on shell commands. RTK filters and compresses command output before it reaches your context.
|
|
13
|
-
|
|
14
|
-
## When This Skill Activates
|
|
15
|
-
|
|
16
|
-
This skill is loaded automatically. Once active, **always** prefix supported commands with `rtk`.
|
|
17
|
-
|
|
18
|
-
## Command Mappings (MANDATORY)
|
|
19
|
-
|
|
20
|
-
When running shell commands via Bash tool, use `rtk` prefix for these commands:
|
|
21
|
-
|
|
22
|
-
| Instead of | Use | Savings |
|
|
23
|
-
|-----------|-----|---------|
|
|
24
|
-
| `git status` | `rtk git status` | ~80% |
|
|
25
|
-
| `git diff` | `rtk git diff` | ~75% |
|
|
26
|
-
| `git log` | `rtk git log` | ~80% |
|
|
27
|
-
| `git add/commit/push/pull` | `rtk git add/commit/push/pull` | ~90% |
|
|
28
|
-
| `ls` / `ls -la` | `rtk ls` | ~80% |
|
|
29
|
-
| `cat file` | `rtk read file` | ~70% |
|
|
30
|
-
| `grep pattern .` | `rtk grep pattern .` | ~80% |
|
|
31
|
-
| `rg pattern` | `rtk grep pattern .` | ~80% |
|
|
32
|
-
| `npm test` / `cargo test` / `pytest` | `rtk test <cmd>` | ~90% |
|
|
33
|
-
| `npm run build` / `cargo build` | `rtk err <cmd>` | ~80% |
|
|
34
|
-
| `gh pr list/view` | `rtk gh pr list/view` | ~70% |
|
|
35
|
-
| `docker ps` | `rtk docker ps` | ~80% |
|
|
36
|
-
| `eslint` / `tsc` | `rtk lint` / `rtk tsc` | ~80% |
|
|
37
|
-
|
|
38
|
-
## Searching Inside `node_modules` / Ignored Directories
|
|
39
|
-
|
|
40
|
-
By default, `rtk grep` respects `.gitignore` rules — meaning `node_modules`, `.nuxt`, `dist`, etc. are **excluded**. This is the right behavior 99% of the time.
|
|
41
|
-
|
|
42
|
-
When you **need** to search inside ignored directories (debugging a library, checking an API signature, tracing a dependency bug):
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
# Search all files including node_modules (--no-ignore bypasses .gitignore)
|
|
46
|
-
rtk grep "defineStore" . --no-ignore
|
|
47
|
-
|
|
48
|
-
# Search a specific package only (combine --no-ignore with --glob)
|
|
49
|
-
rtk grep "defineStore" . --no-ignore --glob 'node_modules/pinia/**'
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
**What does NOT work:**
|
|
53
|
-
- `rtk grep "pattern" node_modules/pinia/` — still excluded even with direct path
|
|
54
|
-
- `rtk grep "pattern" . --glob 'node_modules/**'` — glob alone doesn't override .gitignore
|
|
55
|
-
|
|
56
|
-
**Key flag: `--no-ignore`** — this is the ONLY way to search ignored directories with rtk grep.
|
|
57
|
-
|
|
58
|
-
### Other useful `rtk grep` flags
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
rtk grep "pattern" . -t ts # Filter by file type (ts, py, rust, etc.)
|
|
62
|
-
rtk grep "pattern" . -m 100 # Increase max results (default: 50)
|
|
63
|
-
rtk grep "pattern" . -u # Ultra-compact mode (even fewer tokens)
|
|
64
|
-
rtk grep "pattern" . -l 120 # Max line length before truncation (default: 80)
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
## Commands to NOT Wrap
|
|
68
|
-
|
|
69
|
-
Do NOT prefix these with `rtk` (unsupported or counterproductive):
|
|
70
|
-
|
|
71
|
-
- `npx`, `npm install`, `pip install` (package managers)
|
|
72
|
-
- `node`, `python3`, `ruby` (interpreters)
|
|
73
|
-
- `nano-brain`, `openspec`, `opencode` (custom tools)
|
|
74
|
-
- Heredocs (`<<EOF`)
|
|
75
|
-
- Piped commands (`cmd1 | cmd2`) — wrap only the first command if applicable
|
|
76
|
-
- Commands already prefixed with `rtk`
|
|
77
|
-
|
|
78
|
-
## How RTK Works
|
|
79
|
-
|
|
80
|
-
```
|
|
81
|
-
Without RTK: git status → 50 lines raw output → 2,000 tokens
|
|
82
|
-
With RTK: rtk git status → "3 modified, 1 untracked ✓" → 200 tokens
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
RTK runs the real command, then filters/compresses the output. The agent sees a compact summary instead of verbose raw output.
|
|
86
|
-
|
|
87
|
-
## Detection
|
|
88
|
-
|
|
89
|
-
Before using RTK commands, verify it's installed:
|
|
90
|
-
```bash
|
|
91
|
-
rtk --version
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
If `rtk` is not found, skip this skill — run commands normally without the `rtk` prefix.
|
|
95
|
-
|
|
96
|
-
## Token Savings Reference
|
|
97
|
-
|
|
98
|
-
Typical 30-min coding session:
|
|
99
|
-
- Without RTK: ~150,000 tokens
|
|
100
|
-
- With RTK: ~45,000 tokens
|
|
101
|
-
- **Savings: ~70%**
|
|
102
|
-
|
|
103
|
-
Biggest wins: test output (`rtk test` — 90%), git operations (`rtk git` — 80%), file reading (`rtk read` — 70%).
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: rtk-setup
|
|
3
|
-
description: "One-time setup + ongoing enforcement of RTK (Rust Token Killer) across sessions and subagents. Persists RTK instructions to AGENTS.md and propagates to delegated tasks."
|
|
4
|
-
compatibility: "OpenCode with RTK binary installed"
|
|
5
|
-
metadata:
|
|
6
|
-
author: Sisyphus
|
|
7
|
-
version: "1.0.0"
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# RTK Setup — Persistent RTK Enforcement
|
|
11
|
-
|
|
12
|
-
This skill performs **setup** (persist RTK instructions) and **ongoing enforcement** (use rtk, propagate to subagents).
|
|
13
|
-
|
|
14
|
-
## Phase 1: Detection (ALWAYS run first)
|
|
15
|
-
|
|
16
|
-
Run these checks before anything else:
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
rtk --version
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
- If `rtk` is NOT found → **STOP**. Tell the user: "RTK is not installed. Install it first: `cargo install --git https://github.com/rtk-ai/rtk --locked`". Do NOT proceed with setup.
|
|
23
|
-
- If `rtk` IS found → continue.
|
|
24
|
-
|
|
25
|
-
### Check oh-my-opencode
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
ls ~/.config/opencode/oh-my-opencode.json 2>/dev/null
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
- If found → omo is installed. Note this for Phase 2.
|
|
32
|
-
- If not found → skip omo-specific steps.
|
|
33
|
-
|
|
34
|
-
## Phase 2: Setup (persist to AGENTS.md)
|
|
35
|
-
|
|
36
|
-
Check BOTH of these files for the RTK managed block:
|
|
37
|
-
|
|
38
|
-
1. **User-level**: `~/.config/opencode/AGENTS.md`
|
|
39
|
-
2. **Project-level**: `./AGENTS.md` (current workspace)
|
|
40
|
-
|
|
41
|
-
For EACH file, check if `<!-- RTK:START -->` exists. If it does NOT exist, **append** the following managed block to the file (create the file if it doesn't exist). NEVER replace existing content — only append.
|
|
42
|
-
|
|
43
|
-
```markdown
|
|
44
|
-
<!-- RTK:START -->
|
|
45
|
-
<!-- Managed block - do not edit manually. Updated by: rtk-setup skill -->
|
|
46
|
-
|
|
47
|
-
## RTK Token Optimizer
|
|
48
|
-
|
|
49
|
-
This project uses **RTK** (Rust Token Killer) to reduce LLM token consumption by 60-90%.
|
|
50
|
-
|
|
51
|
-
### Rules for ALL agents (including subagents)
|
|
52
|
-
|
|
53
|
-
**ALWAYS** prefix these commands with `rtk`:
|
|
54
|
-
|
|
55
|
-
| Command | Use instead |
|
|
56
|
-
|---------|-------------|
|
|
57
|
-
| `git status/diff/log/add/commit/push/pull` | `rtk git ...` |
|
|
58
|
-
| `ls`, `ls -la` | `rtk ls` |
|
|
59
|
-
| `cat file` | `rtk read file` |
|
|
60
|
-
| `grep pattern .` / `rg pattern` | `rtk grep pattern .` |
|
|
61
|
-
| `npm test` / `cargo test` / `pytest` | `rtk test <cmd>` |
|
|
62
|
-
| `npm run build` / `cargo build` | `rtk err <cmd>` |
|
|
63
|
-
| `gh pr list/view` | `rtk gh pr list/view` |
|
|
64
|
-
| `docker ps` | `rtk docker ps` |
|
|
65
|
-
| `eslint` / `tsc` | `rtk lint` / `rtk tsc` |
|
|
66
|
-
|
|
67
|
-
**Do NOT** prefix: `npx`, `npm install`, `pip install`, `node`, `python3`, heredocs, piped commands.
|
|
68
|
-
|
|
69
|
-
<!-- RTK:END -->
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
### If oh-my-opencode is installed
|
|
73
|
-
|
|
74
|
-
After updating AGENTS.md files, check if the omo config at `~/.config/opencode/oh-my-opencode.json` has `prompt_append` fields on agents. If it does, inform the user:
|
|
75
|
-
|
|
76
|
-
> "omo is installed. For maximum coverage, you can add RTK instructions to agent `prompt_append` fields in `oh-my-opencode.json`. This ensures subagents always use rtk even when AGENTS.md is not loaded. Want me to do this?"
|
|
77
|
-
|
|
78
|
-
**Only modify `oh-my-opencode.json` if the user explicitly confirms.** If they confirm, append this line to the `prompt_append` of `sisyphus-junior` agent (the primary coder):
|
|
79
|
-
|
|
80
|
-
```
|
|
81
|
-
\n\nRTK: ALWAYS prefix shell commands with `rtk` when available (git, ls, grep, test, build). Example: `rtk git status` not `git status`.
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
Do NOT modify other agents' prompt_append unless asked.
|
|
85
|
-
|
|
86
|
-
## Phase 3: Ongoing Enforcement (EVERY time this skill is loaded)
|
|
87
|
-
|
|
88
|
-
### For the current agent
|
|
89
|
-
|
|
90
|
-
From this point forward in this session, **you MUST**:
|
|
91
|
-
|
|
92
|
-
1. **Use `rtk` prefix** for all supported shell commands (see table above)
|
|
93
|
-
2. **Verify rtk is available** before first use: `rtk --version`
|
|
94
|
-
3. If rtk is not available in the current environment, fall back to normal commands silently
|
|
95
|
-
|
|
96
|
-
### For subagent delegation
|
|
97
|
-
|
|
98
|
-
When delegating ANY task that involves shell commands (via `task()`, `delegate_task()`, or any delegation mechanism), **ALWAYS** add this to the `MUST DO` section of the delegation prompt:
|
|
99
|
-
|
|
100
|
-
```
|
|
101
|
-
- Use `rtk` prefix for shell commands when available (git, ls, grep, test, build). Run `rtk --version` first to check. If not installed, use normal commands. Examples: `rtk git status`, `rtk ls`, `rtk grep pattern .`, `rtk test npm test`.
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
This is NON-NEGOTIABLE. Subagents do not read AGENTS.md, so RTK instructions MUST be passed explicitly in every delegation prompt.
|
|
105
|
-
|
|
106
|
-
### Quick reference for subagent prompts
|
|
107
|
-
|
|
108
|
-
Copy-paste this one-liner into MUST DO sections:
|
|
109
|
-
|
|
110
|
-
> Use `rtk` prefix for all shell commands (git, ls, grep, test, build, docker). Example: `rtk git status` not `git status`. If `rtk` is not found, use normal commands.
|
|
111
|
-
|
|
112
|
-
## Summary
|
|
113
|
-
|
|
114
|
-
| Phase | When | What |
|
|
115
|
-
|-------|------|------|
|
|
116
|
-
| Detection | Always first | Check rtk installed, check omo |
|
|
117
|
-
| Setup | Once (idempotent) | Append RTK block to AGENTS.md (user + project) |
|
|
118
|
-
| Enforcement | Every session | Use rtk yourself, propagate to all subagents |
|