@kokorolx/ai-sandbox-wrapper 1.0.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 +540 -0
- package/bin/ai-debug +116 -0
- package/bin/ai-network +144 -0
- package/bin/ai-run +631 -0
- package/bin/cli.js +83 -0
- package/bin/setup-ssh-config +328 -0
- package/dockerfiles/AGENTS.md +92 -0
- package/dockerfiles/aider/Dockerfile +5 -0
- package/dockerfiles/amp/Dockerfile +10 -0
- package/dockerfiles/auggie/Dockerfile +12 -0
- package/dockerfiles/base/Dockerfile +73 -0
- package/dockerfiles/claude/Dockerfile +11 -0
- package/dockerfiles/codebuddy/Dockerfile +12 -0
- package/dockerfiles/codex/Dockerfile +9 -0
- package/dockerfiles/droid/Dockerfile +8 -0
- package/dockerfiles/gemini/Dockerfile +9 -0
- package/dockerfiles/jules/Dockerfile +12 -0
- package/dockerfiles/kilo/Dockerfile +25 -0
- package/dockerfiles/opencode/Dockerfile +10 -0
- package/dockerfiles/qoder/Dockerfile +12 -0
- package/dockerfiles/qwen/Dockerfile +10 -0
- package/dockerfiles/shai/Dockerfile +9 -0
- package/lib/AGENTS.md +58 -0
- package/lib/generate-ai-run.sh +19 -0
- package/lib/install-aider.sh +30 -0
- package/lib/install-amp.sh +39 -0
- package/lib/install-auggie.sh +36 -0
- package/lib/install-base.sh +139 -0
- package/lib/install-claude.sh +42 -0
- package/lib/install-codebuddy.sh +36 -0
- package/lib/install-codeserver.sh +171 -0
- package/lib/install-codex.sh +40 -0
- package/lib/install-droid.sh +27 -0
- package/lib/install-gemini.sh +39 -0
- package/lib/install-jules.sh +36 -0
- package/lib/install-kilo.sh +57 -0
- package/lib/install-opencode.sh +39 -0
- package/lib/install-qoder.sh +37 -0
- package/lib/install-qwen.sh +40 -0
- package/lib/install-shai.sh +33 -0
- package/lib/install-tool.sh +40 -0
- package/lib/install-vscode.sh +219 -0
- package/lib/ssh-key-selector.sh +189 -0
- package/package.json +46 -0
- package/setup.sh +530 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# SSH Key Selector Library
|
|
3
|
+
# Provides interactive multi-select for SSH keys with search capability
|
|
4
|
+
|
|
5
|
+
# Multi-select SSH keys
|
|
6
|
+
# Usage: select_ssh_keys
|
|
7
|
+
# Returns: SELECTED_SSH_KEYS array
|
|
8
|
+
select_ssh_keys() {
|
|
9
|
+
local ssh_dir="$HOME/.ssh"
|
|
10
|
+
local title="🔑 Select SSH Keys to Allow"
|
|
11
|
+
|
|
12
|
+
# Analyze git remotes to recommend keys
|
|
13
|
+
local -a recommended_keys=()
|
|
14
|
+
if [ -f ".git/config" ]; then
|
|
15
|
+
# Extract SSH URLs from git config
|
|
16
|
+
local git_hosts
|
|
17
|
+
git_hosts=$(grep -E "url.*@" .git/config 2>/dev/null | sed -E 's/.*@([^:]+).*/\1/' | sort -u)
|
|
18
|
+
|
|
19
|
+
# Look for keys matching these hosts in SSH config
|
|
20
|
+
if [ -f "$ssh_dir/config" ]; then
|
|
21
|
+
for host in $git_hosts; do
|
|
22
|
+
# Find IdentityFile entries for this host
|
|
23
|
+
local keys
|
|
24
|
+
keys=$(awk -v host="$host" '
|
|
25
|
+
/^Host / { current_host=$2 }
|
|
26
|
+
current_host ~ host && /IdentityFile/ {
|
|
27
|
+
gsub(/^~\/\.ssh\//, "", $2)
|
|
28
|
+
print $2
|
|
29
|
+
}
|
|
30
|
+
' "$ssh_dir/config" 2>/dev/null)
|
|
31
|
+
|
|
32
|
+
for key in $keys; do
|
|
33
|
+
[[ -f "$ssh_dir/$key" ]] && recommended_keys+=("$key")
|
|
34
|
+
done
|
|
35
|
+
done
|
|
36
|
+
fi
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
# Find all private key files (including in subdirectories)
|
|
40
|
+
local -a key_files=()
|
|
41
|
+
local file_list
|
|
42
|
+
file_list=$(cd "$ssh_dir" && find . -type f ! -name "*.pub" ! -name "known_hosts*" ! -name "config" 2>/dev/null | sed 's|^\./||' | sort)
|
|
43
|
+
|
|
44
|
+
while IFS= read -r file; do
|
|
45
|
+
# Skip if it's a public key, known_hosts, config
|
|
46
|
+
[[ "$file" == *.pub ]] && continue
|
|
47
|
+
[[ "$file" == *"known_hosts"* ]] && continue
|
|
48
|
+
[[ "$file" == *"config"* ]] && continue
|
|
49
|
+
[[ "$file" == *"/"*.pub ]] && continue
|
|
50
|
+
[[ -z "$file" ]] && continue
|
|
51
|
+
key_files+=("$file")
|
|
52
|
+
done <<< "$file_list"
|
|
53
|
+
|
|
54
|
+
if [ ${#key_files[@]} -eq 0 ]; then
|
|
55
|
+
echo "No SSH keys found in $ssh_dir"
|
|
56
|
+
SELECTED_SSH_KEYS=()
|
|
57
|
+
return 1
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
# Sort: recommended keys first, then alphabetically
|
|
61
|
+
local -a sorted_keys=()
|
|
62
|
+
local -a is_recommended=()
|
|
63
|
+
|
|
64
|
+
# Add recommended keys first
|
|
65
|
+
for key in "${recommended_keys[@]}"; do
|
|
66
|
+
for i in "${!key_files[@]}"; do
|
|
67
|
+
if [[ "${key_files[$i]}" == "$key" ]]; then
|
|
68
|
+
sorted_keys+=("${key_files[$i]}")
|
|
69
|
+
is_recommended+=(1)
|
|
70
|
+
unset 'key_files[i]'
|
|
71
|
+
break
|
|
72
|
+
fi
|
|
73
|
+
done
|
|
74
|
+
done
|
|
75
|
+
|
|
76
|
+
# Add remaining keys
|
|
77
|
+
for key in "${key_files[@]}"; do
|
|
78
|
+
[[ -n "$key" ]] && sorted_keys+=("$key") && is_recommended+=(0)
|
|
79
|
+
done
|
|
80
|
+
|
|
81
|
+
key_files=("${sorted_keys[@]}")
|
|
82
|
+
|
|
83
|
+
# Interactive multi-select
|
|
84
|
+
local cursor=0
|
|
85
|
+
local -a selected=()
|
|
86
|
+
|
|
87
|
+
# Initialize selected array to match key_files length
|
|
88
|
+
for ((i=0; i<${#key_files[@]}; i++)); do
|
|
89
|
+
selected[$i]=0
|
|
90
|
+
done
|
|
91
|
+
|
|
92
|
+
tput civis # Hide cursor
|
|
93
|
+
|
|
94
|
+
while true; do
|
|
95
|
+
clear
|
|
96
|
+
echo "$title"
|
|
97
|
+
echo "Found ${#key_files[@]} keys (${#recommended_keys[@]} recommended for this repo)"
|
|
98
|
+
echo "Use ARROWS to move, SPACE to toggle, ENTER to confirm"
|
|
99
|
+
echo "Press / to search, A to select all recommended"
|
|
100
|
+
echo ""
|
|
101
|
+
|
|
102
|
+
for i in "${!key_files[@]}"; do
|
|
103
|
+
local prefix=" "
|
|
104
|
+
if [ "$i" -eq "$cursor" ]; then
|
|
105
|
+
prefix="➔ "
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
local checkbox="[ ]"
|
|
109
|
+
if [ "${selected[$i]}" -eq 1 ]; then
|
|
110
|
+
checkbox="[x]"
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
local marker=""
|
|
114
|
+
if [ "${is_recommended[$i]}" -eq 1 ]; then
|
|
115
|
+
marker="⭐ "
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
echo "$prefix$checkbox $marker${key_files[$i]}"
|
|
119
|
+
done
|
|
120
|
+
|
|
121
|
+
# Read single key
|
|
122
|
+
IFS= read -rsn1 key
|
|
123
|
+
|
|
124
|
+
# Handle escape sequences (arrow keys)
|
|
125
|
+
if [[ "$key" == $'\x1b' ]]; then
|
|
126
|
+
read -rsn1 -t 1 next1
|
|
127
|
+
read -rsn1 -t 1 next2
|
|
128
|
+
case "$next1$next2" in
|
|
129
|
+
'[A') # Up arrow
|
|
130
|
+
((cursor--))
|
|
131
|
+
;;
|
|
132
|
+
'[B') # Down arrow
|
|
133
|
+
((cursor++))
|
|
134
|
+
;;
|
|
135
|
+
esac
|
|
136
|
+
# Handle regular keys
|
|
137
|
+
else
|
|
138
|
+
case "$key" in
|
|
139
|
+
' ') # Space - toggle selection
|
|
140
|
+
if [ "${selected[$cursor]}" -eq 0 ]; then
|
|
141
|
+
selected[$cursor]=1
|
|
142
|
+
else
|
|
143
|
+
selected[$cursor]=0
|
|
144
|
+
fi
|
|
145
|
+
;;
|
|
146
|
+
'') # Enter - confirm
|
|
147
|
+
break
|
|
148
|
+
;;
|
|
149
|
+
'A'|'a') # Select all recommended
|
|
150
|
+
for i in "${!key_files[@]}"; do
|
|
151
|
+
if [ "${is_recommended[$i]}" -eq 1 ]; then
|
|
152
|
+
selected[$i]=1
|
|
153
|
+
fi
|
|
154
|
+
done
|
|
155
|
+
;;
|
|
156
|
+
'/') # Search (case-insensitive)
|
|
157
|
+
tput cnorm
|
|
158
|
+
echo ""
|
|
159
|
+
read -p "Search (case-insensitive): " search_term
|
|
160
|
+
tput civis
|
|
161
|
+
# Find first match
|
|
162
|
+
for i in "${!key_files[@]}"; do
|
|
163
|
+
if [[ "${key_files[$i],,}" == *"${search_term,,}"* ]]; then
|
|
164
|
+
cursor=$i
|
|
165
|
+
break
|
|
166
|
+
fi
|
|
167
|
+
done
|
|
168
|
+
;;
|
|
169
|
+
esac
|
|
170
|
+
fi
|
|
171
|
+
|
|
172
|
+
# Keep cursor in bounds
|
|
173
|
+
if [ "$cursor" -lt 0 ]; then cursor=$((${#key_files[@]} - 1)); fi
|
|
174
|
+
if [ "$cursor" -ge "${#key_files[@]}" ]; then cursor=0; fi
|
|
175
|
+
done
|
|
176
|
+
|
|
177
|
+
tput cnorm # Show cursor
|
|
178
|
+
clear
|
|
179
|
+
|
|
180
|
+
# Prepare result
|
|
181
|
+
SELECTED_SSH_KEYS=()
|
|
182
|
+
for i in "${!key_files[@]}"; do
|
|
183
|
+
if [ "${selected[$i]}" -eq 1 ]; then
|
|
184
|
+
SELECTED_SSH_KEYS+=("${key_files[$i]}")
|
|
185
|
+
fi
|
|
186
|
+
done
|
|
187
|
+
|
|
188
|
+
return 0
|
|
189
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kokorolx/ai-sandbox-wrapper",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Docker-based security sandbox for AI coding agents. Isolate Claude, Gemini, Aider, and other AI tools from your host system.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ai",
|
|
7
|
+
"sandbox",
|
|
8
|
+
"docker",
|
|
9
|
+
"security",
|
|
10
|
+
"claude",
|
|
11
|
+
"gemini",
|
|
12
|
+
"aider",
|
|
13
|
+
"opencode",
|
|
14
|
+
"coding-assistant"
|
|
15
|
+
],
|
|
16
|
+
"homepage": "https://github.com/kokorolx/ai-sandbox-wrapper",
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/kokorolx/ai-sandbox-wrapper/issues"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/kokorolx/ai-sandbox-wrapper.git"
|
|
23
|
+
},
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"author": "kokorolx",
|
|
26
|
+
"bin": {
|
|
27
|
+
"ai-sandbox-wrapper": "./bin/cli.js"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"bin/",
|
|
31
|
+
"lib/",
|
|
32
|
+
"dockerfiles/",
|
|
33
|
+
"setup.sh",
|
|
34
|
+
"README.md",
|
|
35
|
+
"LICENSE"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"test": "node bin/cli.js help && bash -n setup.sh && echo '✅ All tests passed'",
|
|
39
|
+
"lint": "bash -n setup.sh && bash -n lib/*.sh && echo '✅ Shell scripts valid'",
|
|
40
|
+
"lint:js": "node --check bin/cli.js && echo '✅ JavaScript valid'",
|
|
41
|
+
"prepublishOnly": "npm run lint && npm run lint:js && npm run test"
|
|
42
|
+
},
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=18"
|
|
45
|
+
}
|
|
46
|
+
}
|