Skip to content

Commit d53212e

Browse files
committed
Centralize logic
1 parent 685007e commit d53212e

5 files changed

Lines changed: 93 additions & 223 deletions

File tree

dot_files/ai-dev/Justfile

Lines changed: 19 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
# AI Development Environment (Sandboxed Podman Container)
2-
# Uses entrypoint-based UID/GID mapping for correct permissions
2+
# Uses scripts/ for shared logic between local dev and system install
33

44
local_image := "localhost/ai-dev"
55
remote_image := "ghcr.io/binarypie-dev/ai-dev:latest"
66

7-
# Common podman run flags (UID 0 inside = host user in rootless podman)
8-
podman_flags := "--rm -it --init --user 0:0 --security-opt label=disable"
9-
107
# Default recipe - show help
118
default:
129
@just --list
@@ -37,145 +34,44 @@ push:
3734
podman push {{remote_image}}
3835

3936
# =============================================================================
40-
# Usage
37+
# Usage (local image)
4138
# =============================================================================
4239

4340
# Run Claude Code in the current directory
4441
claude *args:
45-
#!/usr/bin/bash
46-
set -euo pipefail
47-
mkdir -p "$HOME/.claude"
48-
touch "$HOME/.claude.json"
49-
exec podman run {{podman_flags}} \
50-
-e HOME="$HOME" \
51-
-v "$(pwd):$(pwd):rw" \
52-
-v "$HOME/.claude:$HOME/.claude:rw" \
53-
-v "$HOME/.claude.json:$HOME/.claude.json:rw" \
54-
-w "$(pwd)" \
55-
{{local_image}} \
56-
claude {{args}}
42+
AI_DEV_IMAGE={{local_image}} ./scripts/claude.sh {{args}}
5743

5844
# Run Gemini CLI in the current directory
5945
gemini *args:
60-
#!/usr/bin/bash
61-
set -euo pipefail
62-
mkdir -p "$HOME/.gemini"
63-
env_flags=""
64-
for var in $(env | grep -E '^(GOOGLE_|GEMINI_)' | cut -d= -f1); do
65-
env_flags="$env_flags -e $var"
66-
done
67-
exec podman run {{podman_flags}} \
68-
-e HOME="$HOME" \
69-
$env_flags \
70-
-v "$(pwd):$(pwd):rw" \
71-
-v "$HOME/.gemini:$HOME/.gemini:rw" \
72-
-w "$(pwd)" \
73-
{{local_image}} \
74-
gemini {{args}}
46+
AI_DEV_IMAGE={{local_image}} ./scripts/gemini.sh {{args}}
7547

7648
# Enter the container interactively
7749
enter:
78-
#!/usr/bin/bash
79-
set -euo pipefail
80-
mkdir -p "$HOME/.claude" "$HOME/.gemini"
81-
touch "$HOME/.claude.json"
82-
env_flags=""
83-
for var in $(env | grep -E '^(GOOGLE_|GEMINI_|ANTHROPIC_)' | cut -d= -f1); do
84-
env_flags="$env_flags -e $var"
85-
done
86-
exec podman run {{podman_flags}} \
87-
-e HOME="$HOME" \
88-
$env_flags \
89-
-v "$(pwd):$(pwd):rw" \
90-
-v "$HOME/.claude:$HOME/.claude:rw" \
91-
-v "$HOME/.claude.json:$HOME/.claude.json:rw" \
92-
-v "$HOME/.gemini:$HOME/.gemini:rw" \
93-
-w "$(pwd)" \
94-
{{local_image}}
50+
AI_DEV_IMAGE={{local_image}} ./scripts/enter.sh
9551

9652
# =============================================================================
9753
# Installation (wrapper scripts to ~/.local/bin)
9854
# =============================================================================
9955

