Repository navigation
feat(skills): add /stuck diagnostic skill for frozen sessions #4133
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 5 commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
3078934
feat(skills): add /stuck diagnostic skill for frozen sessions
doudouOUC d92021d
fix(skills): respect QWEN_RUNTIME_DIR/QWEN_HOME for debug log path in…
doudouOUC a5f85e7
fix(skills): add allowedTools and clarify diagnostic-only boundary in…
doudouOUC 72639a0
fix(skills): address review feedback for /stuck — security, accuracy,…
doudouOUC e7875ae
fix(skills): apply minimal review fixes for /stuck
doudouOUC abb105f
fix(skills): round-3 review fixes for /stuck
doudouOUC e232ddb
fix(skills): /stuck overview-vs-step3 consistency and self-explanator…
doudouOUC 21d419f
fix(skills): correct /stuck runtime base priority order and resolution
doudouOUC 21dfc9a
feat(skills): improve /stuck diagnostic flow
doudouOUC c1fb70d
fix(skills): /stuck — RUNTIME_DIR preamble + jq-free sidecar liveness
doudouOUC 52f5bcc
fix(skills): /stuck — validate fast-path PID is a Qwen Code process
doudouOUC d3f4bfb
fix(skills): /stuck — settings path, sidecar grep, ps regex, lsof safety
doudouOUC 2d987d9
fix(skills): /stuck — expand ~ and resolve relative paths in RUNTIME_DIR
doudouOUC 42c3ca3
fix(skills): /stuck — round-N review feedback
doudouOUC 161fa70
test(skills): add integration test that parses every bundled SKILL.md
doudouOUC File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| --- | ||
| name: stuck | ||
| description: Diagnose frozen, stuck, or slow Qwen Code sessions on this machine. Scans for problematic processes, high CPU/memory usage, hung subprocesses, and debug logs. Use /stuck or /stuck <PID> to focus on a specific process. | ||
| argument-hint: '[PID or symptom]' | ||
| allowedTools: | ||
| - run_shell_command | ||
| - read_file | ||
| --- | ||
|
|
||
| # /stuck — diagnose frozen/slow Qwen Code sessions | ||
|
|
||
| The user thinks another Qwen Code session on this machine is frozen, stuck, or very slow. Investigate and present a diagnostic report. | ||
|
|
||
| ## What to look for | ||
|
|
||
| Scan for other Qwen Code processes (excluding the current one — exclude the PID you see running this prompt). Since Qwen Code is a Node.js CLI (`#!/usr/bin/env node`), the process name (`comm` column) is always `node` (or `bun` if run with Bun). Identify Qwen Code sessions by looking at the `command` column for paths containing "qwen" (e.g., `node /path/to/qwen-code/dist/cli.js` or a symlinked `qwen` script). | ||
|
|
||
| Signs of a stuck session: | ||
|
doudouOUC marked this conversation as resolved.
Resolved
|
||
|
|
||
| - **High CPU (>=90%) sustained** — likely an infinite loop. Sample twice, 1-2s apart, to confirm it's not a transient spike. | ||
| - **Process state `D` / `U` (uninterruptible sleep)** — often an I/O hang. Linux uses `D`, macOS/BSD uses `U`. The `state` column in `ps` output; first character matters (ignore modifiers like `+`, `s`, `<`). | ||
| - **Process state `T` (stopped)** — user probably hit Ctrl+Z by accident. | ||
| - **Process state `Z` (zombie)** — parent isn't reaping. | ||
| - **Very high RSS (>=4GB)** — possible memory leak making the session sluggish. | ||
| - **Stuck child process** — a hung `git`, `node`, or shell subprocess can freeze the parent. Check `pgrep -lP <pid>` for each session. | ||
|
doudouOUC marked this conversation as resolved.
Resolved
|
||
|
|
||
| ## Argument validation | ||
|
|
||
|
doudouOUC marked this conversation as resolved.
Resolved
|
||
| If the user gave an argument, first check whether it is a positive integer (PID). If it contains shell metacharacters (`$`, `;`, `|`, `&`, `` ` ``, `(`, `)`, `<`, `>`, `*`, `?`, backslash, quote, whitespace, etc.), refuse to proceed and tell the user the argument does not look like a valid PID. Treat free-text symptom descriptions as guidance for the report, not as values to substitute into shell commands. | ||
|
|
||
|
doudouOUC marked this conversation as resolved.
Resolved
|
||
| ## Investigation steps | ||
|
doudouOUC marked this conversation as resolved.
Resolved
|
||
|
|
||
| 1. **Enumerate live sessions via the runtime sidecar (preferred, reliable)**: | ||
|
|
||
| Qwen Code writes a `runtime.json` sidecar for each interactive session at `<runtime-base>/projects/<sanitized-cwd>/chats/<sessionId>.runtime.json`. The default `<runtime-base>` is `~/.qwen` (overridable by `QWEN_RUNTIME_DIR`, `QWEN_HOME`, or the `advanced.runtimeOutputDir` setting). Each file contains `{schema_version, pid, session_id, work_dir, hostname, started_at, qwen_version}`. Use this as the authoritative source of `(pid, session_id, work_dir)` mappings: | ||
|
|
||
| ``` | ||
|
doudouOUC marked this conversation as resolved.
Resolved
|
||
| ls -1 ~/.qwen/projects/*/chats/*.runtime.json 2>/dev/null | ||
|
doudouOUC marked this conversation as resolved.
Resolved
|
||
| ``` | ||
|
doudouOUC marked this conversation as resolved.
Resolved
|
||
|
|
||
| For each file, read it and check whether the recorded `pid` is still alive (`kill -0 <pid>` returns 0). Stale files where the PID is gone mean the session has exited — skip them silently. PID reuse is rare but possible, so when you cross-reference with `ps` in step 2, also skip records whose live PID's command line no longer looks like a Qwen Code process. | ||
|
|
||
| 2. **List Qwen Code processes via `ps`** (macOS/Linux) — used to enrich each live session with CPU/RSS/state/uptime, and to catch sessions that may have started before the sidecar feature existed: | ||
|
|
||
| ``` | ||
| ps -xo pid=,pcpu=,rss=,etime=,state=,comm=,command= -u "$(id -u)" -ww | grep -E '(qwen|node.*qwen|bun.*qwen)' | grep -v grep | ||
|
doudouOUC marked this conversation as resolved.
Resolved
|
||
| ``` | ||
|
|
||
| `-u "$(id -u)"` restricts the scan to the current user — on shared hosts this avoids exposing other users' Qwen process paths/arguments into the chat. `-ww` disables column truncation so long "qwen" paths aren't cut off. The `comm` column will be `node` or `bun`, not `qwen`; filter to rows where the `command` column contains a qwen path (e.g., `qwen-code/dist/cli.js`, or a bin symlink ending in `/qwen`). Cross-reference with the PIDs from step 1. | ||
|
|
||
| Note: `ps` reports `rss` in **kilobytes** on both macOS and Linux. Divide by 1024 before comparing to the >=4GB threshold or reporting in MB. | ||
|
|
||
|
doudouOUC marked this conversation as resolved.
Resolved
|
||
| 3. **For anything suspicious**, gather more context. Substitute `<pid>` only after the validation in "Argument validation" above (or after taking it from `ps` / sidecar output, which is trusted): | ||
| - Child processes (with state, so a hung `git` / `node` shows up): `pgrep -P <pid>` to get child PIDs, then `ps -p <child_pids> -o pid=,ppid=,pcpu=,state=,etime=,command=` for their state | ||
| - If high CPU: sample again after 1-2s to confirm it's sustained | ||
| - Check the session's debug log if you can infer the session ID (from the sidecar): `~/.qwen/debug/<session-id>.txt` (the last few hundred lines often show what it was doing before hanging). If `QWEN_RUNTIME_DIR` or `QWEN_HOME` is set, the debug directory is `$QWEN_RUNTIME_DIR/debug/` or `$QWEN_HOME/debug/` instead of the default. Debug logs may contain prompts, file contents, or tokens from other sessions — paste only the lines relevant to the hang, and never quote secrets/API keys you happen to see. | ||
| - The `~/.qwen/debug/latest` symlink points to the most recent session's log | ||
|
|
||
|
doudouOUC marked this conversation as resolved.
Resolved
|
||
| 4. **Consider a stack dump** for a truly frozen process (advanced, optional): | ||
|
doudouOUC marked this conversation as resolved.
Resolved
|
||
| - macOS: `sample <pid> 3` gives a 3-second native stack sample | ||
|
doudouOUC marked this conversation as resolved.
Resolved
|
||
| - Linux: `cat /proc/<pid>/stack` for kernel stack, or `strace -p <pid> -c -f` for syscall profile | ||
| - This is big — only grab it if the process is clearly hung and you want to know _why_ | ||
|
|
||
| ## Report | ||
|
|
||
| Present a structured diagnostic report directly to the user with these sections: | ||
|
|
||
| **For each stuck/slow session found:** | ||
|
doudouOUC marked this conversation as resolved.
Resolved
|
||
|
|
||
| - PID, CPU%, RSS (in MB), process state, uptime, full command line | ||
|
doudouOUC marked this conversation as resolved.
Resolved
|
||
| - Child processes and their states | ||
|
doudouOUC marked this conversation as resolved.
Resolved
|
||
| - Your diagnosis of what's likely wrong | ||
|
doudouOUC marked this conversation as resolved.
Resolved
|
||
| - Relevant debug log tail if you captured it | ||
| - Stack dump output if you captured it | ||
| - Suggested next step for the user to decide (e.g., "user may consider `kill <pid>` if the session is unresponsive", "likely waiting on I/O — check disk", "accidentally stopped — user can resume with `kill -CONT <pid>`"). Do not execute these actions yourself — present them as options for the user. | ||
|
doudouOUC marked this conversation as resolved.
Resolved
|
||
|
|
||
| **If every session looks healthy**, tell the user directly — no diagnostic dump needed. Mention how many sessions you checked and that none showed signs of being stuck. | ||
|
|
||
| ## Notes | ||
|
|
||
| - Don't kill or signal any processes — this is diagnostic only. | ||
| - If the user gave an argument (e.g., a specific PID or symptom), focus there first. | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.