Skip to content

Commit 5807889

Browse files
committed
refactor: extract version management to scripts and add --trace/--dry-run flags
- Move Makefile versions-up logic to scripts/version-upgrade.sh - Add release-utils.sh with unified tool registry and version fetching - Support --trace flag in claude agent for request tracing via claude-trace - Add --dry-run flag to show docker command without execution - Fix duplicate --dangerously-skip-permissions injection - Fix autolink checks to handle existing symlinks correctly - Switch atlas-cli to release-based versioning - Add clickhouse-client to rust image
1 parent 1190dee commit 5807889

9 files changed

Lines changed: 739 additions & 469 deletions

File tree

Dockerfile

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ LABEL org.opencontainers.image.claude_code_version=${CLAUDE_CODE_VERSION}
181181
LABEL org.opencontainers.image.codex_version=${CODEX_VERSION}
182182
LABEL org.opencontainers.image.gemini_cli_version=${GEMINI_CLI_VERSION}
183183

184-
# Use BuildKit cache for npm to speed up repeated builds
184+
# Install CLI tools via npm
185185
RUN --mount=type=cache,target=/home/deva/.npm,uid=${DEVA_UID},gid=${DEVA_GID},sharing=locked \
186186
npm config set prefix "$DEVA_HOME/.npm-global" && \
187187
npm install -g --no-audit --no-fund \
@@ -197,9 +197,12 @@ ARG ATLAS_CLI_VERSION=main
197197

198198
LABEL org.opencontainers.image.atlas_cli_version=${ATLAS_CLI_VERSION}
199199

200-
# Install Go tools for Atlassian integration (Confluence/Jira/Bitbucket)
201-
RUN go install github.com/lroolle/atlas-cli/cmd/atl@${ATLAS_CLI_VERSION} && \
202-
sudo mv $HOME/go/bin/atl /usr/local/bin/
200+
# Install atlas-cli binary + skill via upstream install.sh
201+
# - Uses prebuilt release tarball (faster than go install)
202+
# - Falls back to go install if no prebuilt for platform
203+
# - Installs skill with proper structure (SKILL.md + references/)
204+
RUN curl -fsSL "https://raw.githubusercontent.com/lroolle/atlas-cli/${ATLAS_CLI_VERSION}/install.sh" \
205+
| bash -s -- --skill-dir $DEVA_HOME/.skills
203206

204207
USER root
205208

Dockerfile.rust

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,12 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
2929
libpng-dev libjpeg-dev \
3030
libudev-dev \
3131
libproc2-dev \
32-
libzmq3-dev libzmq5 libczmq-dev
32+
libzmq3-dev libzmq5 libczmq-dev && \
33+
curl -fsSL 'https://packages.clickhouse.com/rpm/lts/repodata/repomd.xml.key' | gpg --dearmor -o /usr/share/keyrings/clickhouse-keyring.gpg && \
34+
ARCH=$(dpkg --print-architecture) && \
35+
echo "deb [signed-by=/usr/share/keyrings/clickhouse-keyring.gpg arch=${ARCH}] https://packages.clickhouse.com/deb stable main" > /etc/apt/sources.list.d/clickhouse.list && \
36+
apt-get update && \
37+
apt-get install -y --no-install-recommends clickhouse-client
3338

3439
RUN --mount=type=cache,target=/tmp/rust-cache,sharing=locked \
3540
set -euxo pipefail && \

Makefile

