axiom-xclog-ref

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

xclog Reference (iOS Simulator Console Capture)

xclog 使用参考(iOS模拟器控制台捕获工具)

xclog captures iOS simulator console output by combining
simctl launch --console
(print/debugPrint/NSLog) with
log stream --style json
(os_log/Logger). Single binary, no dependencies.
xclog 通过结合
simctl launch --console
(捕获print()、debugPrint()、NSLog()输出)与
log stream --style json
(捕获os_log/Logger输出),实现iOS模拟器控制台输出的捕获。它是独立二进制文件,无需依赖其他组件。

Binary Location

二进制文件位置

bash
${CLAUDE_PLUGIN_ROOT}/bin/xclog
bash
${CLAUDE_PLUGIN_ROOT}/bin/xclog

When to Use

适用场景

  • Runtime crashes — capture what the app logged before crashing
  • Silent failures — network calls, data operations that fail without UI feedback
  • Debugging print() output — see what the app is printing to stdout/stderr
  • os_log analysis — structured logging with subsystem, category, and level filtering
  • Automated log capture
    --timeout
    and
    --max-lines
    for bounded collection
  • 运行时崩溃 — 捕获应用崩溃前的日志内容
  • 静默失败 — 无UI反馈的网络请求、数据操作失败场景
  • 调试print()输出 — 查看应用打印到stdout/stderr的内容
  • os_log分析 — 支持按子系统、分类、级别过滤的结构化日志
  • 自动化日志捕获 — 通过
    --timeout
    --max-lines
    参数实现有限范围的日志收集

Critical Best Practices

关键最佳实践

Check
.axiom/preferences.yaml
first.
If no saved preferences, run
list
before
launch
to discover the correct bundle ID.
App already running?
launch
will terminate it and relaunch. Use
attach
if you need to preserve current state (os_log only — no print() capture).
bash
undefined
首先检查
.axiom/preferences.yaml
文件
。如果没有保存的偏好设置,在执行
launch
命令前先运行
list
命令来查找正确的Bundle ID。
应用已在运行?
launch
命令会终止当前应用并重新启动。如果需要保留当前应用状态,请使用
attach
命令(仅支持os_log捕获,无法捕获print()输出)。
bash
undefined

1. FIRST: Check .axiom/preferences.yaml for saved device and bundle ID

1. 第一步:检查.axiom/preferences.yaml中保存的设备和Bundle ID

2. If no preferences: Discover installed apps

2. 如果没有偏好设置:发现已安装的应用

${CLAUDE_PLUGIN_ROOT}/bin/xclog list
${CLAUDE_PLUGIN_ROOT}/bin/xclog list

3. Find the target app's bundle_id from output

3. 从输出中找到目标应用的bundle_id

4. THEN: Launch with the correct bundle ID (restarts app)

4. 然后:使用正确的Bundle ID启动应用(会重启应用)

${CLAUDE_PLUGIN_ROOT}/bin/xclog launch com.example.MyApp --timeout 30s --max-lines 200
${CLAUDE_PLUGIN_ROOT}/bin/xclog launch com.example.MyApp --timeout 30s --max-lines 200

OR: Attach to running app without restarting (os_log only)

或者:附加到运行中的应用而不重启(仅支持os_log)

${CLAUDE_PLUGIN_ROOT}/bin/xclog attach MyApp --timeout 30s --max-lines 200
undefined
${CLAUDE_PLUGIN_ROOT}/bin/xclog attach MyApp --timeout 30s --max-lines 200
undefined

Preferences

偏好设置

Axiom saves simulator preferences to
.axiom/preferences.yaml
in the project root. Check this file before running
xclog list
— if preferences exist, use the saved device and bundle ID directly.
Axiom会将模拟器偏好设置保存到项目根目录下的
.axiom/preferences.yaml
文件中。在运行
xclog list
前先检查该文件
— 如果存在偏好设置,直接使用已保存的设备和Bundle ID。

Reading Preferences

读取偏好设置

Before running
xclog list
, read
.axiom/preferences.yaml
:
yaml
simulator:
  device: iPhone 16 Pro
  deviceUDID: 1A2B3C4D-5E6F-7890-ABCD-EF1234567890
  bundleId: com.example.MyApp
