log-driven-debugging
When the bug is slippery, stop guessing and build observability.
This skill is for situations where:
- the visible symptom is known, but the actual failure layer is not
- static code reading is no longer enough
- one execution with good logs can collapse a large search space
The workflow is simple:
- decide where to instrument
- add high-signal logs
- have the user rerun the scenario
- analyze the returned logs
- only then propose or implement the real fix
First move
Before adding any logs, ask the user for a log prefix.
This is required, not optional. Explain why briefly: the prefix makes the new logs searchable and prevents them from being lost in normal application output.
Good prefixes look like:
PatrickMyDebugDebugTrace
Prefer a short prefix that:
- is unique in the current codebase
- is easy to grep
- is unlikely to collide with existing production logs
If the user does not care, ask for one and wait. Do not silently invent a prefix unless the user explicitly delegates that choice.
Logging strategy
Do not scatter random prints everywhere. Instrument the execution path deliberately.
Choose logs around:
- entry points where the user action first enters the system
- state transitions where data changes shape
- serialization or conversion boundaries
- async handoff points
- final outbound effects such as send, save, render, request, or callback
For each log, include enough structure to reconstruct the flow:
- the shared prefix
- a timestamp
- a short tag for the subsystem or phase
- the minimum fields needed to compare expected vs actual behavior
Treat the timestamp as part of the standard format, not a nice-to-have. For tricky bugs, ordering is often as important as values.
Prefer logs that answer:
- Did this code path run?
- In what order did the steps happen?
- What data existed at this point?
- Where did duplication, loss, mutation, or branching first appear?
Avoid:
- giant object dumps unless they are truly needed
- vague messages like "here" or "called"
- logging so much that the signal disappears
What to log
The exact fields depend on the bug, but in general log:
- identifiers
- counts
- ranges or indexes
- booleans for state
- input and output summaries
- boundary transformations
Examples:
count=4state=editingrange={loc=12,len=3}contentList=[0] mention | [1] textrequestID=...
Prefer a consistent line shape such as:
[<PREFIX>][2026-03-28T13:45:27.870+08:00][Serializer] contentList=[0] mention | [1] text
When strings are important, escape newlines so one logical log stays on one physical line.
Handoff to the user
After instrumenting, tell the user exactly what to do next:
- rebuild or rerun the app/program
- reproduce the issue once
- collect the logs containing the chosen prefix
- send those logs back
Be explicit that they should return only the lines with the prefix when possible.
Recommend a filter like:
rg "\\[<PREFIX>\\]" <log-file>
or an equivalent grep/search flow in their environment.
Analysis pass
When the user sends logs back, do not jump straight to a fix. Reconstruct the path first.
Read the logs in order and answer:
- What is the first confirmed event?
- What state is proven correct?
- What is the first line where reality diverges from expectation?
- Which layer owns that divergence?
- Is the bug caused by duplication, missing data, wrong boundary detection, stale state, or ordering/race?
Call out the precise transition where the bug begins, not just where it becomes visible.
If the logs prove the current instrumentation is insufficient, ask for one more round and specify the next smallest set of logs needed. Do not ask for a broad second pass if one or two extra logs will do.
Output expectations
Your response after log analysis should be crisp and causal:
- what the logs prove
- where the root cause starts
- what is not the root cause
- what code should change next
If proposing a fix, tie it directly to the observed divergence in logs.
Scope
Keep this skill general. It applies to:
- app bugs
- backend handlers
- UI flows
- serialization problems
- async ordering issues
- duplicated side effects
- state machine bugs
It is not tied to any single language, framework, or repository.
Practical rule
The user runs the instrumented build. You analyze the prefixed logs.
That division of labor is the whole point of this skill.
More from patrick-fu/awesome-skills
brainstorm
>-
9explore-and-plan
>-
8generate-commit-message
>-
7commit-staged-changes
Create Git commits for already staged changes.
5cursor-coding-agent
>-
4home-config-sync
Initialize and operate a generic personal dotfiles bare repo under ~/.dotfiles with work-tree=$HOME: guide the user to create an empty private remote repo, bootstrap local starter files, push the first commit, deploy onto another machine, update whitelist-managed files, pull remote changes into local home config, resolve stash and merge flows, and push local updates. Use when the user explicitly invokes $home-config-sync or explicitly asks to initialize, manage, or sync a bare-repo dotfiles setup.
2