* fix(serve): keep skill slash commands available after the ACP child is reaped `GET /workspace/skills` is answered exclusively by the ACP child — the daemon has no local SkillManager. `requestWorkspaceStatus` only checks for an already-live channel (`liveChannelInfo()`, never `ensureChannel()`), so when no child is running it returns the idle placeholder (`initialized: false`, empty `skills`). That is the norm before the first session, and — crucially — again after the child is reaped on session close, which happens immediately by default (`--channel-idle-timeout-ms` defaults to 0 = immediate kill). Unlike `/workspace/providers`, skills have no daemon-local status provider to fall back on. So once a user has created and closed a session, every subsequent pre-first-prompt `/workspace/skills` query returns empty, the Web Shell's slash-command list falls back to the hardcoded built-ins (which omit skills), and `/rev` stops autocompleting `/review`. Retain the last skills status a live child produced and replay it while no channel is live, so skill-backed slash commands keep autocompleting; the next live query refreshes the cache. `initialized` cleanly separates a real child answer (always `true`) from the idle placeholder (always `false`). Completes #6153, which wired the Web Shell to fetch `/workspace/skills` in the deferred-connect path but could not surface skills the daemon was unable to answer without a live child. * fix(serve): enumerate workspace skills locally when the ACP child is unavailable The cache from the previous commit keeps the last child answer alive across a reap, but it never warms when the child never answers at all — most visibly under `npm run dev`, where the on-demand-transpiled child's `initialize` handshake routinely exceeds the 10s preheat budget, so preheat times out and no channel ever comes up. `/workspace/skills` then stays empty until the first prompt, dropping `/review` and every other skill from the Web Shell's pre-first-prompt autocomplete even though the skills exist on disk (typing `/review` in full still runs it, since submitting spawns a session — hence "not in the list, but usable"). Add a daemon-local skills provider that enumerates skills straight from the filesystem via SkillManager (a lightweight Config shim — no child, no MCP init), mirroring the existing daemon-local providers-status provider. The facade falls back to it only after both a live child answer and the cached last answer are unavailable, so the live child stays authoritative (and keeps extension-provided skills) while a never-preheated child still yields the on-disk skills — `/review` included. * fix(serve): fall back to cached/local skills when the child query throws mid-flight Addresses review feedback on #6169: the channel can die after `liveChannelInfo()` returns a valid channel but before the RPC completes, so `queryWorkspaceStatus` rejects. Previously that exception propagated even though the cache or the daemon-local provider could still answer. Wrap the query in try/catch (logging via writeStderrLine, matching getWorkspaceEnvStatus / getWorkspacePreflightStatus) and treat a mid-flight failure as "no live child", so the request degrades to the cached last answer or daemon-local enumeration instead of failing. * refactor(serve): address review feedback on daemon-local skills provider - Extract the SkillConfig → ServeWorkspaceSkillStatus mapping into a shared workspace-skills-mapping module used by both the ACP child's buildWorkspaceSkillsStatus and the daemon-local provider, so the two skill listings can't drift; cover it (including the disable-model-invocation branch) with a unit test. - Memoize the SkillManager per workspace so repeat queries reuse its in-memory cache instead of re-scanning every skill level on each call. - Honor the safe-mode env (isSafeModeEnv, as Config does) instead of hardcoding isSafeMode to false; keep bareMode off (the daemon never runs `--bare`). - Log daemon-local enumeration failures via writeStderrLine, matching the rest of the workspace-service error handling. * test(serve): cover daemon-local skills error path; guard the facade provider call - Test the previously-uncovered `buildWorkspaceSkillsStatus` catch branch: when enumeration fails it returns `{ initialized: false, skills: [], errors: [{ kind: 'skills', status: 'error', error }] }` and logs to stderr. Also cover the per-workspace SkillManager memoization. - Wrap the facade's `workspaceSkillsStatusProvider` call in try/catch so a throwing injected provider degrades to the idle placeholder instead of failing the request (matching getWorkspaceEnvStatus / getWorkspacePreflightStatus), with a facade test for the throw path. |
||
|---|---|---|
| .github | ||
| .husky | ||
| .qwen | ||
| .vscode | ||
| docs | ||
| docs-site | ||
| eslint-rules | ||
| integration-tests | ||
| packages | ||
| patches | ||
| scripts | ||
| .dockerignore | ||
| .editorconfig | ||
| .gitattributes | ||
| .gitignore | ||
| .npmrc | ||
| .nvmrc | ||
| .prettierignore | ||
| .prettierrc.json | ||
| .yamllint.yml | ||
| AGENTS.md | ||
| CHANGELOG.md | ||
| CLAUDE.md | ||
| CONTRIBUTING.md | ||
| Dockerfile | ||
| esbuild.config.js | ||
| eslint.config.js | ||
| eslint.legacy-filenames.mjs | ||
| LICENSE | ||
| Makefile | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| SECURITY.md | ||
| tsconfig.json | ||
| vitest.config.ts | ||
The open-source AI coding agent that lives in your terminal.
中文 | Deutsch | français | 日本語 | Русский | Português (Brasil)
Why Qwen Code?
- Agentic out of the box — Auto-Memory, Auto-Skills, SubAgents, Agent Teams, and MCP. Dynamic workflows, zero setup.
- Open-source, inside and out — The framework and the Qwen models are open-source. They evolve together. No vendor lock-in.
- Multi-protocol — Supports OpenAI, Anthropic, Gemini, and Qwen APIs. Any third-party provider or local model (Ollama / vLLM). Switch at runtime.
- Beyond the terminal — IDE plugins, Desktop app, daemon mode, SDKs, and IM bots (Telegram / DingTalk / WeChat / Feishu).
Tip
Qwen Code is actively iterating on itself — using its own agent and models to file issues, submit PRs, review code, and run tests. Powered by the community, driven by AI.
Installation
Linux / macOS:
curl -fsSL https://qwen-code-assets.oss-cn-hangzhou.aliyuncs.com/installation/install-qwen-standalone.sh | bash
Windows:
irm https://qwen-code-assets.oss-cn-hangzhou.aliyuncs.com/installation/install-qwen-standalone.ps1 | iex
Restart your terminal after installation to ensure environment variables take effect.
NPM / Homebrew
NPM (requires Node.js 22+):
npm install -g @qwen-code/qwen-code@latest
Homebrew (macOS / Linux):
brew install qwen-code
Quick Start
qwen # Launch interactive terminal UI
# Inside the session:
/auth # Configure your provider and API key
See the Authentication Guide and Settings Reference for detailed setup.
How to Use Qwen Code
| Mode | Command | Use Case |
|---|---|---|
| Interactive | qwen |
Terminal UI with rich rendering, @file references, slash commands |
| Headless | qwen -p "..." |
Scripts, CI/CD, batch processing — no UI |
| IDE | — | VS Code, Zed, JetBrains |
| Desktop | — | Qwen Code Desktop — GUI for macOS, Windows, Linux |
| Daemon | qwen serve |
Shared agent session over HTTP+SSE (ACP). Multiple clients, one agent. (experimental) Docs |
| SDK | — | TypeScript, Python, Java |
| IM Bot | qwen channel |
Connect to Telegram, DingTalk, WeChat, or Feishu |
SDK example (Python)
import asyncio
from qwen_code_sdk import is_sdk_result_message, query
async def main() -> None:
result = query(
"Summarize the repository layout.",
{
"cwd": "/path/to/project",
"path_to_qwen_executable": "qwen",
},
)
async for message in result:
if is_sdk_result_message(message):
print(message["result"])
asyncio.run(main())
Capabilities
If you know Claude Code, you already know Qwen Code — and then some. We've put significant effort into bringing Qwen Code to feature parity with Claude Code, improving both breadth and reliability across the board.
| Feature | Qwen Code | Claude Code |
|---|---|---|
| SubAgents, Agent Teams, Dynamic Workflows | ✓ | ✓ |
| Auto-Memory, Auto-Skills, Hooks | ✓ | ✓ |
| Built-in Skills (/review, /batch, /loop, /bugfix…) | ✓ | ✓ |
| MCP, Plan Mode, LSP Integration | ✓ | ✓ |
| Auto Mode, Sandbox, Git Worktrees | ✓ | ✓ |
| Computer Use (desktop automation) | ✓ | ✓ |
| IDE Plugins (VS Code / JetBrains / Zed) | ✓ | ✓ |
| SDK | ✓ | ✓ |
| Headless Mode, Session Management | ✓ | ✓ |
| Open-source — model and framework | ✓ | — |
| Multi-protocol (OpenAI / Anthropic / Gemini / Qwen + any provider) | ✓ | — |
| Agent Arena (multi-model head-to-head on same task) | ✓ | — |
Daemon Mode — qwen serve (multi-client shared agent) |
✓ | — |
| IM Channels (Telegram / DingTalk / WeChat / Feishu) | ✓ | — |
Ecosystem
-
Qwen Code Desktop — Official desktop app for macOS, Windows, and Linux
-
AionUi — A modern GUI for command-line AI tools including Qwen Code
-
Gemini CLI Desktop — A cross-platform desktop/web/mobile UI for Qwen Code
-
🦞 Qwen Code Claw — Let other agents (Claude, Codex, etc.) delegate coding tasks to Qwen Code via ACP. Paste this prompt into your agent:
Use Qwen Code as a coding agent. First, fetch and read this skill reference:
https://raw.githubusercontent.com/QwenLM/qwen-code/refs/heads/main/.qwen/skills/qwen-code-claw/SKILL.md
Then follow the instructions inside to install, authenticate, and use Qwen Code via acpx for all coding tasks.
Contributing
Contributions are welcome! See CONTRIBUTING.md for guidelines.
Acknowledgments
This project was originally based on Google Gemini CLI v0.8.2. We gratefully acknowledge the Gemini CLI team's excellent work. Starting from Qwen Code v0.1, we stopped syncing with upstream and began independent development as a multi-protocol, multi-platform agent framework with deep integrations for Qwen models and beyond.