Lines changed: 12 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ DETECTED_IMAGE := $(shell \
2121
CLAUDE_CODE_VERSION := $(shell npm view @anthropic-ai/claude-code version 2>/dev/null || echo "2.0.1")
2222
CODEX_VERSION := $(shell npm view @openai/codex version 2>/dev/null || echo "0.42.0")
2323
GEMINI_CLI_VERSION := $(shell npm view @google/gemini-cli version 2>/dev/null || echo "latest")
24-
ATLAS_CLI_VERSION := $(shell gh api repos/lroolle/atlas-cli/commits/main --jq '.sha' 2>/dev/null || echo "789eefa650d66e97dd8fddceabf9e09f2a5d04a4")
24+
ATLAS_CLI_VERSION := $(shell gh api repos/lroolle/atlas-cli/releases/latest --jq '.tag_name' 2>/dev/null || echo "v0.1.1")
2525
COPILOT_API_VERSION := $(shell gh api repos/ericc-ch/copilot-api/branches/master --jq '.commit.sha' 2>/dev/null || echo "83cdfde17d7d3be36bd2493cc7592ff13be4928d")
2626

2727
export DOCKER_BUILDKIT := 1
@@ -132,70 +132,17 @@ buildx-multi-local:
132132

133133
.PHONY: versions-up
134134
versions-up:
135-
@echo "\033[1;36m╔════════════════════════════════════════════════════╗\033[0m"
136-
@echo "\033[1;36m║ Upgrading to Latest Versions ║\033[0m"
137-
@echo "\033[1;36m╚════════════════════════════════════════════════════╝\033[0m"
138-
@echo "\033[0;90m⏰ Time: $$(date '+%Y-%m-%d %H:%M:%S')\033[0m"
139-
@echo ""
140-
@echo "\033[0;90mFetching release dates...\033[0m"
141-
@echo "\033[0;90mChecking image: $(DETECTED_IMAGE)\033[0m"
142-
@# Get current image versions for comparison
143-
@prev_claude=$$(docker inspect --format='{{ index .Config.Labels "org.opencontainers.image.claude_code_version" }}' $(DETECTED_IMAGE) 2>/dev/null || echo "-"); \
144-
prev_codex=$$(docker inspect --format='{{ index .Config.Labels "org.opencontainers.image.codex_version" }}' $(DETECTED_IMAGE) 2>/dev/null || echo "-"); \
145-
prev_gemini=$$(docker inspect --format='{{ index .Config.Labels "org.opencontainers.image.gemini_cli_version" }}' $(DETECTED_IMAGE) 2>/dev/null || echo "-"); \
146-
prev_atlas=$$(docker inspect --format='{{ index .Config.Labels "org.opencontainers.image.atlas_cli_version" }}' $(DETECTED_IMAGE) 2>/dev/null || echo "-"); \
147-
prev_copilot=$$(docker inspect --format='{{ index .Config.Labels "org.opencontainers.image.copilot_api_version" }}' $(DETECTED_IMAGE) 2>/dev/null || echo "-"); \
148-
fmt() { v="$$1"; if [ -z "$$v" ] || [ "$$v" = "<no value>" ]; then echo "-"; else case "$$v" in v*) echo "$$v";; *) echo "v$$v";; esac; fi; }; \
149-
fmt_date() { d="$$1"; if [ -z "$$d" ]; then echo ""; else date -d "$$d" '+%b %d, %Y %H:%M' 2>/dev/null || date -jf '%Y-%m-%dT%H:%M:%SZ' "$$d" '+%b %d, %Y %H:%M' 2>/dev/null || echo "$$d"; fi; }; \
150-
curC=$$(fmt "$$prev_claude"); curX=$$(fmt "$$prev_codex"); curG=$$(fmt "$$prev_gemini"); curA="$${prev_atlas:0:7}"; curP="$${prev_copilot:0:7}"; \
151-
tgtC=$$(fmt "$(CLAUDE_CODE_VERSION)"); tgtX=$$(fmt "$(CODEX_VERSION)"); tgtG=$$(fmt "$(GEMINI_CLI_VERSION)"); \
152-
tgtA="$(ATLAS_CLI_VERSION)"; tgtA="$${tgtA:0:7}"; tgtP="$(COPILOT_API_VERSION)"; tgtP="$${tgtP:0:7}"; \
153-
dateC=$$(npm view "@anthropic-ai/claude-code@$(CLAUDE_CODE_VERSION)" time --json 2>/dev/null | jq -r '.["$(CLAUDE_CODE_VERSION)"] // .' 2>/dev/null | head -1); \
154-
dateX=$$(npm view "@openai/codex@$(CODEX_VERSION)" time --json 2>/dev/null | jq -r '.["$(CODEX_VERSION)"] // .' 2>/dev/null | head -1); \
155-
dateG=$$(npm view "@google/gemini-cli@$(GEMINI_CLI_VERSION)" time --json 2>/dev/null | jq -r '.["$(GEMINI_CLI_VERSION)"] // .' 2>/dev/null | head -1); \
156-
dateA=$$(gh api "repos/lroolle/atlas-cli/commits/$(ATLAS_CLI_VERSION)" --jq '.commit.committer.date' 2>/dev/null || echo ""); \
157-
dateP=$$(gh api "repos/ericc-ch/copilot-api/commits/$(COPILOT_API_VERSION)" --jq '.commit.committer.date' 2>/dev/null || echo ""); \
158-
fmtC=$$(fmt_date "$$dateC"); fmtX=$$(fmt_date "$$dateX"); fmtG=$$(fmt_date "$$dateG"); fmtA=$$(fmt_date "$$dateA"); fmtP=$$(fmt_date "$$dateP"); \
159-
echo ""; \
160-
echo "\033[1;33m📦 Version Changes:\033[0m"; \
161-
if [ "$$curC" = "$$tgtC" ]; then \
162-
echo " \033[0;90mClaude Code: $$tgtC ($$fmtC) https://www.npmjs.com/package/@anthropic-ai/claude-code\033[0m \033[0;32m(no change)\033[0m"; \
163-
else \
164-
echo " \033[1;37mClaude Code:\033[0m \033[0;31m$$curC\033[0m → \033[0;32m$$tgtC\033[0m \033[0;90m($$fmtC) https://www.npmjs.com/package/@anthropic-ai/claude-code\033[0m"; \
165-
fi; \
166-
if [ "$$curX" = "$$tgtX" ]; then \
167-
echo " \033[0;90mCodex: $$tgtX ($$fmtX) https://www.npmjs.com/package/@openai/codex\033[0m \033[0;32m(no change)\033[0m"; \
168-
else \
169-
echo " \033[1;37mCodex: \033[0m \033[0;31m$$curX\033[0m → \033[0;32m$$tgtX\033[0m \033[0;90m($$fmtX) https://www.npmjs.com/package/@openai/codex\033[0m"; \
170-
fi; \
171-
if [ "$$curG" = "$$tgtG" ]; then \
172-
echo " \033[0;90mGemini CLI: $$tgtG ($$fmtG) https://www.npmjs.com/package/@google/gemini-cli\033[0m \033[0;32m(no change)\033[0m"; \
173-
else \
174-
echo " \033[1;37mGemini CLI: \033[0m \033[0;31m$$curG\033[0m → \033[0;32m$$tgtG\033[0m \033[0;90m($$fmtG) https://www.npmjs.com/package/@google/gemini-cli\033[0m"; \
175-
fi; \
176-
if [ "$$curA" = "$$tgtA" ]; then \
177-
echo " \033[0;90mAtlas CLI: $$tgtA ($$fmtA) https://github.com/lroolle/atlas-cli\033[0m \033[0;32m(no change)\033[0m"; \
178-
else \
179-
echo " \033[1;37mAtlas CLI: \033[0m \033[0;31m$$curA\033[0m → \033[0;32m$$tgtA\033[0m \033[0;90m($$fmtA) https://github.com/lroolle/atlas-cli\033[0m"; \
180-
fi; \
181-
if [ "$$curP" = "$$tgtP" ]; then \
182-
echo " \033[0;90mCopilot API: $$tgtP ($$fmtP) https://github.com/ericc-ch/copilot-api\033[0m \033[0;32m(no change)\033[0m"; \
183-
else \
184-
echo " \033[1;37mCopilot API:\033[0m \033[0;31m$$curP\033[0m → \033[0;32m$$tgtP\033[0m \033[0;90m($$fmtP) https://github.com/ericc-ch/copilot-api\033[0m"; \
185-
fi
186-
@echo ""
187-
@echo "\033[1;33m⚠ Starting build in 5 seconds... Press Ctrl+C to cancel\033[0m"
188-
@echo "\033[0;90mHint: Override via CLAUDE_CODE_VERSION=... CODEX_VERSION=... GEMINI_CLI_VERSION=... ATLAS_CLI_VERSION=... COPILOT_API_VERSION=...\033[0m"
189-
@bash -c 'for i in 5 4 3 2 1; do echo -ne "\r\033[1;36m⏳ $$i...\033[0m "; sleep 1; done; echo -ne "\r\033[K"'
190-
@echo "\033[1;32m✓ Proceeding with build...\033[0m"
191-
@echo ""
192-
@$(MAKE) build-main CLAUDE_CODE_VERSION=$(CLAUDE_CODE_VERSION) CODEX_VERSION=$(CODEX_VERSION) GEMINI_CLI_VERSION=$(GEMINI_CLI_VERSION) ATLAS_CLI_VERSION=$(ATLAS_CLI_VERSION) COPILOT_API_VERSION=$(COPILOT_API_VERSION)
193-
@echo ""
194-
@echo "\033[1;36m🔨 Rebuilding Rust image...\033[0m"
195-
@docker build -f $(RUST_DOCKERFILE) --build-arg BASE_IMAGE=$(MAIN_IMAGE) -t $(RUST_IMAGE) .
196-
@echo ""
197-
@echo "\033[1;32m✅ All images upgraded to latest versions\033[0m"
198-
@echo "\033[0;90m⏰ Completed: $$(date '+%Y-%m-%d %H:%M:%S')\033[0m"
135+
@MAIN_IMAGE=$(DETECTED_IMAGE) \
136+
BUILD_IMAGE=$(MAIN_IMAGE) \
137+
RUST_IMAGE=$(RUST_IMAGE) \
138+
DOCKERFILE=$(DOCKERFILE) \
139+
RUST_DOCKERFILE=$(RUST_DOCKERFILE) \
140+
CLAUDE_CODE_VERSION=$(CLAUDE_CODE_VERSION) \
141+
CODEX_VERSION=$(CODEX_VERSION) \
142+
GEMINI_CLI_VERSION=$(GEMINI_CLI_VERSION) \
143+
ATLAS_CLI_VERSION=$(ATLAS_CLI_VERSION) \
144+
COPILOT_API_VERSION=$(COPILOT_API_VERSION) \
145+
./scripts/version-upgrade.sh
199146

