Probe the secure-agent setup for in-session functional
restrictions that block legitimate workflows. Three live
probes — SSH agent / Yubikey reachability, localhost port
binding, docker / podman runtime socket — each pointing the
user at the matching numbered troubleshooting entry and its
settings.json remediation (see body). Read-only — never
modifies settings.json, never invokes the sandbox bypass.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
Probe the secure-agent setup for in-session functional
restrictions that block legitimate workflows. Three live
probes — SSH agent / Yubikey reachability, localhost port
binding, docker / podman runtime socket — each pointing the
user at the matching numbered troubleshooting entry and its
settings.json remediation (see body). Read-only — never
modifies settings.json, never invokes the sandbox bypass.
when_to_use
Invoke when the user says "doctor my sandbox", "diagnose
sandbox friction", "why is the sandbox blocking X", "check
whether ssh / docker / port-bind works inside the sandbox",
or after the user reports a workflow failure that smells
sandbox-shaped (agent unreachable, socket errors, port
permission errors). Also a good periodic check after every
Claude Code upgrade — the sandbox profile evolves and a
previously-working call may have moved into deny.
capability
["capability:platform","capability:reassess"]
license
Apache-2.0
setup-isolated-setup-doctor
Runtime routing (run before the Claude-specific probes)
When the active harness is Codex, first require the static verification in
docs/adapters/codex.md, then run the
shared live environment probes inside the active Codex sandbox. Attribute
failures separately to native sandbox/network denial, approval policy, or
the POSIX agent-iso layer. Do not prescribe a .claude settings change for
a Codex failure. Then stop before the Claude-specific branch below.
When the harness is Claude Code, continue below. If the harness cannot be
determined, ask once.
The diagnostic layer over the secure agent setup. Complements
the existing setup skills:
setup-isolated-setup-doctor (this skill) answers "are
common workflows functionally blocked by the current
sandbox?" — live probes of SSH agent, port binding, docker /
podman socket. Catches over-restrictive allowlists.
Run verify first when the install is in question (fresh
machine, recent framework upgrade, sandbox-state surprise). Run
doctor when the install is known good but a workflow fails in
a sandbox-shaped way — agent unreachable, socket error, port
permission error.
Every probe maps to a numbered entry in
docs/setup/sandbox-troubleshooting.md;
the doctor's job is to identify which entry applies right now,
not to re-explain the remediation. If a fail surfaces a failure
mode not catalogued there, propose appending a new entry per the
catalog's Adding a new entry section.
Golden rules
Read-only. Each probe runs a small, deterministic,
side-effect-free check. The skill never edits any settings
file, never runs a command with dangerouslyDisableSandbox,
never installs anything. If a check fails, surface the failure
and point at the catalog entry; do not auto-fix.
Run every probe, even on early failure. Do not stop at the
first ✗. The value of the report is in the full picture — a
user may have one of three independent restrictions, or all
three, and discovering them one re-run at a time is annoying.
Distinguish ✗ (failing) from ⊘ (not applicable). ✗ means
the probe ran and the sandbox blocked it. ⊘ means the probe
was skipped because the prerequisite is absent (e.g. no
docker / podman on PATH → docker probe ⊘, not ✗).
Surface evidence. Each report line names the probe command,
the exit code, and the relevant stderr snippet. "Looks
blocked" is not a useful report; "ssh-add -l → rc=2 →
Could not open a connection to your authentication agent" is.
Map each ✗ to a catalog entry. The fail report includes a
direct link to the matching section of
docs/setup/sandbox-troubleshooting.md.
Do not paraphrase the remediation — the catalog is the single
source of truth.
The 3 probes
The current set covers the three failure modes the catalog
documents. New probes are added when new entries land in the
catalog; the two stay in lock-step.
Probe 1 — SSH agent / Yubikey reachable
Tests whether ssh-agent is reachable from inside the sandbox.
Failure mode: SSH_AUTH_SOCK is passed through claude-iso's
env whitelist but the socket file is not in
sandbox.filesystem.allowRead, so the agent's ssh /
git push subprocesses cannot connect(2) to the socket.
Tests whether a process inside the sandbox can bind to a
loopback port AND then talk to itself over loopback. The
failure mode the catalog documents is the second half (egress
proxy blocks 127.0.0.1).
Command:
python3 - <<'PY' 2>&1 || true
import socket, urllib.request, threading, http.server, sys
# 1. Can we bind?
try:
s = socket.socket()
s.bind(("127.0.0.1", 0))
port = s.getsockname()[1]
s.listen(1)
except OSError as e:
print(f"PROBE: localhost-bind → ✗ (bind: {e})")
sys.exit(0)
# 2. Can we GET from our own server over loopback?
class Handler(http.server.BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200); self.end_headers(); self.wfile.write(b"ok")
def log_message(self, *_): pass
server = http.server.HTTPServer(("127.0.0.1", 0), Handler)
threading.Thread(target=server.serve_forever, daemon=True).start()
try:
with urllib.request.urlopen(f"http://127.0.0.1:{server.server_port}/", timeout=5) as r:
body = r.read()
print(f"PROBE: localhost-bind → ✓ (bound + loopback GET → HTTP {r.status}, body={body!r})")
except Exception as e:
print(f"PROBE: localhost-bind → ✗ (bind ok, loopback GET: {type(e).__name__}: {e})")
finally:
server.shutdown()
s.close()
PY
Interpretation:
Result
Status
Meaning
✓ bound + loopback GET → HTTP 200
Pass
Both bind and loopback HTTP work.
✗ bind: ...
Fail
The sandbox blocks bind(2) on 127.0.0.1. Rare.
✗ bind ok, loopback GET: ...
Fail
Bind works but the sandbox egress proxy refuses 127.0.0.1 as a destination. Common shape.
Tests whether the runtime CLI can talk to its daemon. Run for
each of docker / podman that is on PATH; ⊘ each that is
not installed (this is not a sandbox failure, just an absent
prerequisite).
Command:
for rt in docker podman; doif ! command -v "$rt" > /dev/null 2>&1; thenecho"PROBE: ${rt}-runtime → ⊘ ($rt not on PATH)"continuefi
out=$("$rt" info > /dev/null 2>&1 && echo ok || echo"fail:$?")
case"$out"in
ok)
echo"PROBE: ${rt}-runtime → ✓ (${rt} info returned)" ;;
fail:*)
err=$("$rt" info 2>&1 >/dev/null | head -2 | tr'\n'' ')
echo"PROBE: ${rt}-runtime → ✗ ($out: $err)"
;;
esacdone
Interpretation:
Result
Status
Meaning
✓ <rt> info returned
Pass
The CLI reached the daemon successfully.
✗ fail:1: Cannot connect to the Docker daemon …
Fail
Daemon socket not readable from inside the sandbox.
✗ fail:1: connect: permission denied
Fail
Same root cause, different stderr (Linux variant).
All three probes pass (or are not applicable). The sandbox is
not currently blocking the known failure modes catalogued in
docs/setup/sandbox-troubleshooting.md. If you hit a different
sandbox-shaped failure, follow the catalog's Adding a new
entry section and (optionally) extend this skill with a fourth
probe so future runs catch the same shape automatically.
If any probe is ✗:
Surface every fail in one report (do not stop at the first).
For each fail, print the troubleshooting-doc anchor link from
the probe's On ✗ → remediation row above.
Suggest the user open the catalog entry to read the symptom →
root cause → fix shape, then apply the settings.json widening
themselves. Do not propose to apply the widening from this
skill — settings.json widenings are sandbox-bypass-adjacent
and need an explicit user-driven edit.
After the user has applied the widening (in a separate flow),
re-run setup-isolated-setup-doctor to confirm the probe now
passes.
Report the fail with the literal probe command + exit code +
stderr.
Suggest the user add a new entry to the catalog per its
Adding a new entry section (symptom verbatim, root cause,
fix, notes).
Once the catalog has the new entry, extend this skill with a
matching probe in the same shape so the next doctor run
catches it automatically.
Extending the skill with a new probe
When the catalog grows a new entry, add a matching probe section
following the shape above:
Command — a short, deterministic, side-effect-free
one-liner (or short Python heredoc) that triggers the failure
mode reliably.
Interpretation — a 3–5-row table mapping result strings
to ✓ / ✗ / ⊘ / ⚠.
On ✗ → remediation — a direct link to the matching
section of docs/setup/sandbox-troubleshooting.md.
Keep probes narrowly scoped: each probe tests one failure
mode, not a bundle. A probe that conflates two restrictions
makes the report ambiguous when the result is ✗.