mcpField
A
axiom-xclog-ref

axiom-xclog-ref

github.com/charleswiltgen开发1.2k47 次安装今天更新
代码仓库

关于 axiom-xclog-ref

这是 xclog 的参考技能;xclog 是无需依赖的二进制工具,可捕获 iOS 模拟器控制台日志,也可查询连接设备的历史日志,供开发者排查崩溃、静默故障和 Swift 日志问题。

主要功能

  1. 01捕获 print、debugPrint、NSLog、os_log 和 Logger
  2. 02列出模拟器中已安装的应用
  3. 03启动应用并监控日志
  4. 04查询模拟器或设备的近期日志
  5. 05过滤输出并限制采集时长或行数

适用场景

  1. 01检查应用崩溃前的日志
  2. 02追踪界面无反馈的故障
  3. 03按子系统或级别查看结构化日志
  4. 04采集限定范围的日志流用于调试

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/charleswiltgen/axiom --skill axiom-xclog-ref

安装后在 Claude Code 中输入/axiom-xclog-ref确认已加载。

详细介绍

xclog 参考(iOS 模拟器控制台捕获)

xclog 通过结合 simctl launch --console(print/debugPrint/NSLog)与 log stream --style json(os_log/Logger)来捕获 iOS 模拟器控制台输出。单个二进制文件,无依赖项。

二进制文件位置

${CLAUDE_PLUGIN_ROOT}/bin/xclog

适用场景

  • 运行时崩溃 — 捕获应用崩溃前输出的日志
  • 静默失败 — 捕获没有 UI 反馈的网络调用、数据操作失败
  • 调试 print() 输出 — 查看应用输出到 stdout/stderr 的内容
  • os_log 分析 — 按子系统、类别和级别筛选结构化日志
  • 自动化日志捕获 — 使用 --timeout 和 --max-lines 限制收集范围

关键最佳实践

先检查 .axiom/preferences.yaml。 如果没有已保存的偏好设置,先运行 list,再运行 launch,以查找正确的 bundle ID。

应用已在运行? launch 会终止并重新启动应用。如果需要保留当前状态,请使用 attach(仅限 os_log — 不捕获 print())。

# 1. FIRST: Check .axiom/preferences.yaml for saved device and bundle ID
# 2. If no preferences: Discover installed apps
${CLAUDE_PLUGIN_ROOT}/bin/xclog list

# 3. Find the target app's bundle_id from output
# 4. THEN: Launch with the correct bundle ID (restarts app)
${CLAUDE_PLUGIN_ROOT}/bin/xclog launch com.example.MyApp --timeout 30s --max-lines 200

# OR: Attach to running app without restarting (os_log only)
${CLAUDE_PLUGIN_ROOT}/bin/xclog attach MyApp --timeout 30s --max-lines 200

偏好设置

Axiom 会将模拟器偏好设置保存到项目根目录下的 .axiom/preferences.yaml。运行 xclog list 前请先检查此文件 — 如果存在偏好设置,请直接使用已保存的设备和 bundle ID。

读取偏好设置

运行 xclog list 前,请先读取 .axiom/preferences.yaml:

simulator:
  device: iPhone 16 Pro
  deviceUDID: 1A2B3C4D-5E6F-7890-ABCD-EF1234567890
  bundleId: com.example.MyApp

如果文件存在且包含 simulator 部分,请在 xclog 命令中使用已保存的 deviceUDID 和 bundleId。除非用户要求使用其他应用,或已保存的值无效,否则跳过 xclog list。

${CLAUDE_PLUGIN_ROOT}/bin/xclog launch <bundleId> --device <deviceUDID> --timeout 30s --max-lines 200

如果文件不存在或缺少 simulator 部分,则回退到通过 xclog list 查找。

如果在可用模拟器中找不到已保存的 deviceUDID(xclog 或 simctl 运行失败),则回退到查找并保存新的选择。

如果 YAML 格式错误,请提醒开发者并回退到查找。不要覆盖格式错误的文件。

写入偏好设置

成功运行 xclog launch 后,或用户从 xclog list 输出中选择目标应用后,保存设备和 bundle ID:

  1. 如果 .axiom/ 不存在,请创建它。然后检查 .gitignore:如果文件存在,请检查是否有某一行与 .axiom/ 完全匹配;如果没有,请在新行中追加 .axiom/。如果 .gitignore 不存在,请创建该文件,并将 .axiom/ 作为其内容。
  2. 如果 .axiom/preferences.yaml 存在,请读取它(以保留其他键)
  3. 使用 device、deviceUDID 和 bundleId 更新 simulator: 部分
  4. 使用 Write 工具写入合并后的 YAML

写入与上文“读取偏好设置”中所示相同的 simulator: 结构。

