Evlog Log Analyzer
evloghq/evlog
Reads the structured wide-event logs that evlog writes to .evlog/logs/ so the agent can debug errors, find slow requests and explain what the app did.
Correlates a Claude Code session's local transcript with a model router's production cloud logs to explain why a specific response rendered the way it did.
$ npx skills add weave-os/router --skill debug-claude-session -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install weave-os/router debug-claude-session --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/weave-os/router.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/debug-claude-session .claude/skills/debug-claude-session && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "debug-claude-session" agent skill from https://github.com/weave-os/router/tree/main/.agents/skills/debug-claude-session into .claude/skills/debug-claude-session/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "debug-claude-session", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/weave-os/router/tree/main/.agents/skills/debug-claude-sessionType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add weave-os/router --skill debug-claude-session -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install weave-os/router debug-claude-session --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/weave-os/router.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/debug-claude-session .agents/skills/debug-claude-session && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "debug-claude-session" agent skill from https://github.com/weave-os/router/tree/main/.agents/skills/debug-claude-session into .agents/skills/debug-claude-session/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "debug-claude-session", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add weave-os/router --skill debug-claude-session -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install weave-os/router debug-claude-session --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/weave-os/router.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/debug-claude-session .cursor/skills/debug-claude-session && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "debug-claude-session" agent skill from https://github.com/weave-os/router/tree/main/.agents/skills/debug-claude-session into .cursor/skills/debug-claude-session/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "debug-claude-session", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/weave-os/router.git --path .agents/skills/debug-claude-session--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add weave-os/router --skill debug-claude-session -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install weave-os/router debug-claude-session --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/weave-os/router.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/debug-claude-session .gemini/skills/debug-claude-session && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "debug-claude-session" agent skill from https://github.com/weave-os/router/tree/main/.agents/skills/debug-claude-session into .gemini/skills/debug-claude-session/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "debug-claude-session", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install weave-os/router debug-claude-sessionInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add weave-os/router --skill debug-claude-session -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/weave-os/router.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/debug-claude-session .github/skills/debug-claude-session && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "debug-claude-session" agent skill from https://github.com/weave-os/router/tree/main/.agents/skills/debug-claude-session into .github/skills/debug-claude-session/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "debug-claude-session", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add weave-os/router --skill debug-claude-session -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install weave-os/router debug-claude-session --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/weave-os/router.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/debug-claude-session .opencode/skills/debug-claude-session && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "debug-claude-session" agent skill from https://github.com/weave-os/router/tree/main/.agents/skills/debug-claude-session into .opencode/skills/debug-claude-session/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "debug-claude-session", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
debug-claude-sessionCorrelates a Claude Code session's local transcript with a model router's production cloud logs to explain why a specific response rendered the way it did.
Given a session ID, the skill treats the local transcript file as ground truth for what the client actually rendered, the cloud logs as confirmation of what the upstream model served, and the router's internal translation code as the explanation for why the wire shape looks that way. Before starting, it has you create a gitignored deployment config file naming the cloud provider, service, project and region, so log queries can be constructed; if that file is missing, the agent prompts for the details and walks through creating it.
Several gotchas guide the investigation: a streamed turn is split across multiple assistant lines sharing one message id and model, so the full turn has to be reconstructed by collecting every line with that id; block fields like a signature or input often encode provider-specific state such as encrypted reasoning that must be decoded before dismissing a block as empty; and cloud logs are structured, so queries filter on specific JSON fields rather than free text. Because request IDs are often absent, the skill correlates cloud log entries to the transcript by a tight UTC time window plus the served model name instead.
7 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 21c83ab. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
python3gitgcloudFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use git and gcloud, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Claude Session Router Debugger loads about 2.9k tokens when it runs. Until then it costs about 90 tokens; SKILL.md has 933 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from weave-os/router at commit 21c83ab, republished under its Apache-2.0 licence (© weave-os). 933 words, ~2,866 tokens.
.claude/skills/debug-claude-session/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.Given a Claude Code session ID, pull the local transcript (what the client saw) and the corresponding production cloud logs (which model/provider served it), then correlate them to understand the wire-format translation. The local .jsonl is ground truth for what rendered; the cloud logs confirm what the upstream sent; the internal/translate code explains why the wire shape looks that way.
Before starting, create a gitignored config file with your deployment's cloud logging details:
cat > .claude/skills/debug-claude-session/.deployment.json <<'EOF'
{
"cloud_provider": "gcp",
"project_id": "your-project-id",
"region": "us-central1",
"service_name": "router",
"log_command_template": "gcloud logging read ... --project {project_id} --format=json"
}
EOF
git add .claude/skills/debug-claude-session/.deployment.json.example
# .deployment.json itself should be gitignoredIf .deployment.json is missing, the agent will prompt you for these details and walk you through creating it. The file is gitignored and contains no secrets — it's just the service/project/region names needed to construct cloud log queries.
message.content blocks in the .jsonl — not what you assume the model emitted. Always inspect block contents (decode fields, check lengths) before concluding something is "empty" or "corrupt".assistant lines. Each line may hold a single block; they share a message.id and message.model. Reconstruct the full turn by collecting all lines with the same message.id.signature, id, and input often encode provider-specific state (e.g. encrypted reasoning). Decode and inspect before skipping or dismissing a block.jsonPayload.decision_model, jsonPayload.message). The exact field names depend on the router's logging schema — ask if unsure.timestamp field); request IDs are often absent. Use a tight UTC window around transcript timestamps plus the served decision_model to find matching cloud log entries.- [ ] 1. Locate the local transcript
- [ ] 2. Extract the assistant blocks showing the symptom
- [ ] 3. Decode block internals (signatures, ids, sizes)
- [ ] 4. Identify model + provider from the transcript
- [ ] 5. Fetch cloud logs for the matching UTC window
- [ ] 6. Correlate transcript + cloud logs
- [ ] 7. Trace to the translation code in internal/translatefind ~/.claude/projects -name '<SESSION_ID>*' -type fYou get <path>/<SESSION_ID>.jsonl (the transcript, one JSON object per line) and a sibling <SESSION_ID>/ directory (tool-output spillover). The .jsonl file is the ground truth. wc -l it — typical sessions are tens to hundreds of lines.
Each line is a typed event. Scan for type: "assistant" entries. Each carries:
message.id — groups lines from the same logical turn.message.model — the served model (e.g. gpt-5.5, claude-opus-4-8).message.stop_reason — how the turn ended (end_turn, tool_use, max_tokens).message.content[] — list of blocks (text, thinking, tool_use, tool_result).Adapt this template to search for your symptom (empty blocks, missing content, unexpected stop_reason, etc.):
python3 - <<'EOF'
import json
with open("<path>/<SESSION_ID>.jsonl") as f:
for i, line in enumerate(f):
try:
o = json.loads(line)
except:
continue
if o.get("type") != "assistant":
continue
msg = o.get("message", {})
# Adapt this filter to your symptom:
for block in msg.get("content", []):
if isinstance(block, dict) and block.get("type") == "thinking":
thinking_text = block.get("thinking", "")
signature = block.get("signature", "")
if thinking_text == "": # Your condition here
print(f"line {i+1}: model={msg.get('model')} "
f"stop_reason={msg.get('stop_reason')} "
f"thinking_len={len(thinking_text)} "
f"signature_len={len(signature)}")
EOFPrint model, stop_reason, block type/length — enough to see the pattern at a glance.
Don't assume a short or empty field is meaningless. Many blocks carry encoded provider state. Inspect the actual bytes:
python3 - <<'EOF'
import json, base64
line_num = <LINE> # From step 2
with open("<path>/<SESSION_ID>.jsonl") as f:
o = json.loads(f.readlines()[line_num - 1])
for block in o["message"].get("content", []):
block_type = block.get("type")
print(f"=== {block_type} ===")
# Print all fields and their lengths:
for key, val in block.items():
if isinstance(val, str):
print(f" {key}: len={len(val)} head={val[:80]!r}")
else:
print(f" {key}: {type(val).__name__} {val!r}")
# If any field looks base64-encoded, try decoding:
if "signature" in block and block["signature"]:
try:
decoded = base64.b64decode(block["signature"])
print(f" signature (decoded): {decoded[:160]!r}")
except Exception as e:
print(f" signature (decode failed): {e}")
EOFThis reveals what's actually inside. Look for:
encrypted_content, enc fields) that must round-trip to the upstream.tool_use.id).From the message.model field (step 2), note the served model. This tells you:
gpt-* → OpenAI, claude-* → Anthropic, gemini-* → Google).gpt-* Responses → internal/translate/responses_to_anthropic_writer.go).Also note message.id (ids are unique per response; the prefix marks the path):
msg_responses_* → OpenAI Responses API path (streaming).msg_translated_* → OpenAI chat-completions path (router-generated id; upstream-provided ids pass through unchanged).msg_01... (Anthropic-native id) → Anthropic Messages path (passthrough).Extract the timestamp range from the transcript:
python3 - <<'EOF'
import json
with open("<path>/<SESSION_ID>.jsonl") as f:
lines = [json.loads(line) for line in f if json.loads(line).get("timestamp")]
if lines:
print(f"UTC window: {lines[0]['timestamp']} to {lines[-1]['timestamp']}")
EOFThen use your cloud logging tool with the config from .deployment.json:
# Example for gcloud/GCP. Adapt to your cloud provider:
gcloud logging read \
'resource.type="cloud_run_revision" AND resource.labels.service_name="router" AND timestamp>="2026-06-10T01:02:00Z" AND timestamp<="2026-06-10T01:08:00Z"' \
--project <project_id> --limit 20 --format=json \
> /tmp/cloud_logs.jsonFilter for the served model to narrow results:
python3 - <<'EOF'
import json
with open("/tmp/cloud_logs.json") as f:
for entry in json.load(f):
payload = entry.get("jsonPayload", {})
# Adapt filter to your log schema:
if payload.get("decision_model") == "gpt-5.5":
print(json.dumps({
"timestamp": entry.get("timestamp"),
"message": payload.get("message"),
"decision_model": payload.get("decision_model"),
"decision_provider": payload.get("decision_provider"),
"stop_reason": payload.get("resp_stop_reason")
}))
EOFMatch entries from steps 2 and 5 by:
timestamp ≈ cloud log timestamp within ~1-2 seconds).message.model == cloud log decision_model).Once matched, the cloud log entry tells you:
stop_reason demotions, tool_use handling, usage accounting).Now that you've identified the model/provider path (step 4) and confirmed it in cloud logs (step 6), open the relevant translation file in internal/translate/:
responses_to_anthropic_writer.go — OpenAI Responses API.stream.go + emit_anthropic.go — OpenAI-compatible chat.gemini_stream.go + emit_gemini.go — Google Generative Language.emit_anthropic.go — Anthropic passthrough (mostly copy).Find the emitter function that produces the block shape you're seeing:
emitContentBlockStartThinking, emitContentBlockDeltaThinking — thinking blocks.emitContentBlockStartTool, emitContentBlockDeltaTool — tool_use blocks.Read backward from the emitter to the upstream event that triggered it. This is where the "why" lives.
thinking: "" but signature: "<1500 chars>" (step 3).decision_model=gpt-5.5, decision_provider=openai, stop_reason=tool_use (step 5-6).responses_to_anthropic_writer.go (step 4).response.reasoning_summary_text.delta with empty delta but populated item on response.output_item.added (step 7).handleReasoningDelta → emitContentBlockDeltaThinking("", ...) which does nothing (empty delta skipped), but the thinking block was already opened by handleOutputItemAdded (line 279).encrypted_content but under reasoning.summary:"auto", no summary text. The block can't be skipped because the signature must round-trip to the next turn.message.id groups lines from the same logical turn; reconstruct the full turn by collecting all lines sharing an id.test-claude-locally skill to run the router with a mock upstream emitting the exact wire shape you're investigating.© weave-os, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 1 other file in .agents/skills/debug-claude-session of weave-os/router.
Open the folder on GitHubat commit 21c83ab
Claude Session Router Debugger next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Claude Session Router Debugger this skillweave-os/router | 5.6k | — | ~2.9k | Automated safety check: Pass | Apache-2.0 | |
| Evlog Log Analyzerevloghq/evlog | 1.9k | — | ~2.4k | Automated safety check: Pass | MIT | |
| Logging Patternsdecebals/claude-code-java | 750 | 1 repos | ~3.3k | Automated safety check: Pass | MIT | |
| Mecatl Perf MCP Interpretationstacklok/mecatl | 218 | — | ~2.3k | Automated safety check: Pass | Apache-2.0 | |
| NanoClaw Container Debuggingnanocoai/nanoclaw | 31k | — | ~3.8k | Automated safety check: Notes | MIT | |
| LoopX Performance Diagnosisloopx-project/loopx | 6.2k | — | ~880 | Automated safety check: Pass | Apache-2.0 |
evloghq/evlog
Reads the structured wide-event logs that evlog writes to .evlog/logs/ so the agent can debug errors, find slow requests and explain what the app did.
decebals/claude-code-java
Java logging best practices with SLF4J, structured logging (JSON), and MDC for request tracing.
stacklok/mecatl
Guides reading mecatl's perf MCP data to find why a running harness is slow, leaking goroutines or growing in memory, using cheap reads before any CPU capture.
nanocoai/nanoclaw
Troubleshooting guide for NanoClaw's containerized agents: where the logs are, how the two session databases show message flow, and how to raise the log level.
loopx-project/loopx
Profiles a slow command or runtime you own with the right profiler for its language, using uninstrumented baseline timings and keeping raw profiling evidence local and private.
different-ai/openwork
Traces an opaque production error in an OpenWork build to its cause using local server logs and Sentry, names the regressing PR and files a report.
weave-os/router
Stands up the Weave model router in Docker Compose and drives it with claude -p against a real or mocked upstream to reproduce and verify routing and streaming behavior.
weave-os/router
Local test harness for the Weave router: a docker compose stack plus codex exec runs that confirm how Codex requests are routed, translated and marked.
weave-os/router
Works through every review comment on a pull request in one pass, fixes what it can, escalates human decisions and keeps CI churn to a single push.
weave-os/router
Installs a language server such as gopls, typescript-language-server, pyright or rust-analyzer and, with explicit confirmation, its underlying toolchain so the lsp tool can use it.
weave-os/router
Correlates a Codex CLI session's local transcript with a model router's production logs to explain why a reply rendered the way it did.
weave-os/router
Shows when to answer a code question through a real language server instead of grep, covering definitions, references, hover, outlines, and errors.
Categories
Correlates a Claude Code session's local transcript with a model router's production cloud logs to explain why a specific response rendered the way it did. Given a session ID, the skill treats the local transcript file as ground truth for what the client actually rendered, the cloud logs as confirmation of what the upstream model served, and the router's internal translation code as the explanation for why the wire shape looks that way. Before starting, it has you create a gitignored deployment config file naming the cloud provider, service, project and region, so log queries can be constructed; if that file is missing, the agent prompts for the details and walks through creating it.
Claude Session Router Debugger fits situations like: investigating why a specific Claude Code response rendered incorrectly or empty; correlating a session's local transcript with the router's cloud logs; debugging a wire-format or streaming issue for a session routed through the router.
Run `npx skills add weave-os/router --skill debug-claude-session -a claude-code`. Or copy the skill folder (.agents/skills/debug-claude-session in weave-os/router) into .claude/skills/debug-claude-session in your project. Claude Code loads it when a task matches its description.
Run `npx skills add weave-os/router --skill debug-claude-session -a codex`. Or copy the skill folder (.agents/skills/debug-claude-session in weave-os/router) into .agents/skills/debug-claude-session in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add weave-os/router --skill debug-claude-session -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/debug-claude-session, .gemini/skills/debug-claude-session, .github/skills/debug-claude-session and .opencode/skills/debug-claude-session in your project.
Going by SKILL.md and its folder, Claude Session Router Debugger needs the command-line tools its instructions call (python3, git and gcloud). Our summary lists: Access to the router's production cloud logs; A local Claude Code transcript for the session.
SKILL.md contains no URLs. Its commands use git, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Claude Session Router Debugger is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 2.9k tokens (SKILL.md is roughly 11k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Claude Session Router Debugger: Evlog Log Analyzer (evloghq/evlog, 1.9k stars), Logging Patterns (decebals/claude-code-java, 750 stars), Mecatl Perf MCP Interpretation (stacklok/mecatl, 218 stars) and NanoClaw Container Debugging (nanocoai/nanoclaw, 31k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
weave-os (a GitHub organization) maintains it in weave-os/router, which has 5,575 GitHub stars. The repository holds 19 skills in this directory. The repository was last updated on October 7, 2026.
Source: weave-os/router on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.