If the file exists and contains a
simulator
section, use the saved
deviceUDID
and
bundleId
for xclog commands. Skip
xclog list
unless the user asks for a different app or the saved values fail.
bash
${CLAUDE_PLUGIN_ROOT}/bin/xclog launch <bundleId> --device <deviceUDID> --timeout 30s --max-lines 200
If the file doesn't exist or the
simulator
section is missing, fall back to
xclog list
discovery.
If the saved
deviceUDID
is not found among available simulators (xclog or simctl fails), fall back to discovery and save the new selection.
If the YAML is malformed, warn the developer and fall back to discovery. Do not overwrite a malformed file.
运行
xclog list
前,先读取
.axiom/preferences.yaml
yaml
simulator:
  device: iPhone 16 Pro
  deviceUDID: 1A2B3C4D-5E6F-7890-ABCD-EF1234567890
  bundleId: com.example.MyApp
如果文件存在且包含
simulator
部分,使用已保存的
deviceUDID
bundleId
执行xclog命令。除非用户需要切换到其他应用,或保存的值无效,否则无需运行
xclog list
bash
${CLAUDE_PLUGIN_ROOT}/bin/xclog launch <bundleId> --device <deviceUDID> --timeout 30s --max-lines 200
如果文件不存在或缺少
simulator
部分,再执行
xclog list
来发现应用。
如果保存的
deviceUDID
在可用模拟器中不存在(xclog或simctl执行失败),重新发现并保存新的选择。
如果YAML文件格式错误,向开发者发出警告并重新发现应用,不要覆盖格式错误的文件。

Writing Preferences

写入偏好设置

After a successful
xclog launch
or when the user selects a target app from
xclog list
output, save the device and bundle ID:
  1. If
    .axiom/
    doesn't exist, create it. Then check
    .gitignore
    : if the file exists, check if any line matches
    .axiom/
    exactly — if not, append
    .axiom/
    on a new line. If
    .gitignore
    doesn't exist, create it with
    .axiom/
    as its content.
  2. Read
    .axiom/preferences.yaml
    if it exists (to preserve other keys)
  3. Update the
    simulator:
    section with
    device
    ,
    deviceUDID
    , and
    bundleId
  4. Write the merged YAML back using the Write tool
Write the same
simulator:
structure shown in Reading Preferences above.
成功执行
xclog launch
后,或用户从
xclog list
输出中选择目标应用后,保存设备和Bundle ID:
  1. 如果
    .axiom/
    目录不存在,创建该目录。然后检查
    .gitignore
    文件:如果文件存在,检查是否有行完全匹配
    .axiom/
    — 如果没有,在新行添加
    .axiom/
    。如果
    .gitignore
    不存在,创建该文件并写入
    .axiom/
  2. 如果
    .axiom/preferences.yaml
    存在,读取该文件(保留其他配置项)
  3. 更新
    simulator:
    部分的
    device
    deviceUDID
    bundleId
  4. 使用写入工具将合并后的YAML写回文件
写入的
simulator:
结构需与上述「读取偏好设置」中的示例一致。

Commands

命令说明

list — Discover Installed Apps

list — 发现已安装应用

bash
${CLAUDE_PLUGIN_ROOT}/bin/xclog list
${CLAUDE_PLUGIN_ROOT}/bin/xclog list --device <udid>
Output (JSON lines):
json
{"bundle_id":"com.example.MyApp","name":"MyApp","version":"1.2.0"}
{"bundle_id":"com.apple.mobilesafari","name":"Safari","version":"18.0"}
bash
${CLAUDE_PLUGIN_ROOT}/bin/xclog list
${CLAUDE_PLUGIN_ROOT}/bin/xclog list --device <udid>
输出(JSON行格式):
json
{"bundle_id":"com.example.MyApp","name":"MyApp","version":"1.2.0"}
{"bundle_id":"com.apple.mobilesafari","name":"Safari","version":"18.0"}

launch — Full Console Capture

launch — 完整控制台捕获

Launches the app and captures ALL output: print(), debugPrint(), NSLog(), os_log(), Logger.
bash
undefined
启动应用并捕获所有输出:print()、debugPrint()、NSLog()、os_log()、Logger。
bash
undefined

Basic launch (JSON output, runs until app exits or Ctrl-C)

基础启动(JSON输出,直到应用退出或按下Ctrl-C)

${CLAUDE_PLUGIN_ROOT}/bin/xclog launch com.example.MyApp
${CLAUDE_PLUGIN_ROOT}/bin/xclog launch com.example.MyApp

Bounded capture (recommended for LLM use)

有限范围捕获(推荐LLM场景使用)

${CLAUDE_PLUGIN_ROOT}/bin/xclog launch com.example.MyApp --timeout 30s --max-lines 200
${CLAUDE_PLUGIN_ROOT}/bin/xclog launch com.example.MyApp --timeout 30s --max-lines 200

Filter by subsystem

按子系统过滤