100-
# Install wrapper scripts for claude and gemini to ~/.local/bin
56+
# Install wrapper scripts using remote image
10157
install:
10258
#!/usr/bin/bash
10359
set -euo pipefail
10460
mkdir -p "$HOME/.local/bin"
105-
printf '%s\n' '#!/usr/bin/bash' \
106-
'set -euo pipefail' \
107-
'mkdir -p "$HOME/.claude"' \
108-
'touch "$HOME/.claude.json"' \
109-
'exec podman run --rm -it --init \' \
110-
' --user 0:0 \' \
111-
' --security-opt label=disable \' \
112-
' -e HOME="$HOME" \' \
113-
' -v "$(pwd):$(pwd):rw" \' \
114-
' -v "$HOME/.claude:$HOME/.claude:rw" \' \
115-
' -v "$HOME/.claude.json:$HOME/.claude.json:rw" \' \
116-
' -w "$(pwd)" \' \
117-
' ghcr.io/binarypie-dev/ai-dev:latest \' \
118-
' claude "$@"' > "$HOME/.local/bin/claude"
119-
chmod +x "$HOME/.local/bin/claude"
120-
printf '%s\n' '#!/usr/bin/bash' \
121-
'set -euo pipefail' \
122-
'mkdir -p "$HOME/.gemini"' \
123-
'env_flags=""' \
124-
'for var in $(env | grep -E '"'"'^(GOOGLE_|GEMINI_)'"'"' | cut -d= -f1); do' \
125-
' env_flags="$env_flags -e $var"' \
126-
'done' \
127-
'exec podman run --rm -it --init \' \
128-
' --user 0:0 \' \
129-
' --security-opt label=disable \' \
130-
' -e HOME="$HOME" \' \
131-
' $env_flags \' \
132-
' -v "$(pwd):$(pwd):rw" \' \
133-
' -v "$HOME/.gemini:$HOME/.gemini:rw" \' \
134-
' -w "$(pwd)" \' \
135-
' ghcr.io/binarypie-dev/ai-dev:latest \' \
136-
' gemini "$@"' > "$HOME/.local/bin/gemini"
137-
chmod +x "$HOME/.local/bin/gemini"
138-
echo "Installed wrapper scripts to ~/.local/bin/claude and ~/.local/bin/gemini"
139-
140-
# Install wrapper scripts pointing to local image
61+
cp scripts/claude.sh "$HOME/.local/bin/claude"
62+
cp scripts/gemini.sh "$HOME/.local/bin/gemini"
63+
chmod +x "$HOME/.local/bin/claude" "$HOME/.local/bin/gemini"
64+
echo "Installed ~/.local/bin/claude and ~/.local/bin/gemini (image: {{remote_image}})"
65+
66+
# Install wrapper scripts using local image
14167
install-local:
14268
#!/usr/bin/bash
14369
set -euo pipefail
14470
mkdir -p "$HOME/.local/bin"
145-
printf '%s\n' '#!/usr/bin/bash' \
146-
'set -euo pipefail' \
147-
'mkdir -p "$HOME/.claude"' \
148-
'touch "$HOME/.claude.json"' \
149-
'exec podman run --rm -it --init \' \
150-
' --user 0:0 \' \
151-
' --security-opt label=disable \' \
152-
' -e HOME="$HOME" \' \
153-
' -v "$(pwd):$(pwd):rw" \' \
154-
' -v "$HOME/.claude:$HOME/.claude:rw" \' \
155-
' -v "$HOME/.claude.json:$HOME/.claude.json:rw" \' \
156-
' -w "$(pwd)" \' \
157-
' localhost/ai-dev \' \
158-
' claude "$@"' > "$HOME/.local/bin/claude"
159-
chmod +x "$HOME/.local/bin/claude"
160-
printf '%s\n' '#!/usr/bin/bash' \
161-
'set -euo pipefail' \
162-
'mkdir -p "$HOME/.gemini"' \
163-
'env_flags=""' \
164-
'for var in $(env | grep -E '"'"'^(GOOGLE_|GEMINI_)'"'"' | cut -d= -f1); do' \
165-
' env_flags="$env_flags -e $var"' \
166-
'done' \
167-
'exec podman run --rm -it --init \' \
168-
' --user 0:0 \' \
169-
' --security-opt label=disable \' \
170-
' -e HOME="$HOME" \' \
171-
' $env_flags \' \
172-
' -v "$(pwd):$(pwd):rw" \' \
173-
' -v "$HOME/.gemini:$HOME/.gemini:rw" \' \
174-
' -w "$(pwd)" \' \
175-
' localhost/ai-dev \' \
176-
' gemini "$@"' > "$HOME/.local/bin/gemini"
177-
chmod +x "$HOME/.local/bin/gemini"
178-
echo "Installed wrapper scripts (local image) to ~/.local/bin/claude and ~/.local/bin/gemini"
71+
sed 's|ghcr.io/binarypie-dev/ai-dev:latest|localhost/ai-dev|' scripts/claude.sh > "$HOME/.local/bin/claude"
72+
sed 's|ghcr.io/binarypie-dev/ai-dev:latest|localhost/ai-dev|' scripts/gemini.sh > "$HOME/.local/bin/gemini"
73+
chmod +x "$HOME/.local/bin/claude" "$HOME/.local/bin/gemini"
74+
echo "Installed ~/.local/bin/claude and ~/.local/bin/gemini (image: {{local_image}})"
17975

