Skip to content

Commit 97b91f0

Browse files
lroolleclaude
andcommitted
fix(args): honor the -- contract — deva flags only before, verbatim after
deva's arg pipeline flattened AGENT_ARGS (pre-deva flags) and POST_ARGS (post--- agent args) into a single AGENT_ARGV before agent_prepare saw it, destroying the -- boundary. --trace and --auth-with were intercepted from the flat array regardless of position, so `deva grok -- --trace` ate the flag instead of passing it to grok. Fix: inject a -- sentinel into AGENT_ARGV between the two sources. Each agent's flag scanner stops interpreting at the sentinel and strips it at command assembly. The contract: deva <agent> --trace -- --resume # traced, --resume to agent deva <agent> -- --trace --resume # NOT traced, both reach agent deva --trace <agent> -- --resume # traced (--trace is a wrapper arg) parse_auth_args in shared_auth.sh uses the same boundary for --auth-with. gemini.sh (no --trace) strips the sentinel before command assembly. Closes #427 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent a7732eb commit 97b91f0

8 files changed

Lines changed: 71 additions & 11 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3737
answers (poll-then-open; `DEVA_TRACE_OPEN=0` disables). Attaching to a
3838
persistent container created without the port warns instead (#425)
3939

40+
### Fixed
41+
- `--` contract: deva-level flags (`--trace`, `--auth-with`) are now
42+
interpreted only before `--`; everything after passes to the agent CLI
43+
verbatim. `deva claude --trace -- --resume` traces; `deva claude --
44+
--trace --resume` passes `--trace` through to claude as its own flag.
45+
Previous behavior silently intercepted flags from both sides (#427)
46+
4047
### Changed
4148
- cctrace pin bumped 0.4.0 -> 0.11.0 (client profiles, shape-first
4249
categorization, `view --serve`)

agents/claude.sh

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,30 @@ agent_prepare() {
1515
AUTH_METHOD="$PARSED_AUTH_METHOD"
1616
local -a remaining_args=("${PARSED_REMAINING_ARGS[@]+"${PARSED_REMAINING_ARGS[@]}"}")
1717

18-
# Detect --trace flag
18+
# Detect --trace flag — only before the -- sentinel; after it, args
19+
# belong to the agent CLI verbatim (#427). First -- is stripped.
1920
local use_trace=false
21+
local seen_sep=false
2022
local -a claude_args=()
2123

2224
if [ ${#remaining_args[@]} -gt 0 ]; then
2325
local i=0
2426
while [ $i -lt ${#remaining_args[@]} ]; do
2527
local arg="${remaining_args[$i]}"
2628
case "$arg" in
29+
--)
30+
if [ "$seen_sep" = false ]; then
31+
seen_sep=true
32+
else
33+
claude_args+=("$arg")
34+
fi
35+
;;
2736
--trace)
28-
use_trace=true
37+
if [ "$seen_sep" = true ]; then
38+
claude_args+=("$arg")
39+
else
40+
use_trace=true
41+
fi
2942
;;
3043
*)
3144
claude_args+=("$arg")

agents/codex.sh

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,17 @@ agent_prepare() {
3333
AUTH_METHOD="$PARSED_AUTH_METHOD"
3434
local -a remaining_args=("${PARSED_REMAINING_ARGS[@]+"${PARSED_REMAINING_ARGS[@]}"}")
3535

36-
# Detect --trace flag (cctrace codex client profile, cctrace >= 0.11)
36+
# Detect --trace flag — only before the -- sentinel; after it, args
37+
# belong to the agent CLI verbatim (#427). First -- is stripped.
3738
local use_trace=false
39+
local seen_sep=false
3840
if [ ${#remaining_args[@]} -gt 0 ]; then
3941
local -a filtered_args=()
4042
local arg
4143
for arg in "${remaining_args[@]}"; do
42-
if [ "$arg" = "--trace" ]; then
44+
if [ "$arg" = "--" ] && [ "$seen_sep" = false ]; then
45+
seen_sep=true
46+
elif [ "$arg" = "--trace" ] && [ "$seen_sep" = false ]; then
4347
use_trace=true
4448
else
4549
filtered_args+=("$arg")

agents/gemini.sh

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,18 @@ agent_prepare() {
2020

2121
AGENT_COMMAND+=("--yolo")
2222

23-
AGENT_COMMAND+=("${remaining_args[@]+"${remaining_args[@]}"}")
23+
# Strip the deva -- sentinel; everything after it is verbatim (#427).
24+
local -a clean_args=()
25+
local first_sep=false
26+
local arg
27+
for arg in "${remaining_args[@]+"${remaining_args[@]}"}"; do
28+
if [ "$arg" = "--" ] && [ "$first_sep" = false ]; then
29+
first_sep=true
30+
else
31+
clean_args+=("$arg")
32+
fi
33+
done
34+
AGENT_COMMAND+=("${clean_args[@]+"${clean_args[@]}"}")
2435

2536
setup_gemini_auth "$AUTH_METHOD"
2637
}

agents/grok.sh

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,17 @@ agent_prepare() {
1818
AUTH_METHOD="$PARSED_AUTH_METHOD"
1919
local -a remaining_args=("${PARSED_REMAINING_ARGS[@]+"${PARSED_REMAINING_ARGS[@]}"}")
2020

21-
# Detect --trace flag (cctrace grok client profile, cctrace >= 0.11)
21+
# Detect --trace flag — only before the -- sentinel; after it, args
22+
# belong to the agent CLI verbatim (#427). First -- is stripped.
2223
local use_trace=false
24+
local seen_sep=false
2325
if [ ${#remaining_args[@]} -gt 0 ]; then
2426
local -a filtered_args=()
2527
local arg
2628
for arg in "${remaining_args[@]}"; do
27-
if [ "$arg" = "--trace" ]; then
29+
if [ "$arg" = "--" ] && [ "$seen_sep" = false ]; then
30+
seen_sep=true
31+
elif [ "$arg" = "--trace" ] && [ "$seen_sep" = false ]; then
2832
use_trace=true
2933
else
3034
filtered_args+=("$arg")

agents/shared_auth.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,10 +447,23 @@ parse_auth_args() {
447447
local auth_method=""
448448
local -a remaining_args=()
449449
local i=0
450+
local seen_sep=false
450451

451452
while [ $i -lt ${#args[@]} ]; do
452453
case "${args[$i]}" in
454+
--)
455+
# First -- is the deva sentinel; keep it for downstream
456+
# flag scanners (#427). Later --s pass through as-is.
457+
seen_sep=true
458+
remaining_args+=("${args[$i]}")
459+
i=$((i + 1))
460+
;;
453461
--auth-with)
462+
if [ "$seen_sep" = true ]; then
463+
remaining_args+=("${args[$i]}")
464+
i=$((i + 1))
465+
continue
466+
fi
454467
if [ $((i + 1)) -ge ${#args[@]} ]; then
455468
auth_error "--auth-with requires a method or file path"
456469
fi

deva.sh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3278,12 +3278,17 @@ else
32783278
parse_wrapper_args
32793279
fi
32803280
3281+
# Preserve the -- boundary so agent_prepare can distinguish deva-level
3282+
# flags (--auth-with, --trace) from agent CLI args: flags are only
3283+
# interpreted before the sentinel; everything after passes verbatim (#427).
32813284
if [ ${#AGENT_ARGS[@]} -gt 0 ]; then
32823285
if [ ${#AGENT_ARGV[@]} -gt 0 ]; then
3283-
AGENT_ARGV=("${AGENT_ARGS[@]}" "${AGENT_ARGV[@]}")
3286+
AGENT_ARGV=("${AGENT_ARGS[@]}" "--" "${AGENT_ARGV[@]}")
32843287
else
32853288
AGENT_ARGV=("${AGENT_ARGS[@]}")
32863289
fi
3290+
elif [ ${#AGENT_ARGV[@]} -gt 0 ]; then
3291+
AGENT_ARGV=("--" "${AGENT_ARGV[@]}")
32873292
fi
32883293
32893294
_step "start"

docs/advanced-usage.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,14 @@ The printed `docker run` line is diagnostic output. It masks secrets and may con
164164
## Request Tracing
165165

166166
```bash
167-
deva.sh claude -- --trace --continue
168-
deva.sh codex -- --trace exec "fix the failing tests"
169-
deva.sh grok -- --trace -p "explain this stack trace"
167+
deva.sh claude --trace -- --continue
168+
deva.sh codex --trace -- exec "fix the failing tests"
169+
deva.sh grok --trace -- -p "explain this stack trace"
170170
```
171171

172+
`--trace` goes before `--`. Everything after `--` passes to the agent CLI
173+
verbatim and is never intercepted by deva.
174+
172175
`--trace` wraps the agent with [cctrace](https://github.com/thevibeworks/cctrace),
173176
which records every API call the agent makes — messages, OAuth, usage/credits,
174177
MCP — not just the chat endpoint. Everything else on the line goes to the

0 commit comments

Comments
 (0)