命令

list — 查找已安装的应用
${CLAUDE_PLUGIN_ROOT}/bin/xclog list
${CLAUDE_PLUGIN_ROOT}/bin/xclog list --device <udid>

输出(JSON 行):

{"bundle_id":"com.example.MyApp","name":"MyApp","version":"1.2.0"}
{"bundle_id":"com.apple.mobilesafari","name":"Safari","version":"18.0"}
launch — 完整控制台捕获

启动应用并捕获全部输出:print()、debugPrint()、NSLog()、os_log()、Logger。

# Basic launch (JSON output, runs until app exits or Ctrl-C)
${CLAUDE_PLUGIN_ROOT}/bin/xclog launch com.example.MyApp

# Bounded capture (recommended for LLM use)
${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

# Filter by regex
${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
attach — 监控运行中的进程

仅通过 os_log 附加到运行中的进程。不捕获 print()/debugPrint()。仅限模拟器。

# By process name
${CLAUDE_PLUGIN_ROOT}/bin/xclog attach MyApp --timeout 30s

# By PID
${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"
show — 搜索历史日志(模拟器 + 实体设备)

搜索近期日志,无需预先启动捕获。适用于模拟器和已连接的实体设备。

# Simulator: show last 5 minutes of MyApp logs
${CLAUDE_PLUGIN_ROOT}/bin/xclog show MyApp --last 5m --max-lines 200

# Simulator: show last 10 minutes, errors only
${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

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

实体设备工作流:show --device-udid 会运行 log collect,通过 USB 从设备提取日志归档,然后在本地解析。设备必须已连接且已解锁。

何时使用 show 或 attach:

  • show — “刚才发生了什么?”(事后分析,无需预先设置)
  • attach — “现在正在发生什么?”(实时流式传输,必须在事件发生前启动)

输出格式

默认输出为 JSON 行(每行一个 JSON 对象)。

JSON Schema(默认)
{
  "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)。

人类可读模式
${CLAUDE_PLUGIN_ROOT}/bin/xclog attach MyApp --human
${CLAUDE_PLUGIN_ROOT}/bin/xclog attach MyApp --human --no-color

选项参考

选项默认值描述
--device <udid>booted目标模拟器 UDID
--device-udid <udid>none实体设备 UDID(show 命令)
--output <file>stdout同时写入文件
--humanoff人类可读的彩色输出
--no-coloroff禁用 ANSI 颜色(--human 模式)
--filter <regex>none使用 Go 正则表达式筛选行
--subsystem <name>none按子系统筛选 os_log
--max-lines <n>0 (unlimited)达到 n 行后停止
--timeout <duration>0 (unlimited)达到指定时长后停止(例如 30s、5m)
--last <duration>5m向前搜索的时间范围(show 命令)

各来源的覆盖情况

Swift APIlaunchattachshow
print()是否否
debugPrint()是否否
NSLog()是是是
os_log()是是是
Logger是是是
模拟器实体设备
launch是否
attach是否
show是是
Logger是是

如需完整覆盖,请使用 launch。 attach 用于监控已在运行的进程。

注意:launch 会在重新启动应用前终止其所有现有实例。如果应用已在运行,且你不想重启它,请使用 attach(仅限 os_log)。

错误行为

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(仅限字母数字字符、点、下划线和连字符)

解读输出

按级别筛选

os_log 级别表示严重程度。诊断崩溃时,请重点关注 error 和 fault。

注意:--filter 匹配的是消息文本,而不是 JSON 输出。要按级别筛选,请使用 jq:

${CLAUDE_PLUGIN_ROOT}/bin/xclog launch com.example.MyApp --timeout 30s 2>/dev/null | jq -c 'select(.level == "error" or .level == "fault")'

要按文本筛选,--filter 会匹配消息内容:

# Filter messages containing "error" or "failed" (case-insensitive)
${CLAUDE_PLUGIN_ROOT}/bin/xclog launch com.example.MyApp --filter "(?i)error|failed"
常见子系统模式
子系统表示内容
com.apple.networkURLSession / 网络层
com.apple.coredataCore Data / 持久化
com.apple.swiftuiSwiftUI 框架
com.apple.uikitUIKit 框架
应用自身的子系统应用级日志记录
工作流:诊断运行时崩溃
  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,然后重试。

工作流:排查静默故障
  1. xclog launch <bundle-id> --subsystem com.example.MyApp --timeout 30s
  2. 触发失败的操作
  3. 查找应用子系统中的错误级别消息
  4. 如果应用日志没有输出,请与网络或数据子系统交叉参照

资源

技能:axiom-xcode-debugging、axiom-performance-profiling、axiom-lldb

评论

支持 Markdown