18076
# Remove wrapper scripts from ~/.local/bin
18177
uninstall:
@@ -207,28 +103,11 @@ clean:
207103
# Test the built image works correctly
208104
test-build: build
209105
@echo "Testing container..."
210-
podman run {{podman_flags}} -e HOME="$HOME" {{local_image}} claude --version
211-
podman run {{podman_flags}} -e HOME="$HOME" {{local_image}} gemini --version
106+
AI_DEV_IMAGE={{local_image}} ./scripts/claude.sh --version
107+
AI_DEV_IMAGE={{local_image}} ./scripts/gemini.sh --version
212108
@echo ""
213109
@echo "All tests passed!"
214110

215111
# Debug: show container environment, paths, and auth state
216112
debug:
217-
#!/usr/bin/bash
218-
set -euo pipefail
219-
mkdir -p "$HOME/.claude" "$HOME/.gemini"
220-
touch "$HOME/.claude.json"
221-
env_flags=""
222-
for var in $(env | grep -E '^(GOOGLE_|GEMINI_|ANTHROPIC_)' | cut -d= -f1); do
223-
env_flags="$env_flags -e $var"
224-
done
225-
podman run {{podman_flags}} \
226-
-e HOME="$HOME" \
227-
$env_flags \
228-
-v "$(pwd):$(pwd):rw" \
229-
-v "$HOME/.claude:$HOME/.claude:rw" \
230-
-v "$HOME/.claude.json:$HOME/.claude.json:rw" \
231-
-v "$HOME/.gemini:$HOME/.gemini:rw" \
232-
-w "$(pwd)" \
233-
{{local_image}} \
234-
--ai-dev-debug
113+
AI_DEV_IMAGE={{local_image}} ./scripts/enter.sh --ai-dev-debug

dot_files/ai-dev/scripts/claude.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/usr/bin/bash
2+
set -euo pipefail
3+
4+
IMAGE="${AI_DEV_IMAGE:-ghcr.io/binarypie-dev/ai-dev:latest}"
5+
6+
mkdir -p "$HOME/.claude"
7+
touch "$HOME/.claude.json"
8+
9+
exec podman run --rm -it --init \
10+
--user 0:0 \
11+
--security-opt label=disable \
12+
-e HOME="$HOME" \
13+
-v "$(pwd):$(pwd):rw" \
14+
-v "$HOME/.claude:$HOME/.claude:rw" \
15+
-v "$HOME/.claude.json:$HOME/.claude.json:rw" \
16+
-w "$(pwd)" \
17+
"$IMAGE" \
18+
claude "$@"

