Use this reference when the user asks to record a new trace — either to attach to a running app, launch one fresh, or capture a specific session of actions they'll perform interactively.
The bundled scripts/record_trace.py wraps xctrace record with:
- The SwiftUI template by default (override with
--template). - Manual stop via Ctrl+C, a stop-file, or
--time-limit. - JSON discovery for devices and templates.
- Normal Python exit codes so an agent can orchestrate.
- Redacted command logging for values passed through
--env. - An explicit acknowledgement gate for system-wide recordings.
Prefer --attach or --launch, which limits collection to the app being
diagnosed. A system-wide recording can capture activity and metadata from
unrelated applications. Before using --all-processes, explain that scope to
the user and obtain their explicit approval. Then pass
--allow-system-wide-recording to record that acknowledgement in the command.
Values passed through --env KEY=VALUE are forwarded to xctrace, but the
wrapper redacts each value from its displayed command. Avoid placing secrets on
command lines when a safer launch configuration is available, because other
local process-inspection tools may still expose process arguments.
python3 "${SKILL_DIR}/scripts/record_trace.py" \
--device "Pol's iPhone" \
--attach "Helm" \
--output ~/Desktop/helm-session.traceLeave it running while the user exercises the app. Stop with Ctrl+C.
python3 "${SKILL_DIR}/scripts/record_trace.py" \
--device "<UDID>" \
--launch "/path/to/App.app" \
--output ~/Desktop/launch.traceUseful for diagnosing cold-start hitches and view-creation cost.
When you (the agent) are running non-interactively — e.g. via
Bash run_in_background — use a stop-file so you can signal the
recording to end cleanly:
# Start recording (background)
python3 "${SKILL_DIR}/scripts/record_trace.py" \
--attach Helm --stop-file /tmp/stop-trace \
--output ~/Desktop/session.trace
# ...user does their thing...
# Stop cleanly (from another shell or tool call)
touch /tmp/stop-traceThe script polls every 0.5s for the stop-file, sends SIGINT to xctrace when it appears, and waits up to 60s for the trace to finalise.
python3 "${SKILL_DIR}/scripts/record_trace.py" \
--attach Helm --time-limit 30s --output ~/Desktop/30s.tracexctrace stops itself at the limit.
# List every connected device, simulator, and the host — JSON.
python3 "${SKILL_DIR}/scripts/record_trace.py" --list-devices
# List all Instruments templates — JSON with a flat list + by-section map.
python3 "${SKILL_DIR}/scripts/record_trace.py" --list-templatesDevice entries have kind (devices, devices offline, simulators),
name, os, udid. Offline devices are known but unplugged / unpaired —
plug them in before recording.
Hard rule: the
SwiftUItemplate only populates the SwiftUI lane on a real device — a physical iOS/iPadOS device or the host Mac. On the iOS Simulator it records but the SwiftUI lane comes back empty. If the chosen UDID falls under thesimulatorskind from--list-devices, switch toTime Profiler. It still gives you Time Profiler + Hangs + Animation Hitches, whichanalyze_trace.pyanalyses and correlates normally; only theswiftuilane will reportavailable: false.
Decision flow:
| Target | Template to pass |
|---|---|
| Physical iOS/iPadOS device (connected) | SwiftUI (default) |
Host Mac (macOS app, --all-processes, etc.) |
SwiftUI (default) |
| iOS / iPadOS / watchOS / tvOS Simulator | Time Profiler |
Always confirm the target kind with --list-devices before starting a
recording: entries under simulators mean you must switch to Time
Profiler; entries under devices (both connected devices and the host
Mac) support the SwiftUI template. Entries under devices offline need
the user to connect/unlock/trust the device before recording.
For ad-hoc hang hunting on any target, Time Profiler or
Animation Hitches alone may be enough.
For an explicitly approved system-wide recording:
python3 "${SKILL_DIR}/scripts/record_trace.py" \
--all-processes --allow-system-wide-recording \
--time-limit 30s --output ~/Desktop/system-wide.traceThe recording script prints trace written: <path> on exit. Feed that
path straight into analyze_trace.py:
TRACE=$(python3 "${SKILL_DIR}/scripts/record_trace.py" \
--attach Helm --stop-file /tmp/stop-trace --output ~/Desktop/session.trace \
2>&1 | awk '/trace written:/ {print $NF}')
python3 "${SKILL_DIR}/scripts/analyze_trace.py" --trace "$TRACE" --json-onlyIf the user wanted a specific scope, combine with --list-logs /
--list-signposts / --window from references/trace-analysis.md.
- Device offline —
--list-devicesshows it indevices offline. Ask the user to connect/unlock the device and retry. - Output path exists — the script refuses to overwrite. Either pick
a new
--outputor delete the existing bundle. - App not running (for
--attach) — xctrace exits with an error; fall back to--launchor tell the user to open the app first. - Signing / trust on device — iOS requires a development build signed with the user's team. If xctrace returns a signing error, point the user to trust the developer profile on the device.