Originally created by: imshaikot
The side panel runs on whichever agent CLI you already have logged in. Alibaba ships one: Qwen Code (QwenLM/qwen-code, binary qwen, Apache-2.0, 0.24.4 at the time of writing), with a documented headless mode.
This is the part worth getting on the record, because the obvious plan — write a Gemini CLI adapter, then get Qwen nearly free — does not survive contact with the repo.
Qwen Code was forked from Gemini CLI v0.8.2. But per its own README it ceased syncing with upstream at its own v0.1 and now explicitly targets Claude Code parity: "If you know Claude Code, you already know Qwen Code."
The consequence that matters for a runner: -o stream-json emits the Claude Code SDK schema — type: "system" with subtype: "session_start", type: "assistant" carrying an Anthropic-shaped message object with content: [{type: "text"}] and usage, parent_tool_use_id, and a terminal type: "result" with subtype, duration_ms and usage. That is not a Gemini-native stream. Qwen Code's reader is closer to claude.ts than to any Gemini adapter, and its session storage (~/.qwen/projects/<sanitized-cwd>/chats) is its own too.
The flag surface is still largely Gemini-shaped, so the plan is not worthless — just much smaller than it looks.
Runner contract| What a runner needs | Qwen Code (0.24.4) offers |
|---|---|
| Newline-delimited events | -o stream-json, in the Claude Code SDK schema |
| Per-run MCP server | --mcp-config inline JSON, and --allowed-mcp-server-names to scope which load — better than Cursor, better than Grok |
| Appended system prompt | --append-system-prompt, a real flag. No workspace file, no per-mode directory |
| Sessions | --session-id <uuid> to start one, -r/--resume, -c/--continue, --fork-session |
| Off-machine guard | --approval-mode plan — "analyze only, do not modify files or execute commands" — plus --sandbox, --max-tool-calls, --max-wall-time, --max-session-turns |
| Auth | OpenAI-compatible, DashScope, Anthropic, Gemini or Vertex, selected by --auth-type |
Skills for the / picker |
~/.qwen/skills, project .qwen/skills/*/SKILL.md |
Two of those are genuinely better than anything already integrated. --append-system-prompt and --mcp-config together mean no Plan.files at all — no per-conversation workspace, no stale AGENTS.md, none of the §9 pitfalls that Vibe and Grok both hit. And --allowed-mcp-server-names is the flag Cursor does not have and Grok needed environment variables to approximate.
Qwen OAuth's free tier was discontinued on 2026-04-15. qwen-oauth is still a valid --auth-type and still documented, but it is marked discontinued, no longer offered in the interactive /auth menu, and new requests are rejected. Any readiness copy that assumes "install it and log in, no key needed" is wrong. check() has to look for a configured provider, and the fix string has to say which.
The auth model is a containment problem. Qwen authenticates through OpenAI-compatible providers, so an honest keepsEnv would keep OPENAI_* — which means a Qwen run could read the user's OpenAI key, and sealEnv's whole point is that it cannot. Worth deciding deliberately rather than by default: keep a narrow set (QWEN_, DASHSCOPE_) and require the user to configure a provider entry, rather than widening to OPENAI_* and quietly handing one vendor's agent another vendor's credential. The federated mechanism that already exists for Bedrock and Vertex is the closest precedent.
No Policy Engine. --policy / --admin-policy are absent from the whole tree, not merely undocumented — so a Gemini adapter that leans on them shares less with this one than expected.
-p / --prompt is soft-deprecated in favour of a bare positional prompt. It still works and prints a notice. An adapter should target the positional form for longevity.
Two coexisting sandbox mechanisms — the legacy Docker/Podman/Seatbelt one inherited from the Gemini lineage via --sandbox, and a newer Linux-only bwrap tool-execution sandbox configured through tools.executionSandbox in settings. Which one a contained run should use is an open question.
Headless auth may need a settings file, not just env vars. For several providers the docs state that an env key alone does nothing without a matching modelProviders entry in settings.json declaring it as envKey. That would drag Plan.files back in after all, undoing much of the advantage in the table above. Needs checking against the real binary.
qwen "<instruction>" -o stream-json --approval-mode plan
--mcp-config '{"mcpServers":{"browsentic":{...}}}'
--allowed-mcp-server-names browsentic
--append-system-prompt <system prompt>
[--session-id <uuid> | --resume <uuid>] [-m <model>]
No workspace files, if open question 6 resolves favourably.
Catalog entry: label Qwen Code, vendor Alibaba, bin qwen, install npm i -g @qwen-code/qwen-code (or brew install qwen-code), docs https://qwenlm.github.io/qwen-code-docs/en/. Models qwen3-coder-plus, qwen3.7-plus, qwen3.6-plus, qwen3-max-2026-01-23. --yolo is already in FORBIDDEN.
Same reasoning as [#9] and [#8]: the stream shapes here come from the repo's docs and source rather than from captured output, and without a configured provider there is no way to prove the reader against the real CLI. Beta in the picker and the docs until one instruction and a follow-up turn have been through it.
--approval-mode plan still permit MCP tool calls, or does read-only mode block those too? If it blocks them, the browser tools are unreachable and the containment lever has to be something else.--mcp-config exclusive, or does it merge with ~/.qwen/settings.json? Exclusivity is what makes a task run provably browser-free.modelProviders entry on disk? (See friction 6 — this decides whether the runner needs Plan.files.)--session-id accept a caller-minted UUID for a new session, as Grok's does? Grok's docs claimed "create or resume" and only the create half was true.Sources: QwenLM/qwen-code · Docs · packages/cli/src/config/top-level-options.ts for the real flag definitions · docs/users/features/headless.md for the stream sample · docs/users/configuration/auth.md for the OAuth discontinuation
Related: [#25] proposes Cursor CLI as the runner before this one.
Tickets: #25
Tickets: #28
Tickets: #34
Tickets: #8
Tickets: #9
Ticket changed by: imshaikot