dot_files/ai-dev/scripts/enter.sh

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/bash
2+
set -euo pipefail
3+
4+
IMAGE="${AI_DEV_IMAGE:-ghcr.io/binarypie-dev/ai-dev:latest}"
5+
6+
mkdir -p "$HOME/.claude" "$HOME/.gemini"
7+
touch "$HOME/.claude.json"
8+
9+
env_flags=""
10+
for var in $(env | grep -E '^(GOOGLE_|GEMINI_|ANTHROPIC_)' | cut -d= -f1); do
11+
env_flags="$env_flags -e $var"
12+
done
13+
14+
exec podman run --rm -it --init \
15+
--user 0:0 \
16+
--security-opt label=disable \
17+
-e HOME="$HOME" \
18+
$env_flags \
19+
-v "$(pwd):$(pwd):rw" \
20+
-v "$HOME/.claude:$HOME/.claude:rw" \
21+
-v "$HOME/.claude.json:$HOME/.claude.json:rw" \
22+
-v "$HOME/.gemini:$HOME/.gemini:rw" \
23+
-w "$(pwd)" \
24+
"$IMAGE" \
25+
"$@"

dot_files/ai-dev/scripts/gemini.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/bash
2+
set -euo pipefail
3+
4+
IMAGE="${AI_DEV_IMAGE:-ghcr.io/binarypie-dev/ai-dev:latest}"
5+
6+
mkdir -p "$HOME/.gemini"
7+
8+
env_flags=""
9+
for var in $(env | grep -E '^(GOOGLE_|GEMINI_)' | cut -d= -f1); do
10+
env_flags="$env_flags -e $var"
11+
done
12+
13+
exec podman run --rm -it --init \
14+
--user 0:0 \
15+
--security-opt label=disable \
16+
-e HOME="$HOME" \
17+
$env_flags \
18+
-v "$(pwd):$(pwd):rw" \
19+
-v "$HOME/.gemini:$HOME/.gemini:rw" \
20+
-w "$(pwd)" \
21+
"$IMAGE" \
22+
gemini "$@"
Lines changed: 9 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,30 @@
11
# vim: set ft=make :
22
# Hypercube AI development environment commands
33

4-
ai_image := "ghcr.io/binarypie-dev/ai-dev:latest"
5-
ai_podman_flags := "--rm -it --init --user 0:0 --security-opt label=disable"
4+
ai_scripts := "/usr/share/hypercube/config/ai-dev/scripts"
65

76
# Run Claude Code in the current directory
87
ai-claude *args:
9-
#!/usr/bin/bash
10-
set -euo pipefail
11-
mkdir -p "$HOME/.claude"
12-
touch "$HOME/.claude.json"
13-
exec podman run {{ai_podman_flags}} \
14-
-e HOME="$HOME" \
15-
-v "$(pwd):$(pwd):rw" \
16-
-v "$HOME/.claude:$HOME/.claude:rw" \
17-
-v "$HOME/.claude.json:$HOME/.claude.json:rw" \
18-
-w "$(pwd)" \
19-
{{ai_image}} \
20-
claude {{args}}
8+
{{ai_scripts}}/claude.sh {{args}}
219

2210
# Run Gemini CLI in the current directory
2311
ai-gemini *args:
24-
#!/usr/bin/bash
25-
set -euo pipefail
26-
mkdir -p "$HOME/.gemini"
27-
env_flags=""
28-
for var in $(env | grep -E '^(GOOGLE_|GEMINI_)' | cut -d= -f1); do
29-
env_flags="$env_flags -e $var"
30-
done
31-
exec podman run {{ai_podman_flags}} \
32-
-e HOME="$HOME" \
33-
$env_flags \
34-
-v "$(pwd):$(pwd):rw" \
35-
-v "$HOME/.gemini:$HOME/.gemini:rw" \
36-
-w "$(pwd)" \
37-
{{ai_image}} \
38-
gemini {{args}}
12+
{{ai_scripts}}/gemini.sh {{args}}
3913

