@qwen-code/qwen-code 0.15.12-preview.2 → 0.16.0-preview.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/bundled/qc-helper/docs/configuration/settings.md +30 -34
  2. package/bundled/qc-helper/docs/features/lsp.md +87 -10
  3. package/bundled/qc-helper/docs/qwen-serve.md +74 -24
  4. package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +11 -11
  5. package/bundled/stuck/SKILL.md +124 -0
  6. package/chunks/{agent-UQY6A6OS.js → agent-ZNQPH67I.js} +15 -15
  7. package/chunks/{anthropicContentGenerator-4QE6LTVV.js → anthropicContentGenerator-ICBDZ6R2.js} +4 -4
  8. package/chunks/{askUserQuestion-QFSCBTUO.js → askUserQuestion-WQILGUSQ.js} +2 -2
  9. package/chunks/{ca-VQSV6JHA.js → ca-S3XJMT6P.js} +26 -0
  10. package/chunks/{chunk-SQNQIOD5.js → chunk-2B7UBDY5.js} +2 -2
  11. package/chunks/chunk-3MBY4GKN.js +350 -0
  12. package/chunks/{chunk-FSYKVGER.js → chunk-7QXHXMC6.js} +23 -7
  13. package/chunks/{chunk-PCL3EJGY.js → chunk-C3LHPHN2.js} +3924 -3683
  14. package/chunks/{chunk-UXW7MYAW.js → chunk-CW44BRRA.js} +1 -1
  15. package/chunks/{chunk-G27O2LD2.js → chunk-D5NTAHYL.js} +1 -1
  16. package/chunks/{chunk-CBVB66WY.js → chunk-EDYSNFEM.js} +1 -1
  17. package/chunks/{chunk-OCC4MZRS.js → chunk-F23NCRJ2.js} +1 -1
  18. package/chunks/{chunk-FYMSCRHM.js → chunk-FZIUV27X.js} +1 -1
  19. package/chunks/{chunk-SOIEFHIK.js → chunk-G7YTSRES.js} +1 -100
  20. package/chunks/{chunk-MXBWOU2L.js → chunk-JHMX4QTD.js} +15 -15
  21. package/chunks/{chunk-TPGOGCWM.js → chunk-JYQUJ5DS.js} +1 -1
  22. package/chunks/{chunk-FKVKVE6N.js → chunk-KXZ4TJB4.js} +1 -1
  23. package/chunks/{chunk-2WFU3IUH.js → chunk-MNPZ2WO6.js} +4864 -2303
  24. package/chunks/{chunk-BXNCPI75.js → chunk-NAID3ZWF.js} +2 -2
  25. package/chunks/{chunk-JMZQICAL.js → chunk-PPHYLJSS.js} +1 -1
  26. package/chunks/{chunk-CM2IESUE.js → chunk-PR4T27R7.js} +1 -1
  27. package/chunks/{chunk-CAWKL3UC.js → chunk-VTPOO6GV.js} +1 -1
  28. package/chunks/{chunk-GJXIKCKL.js → chunk-XP27SJMH.js} +76 -5
  29. package/chunks/{chunk-B7ZL7HUA.js → chunk-XVHR7ATJ.js} +1 -1
  30. package/chunks/{contextCommand-MQRG6RMG.js → contextCommand-IGBCEXI4.js} +16 -16
  31. package/chunks/{cron-create-WUTD5ZTH.js → cron-create-AVI3Q267.js} +2 -2
  32. package/chunks/{cron-delete-N3UQYCRA.js → cron-delete-ZCEGDXXV.js} +2 -2
  33. package/chunks/{cron-list-Z6RJJ4YH.js → cron-list-VN653OK5.js} +2 -2
  34. package/chunks/{de-M2IPQRBS.js → de-MNR4SMAI.js} +26 -0
  35. package/chunks/{edit-3KCBTA25.js → edit-74Q4AFHQ.js} +20 -16
  36. package/chunks/{en-N5GMPCVT.js → en-FIUWJSZR.js} +28 -0
  37. package/chunks/{enter-worktree-VWS5QZTU.js → enter-worktree-H72HXC7D.js} +15 -15
  38. package/chunks/{exit-worktree-RVXFWAPD.js → exit-worktree-FGIQO3S3.js} +15 -15
  39. package/chunks/{exitPlanMode-UL5DILDG.js → exitPlanMode-NBR2PK2D.js} +15 -15
  40. package/chunks/{fr-BTHRYEXO.js → fr-OFJFHLCR.js} +26 -0
  41. package/chunks/{geminiContentGenerator-O2OPGHJG.js → geminiContentGenerator-33RP4WKD.js} +3 -3
  42. package/chunks/{glob-57BSREPN.js → glob-WEE3CJL6.js} +15 -15
  43. package/chunks/{grep-XO5JOC7T.js → grep-DZKSBFZK.js} +15 -15
  44. package/chunks/{ja-D63TAEBO.js → ja-V6OQ6VL7.js} +26 -0
  45. package/chunks/{keychain-token-storage-DMFP5IJM.js → keychain-token-storage-335UOLJ6.js} +2 -2
  46. package/chunks/{ls-SUILOZZB.js → ls-6F3VSP6S.js} +3 -3
  47. package/chunks/{lsp-6TQBWVMZ.js → lsp-67Y7DJN5.js} +2 -2
  48. package/chunks/{monitor-BECPGO3K.js → monitor-EDZWEZVS.js} +33 -24
  49. package/chunks/{openaiContentGenerator-KEZQHIRM.js → openaiContentGenerator-5NQG3W64.js} +10 -10
  50. package/chunks/{pt-XUV7FSKC.js → pt-ZLE6SA4A.js} +26 -0
  51. package/chunks/{qwenContentGenerator-RPMRXTNH.js → qwenContentGenerator-4DPUUS6R.js} +17 -17
  52. package/chunks/{qwenOAuth2-JSQ7EPR3.js → qwenOAuth2-JE7H47TE.js} +3 -3
  53. package/chunks/{read-file-LGHEIQNH.js → read-file-CQOF7BQ2.js} +7 -7
  54. package/chunks/{ripGrep-6SFSXZ2G.js → ripGrep-KR5LKGTI.js} +15 -15
  55. package/chunks/{ru-7KHWMN3A.js → ru-A4OHIUNN.js} +26 -0
  56. package/chunks/{send-message-Q2JRAC3J.js → send-message-GB4AQZNC.js} +2 -2
  57. package/chunks/{serve-27O2AFE3.js → serve-GAD2PEST.js} +1299 -408
  58. package/chunks/{shell-J7K5KYCH.js → shell-E2HMCBGR.js} +15 -15
  59. package/chunks/{skill-2R7P4ATS.js → skill-KDZH6UZ6.js} +9 -9
  60. package/chunks/{src-CGEDVW67.js → src-LY4RU5AI.js} +96 -24
  61. package/chunks/{syntheticOutput-S4DRGMQM.js → syntheticOutput-HFL3DE7R.js} +3 -3
  62. package/chunks/{task-stop-7THHVAQS.js → task-stop-ZQF26RXS.js} +2 -2
  63. package/chunks/{todoWrite-WKUGUTPX.js → todoWrite-U4SC643O.js} +3 -3
  64. package/chunks/{tool-search-XOH3ZWVS.js → tool-search-U4XQVLFU.js} +7 -7
  65. package/chunks/{web-fetch-OZE6ZQUF.js → web-fetch-BRWZ4WSE.js} +4 -4
  66. package/chunks/{write-file-74NQ27Q2.js → write-file-NBLRMNGB.js} +20 -16
  67. package/chunks/{zh-TW-O36Q4V7E.js → zh-TW-552S24LR.js} +28 -0
  68. package/chunks/{zh-VGHU6XBB.js → zh-V32QONGV.js} +28 -0
  69. package/cli.js +8027 -5104
  70. package/locales/ca.js +40 -0
  71. package/locales/de.js +40 -0
  72. package/locales/en.js +43 -0
  73. package/locales/fr.js +41 -0
  74. package/locales/ja.js +39 -0
  75. package/locales/pt.js +39 -0
  76. package/locales/ru.js +39 -0
  77. package/locales/zh-TW.js +41 -0
  78. package/locales/zh.js +41 -0
  79. package/package.json +2 -2
