Skip to content
Merged
Changes from 5 commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions packages/core/src/skills/bundled/stuck/SKILL.md
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
---
Comment thread
doudouOUC marked this conversation as resolved.
Resolved

# /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:
Comment thread
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.
Comment thread
doudouOUC marked this conversation as resolved.
Resolved

## Argument validation

Comment thread
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.

Comment thread
doudouOUC marked this conversation as resolved.
Resolved
## Investigation steps
Comment thread
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:

```
Comment thread
doudouOUC marked this conversation as resolved.
Resolved
ls -1 ~/.qwen/projects/*/chats/*.runtime.json 2>/dev/null
Comment thread
doudouOUC marked this conversation as resolved.
Resolved
```
Comment thread
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
Comment thread
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.

Comment thread
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

Comment thread
doudouOUC marked this conversation as resolved.
Resolved
4. **Consider a stack dump** for a truly frozen process (advanced, optional):
Comment thread
doudouOUC marked this conversation as resolved.
Resolved
- macOS: `sample <pid> 3` gives a 3-second native stack sample
Comment thread
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:**
Comment thread
doudouOUC marked this conversation as resolved.
Resolved

- PID, CPU%, RSS (in MB), process state, uptime, full command line
Comment thread
doudouOUC marked this conversation as resolved.
Resolved
- Child processes and their states
Comment thread
doudouOUC marked this conversation as resolved.
Resolved
- Your diagnosis of what's likely wrong
Comment thread
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.
Comment thread
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.
Loading