Oslog
Read, stream, and analyze Apple unified logs (OSLog) for iOS/macOS apps. Auto-detects subsystem from Logger usage or bundle identifier. Supports live log show, real-time streaming, and .logarchive analysis with full predicate reference. Use when the user asks to check app logs, stream console output, debug with OSLog, or analyze .logarchive files on iOS/macOS.From its SKILL.md
npx -y skills add artemnovichkov/skills --skill oslogAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
SKILL.md
4.6 KB, as published. Nobody here has run it
oslog
Read, stream, and analyze Apple unified logs for iOS/macOS apps.
When to Use
Activate when the user asks to:
- Check, read, show, or debug app logs
- Stream logs in real time
- Analyze
.logarchivefiles - Filter system logs by process, subsystem, or message content
- Investigate crashes, errors, or unexpected behavior via logs
Step 1 — Detect Subsystem
Auto-detect the OSLog subsystem from the project. Try these sources in order:
- Source code — search for
Logger(subsystem:in Swift files to find the actual subsystem string used in code project.pbxproj— fall back toPRODUCT_BUNDLE_IDENTIFIERbuild setting (common convention is to use bundle ID as subsystem)Info.plist— readCFBundleIdentifiervalue (resolve$(PRODUCT_BUNDLE_IDENTIFIER)if needed)- Ask the user — if all detection fails, ask for the subsystem string
Store the detected subsystem for reuse within the session.
Step 2 — Determine Mode
Mode A: Show Recent Logs
Query recent logs from the live system log store.
/usr/bin/log show --last <N>m --info --debug --no-pager \
--predicate 'subsystem == "<SUBSYSTEM>"' | head -100
- Default to
--last 5m, adjust based on user request - Always pipe through
headon first query to avoid flooding output - Increase
headlimit or remove it only if the user asks for more
Mode B: Stream Live Logs
Stream logs in real time from a running app.
/usr/bin/log stream --info --debug \
--predicate 'subsystem == "<SUBSYSTEM>"'
- Note:
--no-pageris not needed here —log streamis inherently streaming and has no pager - Run via Bash with
run_in_background— the stream is continuous - Notify the user when output is available
- Stop the stream when the user is done or the task changes
Mode C: Analyze .logarchive
Query an exported log archive bundle.
Locate the archive:
ls <path>.logarchive/Info.plist
Determine time range:
/usr/bin/log show --style ndjson --no-pager <archive> | head -1
/usr/bin/log show --style ndjson --no-pager <archive> | tail -1
Query the archive:
/usr/bin/log show --info --debug --no-pager \
--predicate 'subsystem == "<SUBSYSTEM>"' <archive> | head -50
Export a new archive (requires sudo):
# Path must not already exist — log collect creates the directory
sudo /usr/bin/log collect --last 30m --output <path>.logarchive
Critical Rules
- Always use
/usr/bin/log— barelogconflicts with zsh builtin - Always include
--no-pager— interactive pagers hang in non-interactive contexts - Always pipe through
head -Non initial queries — archives and log stores can contain millions of entries - Include
--info --debug— by default only Default and Error/Fault levels are shown - Use
--style ndjsonfor programmatic parsing/counting,--style defaultfor human-readable output
Predicate Reference
See PREDICATES.md for the full predicate field table, comparison operators, and NSPredicate syntax. Key shorthand examples:
's=com.example.app' # filter by subsystem
's=com.example.app AND c=networking' # subsystem + category
's=com.example.app AND type>=error' # errors and faults only
's=com.example.app AND m:"timeout"' # message contains keyword
Common Workflows
Show all errors/faults from the app:
/usr/bin/log show --last 10m --no-pager \
--predicate 's=<SUBSYSTEM> AND type>=error' | head -50
Show logs for a specific category:
/usr/bin/log show --last 5m --info --debug --no-pager \
--predicate 's=<SUBSYSTEM> AND c=networking' | head -100
Search for a keyword in messages:
/usr/bin/log show --last 5m --info --debug --no-pager \
--predicate 's=<SUBSYSTEM> AND m:"timeout"' | head -50
Count events by type in an archive:
/usr/bin/log show --no-pager --style ndjson \
--predicate 's=<SUBSYSTEM> AND type=error' <archive> | wc -l
List unique categories from the app:
/usr/bin/log show --last 30m --info --debug --no-pager --style ndjson \
--predicate 's=<SUBSYSTEM>' | head -500 | \
grep -o '"category":"[^"]*"' | sort -u