Motel Debug
kitlangton/motel
Debug applications with motel, a local OpenTelemetry ingest and query server.
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.
The automated check flagged lines worth reading first. See the safety section below.
$ npx skills add weave-os/router --skill debug-codex-session -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install weave-os/router debug-codex-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-codex-session .claude/skills/debug-codex-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-codex-session" agent skill from https://github.com/weave-os/router/tree/main/.agents/skills/debug-codex-session into .claude/skills/debug-codex-session/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "debug-codex-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-codex-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-codex-session -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install weave-os/router debug-codex-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-codex-session .agents/skills/debug-codex-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-codex-session" agent skill from https://github.com/weave-os/router/tree/main/.agents/skills/debug-codex-session into .agents/skills/debug-codex-session/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "debug-codex-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-codex-session -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install weave-os/router debug-codex-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-codex-session .cursor/skills/debug-codex-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-codex-session" agent skill from https://github.com/weave-os/router/tree/main/.agents/skills/debug-codex-session into .cursor/skills/debug-codex-session/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "debug-codex-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-codex-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-codex-session -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install weave-os/router debug-codex-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-codex-session .gemini/skills/debug-codex-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-codex-session" agent skill from https://github.com/weave-os/router/tree/main/.agents/skills/debug-codex-session into .gemini/skills/debug-codex-session/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "debug-codex-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-codex-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-codex-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-codex-session .github/skills/debug-codex-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-codex-session" agent skill from https://github.com/weave-os/router/tree/main/.agents/skills/debug-codex-session into .github/skills/debug-codex-session/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "debug-codex-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-codex-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-codex-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-codex-session .opencode/skills/debug-codex-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-codex-session" agent skill from https://github.com/weave-os/router/tree/main/.agents/skills/debug-codex-session into .opencode/skills/debug-codex-session/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "debug-codex-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-codex-sessionCorrelates a Codex CLI session's local transcript with a model router's production logs to explain why a reply rendered the way it did.
Given a Codex session id, this skill pulls the local rollout transcript, treated as ground truth for what the client actually rendered, and matches it against the router's cloud logs using the client session id Codex sends in its request headers. That direct lookup is simpler than a sibling skill for Claude sessions, which has to match by time and model instead.
It warns that the transcript never records which model actually served a turn — the request fields only show what Codex asked for, while the served model appears only in an injected routing marker or in a cloud log's decision field. Before starting, it expects a gitignored config file naming the cloud provider, project, and region, and will walk you through creating one if it's missing.
8 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:
python3gcloudFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use 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.
Codex Session Debugging loads about 4.5k tokens when it runs. Until then it costs about 122 tokens; SKILL.md has 1,583 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 patterns that need a careful read before installing.
with invisible provenance characters (`⟨U+2063⟩⟨U+2060⟩`) prefixed by `EnableCodexBadgeProvenance` — that prefix is how the router recAutomated 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). 1,583 words, ~4,482 tokens.
.claude/skills/debug-codex-session/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.Given a Codex session ID, pull the local rollout transcript (what the client saw) and the corresponding production cloud logs (which model/provider served it), then correlate them. The rollout .jsonl is ground truth for what rendered; the cloud logs confirm what the router decided and what the upstream sent; internal/translate/responses*.go + internal/proxy/service.go explain why the wire shape looks that way.
The sibling skill debug-claude-session is the Claude Code counterpart. The workflow is the same shape; the transcript format, the id conventions, and the correlation key are all different — do not carry Claude assumptions over.
Before starting, create a gitignored config file with your deployment's cloud logging details:
cat > .claude/skills/debug-codex-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"
}
EOFIf .deployment.json is missing, prompt the user for these details and walk them through creating it. The file is gitignored and contains no secrets — just the service/project/region names needed to construct cloud log queries.
client_session_id, not by time. Codex 0.149+ sends the session ID as the Session-Id header (and Thread-Id with the same value on the main thread); sessionIDFromHeaders (internal/proxy/client_identity.go) picks it up and bindRequestLogger binds it as client_session_id on every log line. So the Codex session ID from the transcript filename is a direct log filter. This is the big difference from the Claude skill, which has to correlate by time + model.turn_context.model and thread_settings_applied.model are the model Codex requested (e.g. gpt-5.6-sol). The router ignores the request's model field for routing. The served model appears only in (a) the injected Weave routing marker, when one was emitted, and (b) decision_model in cloud logs. Never report turn_context.model as the model that served the turn.summary: [] on a reasoning item is not lost thinking. Native Codex reasoning items carry opaque encrypted_content (replay state for the next Responses request) and a public summary array. With summary: "auto" the upstream frequently returns zero summary text while still billing reasoning_output_tokens. Check event_msg/token_count → info.total_token_usage.reasoning_output_tokens before concluding thinking was dropped — nonzero tokens with empty summaries means the model reasoned and the upstream chose not to surface a summary.codexResponsesRequest (internal/proxy/service.go) detects a ChatGPT JWT + ChatGPT-Account-ID; the original Responses body is preserved and ResponsesWriter.SetPassthrough() / SetPassthroughBadge() (internal/translate/responses.go) forward upstream bytes verbatim. On that path, "the router dropped it" is almost never the answer — verify passthrough before blaming translation.ProxyOpenAIChatCompletion in the logs does not mean Codex used chat completions. ProxyOpenAIResponses delegates into the shared chat proxy for routing/billing/telemetry, so the completion log line is named ProxyOpenAIChatCompletion complete and ingress="openai_chat_completions" even for /v1/responses traffic. Check path on the access-log line to see the real surface.newResponsesID produces msg_23aljo-style ids, so a synthetic routing-badge assistant item looks like msg_s6w20w, while a genuine upstream assistant message looks like msg_09cf01fda402.... Same for rs_, ctc_, fc_ prefixes. This is the fastest way to tell injected content from served content.StripRoutingBadgeFromResponsesInput removes the badge from replayed input so router text never reaches the model. A missing marker on a turn is often expected (sticky same-model turns emit nothing) — see test-codex-locally for the PriorServedModel == ServedIdentity() rule.response_item entries are conversation items (both directions); event_msg entries are client-side UI/telemetry events. developer/user role messages with UUID-shaped ids are locally constructed, not served.- [ ] 1. Locate the local rollout transcript
- [ ] 2. Get the session shape (event histogram + session_meta)
- [ ] 3. Read turn_context: requested model, effort, summary mode
- [ ] 4. Extract the items showing the symptom
- [ ] 5. Check token accounting before calling anything "missing"
- [ ] 6. Fetch cloud logs filtered by client_session_id
- [ ] 7. Correlate transcript + cloud logs
- [ ] 8. Trace to the responses code pathCodex writes one rollout file per session, date-partitioned, with the session ID as the filename suffix:
find ~/.codex/sessions -name "rollout-*<SESSION_ID>.jsonl" -type fYou get ~/.codex/sessions/<YYYY>/<MM>/<DD>/rollout-<ISO8601>-<SESSION_ID>.jsonl — one JSON object per line, no sibling spillover directory (unlike Claude Code). wc -l it; a working session is typically hundreds of lines.
Note the ISO timestamp in the filename is local time; the timestamp field inside each line is UTC (Z-suffixed). Use the in-file timestamps for any time math.
Every line is {"timestamp", "type", "payload"}. The type is the outer kind; payload.type is the specific event. Histogram first — it tells you at a glance whether the session compacted, aborted, or ran tools:
python3 - <<'EOF'
import json, collections
F = "<path>/rollout-...-<SESSION_ID>.jsonl"
c = collections.Counter()
for line in open(F):
try:
o = json.loads(line)
except Exception:
continue
c[(o.get("type"), (o.get("payload") or {}).get("type"))] += 1
for k, v in c.most_common():
print(v, k)
EOFThe kinds you'll see:
type | payload.type | meaning |
|---|---|---|
session_meta | — | one per file: session_id, cwd, originator, cli_version, source, model_provider, git, context_window |
turn_context | — | per-turn settings: model, effort, summary, approval_policy, collaboration_mode |
response_item | message | a conversation message (role: developer / user / assistant) |
response_item | reasoning | id (rs_*), summary[], encrypted_content |
response_item | custom_tool_call / function_call | tool invocations (ctc_* / fc_* ids, call_id) |
response_item | custom_tool_call_output / function_call_output | results, keyed by call_id |
event_msg | token_count | cumulative + last-turn usage, plus rate_limits |
event_msg | agent_message | what the TUI rendered as assistant text — routing markers show up here |
event_msg | task_started / task_complete / turn_aborted | turn lifecycle (turn_id, timings, reason) |
event_msg | context_compacted | paired with a top-level compacted line holding the summary |
world_state | — | workspace snapshot (AGENTS.md text, etc.) |
model_provider on session_meta tells you whether the session went through the router at all — it's the provider id from ~/.codex/config.toml (e.g. weave). If it isn't the router's provider id, stop: this session never hit the router.
python3 - <<'EOF'
import json
F = "<path>/rollout-...-<SESSION_ID>.jsonl"
for i, line in enumerate(open(F), 1):
o = json.loads(line)
if o.get("type") != "turn_context":
continue
p = o["payload"]
print(f"line {i}: turn_id={p.get('turn_id')} requested_model={p.get('model')} "
f"effort={p.get('effort')} summary={p.get('summary')}")
EOFeffort and summary are the two knobs that decide how much reasoning is produced and how much of it is displayable. summary: "auto" is the usual cause of a session with lots of reasoning tokens and no visible thinking. Again: model here is the request, not the route.
Adapt this to your symptom. The template below covers the common "no thinking rendered" case plus assistant-message provenance:
python3 - <<'EOF'
import json
F = "<path>/rollout-...-<SESSION_ID>.jsonl"
reasoning = empty_summary = 0
for i, line in enumerate(open(F), 1):
o = json.loads(line)
p = o.get("payload") or {}
t = p.get("type")
if t == "reasoning":
reasoning += 1
summary = p.get("summary") or []
enc = p.get("encrypted_content") or ""
if not summary:
empty_summary += 1
if reasoning <= 3: # sample the first few
print(f"line {i}: rs id={p.get('id')} summary_parts={len(summary)} "
f"encrypted_len={len(enc)}")
elif t == "message" and p.get("role") == "assistant":
mid = p.get("id") or ""
# short base36 tail => router-minted (badge); long hex => upstream
origin = "router" if len(mid) < 20 else "upstream"
text = "".join(b.get("text", "") for b in (p.get("content") or []))
print(f"line {i}: assistant id={mid} origin={origin} {text[:80]!r}")
print(f"\nreasoning items: {reasoning}, with empty summary: {empty_summary}")
EOFTo see exactly what the TUI rendered (including markers), read the agent_message events instead — those are the client-side render records:
python3 - <<'EOF'
import json
F = "<path>/rollout-...-<SESSION_ID>.jsonl"
for i, line in enumerate(open(F), 1):
o = json.loads(line)
p = o.get("payload") or {}
if p.get("type") == "agent_message":
print(f"line {i}: {(p.get('message') or '')[:120]!r}")
EOFThe routing marker renders with invisible provenance characters (``) prefixed by EnableCodexBadgeProvenance — that prefix is how the router recognizes and strips its own badge on replay. Seeing those codepoints confirms the marker came from the router, not the model.
python3 - <<'EOF'
import json
F = "<path>/rollout-...-<SESSION_ID>.jsonl"
last = None
for line in open(F):
o = json.loads(line)
p = o.get("payload") or {}
if p.get("type") == "token_count":
last = p
if last:
print(json.dumps(last.get("info", {}).get("total_token_usage", {}), indent=2))
print("rate_limits:", json.dumps(last.get("rate_limits", {}))[:300])
EOFreasoning_output_tokens > 0 with zero rendered summaries = the model reasoned and the summary was withheld upstream, not a router bug. output_tokens vs reasoning_output_tokens also tells you whether an apparently empty turn produced anything at all.
Unlike the Claude path, filter directly on the session ID:
gcloud logging read \
'resource.type="cloud_run_revision"
AND resource.labels.service_name="router"
AND jsonPayload.client_session_id="<SESSION_ID>"' \
--project <project_id> --limit 100 --format=json \
> /tmp/codex_logs.jsonIf that returns nothing, widen in this order before assuming the session bypassed the router:
timestamp of first and last line) — log retention and index lag both bite.'"<SESSION_ID>"' — it may appear on lines emitted before bindRequestLogger runs.session_meta.model_provider (step 2) — a non-router provider means there is nothing to find.Then summarize the routing decisions:
python3 - <<'EOF'
import json
for entry in json.load(open("/tmp/codex_logs.json")):
p = entry.get("jsonPayload", {})
if not p.get("decision_model"):
continue
print(json.dumps({
"timestamp": entry.get("timestamp"),
"message": p.get("message"),
"requested_model": p.get("requested_model"),
"decision_model": p.get("decision_model"),
"decision_provider": p.get("decision_provider"),
"decision_reason": p.get("decision_reason"),
"upstream_status": p.get("upstream_status"),
"sticky_hit": p.get("sticky_hit"),
}))
EOFProxyOpenAIChatCompletion complete is the per-turn summary line for Codex traffic (see gotchas — the name is an artifact of ProxyOpenAIResponses delegating into the shared path). Its fields answer most questions on their own: decision_model, decision_provider, decision_reason, failover_used, upstream_status, route_ms, proxy_ms.
Join on:
client_session_id (exact — the primary key for Codex).turn_id from the transcript ↔ turn boundaries in the logs, by timestamp within the session.decision_model ↔ the model named in the transcript's routing marker. If they disagree, the marker was stale or stripped — trust the log.What the logs then tell you: which model/provider actually served, whether a fallback or failover fired, whether the pin was sticky, whether the upstream returned a non-200, and how usage was accounted.
Codex traffic enters at internal/api/openai/responses.go → proxy.Service.ProxyOpenAIResponses (internal/proxy/service.go). From there the path forks:
| Situation | Path | Code |
|---|---|---|
ChatGPT subscription (JWT + ChatGPT-Account-ID) | native Responses passthrough, bytes forwarded verbatim | codexResponsesRequest, ResponsesWriter.SetPassthrough / SetPassthroughBadge in internal/translate/responses.go |
| Prepaid / BYOK, OpenAI decision | Responses → chat completions → Responses re-emit | ConvertResponsesToChatCompletionsWithOptions, emit_openai_responses.go |
| Non-OpenAI decision (Anthropic/Gemini/compat) | Responses → chat → provider format → Responses re-emit | responses_to_openai_chat_writer.go, emit_openai_responses_from_openai.go |
| Badge / marker injection + strip | synthetic assistant item, provenance-prefixed | emitNativeBadgeBeforeOutput, StripRoutingBadgeFromResponsesInput in responses.go |
| Codex-specific item shapes | custom_tool_call vs function_call id prefixes | responses_codex.go, toolCallItemIDPrefix |
Read backward from the emitter to the upstream event that triggered it. On the passthrough path there is no emitter — the bytes are the upstream's, so the answer lives upstream or in the request Codex built.
~/.codex/sessions/2026/08/28/rollout-2026-08-28T09-10-06-<id>.jsonl (step 1).reasoning items, 99 token_count events, 93 custom_tool_call pairs (step 2).turn_context: requested gpt-5.6-sol, effort: "high", summary: "auto" (step 3).summary: [] and 1,400–4,600 chars of encrypted_content (step 4).token_count: ~8,300 reasoning_output_tokens — the model definitely reasoned (step 5).client_session_id show decision_model=gpt-5.6-luna, decision_provider=openai, HTTP 200s, no upstream errors (step 6).SetPassthrough() forwards upstream bytes unchanged (step 8).summary under summary: "auto", so Codex has no text to render. Synthesizing text from encrypted_content is impossible and would be wrong.compacted + context_compacted mark a mid-session context handover; items before it may not reflect what the model actually saw afterward. Check for them before reasoning about "the model ignored X".turn_aborted with reason: "interrupted" is a user cancel, not a failure — don't chase it in the logs.© 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. 2 hidden characters (zero-width or bidirectional) removed. Raw file
SKILL.md and 1 other file in .agents/skills/debug-codex-session of weave-os/router.
Open the folder on GitHubat commit 21c83ab
Codex Session Debugging 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 |
|---|---|---|---|---|---|---|
| Codex Session Debugging this skillweave-os/router | 5.6k | — | ~4.5k | Automated safety check: Warn | Apache-2.0 | |
| Motel Debugkitlangton/motel | 298 | — | ~2.2k | Automated safety check: Pass | MIT | |
| Log Aggregationaspectrr/deer | 405 | — | ~1.4k | Automated safety check: Pass | MIT | |
| Gcloud Usagefcakyon/claude-codex-settings | 1.2k | — | ~871 | Automated safety check: Pass | Apache-2.0 | |
| Dspy Debugging ObservabilityOmidZamani/dspy-skills | 124 | 1 repos | ~2.1k | Automated safety check: Warn | MIT | |
| Axiom SRE Investigatoropenclaw/clawhub | 9.5k | — | ~7.1k | Automated safety check: Pass | MIT |
kitlangton/motel
Debug applications with motel, a local OpenTelemetry ingest and query server.
aspectrr/deer
ELK Stack deployment, Logstash pipeline building, Filebeat configuration, and Kibana dashboard setup.
fcakyon/claude-codex-settings
This skill should be used when user asks about "GCloud logs", "Cloud Logging queries", "Google Cloud metrics", "GCP observability", "trace analysis", or "debugging production issues on GCP".
OmidZamani/dspy-skills
A skill your agent uses for debugging DSPy programs, inspecthistory, tracing LLM calls, custom callbacks, observability, monitoring, and cost tracking.
openclaw/clawhub
Investigates incidents and production problems with hypothesis-driven debugging, queries Axiom observability data when available, and keeps secrets out of commands and output.
livekit-examples/agent-starter-python
Deploys and operates a LiveKit agent in production: shipping a version to LiveKit Cloud and rolling it back, secrets and configuration, the worker process model and prewarming, safe async inside…
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
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.
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
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 Codex CLI session's local transcript with a model router's production logs to explain why a reply rendered the way it did. Given a Codex session id, this skill pulls the local rollout transcript, treated as ground truth for what the client actually rendered, and matches it against the router's cloud logs using the client session id Codex sends in its request headers. That direct lookup is simpler than a sibling skill for Claude sessions, which has to match by time and model instead.
Codex Session Debugging fits situations like: investigating why a Codex response was missing thinking or a routing marker; checking which model actually served a Codex turn versus what was requested; correlating a Codex session's transcript with the router's production logs.
Run `npx skills add weave-os/router --skill debug-codex-session -a claude-code`. Or copy the skill folder (.agents/skills/debug-codex-session in weave-os/router) into .claude/skills/debug-codex-session in your project. Claude Code loads it when a task matches its description.
Run `npx skills add weave-os/router --skill debug-codex-session -a codex`. Or copy the skill folder (.agents/skills/debug-codex-session in weave-os/router) into .agents/skills/debug-codex-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-codex-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-codex-session, .gemini/skills/debug-codex-session, .github/skills/debug-codex-session and .opencode/skills/debug-codex-session in your project.
Going by SKILL.md and its folder, Codex Session Debugging needs the command-line tools its instructions call (python3 and gcloud). Our summary lists: A gitignored deployment config naming the cloud provider, project, and region.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md flagged 1 warning(s): contains zero-width characters. Read the flagged lines before installing; the check is not a guarantee either way.
Codex Session Debugging 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 4.5k tokens (SKILL.md is roughly 18k 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 Codex Session Debugging: Motel Debug (kitlangton/motel, 298 stars), Log Aggregation (aspectrr/deer, 405 stars), Gcloud Usage (fcakyon/claude-codex-settings, 1.2k stars) and Dspy Debugging Observability (OmidZamani/dspy-skills, 124 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.