Skip to content

Commit 4cc3aa8

Browse files
authored
Merge pull request #422 from thevibeworks/feat/trace-418
feat(trace): codex/grok --trace + container-scoped CA trust, cctrace 0.11
2 parents 1d5cc33 + 970b456 commit 4cc3aa8

11 files changed

Lines changed: 130 additions & 10 deletions

File tree

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
against the agent config home (`~/.config/deva/<agent>/`) as a named
1313
credentials store; CWD checked first for compat. Provisioning a missing
1414
bare name creates it in the store (#417)
15+
- `--trace` for codex and grok via cctrace client profiles (#418).
16+
`deva codex -- --trace exec "..."` / `deva grok -- --trace -p "..."`
17+
wrap the agent with `cctrace <client> --no-open --`; always MITM capture
18+
- Container-scoped CA trust for traced sessions (#414): the entrypoint
19+
installs the cctrace MITM CA into the container system store when
20+
`DEVA_TRACE=1` and removes it on the next non-traced start. Covers
21+
subprocesses and tools that ignore the CA env vars; never touches the
22+
host trust store
23+
24+
### Changed
25+
- cctrace pin bumped 0.4.0 -> 0.11.0 (client profiles, shape-first
26+
categorization, `view --serve`)
1527

1628
## [0.14.1] - 2026-07-13
1729

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ FROM agent-base AS final
209209

210210
# Declare ARGs immediately before usage to minimize cache invalidation
211211
ARG CLAUDE_CODE_VERSION=2.1.143
212-
ARG CCTRACE_VERSION=0.4.0
212+
ARG CCTRACE_VERSION=0.11.0
213213
ARG CODEX_VERSION=0.131.0
214214
ARG GEMINI_CLI_VERSION=0.42.0
215215
ARG GROK_CLI_VERSION=0.2.93

Dockerfile.rust

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LABEL org.opencontainers.image.title="deva-rust"
99
LABEL org.opencontainers.image.description="Rust development environment with full toolchain"
1010

1111
ARG CLAUDE_CODE_VERSION=2.1.143
12-
ARG CCTRACE_VERSION=0.4.0
12+
ARG CCTRACE_VERSION=0.11.0
1313
ARG CODEX_VERSION=0.131.0
1414
ARG GEMINI_CLI_VERSION=0.42.0
1515
ARG GROK_CLI_VERSION=0.2.93

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ DELTA_VERSION ?= 0.19.2
3131
TMUX_VERSION ?= 3.6a
3232
TMUX_SHA256 ?= b6d8d9c76585db8ef5fa00d4931902fa4b8cbe8166f528f44fc403961a3f3759
3333
CLAUDE_CODE_VERSION ?= 2.1.143
34-
CCTRACE_VERSION ?= 0.4.0
34+
CCTRACE_VERSION ?= 0.11.0
3535
CODEX_VERSION ?= 0.131.0
3636
GEMINI_CLI_VERSION ?= 0.42.0
3737
GROK_CLI_VERSION ?= 0.2.93

agents/claude.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ agent_prepare() {
4747
if [ "$use_trace" = true ]; then
4848
# Use cctrace wrapper: captures everything by default,
4949
# claude args go after "--"
50+
# DEVA_TRACE=1 tells the entrypoint to install the cctrace MITM CA
51+
# into the container system trust store (#414)
52+
DOCKER_ARGS+=("-e" "DEVA_TRACE=1")
53+
DEVA_TRACE_ACTIVE=true
5054
AGENT_COMMAND=("cctrace" "--no-open" "--")
5155
if [ "$has_dangerously" = false ]; then
5256
AGENT_COMMAND+=("--dangerously-skip-permissions")

agents/codex.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,21 @@ 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)
37+
local use_trace=false
38+
if [ ${#remaining_args[@]} -gt 0 ]; then
39+
local -a filtered_args=()
40+
local arg
41+
for arg in "${remaining_args[@]}"; do
42+
if [ "$arg" = "--trace" ]; then
43+
use_trace=true
44+
else
45+
filtered_args+=("$arg")
46+
fi
47+
done
48+
remaining_args=("${filtered_args[@]+"${filtered_args[@]}"}")
49+
fi
50+
3651
local has_dangerous=false
3752
local has_model=false
3853

@@ -74,6 +89,14 @@ agent_prepare() {
7489

7590
AGENT_COMMAND+=("${remaining_args[@]+"${remaining_args[@]}"}")
7691

92+
if [ "$use_trace" = true ]; then
93+
# cctrace codex profile: codex args go after "--"; always mitm.
94+
# DEVA_TRACE=1 installs the MITM CA into the container store (#414).
95+
DOCKER_ARGS+=("-e" "DEVA_TRACE=1")
96+
DEVA_TRACE_ACTIVE=true
97+
AGENT_COMMAND=("cctrace" "codex" "--no-open" "--" "${AGENT_COMMAND[@]:1}")
98+
fi
99+
77100
DOCKER_ARGS+=("-p" "127.0.0.1:1455:1455")
78101

79102
setup_codex_auth "$AUTH_METHOD"

agents/grok.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,33 @@ 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)
22+
local use_trace=false
23+
if [ ${#remaining_args[@]} -gt 0 ]; then
24+
local -a filtered_args=()
25+
local arg
26+
for arg in "${remaining_args[@]}"; do
27+
if [ "$arg" = "--trace" ]; then
28+
use_trace=true
29+
else
30+
filtered_args+=("$arg")
31+
fi
32+
done
33+
remaining_args=("${filtered_args[@]+"${filtered_args[@]}"}")
34+
fi
35+
2136
AGENT_COMMAND+=("--always-approve")
2237

2338
AGENT_COMMAND+=("${remaining_args[@]+"${remaining_args[@]}"}")
2439

40+
if [ "$use_trace" = true ]; then
41+
# cctrace grok profile: grok args go after "--"; always mitm.
42+
# DEVA_TRACE=1 installs the MITM CA into the container store (#414).
43+
DOCKER_ARGS+=("-e" "DEVA_TRACE=1")
44+
DEVA_TRACE_ACTIVE=true
45+
AGENT_COMMAND=("cctrace" "grok" "--no-open" "--" "${AGENT_COMMAND[@]:1}")
46+
fi
47+
2548
setup_grok_auth "$AUTH_METHOD"
2649
}
2750

deva.sh

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3684,11 +3684,17 @@ if [ "$EPHEMERAL_MODE" = false ]; then
36843684
update_session_file
36853685
fi
36863686
3687+
# docker exec env overrides the container's creation-time env: pass the
3688+
# trace state explicitly so --trace works on an existing container and a
3689+
# non-traced attach un-trusts the CA installed by an earlier traced run.
3690+
_trace_env="DEVA_TRACE=0"
3691+
[ "${DEVA_TRACE_ACTIVE:-false}" = true ] && _trace_env="DEVA_TRACE=1"
3692+
36873693
if [ "$AUTH_PROVISION_MODE" = true ]; then
3688-
docker exec "${DOCKER_TERMINAL_ARGS[@]}" "$CONTAINER_NAME" /usr/local/bin/docker-entrypoint.sh "${AGENT_COMMAND[@]}" || true
3694+
docker exec -e "$_trace_env" "${DOCKER_TERMINAL_ARGS[@]}" "$CONTAINER_NAME" /usr/local/bin/docker-entrypoint.sh "${AGENT_COMMAND[@]}" || true
36893695
finish_auth_provision
36903696
else
3691-
exec docker exec "${DOCKER_TERMINAL_ARGS[@]}" "$CONTAINER_NAME" /usr/local/bin/docker-entrypoint.sh "${AGENT_COMMAND[@]}"
3697+
exec docker exec -e "$_trace_env" "${DOCKER_TERMINAL_ARGS[@]}" "$CONTAINER_NAME" /usr/local/bin/docker-entrypoint.sh "${AGENT_COMMAND[@]}"
36923698
fi
36933699
else
36943700
echo "Launching ${ACTIVE_AGENT} (ephemeral mode) via $(docker_image_ref)"

docker-entrypoint.sh

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,48 @@ build_gosu_env_cmd() {
332332
exec gosu "$user" env "HOME=$DEVA_HOME" "PATH=$PATH" "$@"
333333
}
334334

335+
# Container-scoped CA trust for cctrace MITM (#414). The container is the
336+
# blast radius: the CA key already lives in the container-readable home, so
337+
# trusting the cert system-wide adds convenience, not attack surface. Runs
338+
# each start: installs when tracing, removes otherwise — trust exists only
339+
# in traced sessions.
340+
setup_trace_ca() {
341+
local crt=/usr/local/share/ca-certificates/cctrace-mitm.crt
342+
343+
if [ "${DEVA_TRACE:-}" != "1" ]; then
344+
if [ -f "$crt" ]; then
345+
rm -f "$crt"
346+
if ! update-ca-certificates >/dev/null 2>&1; then
347+
echo "[entrypoint] warning: trust-store update failed; cctrace MITM CA may still be trusted" >&2
348+
fi
349+
fi
350+
return 0
351+
fi
352+
353+
if ! command -v cctrace >/dev/null 2>&1; then
354+
echo "[entrypoint] warning: DEVA_TRACE=1 but cctrace not found; skipping CA trust" >&2
355+
return 0
356+
fi
357+
358+
# --print-ca generates the CA on first use; it must run as the deva user
359+
# so the key lands under $DEVA_HOME/.local/share/cctrace with sane ownership.
360+
local ca_path
361+
ca_path=$(gosu "$DEVA_USER" env "HOME=$DEVA_HOME" "PATH=$PATH" cctrace --print-ca 2>/dev/null | tail -1)
362+
if [ -z "$ca_path" ] || [ ! -f "$ca_path" ]; then
363+
echo "[entrypoint] warning: cctrace --print-ca gave no usable path; skipping CA trust" >&2
364+
return 0
365+
fi
366+
367+
cp "$ca_path" "$crt"
368+
chmod 644 "$crt"
369+
if update-ca-certificates >/dev/null 2>&1; then
370+
[ "$VERBOSE" = "true" ] && echo "[entrypoint] cctrace MITM CA trusted container-wide: $crt"
371+
else
372+
echo "[entrypoint] warning: trust-store update failed; container-wide CA trust incomplete (cctrace env-scoped trust still applies)" >&2
373+
fi
374+
return 0
375+
}
376+
335377
ensure_agent_binaries() {
336378
case "$DEVA_AGENT" in
337379
claude)
@@ -385,6 +427,7 @@ main() {
385427
setup_claude_chrome_bridge
386428
fix_rust_permissions
387429
fix_docker_socket_permissions
430+
setup_trace_ca
388431
ensure_agent_binaries
389432

390433
if [ $# -eq 0 ]; then

docs/advanced-usage.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,12 +165,21 @@ The printed `docker run` line is diagnostic output. It masks secrets and may con
165165

166166
```bash
167167
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"
168170
```
169171

170-
`--trace` wraps Claude with [cctrace](https://github.com/thevibeworks/cctrace),
171-
which records every API call Claude makes — messages, OAuth, usage/credits,
172-
MCP — not just the chat endpoint. Everything else on the line goes to Claude
173-
unchanged.
172+
`--trace` wraps the agent with [cctrace](https://github.com/thevibeworks/cctrace),
173+
which records every API call the agent makes — messages, OAuth, usage/credits,
174+
MCP — not just the chat endpoint. Everything else on the line goes to the
175+
agent unchanged. Codex and Grok use cctrace client profiles (cctrace >= 0.11)
176+
and always run MITM capture.
177+
178+
When tracing is on, the entrypoint installs the cctrace MITM CA into the
179+
container's system trust store (`update-ca-certificates`) so subprocesses and
180+
tools that ignore `NODE_EXTRA_CA_CERTS`/`SSL_CERT_FILE` still verify. The
181+
container is the blast radius: trust never touches the host store and is
182+
removed at the next non-traced start.
174183

175184
Traces land in `.cctrace/` inside your workspace, so they survive the
176185
container. Each run writes a JSONL log plus a self-contained HTML snapshot you

0 commit comments

Comments
 (0)