${CLAUDE_PLUGIN_ROOT}/bin/xclog launch com.example.MyApp --subsystem com.example.MyApp.networking
${CLAUDE_PLUGIN_ROOT}/bin/xclog launch com.example.MyApp --subsystem com.example.MyApp.networking

Filter by regex

按正则表达式过滤

${CLAUDE_PLUGIN_ROOT}/bin/xclog launch com.example.MyApp --filter "error|warning|crash"
${CLAUDE_PLUGIN_ROOT}/bin/xclog launch com.example.MyApp --filter "error|warning|crash"

Save to file

保存到文件

${CLAUDE_PLUGIN_ROOT}/bin/xclog launch com.example.MyApp --output /tmp/console.log --timeout 60s
undefined
${CLAUDE_PLUGIN_ROOT}/bin/xclog launch com.example.MyApp --output /tmp/console.log --timeout 60s
undefined

attach — Monitor Running Process

attach — 监控运行中的进程

Attaches to a running process via os_log only. Does NOT capture print()/debugPrint(). Simulator only.
bash
undefined
仅通过os_log附加到运行中的进程,无法捕获print()/debugPrint()输出,仅支持模拟器。
bash
undefined

By process name

通过进程名

${CLAUDE_PLUGIN_ROOT}/bin/xclog attach MyApp --timeout 30s
${CLAUDE_PLUGIN_ROOT}/bin/xclog attach MyApp --timeout 30s

By PID

通过PID

${CLAUDE_PLUGIN_ROOT}/bin/xclog attach 12345 --max-lines 100
${CLAUDE_PLUGIN_ROOT}/bin/xclog attach 12345 --max-lines 100

Filter for errors only

仅过滤错误信息

${CLAUDE_PLUGIN_ROOT}/bin/xclog attach MyApp --filter "(?i)error|fault"
undefined
${CLAUDE_PLUGIN_ROOT}/bin/xclog attach MyApp --filter "(?i)error|fault"
undefined

show — Historical Log Search (Simulator + Physical Device)

show — 历史日志搜索(模拟器+物理设备)

Searches recent logs without needing proactive capture. Works with both simulator and connected physical devices.
bash
undefined
无需提前捕获,直接搜索近期日志。支持模拟器和已连接的物理设备。
bash
undefined

Simulator: show last 5 minutes of MyApp logs

模拟器:显示MyApp最近5分钟的日志

${CLAUDE_PLUGIN_ROOT}/bin/xclog show MyApp --last 5m --max-lines 200
${CLAUDE_PLUGIN_ROOT}/bin/xclog show MyApp --last 5m --max-lines 200

Simulator: show last 10 minutes, errors only

模拟器:显示最近10分钟的日志,仅包含错误

${CLAUDE_PLUGIN_ROOT}/bin/xclog show MyApp --last 10m --max-lines 100 --filter "(?i)error|fault"
${CLAUDE_PLUGIN_ROOT}/bin/xclog show MyApp --last 10m --max-lines 100 --filter "(?i)error|fault"

Physical device: collect and show logs (device must be connected + unlocked)

物理设备:收集并显示日志(设备需已连接且解锁)

${CLAUDE_PLUGIN_ROOT}/bin/xclog show MyApp --device-udid 00008101-... --last 5m --max-lines 200
${CLAUDE_PLUGIN_ROOT}/bin/xclog show MyApp --device-udid 00008101-... --last 5m --max-lines 200

By PID

通过PID

${CLAUDE_PLUGIN_ROOT}/bin/xclog show 12345 --last 2m

**Physical device workflow**: `show --device-udid` runs `log collect` to pull a log archive from the device over USB, then parses it locally. The device must be connected and unlocked.

**When to use `show` vs `attach`**:
- `show` — "What just happened?" (post-mortem, no setup needed)
- `attach` — "What's happening now?" (live streaming, must be running before the event)
${CLAUDE_PLUGIN_ROOT}/bin/xclog show 12345 --last 2m

**物理设备工作流**:`show --device-udid`命令会执行`log collect`,通过USB从设备拉取日志归档,然后在本地解析。设备必须已连接且处于解锁状态。

**`show`与`attach`的适用场景对比**:
- `show` — 「刚才发生了什么?」(事后分析,无需提前配置)
- `attach` — 「现在正在发生什么?」(实时流,需在事件发生前启动)

Output Format

输出格式

Default output is JSON lines (one JSON object per line).
默认输出为JSON行格式(每行一个JSON对象)。

JSON Schema (Default)

JSON Schema(默认)

