* fix(cli): stop scroll snap-back during parallel-agent runs (non-VP)
In non-VP mode ink clears the whole terminal (including scrollback) on every
repaint once the non-<Static> live frame exceeds the terminal height (see
ink's shouldClearTerminalForFrame). During a parallel-agent run the
pure-parallel inline panel rendered the UNFILTERED toolCalls, so running
subagents were shown inline AND in LiveAgentPanel below the composer — two
full rosters that push the live frame past the viewport. The per-second
elapsed/token ticks then fire that clear continuously, so scroll-up snaps
straight back to the bottom and flickers.
Route the pure-parallel branch through the same inlineToolCalls hand-off as
every other group: during the live phase render only the agents the panel is
not showing (terminal rows en route to <Static>), keeping the header total
honest via totalAgentCount. Add an availableTerminalHeight backstop to
InlineParallelAgentsDisplay that windows the rows ("+N more") so the panel can
never exceed its height budget.
Refs #5798
Generated with AI
Co-authored-by: Qwen-Coder <[email protected]>
* fix(cli): gate SGR mouse tracking to VP mode so non-VP keeps native scrollback
Enabling SGR mouse tracking (?1002h) makes the host terminal stop doing native
scrollback on the wheel — it hands wheel events to the app (Terminal.app even
diverts them to arrow keys, which then drive composer input history and the
background-agent panel). That is only acceptable when the app itself owns the
wheel: VP mode (ScrollableList) or an alternate-screen modal (ThinkingViewer),
neither of which relies on main-screen scrollback. But a collapsed thinking
block armed mouse tracking just for click-to-expand, unconditionally, so any
non-VP session with thinking blocks could no longer scroll its transcript.
Make useMouseEvents gate on VP mode by default: mouse tracking turns on only
when `ui.useTerminalBuffer` is set. Surfaces that legitimately own the wheel
pass the new `bypassVpGate` option (ScrollableList, ThinkingViewer). The
thinking-block click handler does not, so in non-VP it stays dormant and native
terminal scrollback is preserved (the block still expands via Alt+T). This is a
single chokepoint, so future non-VP mouse subscribers can't reintroduce the
regression.
Refs #5798
Generated with AI
Co-authored-by: Qwen-Coder <[email protected]>
* fix(cli): tighten inline parallel-agent windowing and drop redundant filters
Address review feedback on the parallel-agent snap-back fix:
- InlineParallelAgentsDisplay: the height backstop kept Math.max(1, budget-2)
rows, so at availableTerminalHeight <= 2 it rendered header + indicator + 1
data row (3 lines) and overflowed the very budget meant to cap it, which can
re-trigger the shouldClearTerminalForFrame snap-back. Reserve the header and
(when overflowing) the indicator first, then window the remaining rows; at a
budget of 1 keep only the header (its label still states the total). Total
rendered height now never exceeds the budget. Adds budget=1/2 regression tests.
- ToolGroupMessage: isPureParallelAgentGroup already guarantees every entry is
a subagent, so the isSubagentToolEntry filters on inlineToolCalls and on
totalAgentCount were no-ops; use inlineToolCalls and toolCalls.length directly.
Generated with AI
Co-authored-by: Qwen-Coder <[email protected]>
* fix(cli): cap inline parallel-agents only in the live phase + test gaps
Address /review feedback:
- ToolGroupMessage: only forward availableTerminalHeight to
InlineParallelAgentsDisplay during the live phase (isPending). The height
backstop guards the non-<Static> live frame; once committed the rows live in
<Static> with no snap-back risk, and MainContent passes staticAreaMaxItemHeight
(>=100) for committed items. Forwarding that let the cap fire on scrollback and
could permanently hide completed agents behind a static "+N more". Pass
undefined when committed, per the component's documented contract.
- InlineParallelAgentsDisplay.test: add a "generous budget" case (10 agents,
budget 20) pinning the `rows.length + 1 > budget` boundary so a regression to
>= would be caught instead of silently truncating when there is room.
- ThinkingViewer.test (new): pin that the modal wheel handler subscribes WITH
bypassVpGate: true (mirror of the HistoryItemDisplay test that pins the
opposite contract), so a future refactor dropping the flag can't silently
break wheel scrolling in non-VP mode.
Generated with AI
Co-authored-by: Qwen-Coder <[email protected]>
* test(cli): pin live-only height cap and windowing boundary
Address /review test-coverage feedback:
- ToolGroupMessage.test: add a contrast case that renders the same many-agent
group with isPending={true} vs isPending={false} at the same tight
availableTerminalHeight, asserting the overflow indicator appears only in the
live phase and every agent renders in the committed phase. Pins the
load-bearing `isPending ? availableTerminalHeight : undefined` conditional.
- InlineParallelAgentsDisplay.test: add the budget=3 boundary case (the first
budget at which a single data row appears: rowsFit = budget - 2 = 1), so an
off-by-one in the windowing arithmetic is caught at the transition point
between budget=2 (zero rows) and budget=3 (one row).
Generated with AI
Co-authored-by: Qwen-Coder <[email protected]>
* docs(cli): document the 1-line-per-AgentRow invariant the height backstop relies on
Address /review feedback: the windowing math (rowsFit = availableTerminalHeight
- 2) counts exactly one terminal line per AgentRow. That invariant — held today
by the wrap="truncate-end" Texts in AgentRow — was undocumented, so a future
change adding multi-line content (wrapped activity column, progress bar) would
silently overflow the budget and re-trigger the shouldClearTerminalForFrame
snap-back this PR fixes. Add the invariant at both the AgentRow definition and
its render site. Comment-only; no behavior change.
Generated with AI
Co-authored-by: Qwen-Coder <[email protected]>
* test(cli): pin the windowing `>` boundary at the exact-fit budget
Address /review feedback: the "generous budget" case used budget=20 with 10
agents, but `11 > 20` and `11 >= 20` are both false, so a regression from `>` to
`>=` in `rows.length + 1 > availableTerminalHeight` would go undetected. Use
budget=11 (= rows.length + 1) instead: `11 > 11` is false (no windowing) while
`11 >= 11` is true (windowing fires a spurious "+1 more"). The not.toContain(
'more agent') assertion catches the flip — the line count coincides at 11 either
way, so it is the indicator, not the height, that pins the boundary.
Generated with AI
Co-authored-by: Qwen-Coder <[email protected]>
* docs(cli): correct InlineParallelAgentsDisplay docstring to dual-phase usage
Address /review feedback: the module docstring claimed the panel is "Rendered in
the committed phase only", but this PR routes it through ToolGroupMessage's
inlineToolCalls hand-off so it renders in BOTH phases — live phase showing only
terminal agents (running/background owned by LiveAgentPanel) under an
availableTerminalHeight windowing cap, committed phase showing the full roster
uncapped. Update the docstring to describe the dual-phase behaviour and the
height backstop. Comment-only; no behaviour change.
Generated with AI
Co-authored-by: Qwen-Coder <[email protected]>
* fix(cli): enforce 1-line-per-element with wrap="truncate-end" everywhere
Address /review [Critical]: the height backstop budgets the header, the optional
"+N more" overflow indicator, and each AgentRow as exactly 1 terminal line, but
the header Text, the indicator Text, and the AgentRow trailing (elapsed · tokens)
Text lacked wrap="truncate-end". On a narrow terminal any of them could wrap to
2+ lines, pushing the rendered frame past availableTerminalHeight and re-firing
the shouldClearTerminalForFrame snap-back this PR fixes — and it made the
documented "all Text elements use truncate-end" invariant false. Add
wrap="truncate-end" to every Text in the panel (header, indicator, glyph,
trailing) so the 1-line invariant actually holds. No behaviour change at normal
widths (the labels already fit); tightens the degenerate-width guarantee.
Generated with AI
Co-authored-by: Qwen-Coder <[email protected]>
---------
Co-authored-by: 秦奇 <[email protected]>
Co-authored-by: Qwen-Coder <[email protected]>
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.
