axiom-xclog-ref
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesexclog Reference (iOS Simulator Console Capture)
xclog 使用参考(iOS模拟器控制台捕获工具)
xclog captures iOS simulator console output by combining (print/debugPrint/NSLog) with (os_log/Logger). Single binary, no dependencies.
simctl launch --consolelog stream --style jsonxclog 通过结合(捕获print()、debugPrint()、NSLog()输出)与(捕获os_log/Logger输出),实现iOS模拟器控制台输出的捕获。它是独立二进制文件,无需依赖其他组件。
simctl launch --consolelog stream --style jsonBinary Location
二进制文件位置
bash
${CLAUDE_PLUGIN_ROOT}/bin/xclogbash
${CLAUDE_PLUGIN_ROOT}/bin/xclogWhen 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 — and
--timeoutfor bounded collection--max-lines
- 运行时崩溃 — 捕获应用崩溃前的日志内容
- 静默失败 — 无UI反馈的网络请求、数据操作失败场景
- 调试print()输出 — 查看应用打印到stdout/stderr的内容
- os_log分析 — 支持按子系统、分类、级别过滤的结构化日志
- 自动化日志捕获 — 通过和
--timeout参数实现有限范围的日志收集--max-lines
Critical Best Practices
关键最佳实践
Check first. If no saved preferences, run before to discover the correct bundle ID.
.axiom/preferences.yamllistlaunchApp already running? will terminate it and relaunch. Use if you need to preserve current state (os_log only — no print() capture).
launchattachbash
undefined首先检查文件。如果没有保存的偏好设置,在执行命令前先运行命令来查找正确的Bundle ID。
.axiom/preferences.yamllaunchlist应用已在运行? 命令会终止当前应用并重新启动。如果需要保留当前应用状态,请使用命令(仅支持os_log捕获,无法捕获print()输出)。
launchattachbash
undefined1. 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
undefinedPreferences
偏好设置
Axiom saves simulator preferences to in the project root. Check this file before running — if preferences exist, use the saved device and bundle ID directly.
.axiom/preferences.yamlxclog listAxiom会将模拟器偏好设置保存到项目根目录下的文件中。在运行前先检查该文件 — 如果存在偏好设置,直接使用已保存的设备和Bundle ID。
.axiom/preferences.yamlxclog listReading Preferences
读取偏好设置
Before running , read :
xclog list.axiom/preferences.yamlyaml
simulator:
device: iPhone 16 Pro
deviceUDID: 1A2B3C4D-5E6F-7890-ABCD-EF1234567890
bundleId: com.example.MyAppIf the file exists and contains a section, use the saved and for xclog commands. Skip unless the user asks for a different app or the saved values fail.
simulatordeviceUDIDbundleIdxclog listbash
${CLAUDE_PLUGIN_ROOT}/bin/xclog launch <bundleId> --device <deviceUDID> --timeout 30s --max-lines 200If the file doesn't exist or the section is missing, fall back to discovery.
simulatorxclog listIf the saved is not found among available simulators (xclog or simctl fails), fall back to discovery and save the new selection.
deviceUDIDIf the YAML is malformed, warn the developer and fall back to discovery. Do not overwrite a malformed file.
运行前,先读取:
xclog list.axiom/preferences.yamlyaml
simulator:
device: iPhone 16 Pro
deviceUDID: 1A2B3C4D-5E6F-7890-ABCD-EF1234567890
bundleId: com.example.MyApp如果文件存在且包含部分,使用已保存的和执行xclog命令。除非用户需要切换到其他应用,或保存的值无效,否则无需运行。
simulatordeviceUDIDbundleIdxclog listbash
${CLAUDE_PLUGIN_ROOT}/bin/xclog launch <bundleId> --device <deviceUDID> --timeout 30s --max-lines 200如果文件不存在或缺少部分,再执行来发现应用。
simulatorxclog list如果保存的在可用模拟器中不存在(xclog或simctl执行失败),重新发现并保存新的选择。
deviceUDID如果YAML文件格式错误,向开发者发出警告并重新发现应用,不要覆盖格式错误的文件。
Writing Preferences
写入偏好设置
After a successful or when the user selects a target app from output, save the device and bundle ID:
xclog launchxclog list- If doesn't exist, create it. Then check
.axiom/: if the file exists, check if any line matches.gitignoreexactly — if not, append.axiom/on a new line. If.axiom/doesn't exist, create it with.gitignoreas its content..axiom/ - Read if it exists (to preserve other keys)
.axiom/preferences.yaml - Update the section with
simulator:,device, anddeviceUDIDbundleId - Write the merged YAML back using the Write tool
Write the same structure shown in Reading Preferences above.
simulator:成功执行后,或用户从输出中选择目标应用后,保存设备和Bundle ID:
xclog launchxclog list- 如果目录不存在,创建该目录。然后检查
.axiom/文件:如果文件存在,检查是否有行完全匹配.gitignore— 如果没有,在新行添加.axiom/。如果.axiom/不存在,创建该文件并写入.gitignore。.axiom/ - 如果存在,读取该文件(保留其他配置项)
.axiom/preferences.yaml - 更新部分的
simulator:、device和deviceUDIDbundleId - 使用写入工具将合并后的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
undefinedBasic 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
undefinedattach — 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
undefinedBy 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"
undefinedshow — 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
undefinedSimulator: 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"
}| Field | Type | Present | Description |
|---|---|---|---|
| time | string | Always | HH:MM:SS.mmm timestamp |
| source | string | Always | |
| level | string | os_log only | |
| subsystem | string | os_log only | Reverse-DNS subsystem (e.g. |
| category | string | os_log only | Log category within subsystem |
| process | string | os_log only | Process binary name |
| pid | int | os_log only | Process ID |
| text | string | Always | The 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"
}| 字段 | 类型 | 是否存在 | 说明 |
|---|---|---|---|
| time | string | 始终存在 | HH:MM:SS.mmm时间戳 |
| source | string | 始终存在 | |
| level | string | 仅os_log | |
| subsystem | string | 仅os_log | 反向DNS格式的子系统(如 |
| category | string | 仅os_log | 子系统内的日志分类 |
| process | string | 仅os_log | 进程二进制文件名 |
| pid | int | 仅os_log | 进程ID |
| text | string | 始终存在 | 日志消息内容 |
不适用于当前日志源的字段会被省略(不会设为null)。
Human-Readable Mode
人类可读模式
bash
${CLAUDE_PLUGIN_ROOT}/bin/xclog attach MyApp --human
${CLAUDE_PLUGIN_ROOT}/bin/xclog attach MyApp --human --no-colorbash
${CLAUDE_PLUGIN_ROOT}/bin/xclog attach MyApp --human
${CLAUDE_PLUGIN_ROOT}/bin/xclog attach MyApp --human --no-colorOptions Reference
选项参考
| Option | Default | Description |
|---|---|---|
| | Target simulator UDID |
| none | Physical device UDID (show command) |
| stdout | Also write to file |
| off | Human-readable colored output |
| off | Disable ANSI colors (--human mode) |
| none | Filter lines by Go regex |
| none | Filter os_log by subsystem |
| 0 (unlimited) | Stop after n lines |
| 0 (unlimited) | Stop after duration (e.g. |
| | How far back to search (show command) |
| 选项 | 默认值 | 说明 |
|---|---|---|
| | 目标模拟器UDID |
| 无 | 物理设备UDID(仅show命令) |
| stdout | 同时将输出写入文件 |
| 关闭 | 人类可读的彩色输出 |
| 关闭 | 禁用ANSI颜色(仅--human模式) |
| 无 | 使用Go正则表达式过滤日志行 |
| 无 | 按子系统过滤os_log |
| 0(无限制) | 捕获n行后停止 |
| 0(无限制) | 持续指定时长后停止(如 |
| | 搜索的时间范围(仅show命令) |
Coverage by Source
各命令支持的日志源
| Swift API | launch | attach | show |
|---|---|---|---|
| yes | no | no |
| yes | no | no |
| yes | yes | yes |
| yes | yes | yes |
| yes | yes | yes |
| Simulator | Physical Device | |
|---|---|---|
| yes | no |
| yes | no |
| yes | yes |
| yes | yes |
Use for full coverage. is for monitoring already-running processes.
launchattachNote: terminates any existing instance of the app before relaunching. If the app is already running and you don't want to restart it, use (os_log only).
launchattach| Swift API | launch | attach | show |
|---|---|---|---|
| 是 | 否 | 否 |
| 是 | 否 | 否 |
| 是 | 是 | 是 |
| 是 | 是 | 是 |
| 是 | 是 | 是 |
| 命令 | 模拟器 | 物理设备 |
|---|---|---|
| 是 | 否 |
| 是 | 否 |
| 是 | 是 |
| 是 | 是 |
推荐使用以获得完整的日志覆盖。仅适用于监控已运行的进程。
launchattach注意:命令会终止应用的现有实例并重新启动。如果应用已在运行且你不想重启它,请使用命令(仅支持os_log)。
launchattachError Behavior
错误处理
xclog prints errors to stderr and exits with code 1. Common errors:
| Error | Cause | Fix |
|---|---|---|
| Bad bundle ID or no booted simulator | Run |
| App failed to launch | Check the app builds and runs in the simulator |
| Bad | Check Go regex syntax (similar to RE2) |
| Subsystem contains spaces or special characters | Use reverse-DNS format: |
xclog会将错误信息打印到stderr并以代码1退出。常见错误:
| 错误信息 | 原因 | 解决方法 |
|---|---|---|
| Bundle ID无效或没有已启动的模拟器 | 运行 |
| 应用启动失败 | 检查应用是否能在模拟器中正常构建和运行 |
| | 检查Go正则表达式语法(与RE2类似) |
| 子系统名称包含空格或特殊字符 | 使用反向DNS格式: |
Interpreting Output
输出解读
Filtering by Level
按级别过滤
os_log levels indicate severity. For crash diagnosis, focus on and .
errorfaultNote: matches against the message text, not the JSON output. To filter by level, use jq:
--filterbash
${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, works on message content:
--filterbash
undefinedos_log的级别表示日志的严重程度。诊断崩溃时,重点关注和级别。
errorfault注意:参数匹配的是日志消息文本,而非JSON输出。如果需要按级别过滤,请使用jq:
--filterbash
${CLAUDE_PLUGIN_ROOT}/bin/xclog launch com.example.MyApp --timeout 30s 2>/dev/null | jq -c 'select(.level == "error" or .level == "fault")'基于文本内容过滤时,参数作用于日志消息:
--filterbash
undefinedFilter 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"
undefinedCommon Subsystem Patterns
常见子系统模式
| Subsystem | What it indicates |
|---|---|
| URLSession / networking layer |
| Core Data / persistence |
| SwiftUI framework |
| UIKit framework |
| App's own subsystem | Application-level logging |
| 子系统 | 含义 |
|---|---|
| URLSession/网络层 |
| Core Data/持久化层 |
| SwiftUI框架 |
| UIKit框架 |
| 应用自身的子系统 | 应用级日志 |
Workflow: Diagnose a Runtime Crash
工作流:诊断运行时崩溃
- → find bundle ID
xclog list - → start capture (this restarts the app — expected)
xclog launch <bundle-id> --timeout 60s --max-lines 500 --output /tmp/crash.log - Reproduce the crash in the simulator
- Read and filter for errors:
/tmp/crash.logjq 'select(.level == "error" or .level == "fault")' /tmp/crash.log - Check the last few lines before the stream ended (crash point)
If the crash is intermittent, increase bounds: and repeat.
--timeout 120s --max-lines 1000- → 查找Bundle ID
xclog list - → 启动捕获(会重启应用,属于正常行为)
xclog launch <bundle-id> --timeout 60s --max-lines 500 --output /tmp/crash.log - 在模拟器中复现崩溃
- 读取并过滤错误:
/tmp/crash.logjq 'select(.level == "error" or .level == "fault")' /tmp/crash.log - 检查流结束前的最后几行(崩溃发生点)
如果崩溃是间歇性的,扩大捕获范围:并重复上述步骤。
--timeout 120s --max-lines 1000Workflow: Investigate Silent Failure
工作流:调查静默失败
xclog launch <bundle-id> --subsystem com.example.MyApp --timeout 30s- Trigger the failing operation
- Look for error-level messages in the app's subsystem
- Cross-reference with network or data subsystems if app logs are silent
xclog launch <bundle-id> --subsystem com.example.MyApp --timeout 30s- 触发失败操作
- 在应用的子系统中查找错误级别的消息
- 如果应用日志没有相关信息,交叉查看网络或数据子系统的日志
Resources
相关资源
Skills: axiom-xcode-debugging, axiom-performance-profiling, axiom-lldb
Skills: axiom-xcode-debugging, axiom-performance-profiling, axiom-lldb