200147
.PHONY: versions
201148
versions:

agents/claude.sh

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,60 @@ agent_prepare() {
1010
else
1111
args=()
1212
fi
13-
AGENT_COMMAND=("claude")
1413

1514
parse_auth_args "claude" "${args[@]+"${args[@]}"}"
1615
AUTH_METHOD="$PARSED_AUTH_METHOD"
1716
local -a remaining_args=("${PARSED_REMAINING_ARGS[@]+"${PARSED_REMAINING_ARGS[@]}"}")
1817

19-
local has_dangerously=false
18+
# Detect --trace flag and extract trace options
19+
local use_trace=false
20+
local -a trace_args=()
21+
local -a claude_args=()
22+
2023
if [ ${#remaining_args[@]} -gt 0 ]; then
21-
for arg in "${remaining_args[@]}"; do
22-
if [ "$arg" = "--dangerously-skip-permissions" ]; then
23-
has_dangerously=true
24-
break
25-
fi
24+
local i=0
25+
while [ $i -lt ${#remaining_args[@]} ]; do
26+
local arg="${remaining_args[$i]}"
27+
case "$arg" in
28+
--trace)
29+
use_trace=true
30+
# Default trace options - include all requests for visibility
31+
trace_args+=("--include-all-requests")
32+
;;
33+
*)
34+
claude_args+=("$arg")
35+
;;
36+
esac
37+
i=$((i + 1))
2638
done
2739
fi
28-
if [ "$has_dangerously" = false ]; then
29-
AGENT_COMMAND+=("--dangerously-skip-permissions")
30-
fi
3140

32-
AGENT_COMMAND+=("${remaining_args[@]+"${remaining_args[@]}"}")
41+
# Check if --dangerously-skip-permissions already in claude_args
42+
local has_dangerously=false
43+
for arg in "${claude_args[@]+"${claude_args[@]}"}"; do
44+
if [ "$arg" = "--dangerously-skip-permissions" ]; then
45+
has_dangerously=true
46+
break
47+
fi
48+
done
49+
50+
if [ "$use_trace" = true ]; then
51+
# Use claude-trace wrapper
52+
AGENT_COMMAND=("claude-trace")
53+
AGENT_COMMAND+=("${trace_args[@]}")
54+
AGENT_COMMAND+=("--run-with")
55+
if [ "$has_dangerously" = false ]; then
56+
AGENT_COMMAND+=("--dangerously-skip-permissions")
57+
fi
58+
AGENT_COMMAND+=("${claude_args[@]+"${claude_args[@]}"}")
59+
else
60+
# Direct claude invocation
61+
AGENT_COMMAND=("claude")
62+
if [ "$has_dangerously" = false ]; then
63+
AGENT_COMMAND+=("--dangerously-skip-permissions")
64+
fi
65+
AGENT_COMMAND+=("${claude_args[@]+"${claude_args[@]}"}")
66+
fi
3367

3468
setup_claude_auth "$AUTH_METHOD"
3569
}

deva.sh

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ AGENT_EXPLICIT=false
4141
EPHEMERAL_MODE=false
4242
GLOBAL_MODE=false
4343
DEBUG_MODE=false
44+
DRY_RUN=false
4445

4546
usage() {
4647
cat <<'USAGE'
@@ -73,6 +74,7 @@ Deva flags:
7374
Select profile: base (default), rust. Pulls tag, falls back to Dockerfile.<profile>
7475
--host-net Use host networking for the agent container
7576
--no-docker Disable auto-mount of Docker socket (default: auto-mount if present)
77+
--dry-run Show docker command without executing (implies --debug)
7678
--verbose, --debug Print full docker command before execution
7779
-- Everything after this sentinel is passed to the agent unchanged
7880
@@ -114,9 +116,9 @@ Examples:
114116
115117
Advanced:
116118
deva.sh codex -v ~/.ssh:/home/deva/.ssh:ro -- -m gpt-5-codex
117-
deva.sh -c ~/work-claude-home -- --trace
118-
deva.sh --show-config # Debug configuration
119-
deva.sh --no-docker claude # Disable Docker-in-Docker auto-mount
119+
deva.sh claude -- --trace --continue # Use claude-trace wrapper for request tracing
120+
deva.sh --show-config # Debug configuration
121+
deva.sh --no-docker claude # Disable Docker-in-Docker auto-mount
120122
USAGE
121123
}
122124

@@ -1426,6 +1428,12 @@ parse_wrapper_args() {
14261428
i=$((i + 1))
14271429
continue
14281430
;;
1431+
--dry-run)
1432+
DRY_RUN=true
1433+
DEBUG_MODE=true
1434+
i=$((i + 1))
1435+
continue
1436+
;;
14291437
*)
14301438
remaining+=("$arg")
14311439
i=$((i + 1))
@@ -1879,9 +1887,9 @@ if [ "$CONFIG_HOME_FROM_CLI" = true ] && [ -n "$CONFIG_HOME" ]; then
18791887
fi
18801888
18811889
autolink_legacy_into_deva_root() {
1882-
[ "$AUTOLINK" = true ] || return
1883-
[ "$CONFIG_HOME_FROM_CLI" = false ] || return
1884-
[ -n "${CONFIG_ROOT:-}" ] || return
1890+
[ "$AUTOLINK" = true ] || return 0
1891+
[ "$CONFIG_HOME_FROM_CLI" = false ] || return 0
1892+
[ -n "${CONFIG_ROOT:-}" ] || return 0
18851893
[ -d "$CONFIG_ROOT" ] || mkdir -p "$CONFIG_ROOT"
18861894
18871895
if [ -d "$HOME/.claude" ] || [ -f "$HOME/.claude.json" ]; then
@@ -1908,7 +1916,7 @@ autolink_legacy_into_deva_root() {
19081916
fi
19091917
fi
19101918
if [ -d "$CONFIG_ROOT" ]; then
1911-
[ -d "$CONFIG_ROOT/codex/.codex" ] || mkdir -p "$CONFIG_ROOT/codex/.codex"
1919+
[ -d "$CONFIG_ROOT/codex/.codex" ] || [ -L "$CONFIG_ROOT/codex/.codex" ] || mkdir -p "$CONFIG_ROOT/codex/.codex"
19121920
fi
19131921
19141922
if [ -d "$HOME/.gemini" ]; then
@@ -1919,7 +1927,7 @@ autolink_legacy_into_deva_root() {
19191927
fi
19201928
fi
19211929
if [ -d "$CONFIG_ROOT" ]; then
1922-
[ -d "$CONFIG_ROOT/gemini/.gemini" ] || mkdir -p "$CONFIG_ROOT/gemini/.gemini"
1930+
[ -d "$CONFIG_ROOT/gemini/.gemini" ] || [ -L "$CONFIG_ROOT/gemini/.gemini" ] || mkdir -p "$CONFIG_ROOT/gemini/.gemini"
19231931
fi
19241932
}
19251933
@@ -2036,7 +2044,10 @@ DOCKER_ARGS+=(-e "DEVA_WORKSPACE=$(pwd)")
20362044
DOCKER_ARGS+=(-e "DEVA_EPHEMERAL=${EPHEMERAL_MODE}")
20372045
20382046
# Centralized mounting logic based on auth method
2039-
if [ -n "${AUTH_METHOD:-}" ]; then
2047+
# If --config-home is set, use it exclusively and skip auth-based mounting
2048+
if [ -n "$CONFIG_HOME" ]; then
2049+
mount_config_home
2050+
elif [ -n "${AUTH_METHOD:-}" ]; then
20402051
is_default_auth=false
20412052
if [ "$ACTIVE_AGENT" = "claude" ] && [ "$AUTH_METHOD" = "claude" ]; then
20422053
is_default_auth=true
@@ -2206,6 +2217,10 @@ if [ "$DEBUG_MODE" = true ]; then
22062217
echo "" >&2
22072218
fi
22082219
2220+
if [ "$DRY_RUN" = true ]; then
2221+
exit 0
2222+
fi
2223+
22092224
if [ "$EPHEMERAL_MODE" = false ]; then
22102225
# Check if container is running
22112226
container_action="attach"

docker-entrypoint.sh

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@ setup_nonroot_user() {
203203
if [ "$DEVA_UID" != "$current_uid" ]; then
204204
[ "$VERBOSE" = "true" ] && echo "[entrypoint] updating $DEVA_USER UID: $current_uid -> $DEVA_UID"
205205
usermod -u "$DEVA_UID" -g "$DEVA_GID" "$DEVA_USER"
206-
chown -R "$DEVA_UID:$DEVA_GID" "$DEVA_HOME" 2>/dev/null || true
206+
# Only chown files owned by container, skip mounted volumes
207+
find "$DEVA_HOME" -maxdepth 1 ! -type l -user root -exec chown "$DEVA_UID:$DEVA_GID" {} \; 2>/dev/null || true
207208
fi
208209

209210
chmod 755 /root 2>/dev/null || true
@@ -291,18 +292,44 @@ main() {
291292

292293
if [ "$DEVA_AGENT" = "claude" ]; then
293294
if [ "$cmd" = "claude" ] || [ "$cmd" = "$(command -v claude 2>/dev/null)" ]; then
294-
build_gosu_env_cmd "$DEVA_USER" "$cmd" "$@" --dangerously-skip-permissions
295+
# Add --dangerously-skip-permissions if not already present
296+
local has_dsp=false
297+
for arg in "$@"; do
298+
if [ "$arg" = "--dangerously-skip-permissions" ]; then
299+
has_dsp=true
300+
break
301+
fi
302+
done
303+
if [ "$has_dsp" = true ]; then
304+
build_gosu_env_cmd "$DEVA_USER" "$cmd" "$@"
305+
else
306+
build_gosu_env_cmd "$DEVA_USER" "$cmd" "$@" --dangerously-skip-permissions
307+
fi
295308
elif [ "$cmd" = "claude-trace" ]; then
296-
args=("$@")
297-
new_args=()
298-
for arg in "${args[@]}"; do
299-
if [ "$arg" = "--run-with" ]; then
300-
new_args+=("--run-with" "--dangerously-skip-permissions")
301-
else
302-
new_args+=("$arg")
309+
# claude-trace: ensure --dangerously-skip-permissions follows --run-with
310+
local has_dsp=false
311+
for arg in "$@"; do
312+
if [ "$arg" = "--dangerously-skip-permissions" ]; then
313+
has_dsp=true
314+
break
303315
fi
304316
done
305-
build_gosu_env_cmd "$DEVA_USER" "$cmd" "${new_args[@]}"
317+
if [ "$has_dsp" = true ]; then
318+
# Already has --dangerously-skip-permissions, pass through
319+
build_gosu_env_cmd "$DEVA_USER" "$cmd" "$@"
320+
else
321+
# Insert --dangerously-skip-permissions after --run-with
322+
args=("$@")
323+
new_args=()
324+
for arg in "${args[@]}"; do
325+
if [ "$arg" = "--run-with" ]; then
326+
new_args+=("--run-with" "--dangerously-skip-permissions")
327+
else
328+
new_args+=("$arg")
329+
fi
330+
done
331+
build_gosu_env_cmd "$DEVA_USER" "$cmd" "${new_args[@]}"
332+
fi
306333
else
307334
build_gosu_env_cmd "$DEVA_USER" "$cmd" "$@"
308335
fi

0 commit comments

Comments
 (0)