@@ -73,13 +73,7 @@ When both legacy settings are present with different values, the migration follo
73
73
 
74
74
  ### Available settings in `settings.json`
75
75
 
76
- Settings are organized into categories. Most settings should be placed within their corresponding top-level category object in your `settings.json` file. A few compatibility settings, such as `proxy`, are top-level keys.
77
-
78
- #### top-level
79
-
80
- | Setting | Type | Description | Default |
81
- | ------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
82
- | `proxy` | string | Proxy URL for CLI HTTP requests. Precedence is `--proxy` > `proxy` in `settings.json` > `HTTPS_PROXY` / `https_proxy` / `HTTP_PROXY` / `http_proxy` environment variables. | `undefined` |
76
+ Settings are organized into categories. Most settings should be placed within their corresponding top-level category object in your `settings.json` file. A few top-level settings like `proxy` and `plansDirectory` remain direct root keys for compatibility.
83
77
 
84
78
  #### general
85
79
 
@@ -145,17 +139,17 @@ Settings are organized into categories. Most settings should be placed within th
145
139
 
146
140
  #### model
147
141
 
148
- | Setting | Type | Description | Default |
149
- | -------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------- |
150
- | `model.name` | string | The Qwen model to use for conversations. | `undefined` |
151
- | `model.maxSessionTurns` | number | Maximum number of user/model/tool turns to keep in a session. -1 means unlimited. | `-1` |
152
- | `model.generationConfig` | object | Advanced overrides passed to the underlying content generator. Supports request controls such as `timeout`, `maxRetries`, `enableCacheControl`, `splitToolMedia` (set `true` for strict OpenAI-compatible servers like LM Studio that reject non-text content on `role: "tool"` messages — splits media into a follow-up user message), `contextWindowSize` (override model's context window size), `modalities` (override auto-detected input modalities), `customHeaders` (custom HTTP headers for API requests), `extra_body` (additional body parameters for OpenAI-compatible API requests only), and `reasoning` (`{ effort: 'low' \| 'medium' \| 'high' \| 'max', budget_tokens?: number }` to control thinking intensity, or `false` to disable; `'max'` is a DeepSeek extension — see [Reasoning / thinking configuration](./model-providers.md#reasoning--thinking-configuration) for per-provider behavior. **Note:** when `samplingParams` is set on an OpenAI-compatible provider, the pipeline ships those keys verbatim and the separate top-level `reasoning` field is dropped — put `reasoning_effort` inside `samplingParams` (or `extra_body`) instead in that case), along with fine-tuning knobs under `samplingParams` (for example `temperature`, `top_p`, `max_tokens`). Leave unset to rely on provider defaults. | `undefined` |
153
- | `model.chatCompression.contextPercentageThreshold` | number | Sets the threshold for chat history compression as a percentage of the model's total token limit. This is a value between 0 and 1 that applies to both automatic compression and the manual `/compress` command. For example, a value of `0.6` will trigger compression when the chat history exceeds 60% of the token limit. Use `0` to disable compression entirely. | `0.7` |
154
- | `model.skipNextSpeakerCheck` | boolean | Skip the next speaker check. | `false` |
155
- | `model.skipLoopDetection` | boolean | Disables loop detection checks. Loop detection prevents infinite loops in AI responses but can generate false positives that interrupt legitimate workflows. Enable this option if you experience frequent false positive loop detection interruptions. | `false` |
156
- | `model.skipStartupContext` | boolean | Skips sending the startup workspace context (environment summary and acknowledgement) at the beginning of each session. Enable this if you prefer to provide context manually or want to save tokens on startup. | `false` |
157
- | `model.enableOpenAILogging` | boolean | Enables logging of OpenAI API calls for debugging and analysis. When enabled, API requests and responses are logged to JSON files. | `false` |
158
- | `model.openAILoggingDir` | string | Custom directory path for OpenAI API logs. If not specified, defaults to `logs/openai` in the current working directory. Supports absolute paths, relative paths (resolved from current working directory), and `~` expansion (home directory). | `undefined` |
142
+ | Setting | Type | Description | Default |
143
+ | -------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------- |
144
+ | `model.name` | string | The Qwen model to use for conversations. | `undefined` |
145
+ | `model.maxSessionTurns` | number | Maximum number of user/model/tool turns to keep in a session. -1 means unlimited. | `-1` |
146
+ | `model.generationConfig` | object | Advanced overrides passed to the underlying content generator. Supports request controls such as `timeout`, `maxRetries`, `enableCacheControl`, `splitToolMedia` (set `true` for strict OpenAI-compatible servers like LM Studio that reject non-text content on `role: "tool"` messages — splits media into a follow-up user message), `contextWindowSize` (override model's context window size), `modalities` (override auto-detected input modalities), `customHeaders` (custom HTTP headers for API requests), and `extra_body` (additional body parameters for OpenAI-compatible API requests only), along with fine-tuning knobs under `samplingParams` (for example `temperature`, `top_p`, `max_tokens`). Leave unset to rely on provider defaults. | `undefined` |
147
+ | `model.chatCompression.contextPercentageThreshold` | number | Sets the threshold for chat history compression as a percentage of the model's total token limit. This is a value between 0 and 1 that applies to both automatic compression and the manual `/compress` command. For example, a value of `0.6` will trigger compression when the chat history exceeds 60% of the token limit. Use `0` to disable compression entirely. | `0.7` |
148
+ | `model.skipNextSpeakerCheck` | boolean | Skip the next speaker check. | `false` |
149
+ | `model.skipLoopDetection` | boolean | Disables loop detection checks. Loop detection prevents infinite loops in AI responses but can generate false positives that interrupt legitimate workflows. Enable this option if you experience frequent false positive loop detection interruptions. | `false` |
150
+ | `model.skipStartupContext` | boolean | Skips sending the startup workspace context (environment summary and acknowledgement) at the beginning of each session. Enable this if you prefer to provide context manually or want to save tokens on startup. | `false` |
151
+ | `model.enableOpenAILogging` | boolean | Enables logging of OpenAI API calls for debugging and analysis. When enabled, API requests and responses are logged to JSON files. | `false` |
152
+ | `model.openAILoggingDir` | string | Custom directory path for OpenAI API logs. If not specified, defaults to `logs/openai` in the current working directory. Supports absolute paths, relative paths (resolved from current working directory), and `~` expansion (home directory). | `undefined` |
159
153
 
160
154
  **Example model.generationConfig:**
161
155
 
@@ -440,12 +434,13 @@ LSP server configuration is done through `.lsp.json` files in your project root
440
434
 
441
435
  #### advanced
442
436
 
443
- | Setting | Type | Description | Default |
444
- | ------------------------------ | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ |
445
- | `advanced.autoConfigureMemory` | boolean | Automatically configure Node.js memory limits. | `false` |
446
- | `advanced.dnsResolutionOrder` | string | The DNS resolution order. | `undefined` |
447
- | `advanced.excludedEnvVars` | array of strings | Environment variables to exclude from project context. Specifies environment variables that should be excluded from being loaded from project `.env` files. This prevents project-specific environment variables (like `DEBUG=true`) from interfering with the CLI behavior. Variables from `.qwen/.env` files are never excluded. | `["DEBUG","DEBUG_MODE"]` |
448
- | `advanced.bugCommand` | object | Configuration for the bug report command. Overrides the default URL for the `/bug` command. Properties: `urlTemplate` (string): A URL that can contain `{title}` and `{info}` placeholders. Example: `"bugCommand": { "urlTemplate": "https://bug.example.com/new?title={title}&info={info}" }` | `undefined` |
437
+ | Setting | Type | Description | Default |
438
+ | ------------------------------ | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ |
439
+ | `advanced.autoConfigureMemory` | boolean | Automatically configure Node.js memory limits. | `false` |
440
+ | `advanced.dnsResolutionOrder` | string | The DNS resolution order. | `undefined` |
441
+ | `advanced.excludedEnvVars` | array of strings | Environment variables to exclude from project context. Specifies environment variables that should be excluded from being loaded from project `.env` files. This prevents project-specific environment variables (like `DEBUG=true`) from interfering with the CLI behavior. Variables from `.qwen/.env` files are never excluded. | `["DEBUG","DEBUG_MODE"]` |
442
+ | `advanced.bugCommand` | object | Configuration for the bug report command. Overrides the default URL for the `/bug` command. Properties: `urlTemplate` (string): A URL that can contain `{title}` and `{info}` placeholders. Example: `"bugCommand": { "urlTemplate": "https://bug.example.com/new?title={title}&info={info}" }` | `undefined` |
443
+ | `plansDirectory` | string | Custom directory for approved Plan Mode files. Relative paths are resolved from the project root, and the resolved path must stay within the project root. If unset, plan files are stored in `~/.qwen/plans`. **Requires restart.** If the directory is inside the project root, add it to `.gitignore` to avoid committing plan files. | `undefined` |
449
444
 
450
445
  #### mcpServers
451
446
 
@@ -470,15 +465,15 @@ Configures connections to one or more Model-Context Protocol (MCP) servers for d
470
465
 
471
466
  Configures logging and metrics collection for Qwen Code. For more information, see [telemetry](/developers/development/telemetry).
472
467
 
473
- | Setting | Type | Description | Default |
474
- | ------------------------------------------ | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
475
- | `telemetry.enabled` | boolean | Whether or not telemetry is enabled. | |
476
- | `telemetry.target` | string | Informational label for the telemetry destination (`local` or `gcp`). Does not control exporter routing; set `telemetry.otlpEndpoint` or `telemetry.outfile` to configure where data is sent. | |
477
- | `telemetry.otlpEndpoint` | string | The endpoint for the OTLP Exporter. | |
478
- | `telemetry.otlpProtocol` | string | The protocol for the OTLP Exporter (`grpc` or `http`). | |
479
- | `telemetry.logPrompts` | boolean | Whether or not to include the content of user prompts in the logs. | |
480
- | `telemetry.includeSensitiveSpanAttributes` | boolean | Whether to include `prompt`, `function_args`, and `response_text` in spans created by the log-to-span bridge. Only controls bridge spans; OTel logs and other telemetry sinks may still receive `response_text`. | `false` |
481
- | `telemetry.outfile` | string | Path to write telemetry to a file. When set, overrides OTLP export. | |
468
+ | Setting | Type | Description | Default |
469
+ | ------------------------------------------ | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
470
+ | `telemetry.enabled` | boolean | Whether or not telemetry is enabled. | |
471
+ | `telemetry.target` | string | Informational label for the telemetry destination (`local` or `gcp`). Does not control exporter routing; set `telemetry.otlpEndpoint` or `telemetry.outfile` to configure where data is sent. | |
472
+ | `telemetry.otlpEndpoint` | string | The endpoint for the OTLP Exporter. | |
473
+ | `telemetry.otlpProtocol` | string | The protocol for the OTLP Exporter (`grpc` or `http`). | |
474
+ | `telemetry.logPrompts` | boolean | Whether or not to include the content of user prompts in the logs. | |
475
+ | `telemetry.includeSensitiveSpanAttributes` | boolean | When enabled, attaches verbatim user prompts, system prompts, tool inputs/outputs, and model responses to native OTel span attributes (in addition to log-to-span bridge spans). ⚠️ Streams sensitive data file contents, shell commands, conversation history to your OTLP backend. | `false` |
476
+ | `telemetry.outfile` | string | Path to write telemetry to a file. When set, overrides OTLP export. | |
482
477
 
483
478
  ### Example `settings.json`
484
479
 
@@ -487,6 +482,7 @@ Here is an example of a `settings.json` file with the nested structure, new as o
487
482
  ```
488
483
  {
489
484
  "proxy": "http://localhost:7890",
485
+ "plansDirectory": "./.qwen/plans",
490
486
  "general": {
491
487
  "vimMode": true,
492
488
  "preferredEditor": "code"
@@ -576,7 +572,7 @@ For authentication-related variables (like `OPENAI_*`) and the recommended `.qwe
576
572
  | `QWEN_TELEMETRY_OTLP_ENDPOINT` | Sets the OTLP endpoint for telemetry. | Overrides the `telemetry.otlpEndpoint` setting. |
577
573
  | `QWEN_TELEMETRY_OTLP_PROTOCOL` | Sets the OTLP protocol (`grpc` or `http`). | Overrides the `telemetry.otlpProtocol` setting. |
578
574
  | `QWEN_TELEMETRY_LOG_PROMPTS` | Set to `true` or `1` to enable or disable logging of user prompts. Any other value is treated as disabling it. | Overrides the `telemetry.logPrompts` setting. |
579
- | `QWEN_TELEMETRY_INCLUDE_SENSITIVE_SPAN_ATTRIBUTES` | Set to `true` or `1` to include `prompt`, `function_args`, and `response_text` in spans created by the log-to-span bridge. Any other value disables it. | Overrides the `telemetry.includeSensitiveSpanAttributes` setting. Only controls bridge spans; OTel logs and other telemetry sinks may still receive `response_text`. |
575
+ | `QWEN_TELEMETRY_INCLUDE_SENSITIVE_SPAN_ATTRIBUTES` | Set to `true` or `1` to attach verbatim user prompts, system prompts, tool I/O, and model responses to native OTel span attributes (and keep `prompt` / `function_args` / `response_text` on log-to-span bridge spans). Any other value disables it. | Overrides the `telemetry.includeSensitiveSpanAttributes` setting. ⚠️ Streams sensitive data to your OTLP backend. |
580
576
  | `QWEN_TELEMETRY_OUTFILE` | Sets the file path to write telemetry to. When set, overrides OTLP export. | Overrides the `telemetry.outfile` setting. |
581
577
  | `QWEN_SANDBOX` | Alternative to the `sandbox` setting in `settings.json`. | Accepts `true`, `false`, `docker`, `podman`, or a custom command string. |
582
578
  | `QWEN_SANDBOX_IMAGE` | Overrides sandbox image selection for Docker/Podman. | Takes precedence over `tools.sandboxImage`. |
@@ -344,7 +344,7 @@ You can override trust requirements for specific servers in their configuration:
344
344
  2. **Check if the server is installed**: Run the command manually (e.g. `clangd --version`) to verify
345
345
  3. **Check the command**: The server binary must be in your system `PATH`, or specified as an absolute path (e.g. `/opt/llvm/bin/clangd`). Relative paths that escape the workspace are blocked
346
346
  4. **Check workspace trust**: The workspace must be trusted for LSP (use `/trust`)
347
- 5. **Check logs**: Look for `[LSP]` entries in the debug log (see Debugging section below)
347
+ 5. **Check logs**: Start Qwen Code with `--debug`, then search for LSP-related entries in the debug log (see Debugging section below)
348
348
  6. **Check the process**: Run `ps aux | grep <server-name>` to verify the server process is running
349
349
 
350
350
  ### Slow Performance
@@ -361,19 +361,78 @@ You can override trust requirements for specific servers in their configuration:
361
361
 
362
362
  ### Debugging
363
363
 
364
- LSP debug logs are automatically written to session log files in `~/.qwen/debug/`. To check LSP-related entries:
364
+ LSP does not have a separate debug flag. Use Qwen Code's normal debug mode together with the LSP feature flag:
365
365
 
366
366
  ```bash
367
- # View the latest session log
368
- grep '\[LSP\]' ~/.qwen/debug/latest
367
+ qwen --experimental-lsp --debug
368
+ ```
369
+
370
+ Debug logs are written to the session debug log directory. To check LSP-related entries:
371
+
372
+ ```bash
373
+ # Default runtime directory
374
+ rg "LSP|Native LSP|clangd|connection closed" ~/.qwen/debug/latest
375
+ # Or, without ripgrep:
376
+ grep -E "LSP|Native LSP|clangd|connection closed" ~/.qwen/debug/latest
377
+
378
+ # If QWEN_RUNTIME_DIR is configured
379
+ rg "LSP|Native LSP|clangd|connection closed" "$QWEN_RUNTIME_DIR/debug/latest"
380
+ ```
381
+
382
+ Useful entries include:
383
+
384
+ - `[LSP] ...`: Logs emitted by the native LSP service and server manager.
385
+ - `[CONFIG] Native LSP status after discovery: ...`: LSP server configuration discovered for the session.
386
+ - `[CONFIG] Native LSP status after startup: ...`: Server startup result, including ready/failed counts.
387
+ - `[STATUS] LSP status snapshot for /status: ...`: Status snapshot printed when running `/status` in debug mode.
369
388
 
370
- # Common error messages to look for:
371
- # "command path is unsafe" → relative path escapes workspace, use absolute path or add to PATH
372
- # "command not found" → server binary not installed or not in PATH
373
- # "requires trusted workspace" → run /trust first
389
+ You can also run `/status` in the CLI to see a short LSP summary:
390
+
391
+ ```text
392
+ LSP: disabled
393
+ LSP: enabled, 1/1 ready
394
+ LSP: enabled, 0/1 ready (1 failed)
395
+ LSP: enabled, no servers configured
396
+ LSP: enabled, status unavailable
374
397
  ```
375
398
 
376
- You can also verify the server process is running:
399
+ For per-server details, run `/lsp`:
400
+
401
+ ```text
402
+ **LSP Server Status**
403
+
404
+ | Server | Command | Languages | Status |
405
+ |--------|---------|-----------|--------|
406
+ | clangd | `clangd` | c, cpp | READY |
407
+ | pyright | `pyright-langserver` | python | FAILED - startup failed |
408
+ ```
409
+
410
+ Common error messages to look for:
411
+
412
+ ```text
413
+ command path is unsafe -> relative path escapes workspace, use absolute path or add to PATH
414
+ command not found -> server binary not installed or not in PATH
415
+ requires trusted workspace -> run /trust first
416
+ LSP connection closed -> server started but exited or closed stdio before replying to initialize
417
+ ```
418
+
419
+ For clangd startup failures, verify the server directly from the project root:
420
+
421
+ ```bash
422
+ clangd --version
423
+ clangd --check=/path/to/file.cpp --log=verbose
424
+ ```
425
+
426
+ C/C++ projects should usually provide a `compile_commands.json` or `compile_flags.txt`. If the compile database is in a build directory, pass it to clangd:
427
+
428
+ ```json
429
+ {
430
+ "cpp": {
431
+ "command": "clangd",
432
+ "args": ["--background-index", "--compile-commands-dir=build"]
433
+ }
434
+ }
435
+ ```
377
436
 
378
437
  ```bash
379
438
  ps aux | grep clangd # or typescript-language-server, jdtls, etc.
@@ -402,7 +461,25 @@ qwen --experimental-lsp
402
461
 
403
462
  ### Q: How do I know which language servers are running?
404
463
 
405
- Check the debug log for `[LSP]` entries (`grep '\[LSP\]' ~/.qwen/debug/latest`), or verify the process directly with `ps aux | grep <server-name>`.
464
+ Start Qwen Code with LSP and debug mode enabled:
465
+
466
+ ```bash
467
+ qwen --experimental-lsp --debug
468
+ ```
469
+
470
+ Then run `/status` for a short summary, `/lsp` for per-server status, or inspect the debug log:
471
+
472
+ ```bash
473
+ # Default runtime directory
474
+ rg "LSP|Native LSP|<server-name>" ~/.qwen/debug/latest
475
+ # Or:
476
+ grep -E "LSP|Native LSP|<server-name>" ~/.qwen/debug/latest
477
+
478
+ # If QWEN_RUNTIME_DIR is configured
479
+ rg "LSP|Native LSP|<server-name>" "$QWEN_RUNTIME_DIR/debug/latest"
480
+ ```
481
+
482
+ LSP uses Qwen Code's normal `--debug` mode; there is no separate LSP debug flag.
406
483
 
407
484
  ### Q: Can I use multiple language servers for the same file type?
408
485
 
@@ -38,6 +38,12 @@ curl http://127.0.0.1:4170/capabilities
38
38
 
39
39
  The `workspaceCwd` field surfaces the bound workspace so clients can pre-flight check + omit `cwd` on `POST /session`.
40
40
 
41
+ The daemon also exposes read-only runtime snapshots for client UIs:
42
+ `GET /workspace/mcp`, `GET /workspace/skills`, `GET /workspace/providers`,
43
+ `GET /session/:id/context`, and `GET /session/:id/supported-commands`. The
44
+ workspace routes report the live daemon runtime and do not start the ACP child
45
+ when idle; an idle daemon returns `initialized: false` with an empty snapshot.
46
+
41
47
  ### 3. Open a session
42
48
 
43
49
  ```bash
@@ -97,6 +103,17 @@ qwen serve --hostname 0.0.0.0 --port 4170
97
103
 
98
104
  Clients then send `Authorization: Bearer $QWEN_SERVER_TOKEN` on every request. `/health` is exempted **only on loopback binds** so k8s/Compose liveness probes inside the pod (where the daemon listens on `127.0.0.1`) don't need credentials. On non-loopback binds (`--hostname 0.0.0.0` etc.) `/health` requires the token like every other route — otherwise an attacker can probe arbitrary addresses to confirm the daemon's existence. Use `/capabilities` to verify your token is correct end-to-end (it always requires auth):
99
105
 
106
+ > **Hardened loopback (`--require-auth`).** The default loopback no-token behavior is fine for a single-user laptop but unsafe on shared dev hosts, CI runners, or multi-tenant workstations where any local user can `curl 127.0.0.1:4170`. Pass `--require-auth` to make the bearer token mandatory on every route — including `/health` and `/capabilities` — even when bound to `127.0.0.1`. Boot fails without a token. With the flag on, an **unauthenticated** client can't read `/capabilities` to discover that auth is required; the discovery surface is the 401 response body itself. Once authenticated, the `caps.features.require_auth` tag is a post-auth confirmation that the deployment is hardened (useful for audit / compliance UIs):
107
+ >
108
+ > ```bash
109
+ > qwen serve --require-auth --token "$(openssl rand -hex 32)"
110
+ > # → /health, /capabilities, /session, … all require Authorization: Bearer …
111
+ > curl http://127.0.0.1:4170/health
112
+ > # → 401
113
+ > curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:4170/capabilities | jq '.features | index("require_auth")'
114
+ > # → 13 (or whatever index — non-null after authenticating means the tag is present)
115
+ > ```
116
+
100
117
  ```bash
101
118
  curl -H "Authorization: Bearer $QWEN_SERVER_TOKEN" http://your-host:4170/capabilities
102
119
  # → {"v":1,"mode":"http-bridge","features":[...],"modelServices":[],"workspaceCwd":"/path/to/your-project"}
@@ -107,15 +124,17 @@ The token comparison is constant-time (SHA-256 + `crypto.timingSafeEqual`); 401
107
124
 
108
125
  ## CLI flags
109
126
 
110
- | Flag | Default | Purpose |
111
- | ----------------------- | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
112
- | `--port <n>` | `4170` | TCP port. `0` = OS-assigned ephemeral port. |
113
- | `--hostname <addr>` | `127.0.0.1` | Bind interface. Anything beyond loopback requires a token. |
114
- | `--token <str>` | — | Bearer token. Falls back to `QWEN_SERVER_TOKEN` env var (with leading/trailing whitespace stripped — handy for `$(cat token.txt)`). |
115
- | `--max-sessions <n>` | `20` | Cap on concurrent live sessions. New `POST /session` requests that would spawn a fresh child return `503` (with `Retry-After: 5`) when the cap is hit; attaches to existing sessions are NOT counted. Set to `0` to disable. Sized for single-user / small-team usage; raise it if your deployment has the RAM/FD headroom (~30–50 MB per session). |
116
- | `--workspace <path>` | `process.cwd()` | Absolute workspace path this daemon binds to (per [#3803](https://github.com/QwenLM/qwen-code/issues/3803) §02 1 daemon = 1 workspace). `POST /session` requests with a mismatched `cwd` return `400 workspace_mismatch`. For multi-workspace deployments, run one `qwen serve` per workspace on separate ports. |
117
- | `--max-connections <n>` | `256` | Listener-level TCP connection cap (`server.maxConnections`). Bounds raw socket count irrespective of session count slow / phantom SSE clients get rejected at accept time once full. Raise alongside `--max-sessions` if your deployment expects many SSE subscribers per session. |
118
- | `--http-bridge` | `true` | Stage 1 mode: one `qwen --acp` child per daemon (bound to one workspace at boot, per [#3803](https://github.com/QwenLM/qwen-code/issues/3803) §02); N sessions multiplex onto that child via ACP `newSession()`. Stage 2 native in-process becomes available later. |
127
+ | Flag | Default | Purpose |
128
+ | ----------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
129
+ | `--port <n>` | `4170` | TCP port. `0` = OS-assigned ephemeral port. |
130
+ | `--hostname <addr>` | `127.0.0.1` | Bind interface. Anything beyond loopback requires a token. |
131
+ | `--token <str>` | — | Bearer token. Falls back to `QWEN_SERVER_TOKEN` env var (with leading/trailing whitespace stripped — handy for `$(cat token.txt)`). |
132
+ | `--require-auth` | `false` | Refuse to start without a bearer token, even on loopback. Hardens the `127.0.0.1` developer default for shared dev hosts / CI runners / multi-tenant workstations where any local user can hit the listener. Boots only with `--token` or `QWEN_SERVER_TOKEN` set; gates `/health` behind the bearer too. |
133
+ | `--max-sessions <n>` | `20` | Cap on concurrent live sessions. New `POST /session` requests that would spawn a fresh child return `503` (with `Retry-After: 5`) when the cap is hit; attaches to existing sessions are NOT counted. Set to `0` to disable. Sized for single-user / small-team usage; raise it if your deployment has the RAM/FD headroom (~30–50 MB per session). |
134
+ | `--workspace <path>` | `process.cwd()` | Absolute workspace path this daemon binds to (per [#3803](https://github.com/QwenLM/qwen-code/issues/3803) §02 1 daemon = 1 workspace). `POST /session` requests with a mismatched `cwd` return `400 workspace_mismatch`. For multi-workspace deployments, run one `qwen serve` per workspace on separate ports. |
135
+ | `--max-connections <n>` | `256` | Listener-level TCP connection cap (`server.maxConnections`). Bounds raw socket count irrespective of session count slow / phantom SSE clients get rejected at accept time once full. Raise alongside `--max-sessions` if your deployment expects many SSE subscribers per session. |
136
+ | `--event-ring-size <n>` | `8000` | Per-session SSE replay ring depth (#3803 §02 target). Sets the backlog available to `GET /session/:id/events` with `Last-Event-ID: N`. Larger = more reconnect headroom at the cost of a few hundred KB extra RAM per session. SDK clients can additionally request a larger per-subscriber backlog cap on a specific subscription via `?maxQueued=N` (range `[16, 2048]`, default 256). Daemons also emit a non-terminal `slow_client_warning` SSE frame at 75% queue fill so clients can drain / reconnect before getting evicted. Pre-flight `caps.features.slow_client_warning`. |
137
+ | `--http-bridge` | `true` | Stage 1 mode: one `qwen --acp` child per daemon (bound to one workspace at boot, per [#3803](https://github.com/QwenLM/qwen-code/issues/3803) §02); N sessions multiplex onto that child via ACP `newSession()`. Stage 2 native in-process becomes available later. |
119
138
 
120
139
  > **Sizing the load knobs.** `--max-sessions` is the **new-child** cap.
121
140
  > Three other layers also limit load — when sizing for a high-concurrency
@@ -173,16 +192,48 @@ To host **multiple workspaces** (one user, several repos; or several users on th
173
192
 
174
193
  To handle multiple **users** (each with their own quota, audit log, sandbox) or to scale beyond one process's reach (cold-start budget, FD count, RSS), spawn one daemon per workspace per user behind an external orchestrator. That orchestrator (multi-tenancy / OIDC / Quota / Audit / k8s) is **out of scope** for the qwen-code project — see issue [#3803](https://github.com/QwenLM/qwen-code/issues/3803) "External Reference Architecture" for the design pointers.
175
194
 
195
+ ## Loading and resuming a persisted session
196
+
197
+ The daemon exposes ACP's `session/load` and `session/unstable_resumeSession` over HTTP via two routes:
198
+
199
+ | Route | Use when |
200
+ | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
201
+ | `POST /session/:id/load` | The client has **no** history rendered (cold reconnect, picker-then-open). The daemon replays every persisted turn through SSE so subscribers see the full transcript. Capability tag: `session_load`. |
202
+ | `POST /session/:id/resume` | The client already has the turns on screen and only needs the daemon-side handle back. Model context is restored on the agent side without UI replay — the SSE stream stays clean. Capability tag: `unstable_session_resume`. |
203
+
204
+ The TypeScript SDK exposes both as static factories on `DaemonSessionClient`:
205
+
206
+ ```ts
207
+ import { DaemonClient, DaemonSessionClient } from '@qwen-code/sdk';
208
+
209
+ const client = new DaemonClient({ baseUrl: 'http://127.0.0.1:4170' });
210
+
211
+ // Cold reconnect — daemon will replay history through SSE.
212
+ const session = await DaemonSessionClient.load(client, 'persisted-id');
213
+
214
+ // Or, if your UI already has the history, skip the replay:
215
+ // const session = await DaemonSessionClient.resume(client, 'persisted-id');
216
+
217
+ for await (const event of session.events()) {
218
+ // First the replayed `session_update` frames (load only),
219
+ // then live events.
220
+ }
221
+ ```
222
+
223
+ Pre-flight `caps.features.session_load` / `caps.features.unstable_session_resume` before calling — older daemons return `404`. Concurrent same-action requests for the same id coalesce; cross-action races (a `load` racing a `resume`) get `409 restore_in_progress` with `Retry-After: 5`. See the [protocol reference](../developers/qwen-serve-protocol.md) for the full error envelope.
224
+
225
+ Note: history replay is bounded by the SSE ring (default 4000 frames). Long histories with chatty turns can exceed that — earliest frames are dropped silently. For very long sessions, prefer `resume` and rely on the client's local persisted UI.
226
+
176
227
  ## Durability model
177
228
 
178
- **Sessions are ephemeral in Stage 1.** Plan accordingly:
229
+ **Sessions are still ephemeral in Stage 1 across daemon restarts**, but persisted sessions on disk can be reloaded:
179
230
 
180
- - A child process crash publishes `session_died` and removes the session from the daemon's maps. There is **no resume** clients must `POST /session` again.
181
- - A daemon restart loses every in-flight session. ACP's `loadSession` / `unstable_resumeSession` are **not exposed via HTTP** in Stage 1; sessions don't outlive the daemon.
182
- - Long client disconnects (>5 min on a chatty turn) can outrun the SSE replay ring (default 4000 frames) — `Last-Event-ID` reconnect succeeds but state may be incoherent. For mobile / flaky-network clients, plan to re-create the session and re-open SSE on long drops.
231
+ - A child process crash publishes `session_died` and removes the live session from the daemon's maps. The persisted on-disk session **can** be reloaded via `POST /session/:id/load` if a fresh agent child is spawnable.
232
+ - A daemon restart loses every in-flight live session. The persisted sessions remain on disk and can be loaded against a new daemon process, subject to the same workspace binding rules.
233
+ - Long client disconnects (>5 min on a chatty turn) can outrun the SSE replay ring (default 4000 frames) — `Last-Event-ID` reconnect succeeds but state may be incoherent. For mobile / flaky-network clients, plan to re-open SSE on long drops or call `POST /session/:id/load` to replay from disk.
183
234
  - File operations (`writeTextFile`) are atomic across crashes (write-then-rename); they aren't atomic across daemon restarts in the sense of replaying — the file write either landed or it didn't.
184
235
 
185
- If your integration needs cross-restart durability, you need either Stage 1.5+ (`loadSession` over HTTP, persistence layer) or your own application-level state recovery. Don't hold long-running, restart-sensitive state inside the daemon's session.
236
+ If your integration needs server-side cross-restart durability beyond what `session/load` covers (e.g. server-managed retry queues), you still need application-level state recovery. Don't hold long-running, restart-sensitive state inside the daemon's session.
186
237
 
187
238
  ## Stage 1.5+ runtime guarantees
188
239
 
@@ -190,22 +241,21 @@ Stage 1's contract is sized for prototyping. Per [#3889 chiga0 downstream-consum
190
241
 
191
242
  **Blockers for serious downstream use:**
192
243
 
193
- 1. **Per-request `sessionScope` override** on `POST /session` today the daemon-wide default is the only setting; a VSCode extension can't say "I want a private session for this window" against a daemon configured for shared sessions.
194
- 2. **`loadSession` / `unstable_resumeSession` over HTTP** — without this, no integration can survive a child crash or daemon restart, and any orchestrator coordinating the daemon can't recover state either.
195
- 3. **Persistent client identity (pair tokens + per-client revocation)** — Stage 1 uses one shared bearer; a leaked token revokes everyone, and `originatorClientId` is client-self-declared rather than daemon-stamped from authenticated identity.
244
+ 1. **`loadSession` / `unstable_resumeSession` over HTTP** without this, no integration can survive a child crash or daemon restart, and any orchestrator coordinating the daemon can't recover state either.
245
+ 2. **Persistent client identity (pair tokens + per-client revocation)** — Stage 1 uses one shared bearer; a leaked token revokes everyone, and `originatorClientId` is client-self-declared rather than daemon-stamped from authenticated identity.
196
246
 
197
247
  **Reliability baseline:**
198
248
 
199
- 4. **Client-initiated heartbeat path**distinguish "agent thinking" from "daemon dead" without waiting for the 15s server heartbeat.
200
- 5. **`permission_already_resolved` event** when a vote loses the first-responder race — currently UIs have to infer state from a `404`.
201
- 6. **Larger / per-session-configurable replay ring** — default 4000 covers short drops; mobile / chatty-turn workloads need 8000+ or per-session config.
202
- 7. **`slow_client_warning` event before `client_evicted`** — soft backpressure so well-behaved slow clients can self-throttle (trim render depth, drop chunks) before being terminated.
249
+ 3. ~~**Client-initiated heartbeat path**~~shipped via [#4175](https://github.com/QwenLM/qwen-code/issues/4175) PR 9. `POST /session/:id/heartbeat` records last-seen timestamps on the daemon (capability tag `client_heartbeat`); SDK helpers are `DaemonClient.heartbeat()` / `DaemonSessionClient.heartbeat()`.
250
+ 4. **`permission_already_resolved` event** when a vote loses the first-responder race — currently UIs have to infer state from a `404`.
251
+ 5. **Larger / per-session-configurable replay ring** — default 4000 covers short drops; mobile / chatty-turn workloads need 8000+ or per-session config.
252
+ 6. **`slow_client_warning` event before `client_evicted`** — soft backpressure so well-behaved slow clients can self-throttle (trim render depth, drop chunks) before being terminated.
203
253
 
204
254
  **Integration ergonomics:**
205
255
 
206
- 8. **`POST /session/:id/_meta` for IM-style context** — per-session key-value attached to subsequent prompts (chat id, sender, thread id) replaces the per-channel improvisation.
207
- 9. **`/capabilities` actual feature negotiation** — `protocol_versions: { acp: '0.14.x', daemon_envelope: 1 }` so clients can detect drift instead of falling through to "unknown frame, ignore".
208
- 10. **First-class durability documentation** (this section) — already shipped above.
256
+ 7. **`POST /session/:id/_meta` for IM-style context** — per-session key-value attached to subsequent prompts (chat id, sender, thread id) replaces the per-channel improvisation.
257
+ 8. **`/capabilities` actual feature negotiation** — `protocol_versions: { acp: '0.14.x', daemon_envelope: 1 }` so clients can detect drift instead of falling through to "unknown frame, ignore".
258
+ 9. **First-class durability documentation** (this section) — already shipped above.
209
259
 
210
260
  The full convergence roadmap is tracked on [#3803](https://github.com/QwenLM/qwen-code/issues/3803).
211
261
 
@@ -24,11 +24,11 @@ This document lists the available keyboard shortcuts in Qwen Code.
24
24
  | `!` | Toggle shell mode when the input is empty. |
25
25
  | `?` | Toggle keyboard shortcuts display when the input is empty. |
26
26
  | `\` (at end of line) + `Enter` | Insert a newline. |
27
- | `Down Arrow` | Navigate down through the input history. |
27
+ | `Down Arrow` | Row down, then snap to end, then history next. |
28
28
  | `Enter` | Submit the current prompt. |
29
29
  | `Meta+Delete` / `Ctrl+Delete` | Delete the word to the right of the cursor. |
30
30
  | `Tab` | Autocomplete the current suggestion if one exists. |
31
- | `Up Arrow` | Navigate up through the input history. |
31
+ | `Up Arrow` | Row up, then snap to start, then history prev. |
32
32
  | `Ctrl+A` / `Home` | Move the cursor to the beginning of the line. |
33
33
  | `Ctrl+B` / `Left Arrow` | Move the cursor one character to the left. |
34
34
  | `Ctrl+C` | Clear the input prompt |
@@ -39,8 +39,8 @@ This document lists the available keyboard shortcuts in Qwen Code.
39
39
  | `Ctrl+H` / `Backspace` | Delete the character to the left of the cursor. |
40
40
  | `Ctrl+K` | Delete from the cursor to the end of the line. |
41
41
  | `Ctrl+Left Arrow` / `Meta+Left Arrow` / `Meta+B` | Move the cursor one word to the left. |
42
- | `Ctrl+N` | Navigate down through the input history. |
43
- | `Ctrl+P` | Navigate up through the input history. |
42
+ | `Ctrl+N` | Row down, then snap to end, then history next. |
43
+ | `Ctrl+P` | Row up, then snap to start, then history prev. |
44
44
  | `Ctrl+R` | Reverse search through input/shell history. |
45
45
  | `Ctrl+Y` | Retry the last failed request. |
46
46
  | `Ctrl+Right Arrow` / `Meta+Right Arrow` / `Meta+F` | Move the cursor one word to the right. |
@@ -59,13 +59,13 @@ This document lists the available keyboard shortcuts in Qwen Code.
59
59
 
60
60
  ## Radio Button Select
61
61
 
62
- | Shortcut | Description |
63
- | ------------------ | ------------------------------------------------------------------------------------------------------------- |
64
- | `Down Arrow` / `j` | Move selection down. |
65
- | `Enter` | Confirm selection. |
66
- | `Up Arrow` / `k` | Move selection up. |
67
- | `1-9` | Select an item by its number. |
68
- | (multi-digit) | For items with numbers greater than 9, press the digits in quick succession to select the corresponding item. |
62
+ | Shortcut | Description |
63
+ | ----------------------------- | ------------------------------------------------------------------------------------------------------------- |
64
+ | `Down Arrow` / `j` / `Ctrl+N` | Move selection down. |
65
+ | `Enter` | Confirm selection. |
66
+ | `Up Arrow` / `k` / `Ctrl+P` | Move selection up. |
67
+ | `1-9` | Select an item by its number. |
68
+ | (multi-digit) | For items with numbers greater than 9, press the digits in quick succession to select the corresponding item. |
69
69
 
70
70
  ## IDE Integration
71
71