* feat(cli): add session recap with /recap and auto-show on return
Users often open an old session days later and need to scroll through
pages to remember where they left off. This change adds a short
"where did I leave off" recap — a 1-3 sentence summary generated by
the fast model — so they can resume without re-reading the history.
Two triggers:
- /recap: manual slash command.
- Auto: when the terminal has been blurred for 5+ minutes and gets
focused again (uses the existing DECSET 1004 focus protocol via
useFocus). Gated on streamingState === Idle so it never interrupts
an active turn. Only fires once per blur cycle.
The recap is rendered in dim color with a chevron prefix, visually
distinct from assistant replies. A new `general.showSessionRecap`
setting controls the auto-trigger (default on). /recap works
independent of the setting.
Implementation notes:
- generateSessionRecap uses fastModel (falls back to main model),
tools: [], maxOutputTokens: 300, and a tight system prompt. It
strips tool calls / responses from history before sending — tool
responses can hold 10K+ tokens of file content that drown the recap
in irrelevant detail. The 30-message window respects turn boundaries
(slice never starts on a dangling model/tool response).
- Output is wrapped in <recap>...</recap> tags; the extractor returns
empty (skips render) if the tag is missing, preventing model
reasoning from leaking into the UI.
- All failures are silent (return null) and logged via a scoped
debugLogger; recap is best-effort and must never break main flow.
- /recap refuses to run while a turn is pending.
* fix(cli): abort in-flight recap when showSessionRecap is disabled
If the user disables showSessionRecap while an auto-recap LLM call is
already in flight, the previous code returned early without aborting.
The pending .then would still pass its idle/abort guards and append the
recap, producing an unwanted message after the user has opted out.
Abort the controller and clear it eagerly so the resolved promise no
longer adds to history.
* fix(cli): gate /recap and auto-recap on streaming idle state
Two related issues from review:
1. /recap was only refusing when ui.pendingItem was set, but a normal
model reply runs with streamingState === Responding and a null
pendingItem. Invoking /recap mid-stream would generate a recap from
a partial conversation and insert it between the user prompt and
the assistant reply.
2. useAwaySummary cleared blurredAtRef before checking isIdle, so if
focus returned during a still-streaming turn (after a >5min blur)
the recap was permanently dropped — there was no later retry when
the turn became idle, because isIdle was not in the effect deps.
Fixes:
- Expose isIdleRef on CommandContext.ui (mirrors btwAbortControllerRef
pattern). Plumb it from AppContainer through useSlashCommandProcessor.
- recapCommand now refuses when isIdleRef.current is false OR
pendingItem is non-null.
- useAwaySummary preserves blurredAtRef on the !isIdle bail and adds
isIdle to the effect deps, so the trigger re-evaluates when the
current turn finishes.
- Brief blurs (< AWAY_THRESHOLD_MS) still reset blurredAtRef.
Also seeds isIdleRef in nonInteractiveUi and mockCommandContext so the
new field has a sensible default outside the interactive UI.
* docs: document /recap command, showSessionRecap setting, and design
- User docs: add /recap to the Session and Project Management table in
features/commands.md and a dedicated subsection covering manual use,
the auto-trigger, the dim-color rendering, and the fast-model tip.
- User docs: add general.showSessionRecap row to the configuration
settings reference.
- Design doc: docs/design/session-recap/session-recap-design.md covers
motivation, the two trigger paths, the per-file architecture, prompt
design with the <recap> tag and three-tier extractor, history
filtering rationale (functionResponse can be 10K+ tokens), the
useAwaySummary state machine, the isIdleRef gating for /recap, model
selection, observability, and out-of-scope items.
* fix(core): exclude thought parts from session recap context
filterToDialog kept any non-empty text part, but @google/genai's Part
type also marks model reasoning with part.thought / part.thoughtSignature.
That hidden chain-of-thought was being fed to the recap LLM and could
get summarized as if it were user-visible dialogue.
Drop parts where either flag is set. Update the design doc's
History 过滤 section to call this out alongside the existing
tool-call/response rationale.
* docs(session-recap): correct debug-logging guidance, fill in state machine, sharpen UX wording
Audit of the session recap docs against the implementation found three
issues worth fixing:
- Design doc claimed debug logs were enabled via a QWEN_CODE_DEBUG_LOGGING
env var. That var does not exist; debug logs are written to
~/.qwen/debug/<sessionId>.txt by default, gated by QWEN_DEBUG_LOG_FILE.
Replace with the accurate path + opt-out behavior, and tell the reader
to grep for the [SESSION_RECAP] tag.
- Design doc's useAwaySummary state machine table was missing the
isFocused && blurredAtRef === null path (taken on first render and
right after a brief-blur reset). Add the row.
- User doc's "Refuses to run ... failures are silent" line conflated the
inline-error refusal with silent generation failures, and "(when the
conversation is idle)" used internal jargon. Split the two cases and
spell out what "idle" means, including the wait-then-fire behavior
when focus returns mid-turn.
* docs(session-recap): correctly describe /recap vs auto-trigger failure modes
The previous wording said "Generation/network failures are silent — the
recap simply does not appear", but recapCommand returns a user-facing
info message ("Not enough conversation context for a recap yet.") in
exactly that path, and also returns inline messages for the
config-not-loaded and busy-turn guards.
Only the auto-trigger path is truly silent (it just skips addItem when
generateSessionRecap returns null). Split the two paths in the doc so
the manual command's "always responds with something" behavior is
distinguished from the auto-trigger's no-op-on-failure behavior.
* docs(session-recap): align prompt-rules section with the actual prompt
Two doc-vs-code mismatches in the design doc's "System Prompt" section,
caught with the same lens as yiliang114's failure-mode review:
- The bullet list claimed RECAP_SYSTEM_PROMPT forbids "推测用户意图"
and "用 'you' 称呼用户". Those rules existed in an early draft but
were dropped when the <recap> tag rules were added; the current
prompt has no such restrictions. Replace with the actual rules and
add a "与 RECAP_SYSTEM_PROMPT 一一对应" marker so future edits stay
in sync.
- The doc said systemInstruction "覆盖" the main agent prompt. True
for the agent prompt portion, but GeminiClient.generateContent
internally calls getCustomSystemPrompt which appends user memory
(QWEN.md / 自动 memory) as a suffix. Spell that out — the final
system prompt is recap prompt + user memory, which is actually
useful project context for the recap.
* docs(session-recap): translate design doc to English
The repo convention for docs/design is English (7 of 8 existing files;
auto-memory/memory-system.md is the only Chinese one). The first version
of this design doc followed the auto-memory example, which turned out
to be the wrong sample.
Translate to English while preserving the existing structure, the
state-machine table, the prompt-vs-doc 1:1 alignment, the
QWEN_DEBUG_LOG_FILE description, and the failure-mode notes added in
prior commits.
* fix(cli): drop empty info return from /recap interactive success path
The interactive success path inserts the away_recap history item
directly via ui.addItem and then returned `{type: 'message',
messageType: 'info', content: ''}`. The slash-command processor's
'message' case unconditionally calls addMessage, which adds another
HistoryItemInfo with empty text. The empty info renders as nothing
(StatusMessage early-returns null), but it still bloats the in-memory
history list and shows up in /export and saved sessions.
Return void on the interactive success path and on the abort path so
the processor's `if (result)` check skips the message-handler branch
entirely. Widen the action's return type to `void | SlashCommandActionReturn`
to match (same shape as btwCommand).
26 KiB
Commands
This document details all commands supported by Qwen Code, helping you efficiently manage sessions, customize the interface, and control its behavior.
Qwen Code commands are triggered through specific prefixes and fall into three categories:
| Prefix Type | Function Description | Typical Use Case |
|---|---|---|
Slash Commands (/) |
Meta-level control of Qwen Code itself | Managing sessions, modifying settings, getting help |
At Commands (@) |
Quickly inject local file content into conversation | Allowing AI to analyze specified files or code under directories |
Exclamation Commands (!) |
Direct interaction with system Shell | Executing system commands like git status, ls, etc. |
1. Slash Commands (/)
Slash commands are used to manage Qwen Code sessions, interface, and basic behavior.
1.1 Session and Project Management
These commands help you save, restore, and summarize work progress.
| Command | Description | Usage Examples |
|---|---|---|
/init |
Analyze current directory and create initial context file | /init |
/summary |
Generate project summary based on conversation history | /summary |
/compress |
Replace chat history with summary to save Tokens | /compress |
/resume |
Resume a previous conversation session | /resume |
/recap |
Show a 1-3 sentence "where you left off" summary | /recap |
/restore |
Restore files to state before tool execution | /restore (list) or /restore <ID> |
1.2 Interface and Workspace Control
Commands for adjusting interface appearance and work environment.
| Command | Description | Usage Examples |
|---|---|---|
/clear |
Clear terminal screen content | /clear (shortcut: Ctrl+L) |
/context |
Show context window usage breakdown | /context |
→ detail |
Show per-item context usage breakdown | /context detail |
/theme |
Change Qwen Code visual theme | /theme |
/vim |
Turn input area Vim editing mode on/off | /vim |
/directory |
Manage multi-directory support workspace | /dir add ./src,./tests |
/editor |
Open dialog to select supported editor | /editor |
1.3 Language Settings
Commands specifically for controlling interface and output language.
| Command | Description | Usage Examples |
|---|---|---|
/language |
View or change language settings | /language |
→ ui [language] |
Set UI interface language | /language ui zh-CN |
→ output [language] |
Set LLM output language | /language output Chinese |
- Available built-in UI languages:
zh-CN(Simplified Chinese),en-US(English),ru-RU(Russian),de-DE(German) - Output language examples:
Chinese,English,Japanese, etc.
1.4 Tool and Model Management
Commands for managing AI tools and models.
| Command | Description | Usage Examples |
|---|---|---|
/mcp |
List configured MCP servers and tools | /mcp, /mcp desc |
/tools |
Display currently available tool list | /tools, /tools desc |
/skills |
List and run available skills | /skills, /skills <name> |
/plan |
Switch to plan mode or exit plan mode | /plan, /plan <task>, /plan exit |
/approval-mode |
Change approval mode for tool usage | /approval-mode <mode (auto-edit)> --project |
→plan |
Analysis only, no execution | Secure review |
→default |
Require approval for edits | Daily use |
→auto-edit |
Automatically approve edits | Trusted environment |
→yolo |
Automatically approve all | Quick prototyping |
/model |
Switch model used in current session | /model |
/model --fast |
Set a lighter model for prompt suggestions | /model --fast qwen3-coder-flash |
/extensions |
List all active extensions in current session | /extensions |
/memory |
Open the Memory Manager dialog | /memory |
/remember |
Save a durable memory | /remember Prefer terse responses |
/forget |
Remove matching entries from auto-memory | /forget <query> |
/dream |
Manually run auto-memory consolidation | /dream |
1.5 Built-in Skills
These commands invoke bundled skills that provide specialized workflows.
| Command | Description | Usage Examples |
|---|---|---|
/review |
Review code changes with 5 parallel agents + deterministic analysis | /review, /review 123, /review 123 --comment |
/loop |
Run a prompt on a recurring schedule | /loop 5m check the build |
/qc-helper |
Answer questions about Qwen Code usage and configuration | /qc-helper how do I configure MCP? |
See Code Review for full /review documentation.
1.6 Side Question (/btw)
The /btw command allows you to ask quick side questions without interrupting or affecting the main conversation flow.
| Command | Description |
|---|---|
/btw <your question> |
Ask a quick side question |
?btw <your question> |
Alternative syntax for side questions |
How It Works:
- The side question is sent as a separate API call with recent conversation context (up to the last 20 messages)
- The response is displayed above the Composer — you can continue typing while waiting
- The main conversation is not blocked — it continues independently
- The side question response does not become part of the main conversation history
- Answers are rendered with full Markdown support (code blocks, lists, tables, etc.)
Keyboard Shortcuts (Interactive Mode):
| Shortcut | Action |
|---|---|
Escape |
Cancel (while loading) or dismiss (after completed) |
Space or Enter |
Dismiss the answer (when input is empty) |
Ctrl+C or Ctrl+D |
Cancel an in-flight side question |
Example:
(While the main conversation is about refactoring code)
> /btw What's the difference between let and var in JavaScript?
╭──────────────────────────────────────────╮
│ /btw What's the difference between let │
│ and var in JavaScript? │
│ │
│ + Answering... │
│ Press Escape, Ctrl+C, or Ctrl+D to cancel│
╰──────────────────────────────────────────╯
> (Composer remains active — keep typing)
(After the answer arrives)
╭──────────────────────────────────────────╮
│ /btw What's the difference between let │
│ and var in JavaScript? │
│ │
│ `let` is block-scoped, while `var` is │
│ function-scoped. `let` was introduced │
│ in ES6 and doesn't hoist the same way. │
│ │
│ Press Space, Enter, or Escape to dismiss │
╰──────────────────────────────────────────╯
> (Composer still active)
Supported Execution Modes:
| Mode | Behavior |
|---|---|
| Interactive | Shows above Composer with Markdown rendering |
| Non-interactive | Returns text result: btw> question\nanswer |
| ACP (Agent Protocol) | Returns stream_messages async generator |
Tip
Use
/btwwhen you need a quick answer without derailing your main task. It's especially useful for clarifying concepts, checking facts, or getting quick explanations while staying focused on your primary workflow.
1.7 Session Recap (/recap)
The /recap command generates a short "where you left off" summary of the
current session, so you can resume an old conversation without scrolling
back through pages of history.
| Command | Description |
|---|---|
/recap |
Generate and show a 1-3 sentence session summary |
How it works:
- Uses the configured fast model (
fastModelsetting) when available, falling back to the main session model. A small, cheap model is enough for a recap. - The recent conversation (up to 30 messages, text only — tool calls and tool responses are filtered out) is sent to the model with a tight system prompt.
- The recap is rendered in dim color with a
❯prefix so it stands apart from real assistant replies. - Refuses with an inline error if a model turn is in flight or another command
is processing. If there is no usable conversation, or the underlying
generation fails,
/recapshows a short info message instead of a recap — the manual command always responds with something.
Auto-trigger when returning from being away:
If the terminal is blurred for 5+ minutes and gets focused again, a recap
is generated and shown automatically (only when no model response is in
progress; otherwise it waits for the current turn to finish and then fires).
Unlike the manual command, the auto-trigger is fully silent on failure: if
generation errors or there is nothing to summarize, no message is added to
the history. Controlled by the general.showSessionRecap setting
(default: true); the manual /recap command always works regardless of
this setting.
Example:
> /recap
❯ Refactoring loopDetectionService.ts to address long-session OOM caused by
unbounded streamContentHistory and contentStats. The next step is to
implement option B (LRU sliding window with FNV-1a) pending confirmation.
Tip
Configure a fast model via
/model --fast <model>(e.g.qwen3-coder-flash) to make/recapfast and cheap. Setgeneral.showSessionRecaptofalseto opt out of the auto-trigger while keeping the manual command available.
1.8 Information, Settings, and Help
Commands for obtaining information and performing system settings.
| Command | Description | Usage Examples |
|---|---|---|
/help |
Display help information for available commands | /help or /? |
/about |
Display version information | /about |
/stats |
Display detailed statistics for current session | /stats |
/settings |
Open settings editor | /settings |
/auth |
Change authentication method | /auth |
/bug |
Submit issue about Qwen Code | /bug Button click unresponsive |
/copy |
Copy last output content to clipboard | /copy |
/quit |
Exit Qwen Code immediately | /quit or /exit |
1.9 Common Shortcuts
| Shortcut | Function | Note |
|---|---|---|
Ctrl/cmd+L |
Clear screen | Equivalent to /clear |
Ctrl/cmd+T |
Toggle tool description | MCP tool management |
Ctrl/cmd+C×2 |
Exit confirmation | Secure exit mechanism |
Ctrl/cmd+Z |
Undo input | Text editing |
Ctrl/cmd+Shift+Z |
Redo input | Text editing |
1.10 CLI Auth Subcommands
In addition to the in-session /auth slash command, Qwen Code provides standalone CLI subcommands for managing authentication directly from the terminal:
| Command | Description |
|---|---|
qwen auth |
Interactive authentication setup |
qwen auth qwen-oauth |
|
qwen auth coding-plan |
Authenticate with Alibaba Cloud Coding Plan |
qwen auth coding-plan --region china --key sk-sp-… |
Non-interactive Coding Plan setup (for scripting) |
qwen auth status |
Show current authentication status |
Tip
These commands run outside of a Qwen Code session. Use them to configure authentication before starting a session, or in scripts and CI environments. See the Authentication page for full details.
2. @ Commands (Introducing Files)
@ commands are used to quickly add local file or directory content to the conversation.
| Command Format | Description | Examples |
|---|---|---|
@<file path> |
Inject content of specified file | @src/main.py Please explain this code |
@<directory path> |
Recursively read all text files in directory | @docs/ Summarize content of this document |
Standalone @ |
Used when discussing @ symbol itself |
@ What is this symbol used for in programming? |
Note: Spaces in paths need to be escaped with backslash (e.g., @My\ Documents/file.txt)
3. Exclamation Commands (!) - Shell Command Execution
Exclamation commands allow you to execute system commands directly within Qwen Code.
| Command Format | Description | Examples |
|---|---|---|
!<shell command> |
Execute command in sub-Shell | !ls -la, !git status |
Standalone ! |
Switch Shell mode, any input is executed directly as Shell command | !(enter) → Input command → !(exit) |
Environment Variables: Commands executed via ! will set the QWEN_CODE=1 environment variable.
4. Custom Commands
Save frequently used prompts as shortcut commands to improve work efficiency and ensure consistency.
Note
Custom commands now use Markdown format with optional YAML frontmatter. TOML format is deprecated but still supported for backwards compatibility. When TOML files are detected, an automatic migration prompt will be displayed.
Quick Overview
| Function | Description | Advantages | Priority | Applicable Scenarios |
|---|---|---|---|---|
| Namespace | Subdirectory creates colon-named commands | Better command organization | ||
| Global Commands | ~/.qwen/commands/ |
Available in all projects | Low | Personal frequently used commands, cross-project use |
| Project Commands | <project root directory>/.qwen/commands/ |
Project-specific, version-controllable | High | Team sharing, project-specific commands |
Priority Rules: Project commands > User commands (project command used when names are same)
Command Naming Rules
File Path to Command Name Mapping Table
| File Location | Generated Command | Example Call |
|---|---|---|
~/.qwen/commands/test.md |
/test |
/test Parameter |
<project>/.qwen/commands/git/commit.md |
/git:commit |
/git:commit Message |
Naming Rules: Path separator (/ or \) converted to colon (:)
Markdown File Format Specification (Recommended)
Custom commands use Markdown files with optional YAML frontmatter:
---
description: Optional description (displayed in /help)
---
Your prompt content here.
Use {{args}} for parameter injection.
| Field | Required | Description | Example |
|---|---|---|---|
description |
Optional | Command description (displayed in /help) | description: Code analysis tool |
| Prompt body | Required | Prompt content sent to model | Any Markdown content after the frontmatter |
TOML File Format (Deprecated)
Warning
Deprecated: TOML format is still supported but will be removed in a future version. Please migrate to Markdown format.
| Field | Required | Description | Example |
|---|---|---|---|
prompt |
Required | Prompt content sent to model | prompt = "Please analyze code: {{args}}" |
description |
Optional | Command description (displayed in /help) | description = "Code analysis tool" |
Parameter Processing Mechanism
| Processing Method | Syntax | Applicable Scenarios | Security Features |
|---|---|---|---|
| Context-aware Injection | {{args}} |
Need precise parameter control | Automatic Shell escaping |
| Default Parameter Processing | No special marking | Simple commands, parameter appending | Append as-is |
| Shell Command Injection | !{command} |
Need dynamic content | Execution confirmation required before |
1. Context-aware Injection ({{args}})
| Scenario | TOML Configuration | Call Method | Actual Effect |
|---|---|---|---|
| Raw Injection | prompt = "Fix: {{args}}" |
/fix "Button issue" |
Fix: "Button issue" |
| In Shell Command | prompt = "Search: !{grep {{args}} .}" |
/search "hello" |
Execute grep "hello" . |
2. Default Parameter Processing
| Input Situation | Processing Method | Example |
|---|---|---|
| Has parameters | Append to end of prompt (separated by two line breaks) | /cmd parameter → Original prompt + parameter |
| No parameters | Send prompt as is | /cmd → Original prompt |
🚀 Dynamic Content Injection
| Injection Type | Syntax | Processing Order | Purpose |
|---|---|---|---|
| File Content | @{file path} |
Processed first | Inject static reference files |
| Shell Commands | !{command} |
Processed in middle | Inject dynamic execution results |
| Parameter Replacement | {{args}} |
Processed last | Inject user parameters |
3. Shell Command Execution (!{...})
| Operation | User Interaction |
|---|---|
| 1. Parse command and parameters | - |
| 2. Automatic Shell escaping | - |
| 3. Show confirmation dialog | ✅ User confirmation |
| 4. Execute command | - |
| 5. Inject output to prompt | - |
Example: Git Commit Message Generation
---
description: Generate Commit message based on staged changes
---
Please generate a Commit message based on the following diff:
```diff
!{git diff --staged}
```
4. File Content Injection (@{...})
| File Type | Support Status | Processing Method |
|---|---|---|
| Text Files | ✅ Full Support | Directly inject content |
| Images/PDF | ✅ Multi-modal Support | Encode and inject |
| Binary Files | ⚠️ Limited Support | May be skipped or truncated |
| Directory | ✅ Recursive Injection | Follow .gitignore rules |
Example: Code Review Command
---
description: Code review based on best practices
---
Review {{args}}, reference standards:
@{docs/code-standards.md}
Practical Creation Example
"Pure Function Refactoring" Command Creation Steps Table
| Operation | Command/Code |
|---|---|
| 1. Create directory structure | mkdir -p ~/.qwen/commands/refactor |
| 2. Create command file | touch ~/.qwen/commands/refactor/pure.md |
| 3. Edit command content | Refer to the complete code below. |
| 4. Test command | @file.js → /refactor:pure |
---
description: Refactor code to pure function
---
Please analyze code in current context, refactor to pure function.
Requirements:
1. Provide refactored code
2. Explain key changes and pure function characteristic implementation
3. Maintain function unchanged
Custom Command Best Practices Summary
Command Design Recommendations Table
| Practice Points | Recommended Approach | Avoid |
|---|---|---|
| Command Naming | Use namespaces for organization | Avoid overly generic names |
| Parameter Processing | Clearly use {{args}} |
Rely on default appending (easy to confuse) |
| Error Handling | Utilize Shell error output | Ignore execution failure |
| File Organization | Organize by function in directories | All commands in root directory |
| Description Field | Always provide clear description | Rely on auto-generated description |
Security Features Reminder Table
| Security Mechanism | Protection Effect | User Operation |
|---|---|---|
| Shell Escaping | Prevent command injection | Automatic processing |
| Execution Confirmation | Avoid accidental execution | Dialog confirmation |
| Error Reporting | Help diagnose issues | View error information |