4014
# Enter the ai-dev container interactively
4115
ai-dev:
42-
#!/usr/bin/bash
43-
set -euo pipefail
44-
mkdir -p "$HOME/.claude" "$HOME/.gemini"
45-
touch "$HOME/.claude.json"
46-
env_flags=""
47-
for var in $(env | grep -E '^(GOOGLE_|GEMINI_|ANTHROPIC_)' | cut -d= -f1); do
48-
env_flags="$env_flags -e $var"
49-
done
50-
exec podman run {{ai_podman_flags}} \
51-
-e HOME="$HOME" \
52-
$env_flags \
53-
-v "$(pwd):$(pwd):rw" \
54-
-v "$HOME/.claude:$HOME/.claude:rw" \
55-
-v "$HOME/.claude.json:$HOME/.claude.json:rw" \
56-
-v "$HOME/.gemini:$HOME/.gemini:rw" \
57-
-w "$(pwd)" \
58-
{{ai_image}}
16+
{{ai_scripts}}/enter.sh
5917

6018
# Install claude and gemini wrapper scripts to ~/.local/bin
6119
ai-setup:
6220
#!/usr/bin/bash
6321
set -euo pipefail
64-
6522
echo "Pulling ai-dev image..."
66-
podman pull {{ai_image}}
67-
23+
podman pull ghcr.io/binarypie-dev/ai-dev:latest
6824
mkdir -p "$HOME/.local/bin"
69-
printf '%s\n' '#!/usr/bin/bash' \
70-
'set -euo pipefail' \
71-
'mkdir -p "$HOME/.claude"' \
72-
'touch "$HOME/.claude.json"' \
73-
'exec podman run --rm -it --init \' \
74-
' --user 0:0 \' \
75-
' --security-opt label=disable \' \
76-
' -e HOME="$HOME" \' \
77-
' -v "$(pwd):$(pwd):rw" \' \
78-
' -v "$HOME/.claude:$HOME/.claude:rw" \' \
79-
' -v "$HOME/.claude.json:$HOME/.claude.json:rw" \' \
80-
' -w "$(pwd)" \' \
81-
' ghcr.io/binarypie-dev/ai-dev:latest \' \
82-
' claude "$@"' > "$HOME/.local/bin/claude"
83-
chmod +x "$HOME/.local/bin/claude"
84-
printf '%s\n' '#!/usr/bin/bash' \
85-
'set -euo pipefail' \
86-
'mkdir -p "$HOME/.gemini"' \
87-
'env_flags=""' \
88-
'for var in $(env | grep -E '"'"'^(GOOGLE_|GEMINI_)'"'"' | cut -d= -f1); do' \
89-
' env_flags="$env_flags -e $var"' \
90-
'done' \
91-
'exec podman run --rm -it --init \' \
92-
' --user 0:0 \' \
93-
' --security-opt label=disable \' \
94-
' -e HOME="$HOME" \' \
95-
' $env_flags \' \
96-
' -v "$(pwd):$(pwd):rw" \' \
97-
' -v "$HOME/.gemini:$HOME/.gemini:rw" \' \
98-
' -w "$(pwd)" \' \
99-
' ghcr.io/binarypie-dev/ai-dev:latest \' \
100-
' gemini "$@"' > "$HOME/.local/bin/gemini"
101-
chmod +x "$HOME/.local/bin/gemini"
25+
cp {{ai_scripts}}/claude.sh "$HOME/.local/bin/claude"
26+
cp {{ai_scripts}}/gemini.sh "$HOME/.local/bin/gemini"
27+
chmod +x "$HOME/.local/bin/claude" "$HOME/.local/bin/gemini"
10228
echo ""
10329
echo "Setup complete! You can now run 'claude' and 'gemini' directly."
10430

@@ -107,5 +33,5 @@ ai-upgrade:
10733
#!/usr/bin/bash
10834
set -euo pipefail
10935
echo "Pulling latest ai-dev image..."
110-
podman pull {{ai_image}}
36+
podman pull ghcr.io/binarypie-dev/ai-dev:latest
11137
echo "Done! Latest image pulled."

0 commit comments

Comments
 (0)