logs-start
GitHub启动 VivaDicta 应用日志捕获,支持模拟器、真机及结构化归档三种层级。用于收集调试日志以排查问题,配合 logs-stop 结束捕获。
Trigger Scenarios
Install
npx skills add n0an/VivaDicta --skill logs-start -g -y
SKILL.md
Frontmatter
{
"name": "logs-start",
"description": "Start a VivaDicta log capture. Defaults to the simulator; takes sim, device, or structured to pick a tier.",
"disable-model-invocation": true
}
logs-start
Start a log capture. Stop it with logs-stop, which
resolves the active tier on its own - you never have to name it again.
Argument
$ARGUMENTS selects the tier. Empty means sim.
| Argument | Tier | Reaches extensions? | Cost |
|---|---|---|---|
(empty) or sim |
Simulator, live unified log | yes (all sim processes) | none |
device |
Device, live stdout | no, main app only | none |
structured |
Device, unified log archive | yes | interactive sudo, large archive |
Anything else: say what was passed, list the three, and stop. Do not guess.
When invoked with no argument, start the simulator capture as usual, then close your report with this reminder so the other tiers stay discoverable:
Started the simulator capture (default). Other tiers:
/logs-start devicefor live device stdout (main app only),/logs-start structuredfor the device unified log (the only tier that sees the keyboard and other extensions).
Do not ask which tier to use instead of starting - the default is the default. Only mention the alternatives after the capture is already running.
Choosing a tier
simis the default because it is free and the richest: real unified-log metadata, timestamps, levels, categories, threads.deviceis for hardware-only bugs. Live and cheap, but see the limitation below - it cannot see the keyboard or any other extension.structuredis the only tier that sees extensions on hardware. Reach for it when the keyboard, share, action, or widget target is involved, or for a post-mortem.logarchiveyou want to reopen in Console.app.
sim
mkdir -p logs- Run
./scripts/launch_simulator.shin a background/long-lived shell solog streamkeeps running. - Report the
logs/sim-YYYYMMDD-HHMMSS.logpath the script prints.
Attaches to the already-booted Simulator; it does not relaunch the app, and it
fails if none is booted. Captures Logger output filtered to
subsystem == "com.antonnovoselov.VivaDicta"; raw print() is not included.
device
./scripts/launch_device.sh --checkfirst - it resolves device and bundle id without launching. Fix whatever it reports before continuing.mkdir -p logs- Run
./scripts/launch_device.shin a background/long-lived shell. - Report the
logs/device-YYYYMMDD-HHMMSS.logpath.
Uses xcrun devicectl device process launch --console with
ENABLE_PRINT_LOGS=1. --terminate-existing restarts the app, so in-progress
state is lost.
Limitation: main app only, no extensions
--console pipes the stdout of the single process devicectl launched. Every
extension runs in its own system-spawned process, so devicectl never sees it.
Their output is absent entirely and nothing says so - you get a
complete-looking stream that is silently missing a target.
Measured: a capture during keyboard use carried 213 lines from VivaDicta/ and
0 from VivaDictaKeyboard/, though the keyboard logs from
KeyboardViewController, KeyboardTextProcessor and VivaModeManager. Use
structured for extensions.
Timestamps
Lines carry time, level and call site, because LoggerExtension's print mirror
stamps them itself:
19:09:40.709 [INFO] VivaDicta/AIService.swift:666 Loaded 1 Viva Modes
That is app-side, so it only appears in builds you install. Bare, unstamped lines mean the installed binary predates the print mirror - rebuild to the device rather than changing the capture. Category and thread are still absent; stdout has no room for unified-log metadata.
structured
Starts nothing - it only records where to collect from. logs-stop does the
work.
- Find the device:
xcrun xctrace list devices | grep iPhone | grep -v Simulator | head -1 mkdir -p llmtemp-
date '+%Y-%m-%d %H:%M:%S' > llmtemp/.device-log-start-time echo "<UDID>" > llmtemp/.device-log-udid - Report the start time and UDID, and warn that
logs-stopwill need interactivesudoand will write a large archive.
Why this tier reaches extensions: sudo log collect --device-udid pulls the
device's whole unified log, and extension lines survive the subsystem filter
because LoggerExtension.swift hardcodes one subsystem across all targets:
private nonisolated let kLoggingSubsystem = "com.antonnovoselov.VivaDicta"
That constant is load-bearing. If a target is ever changed to log under its own bundle id, it disappears from these captures silently.
Concurrent captures
sim and device can run at once; logs-stop handles all active tiers. Do not
start a second capture of the same tier - the first one's file stops receiving
the lines you expect.
Manual analysis
ls -lt logs/sim-*.log | head -5
grep -i "error\|fault" logs/sim-*.log
grep "\[AppState\]" logs/sim-*.log
log show logs/vivadicta_device_*.logarchive \
--predicate 'subsystem == "com.antonnovoselov.VivaDicta"'
Related
logs-stopxcodebuild-testingaxe-simulator-control- drive the simulator before capturing
Version History
- fbbdfe0 Current 2026-09-09 09:13