json
{
  "time": "10:30:45.123",
  "source": "os_log",
  "level": "error",
  "subsystem": "com.example.MyApp",
  "category": "networking",
  "process": "MyApp",
  "pid": 12345,
  "text": "Connection failed: timeout"
}
FieldTypePresentDescription
timestringAlwaysHH:MM:SS.mmm timestamp
sourcestringAlways
"print"
,
"stderr"
, or
"os_log"
levelstringos_log only
"debug"
,
"default"
,
"info"
,
"error"
,
"fault"
subsystemstringos_log onlyReverse-DNS subsystem (e.g.
com.example.MyApp
)
categorystringos_log onlyLog category within subsystem
processstringos_log onlyProcess binary name
pidintos_log onlyProcess ID
textstringAlwaysThe log message content
Fields not applicable to a source are omitted (not null).
json
{
  "time": "10:30:45.123",
  "source": "os_log",
  "level": "error",
  "subsystem": "com.example.MyApp",
  "category": "networking",
  "process": "MyApp",
  "pid": 12345,
  "text": "Connection failed: timeout"
}
字段类型是否存在说明
timestring始终存在HH:MM:SS.mmm时间戳
sourcestring始终存在
"print"
"stderr"
"os_log"
levelstring仅os_log
"debug"
"default"
"info"
"error"
"fault"
subsystemstring仅os_log反向DNS格式的子系统(如
com.example.MyApp
categorystring仅os_log子系统内的日志分类
processstring仅os_log进程二进制文件名
pidint仅os_log进程ID
textstring始终存在日志消息内容
不适用于当前日志源的字段会被省略(不会设为null)。

Human-Readable Mode

人类可读模式

bash
${CLAUDE_PLUGIN_ROOT}/bin/xclog attach MyApp --human
${CLAUDE_PLUGIN_ROOT}/bin/xclog attach MyApp --human --no-color
bash
${CLAUDE_PLUGIN_ROOT}/bin/xclog attach MyApp --human
${CLAUDE_PLUGIN_ROOT}/bin/xclog attach MyApp --human --no-color

Options Reference

选项参考

OptionDefaultDescription
--device <udid>
booted
Target simulator UDID
--device-udid <udid>
nonePhysical device UDID (show command)
--output <file>
stdoutAlso write to file
--human
offHuman-readable colored output
--no-color
offDisable ANSI colors (--human mode)
--filter <regex>
noneFilter lines by Go regex
--subsystem <name>
noneFilter os_log by subsystem
--max-lines <n>
0 (unlimited)Stop after n lines
--timeout <duration>
0 (unlimited)Stop after duration (e.g.
30s
,
5m
)
--last <duration>
5m
How far back to search (show command)
选项默认值说明
--device <udid>
booted
目标模拟器UDID
--device-udid <udid>
物理设备UDID(仅show命令)
--output <file>
stdout同时将输出写入文件
--human
关闭人类可读的彩色输出
--no-color
关闭禁用ANSI颜色(仅--human模式)
--filter <regex>
使用Go正则表达式过滤日志行
--subsystem <name>
按子系统过滤os_log
--max-lines <n>
0(无限制)捕获n行后停止
--timeout <duration>
0(无限制)持续指定时长后停止(如
30s
5m
--last <duration>
5m
搜索的时间范围(仅show命令)

Coverage by Source

各命令支持的日志源

Swift APIlaunchattachshow
print()
yesnono
debugPrint()
yesnono
NSLog()
yesyesyes
os_log()
yesyesyes
Logger
yesyesyes
SimulatorPhysical Device
launch
yesno
attach
yesno
show
yesyes
Logger
yesyes
Use
launch
for full coverage.
attach
is for monitoring already-running processes.
Note:
launch
terminates any existing instance of the app before relaunching. If the app is already running and you don't want to restart it, use
attach
(os_log only).
Swift APIlaunchattachshow
print()
debugPrint()
NSLog()
os_log()
Logger
命令模拟器物理设备
launch
attach
show
Logger
推荐使用
launch
以获得完整的日志覆盖
attach
仅适用于监控已运行的进程。
注意
launch
命令会终止应用的现有实例并重新启动。如果应用已在运行且你不想重启它,请使用
attach
命令(仅支持os_log)。

Error Behavior

错误处理

xclog prints errors to stderr and exits with code 1. Common errors:
ErrorCauseFix
simctl launch: ...
Bad bundle ID or no booted simulatorRun
xclog list
to verify bundle ID; check
xcrun simctl list devices booted
could not parse PID from simctl output
App failed to launchCheck the app builds and runs in the simulator
invalid filter regex
Bad
--filter
pattern
Check Go regex syntax (similar to RE2)
invalid subsystem
Subsystem contains spaces or special charactersUse reverse-DNS format:
com.example.MyApp
(alphanumeric, dots, underscores, hyphens only)
xclog会将错误信息打印到stderr并以代码1退出。常见错误:
错误信息原因解决方法
simctl launch: ...
Bundle ID无效或没有已启动的模拟器运行
xclog list
验证Bundle ID;执行
xcrun simctl list devices booted
检查模拟器状态
could not parse PID from simctl output
应用启动失败检查应用是否能在模拟器中正常构建和运行
invalid filter regex
--filter
参数的正则表达式格式错误
检查Go正则表达式语法(与RE2类似)
invalid subsystem
子系统名称包含空格或特殊字符使用反向DNS格式:
com.example.MyApp
(仅允许字母、数字、点、下划线、连字符)

Interpreting Output

输出解读

Filtering by Level

按级别过滤

os_log levels indicate severity. For crash diagnosis, focus on
error
and
fault
.
Note:
--filter
matches against the message text, not the JSON output. To filter by level, use jq:
bash
${CLAUDE_PLUGIN_ROOT}/bin/xclog launch com.example.MyApp --timeout 30s 2>/dev/null | jq -c 'select(.level == "error" or .level == "fault")'
For text-based filtering,
--filter
works on message content:
bash
undefined
os_log的级别表示日志的严重程度。诊断崩溃时,重点关注
error
fault
级别。
注意
--filter
参数匹配的是日志消息文本,而非JSON输出。如果需要按级别过滤,请使用jq:
bash
${CLAUDE_PLUGIN_ROOT}/bin/xclog launch com.example.MyApp --timeout 30s 2>/dev/null | jq -c 'select(.level == "error" or .level == "fault")'
基于文本内容过滤时,
--filter
参数作用于日志消息:
bash
undefined

Filter messages containing "error" or "failed" (case-insensitive)

过滤包含"error"或"failed"的消息(不区分大小写)

${CLAUDE_PLUGIN_ROOT}/bin/xclog launch com.example.MyApp --filter "(?i)error|failed"
undefined
${CLAUDE_PLUGIN_ROOT}/bin/xclog launch com.example.MyApp --filter "(?i)error|failed"
undefined

Common Subsystem Patterns

常见子系统模式

SubsystemWhat it indicates
com.apple.network
URLSession / networking layer
com.apple.coredata
Core Data / persistence
com.apple.swiftui
SwiftUI framework
com.apple.uikit
UIKit framework
App's own subsystemApplication-level logging
子系统含义
com.apple.network
URLSession/网络层
com.apple.coredata
Core Data/持久化层
com.apple.swiftui
SwiftUI框架
com.apple.uikit
UIKit框架
应用自身的子系统应用级日志

Workflow: Diagnose a Runtime Crash

工作流:诊断运行时崩溃

  1. xclog list
    → find bundle ID
  2. xclog launch <bundle-id> --timeout 60s --max-lines 500 --output /tmp/crash.log
    → start capture (this restarts the app — expected)
  3. Reproduce the crash in the simulator
  4. Read
    /tmp/crash.log
    and filter for errors:
    jq 'select(.level == "error" or .level == "fault")' /tmp/crash.log
  5. Check the last few lines before the stream ended (crash point)
If the crash is intermittent, increase bounds:
--timeout 120s --max-lines 1000
and repeat.
  1. xclog list
    → 查找Bundle ID
  2. xclog launch <bundle-id> --timeout 60s --max-lines 500 --output /tmp/crash.log
    → 启动捕获(会重启应用,属于正常行为)
  3. 在模拟器中复现崩溃
  4. 读取
    /tmp/crash.log
    并过滤错误:
    jq 'select(.level == "error" or .level == "fault")' /tmp/crash.log
  5. 检查流结束前的最后几行(崩溃发生点)
如果崩溃是间歇性的,扩大捕获范围:
--timeout 120s --max-lines 1000
并重复上述步骤。

Workflow: Investigate Silent Failure

工作流:调查静默失败

  1. xclog launch <bundle-id> --subsystem com.example.MyApp --timeout 30s
  2. Trigger the failing operation
  3. Look for error-level messages in the app's subsystem
  4. Cross-reference with network or data subsystems if app logs are silent
  1. xclog launch <bundle-id> --subsystem com.example.MyApp --timeout 30s
  2. 触发失败操作
  3. 在应用的子系统中查找错误级别的消息
  4. 如果应用日志没有相关信息,交叉查看网络或数据子系统的日志

Resources

相关资源

Skills: axiom-xcode-debugging, axiom-performance-profiling, axiom-lldb
Skills: axiom-xcode-debugging, axiom-performance-profiling, axiom-lldb