Skip to content

fix(cli): honor list extensions flag#4673

Merged
pomelo-nwu merged 1 commit into
QwenLM:mainfrom
he-yufeng:fix/list-extensions-flag
Jun 3, 2026
Merged

fix(cli): honor list extensions flag#4673
pomelo-nwu merged 1 commit into
QwenLM:mainfrom
he-yufeng:fix/list-extensions-flag

Conversation

@he-yufeng
Copy link
Copy Markdown
Contributor

What this PR does

Wires the top-level qwen --list-extensions / qwen -l flag to the existing extension list command and exits before the normal sandbox/auth/TUI startup path runs.

Why it's needed

The flag is advertised in qwen --help, but it currently falls through into the interactive CLI. This restores the documented non-interactive behavior and reuses the same listing code as qwen extensions list.

Reviewer Test Plan

How to verify

Run qwen --list-extensions or qwen -l with at least one installed extension. The command should print the extension list and exit instead of opening the interactive prompt.

Evidence (Before & After)

Before: qwen --list-extensions ignored the flag and launched the regular interactive prompt. After: the main startup path calls the extension list handler and exits before sandbox setup or app config startup. Regression coverage is in packages/cli/src/gemini.test.tsx.

Tested on

OS Status
macOS N/A
Windows tested
Linux N/A

Environment (optional)

Windows, Node v24.15.0, npm 11.12.1.

Commands run:

npm exec -- vitest run packages/cli/src/gemini.test.tsx -t "list-extensions"
npm exec -- vitest run packages/cli/src/gemini.test.tsx packages/cli/src/commands/extensions/list.test.ts
npm exec -- eslint packages/cli/src/gemini.tsx packages/cli/src/gemini.test.tsx
npm run typecheck --workspace=packages/cli
git diff --check -- packages/cli/src/gemini.tsx packages/cli/src/gemini.test.tsx

Risk & Scope

  • Main risk or tradeoff: The flag now exits before sandbox setup, auth setup, and TUI rendering; that is the intended behavior for a local listing command.
  • Not validated / out of scope: Full package build in this local checkout is blocked by existing packages/core/dist declaration files being treated as TypeScript inputs (TS5055: Cannot write file ... because it would overwrite input file).
  • Breaking changes / migration notes: None.

Linked Issues

Fixes #4450

中文说明

这个 PR 做了什么

把顶层 qwen --list-extensions / qwen -l 参数接到已有的扩展列表命令,并在进入常规 sandbox、auth、TUI 启动路径前退出。

为什么需要

qwen --help 已经声明了这个参数,但当前实现会忽略它并继续进入交互式 CLI。这个改动恢复文档中的非交互行为,并复用 qwen extensions list 的列表输出逻辑。

Reviewer Test Plan

如何验证

安装至少一个 extension 后运行 qwen --list-extensionsqwen -l。命令应打印扩展列表并退出,而不是打开交互式 prompt。

Before / After 证据

Before:qwen --list-extensions 忽略参数并启动普通交互界面。After:主启动流程调用 extension list handler,并在 sandbox setup 或 app config startup 前退出。回归测试在 packages/cli/src/gemini.test.tsx

Tested on

OS Status
macOS N/A
Windows tested
Linux N/A

Environment

Windows, Node v24.15.0, npm 11.12.1。

已运行命令:

npm exec -- vitest run packages/cli/src/gemini.test.tsx -t "list-extensions"
npm exec -- vitest run packages/cli/src/gemini.test.tsx packages/cli/src/commands/extensions/list.test.ts
npm exec -- eslint packages/cli/src/gemini.tsx packages/cli/src/gemini.test.tsx
npm run typecheck --workspace=packages/cli
git diff --check -- packages/cli/src/gemini.tsx packages/cli/src/gemini.test.tsx

风险和范围

  • 主要风险或取舍:这个参数现在会在 sandbox setup、auth setup 和 TUI 渲染前退出;这符合本地列表命令的预期行为。
  • 未验证 / 不在范围内:本地 full package build 被当前 checkout 中已有的 packages/core/dist 声明文件阻塞,TypeScript 报 TS5055: Cannot write file ... because it would overwrite input file
  • 破坏性变更 / 迁移说明:无。

关联 Issue

Fixes #4450

@pomelo-nwu
Copy link
Copy Markdown
Collaborator

pomelo-nwu commented Jun 1, 2026

Stage 1: Template Gate — ✅ Passed

All required headings are present in the PR body:

  • ## What this PR does
  • ## Why it's needed
  • ## Reviewer Test Plan
  • ### Evidence (Before & After)

Bilingual body (English + Chinese in <details>), linked issue (#4450), and tested-on table included.

中文说明

PR 模板检查通过。所有必需标题均存在:## What this PR does## Why it's needed## Reviewer Test Plan### Evidence (Before & After)。PR body 包含中英双语,关联了 issue #4450,并提供了测试环境信息。

@pomelo-nwu
Copy link
Copy Markdown
Collaborator

pomelo-nwu commented Jun 1, 2026

Stage 2: Product Direction Gate — ✅ Aligned

Classification: Bug fix for a documented but non-functional CLI flag.

Evidence:

  • Issue qwen --list-extensions does nothing #4450 reports that qwen --list-extensions (advertised in --help) launches the interactive TUI instead of printing extensions and exiting.
  • The flag is part of Qwen Code's extensions system — Claude Code has no equivalent feature (confirmed by searching its changelog for list-extensions, list extensions, extensions list — no matches). This is Qwen Code–specific scope, not a parity question.
  • The fix restores documented behavior: --help says "List all available extensions and exit."

Direction verdict: Clearly in-scope bug fix. No product direction concern.

中文说明

分类: 修复已文档化但不可用的 CLI 参数。

证据:

  • Issue qwen --list-extensions does nothing #4450 报告 qwen --list-extensions--help 中已声明)会启动交互式 TUI 而非打印扩展列表后退出。
  • 该参数属于 Qwen Code 的扩展系统——Claude Code 没有等价功能(已搜索其 changelog,无匹配)。这是 Qwen Code 自身的范围,不涉及竞品对齐问题。
  • 修复恢复了文档中声明的行为:--help 写明 "List all available extensions and exit."

方向判断: 明确的范围内 bug 修复,无产品方向问题。

@pomelo-nwu
Copy link
Copy Markdown
Collaborator

pomelo-nwu commented Jun 1, 2026

Stage 3: KISS-Focused Code Review — ✅ Clean

Summary: 57 additions, 9 deletions across 2 files. Minimal, focused bug fix with no unnecessary complexity.

Implementation (gemini.tsx)

  • 4 lines of logic: Check argv.listExtensions, call handleListExtensions(), process.exit(0). Placed after settings loading but before sandbox/auth/TUI startup — correct position for a non-interactive listing command.
  • Reuses existing handler: handleList() from commands/extensions/list.js — no duplicate logic.
  • Removes dead code: Deletes the 9-line commented-out FIXME block that was deep in the interactive startup path (line ~817).

Test (gemini.test.tsx)

  • Proper mocking: Uses vi.hoisted() for the mock (consistent with existing patterns), mocks ./commands/extensions/list.js.
  • Key assertions: handleList called once, process.exit(0) called, loadSandboxConfig NOT called, loadCliConfig NOT called — proves the early exit before heavy initialization.

Observations (non-blocking)

  • The test verifies that sandbox and CLI config are skipped, which is the core behavioral contract.
  • CI Windows failures (crawler.test.ts, gitDiff.test.ts timeouts) are pre-existing flaky tests unrelated to this PR.
中文说明

总结: 2 个文件,+57/-9。最小化的专注 bug 修复,无不必要的复杂度。

实现 (gemini.tsx)

  • 4 行逻辑代码: 检查 argv.listExtensions,调用 handleListExtensions()process.exit(0)。放置在 settings 加载之后、sandbox/auth/TUI 启动之前——对于非交互式列表命令来说位置正确。
  • 复用已有处理器: 使用 commands/extensions/list.js 中的 handleList()——无重复逻辑。
  • 删除死代码: 移除了交互启动路径中 9 行被注释掉的 FIXME 块(约第 817 行)。

测试 (gemini.test.tsx)

  • 正确的 mock 方式: 使用 vi.hoisted()(与现有模式一致),mock ./commands/extensions/list.js
  • 关键断言: handleList 被调用一次,process.exit(0) 被调用,loadSandboxConfig 未被调用,loadCliConfig 未被调用——证明在重量级初始化之前提前退出。

观察(非阻塞)

  • 测试验证了 sandbox 和 CLI config 被跳过,这是核心行为契约。
  • CI Windows 失败(crawler.test.tsgitDiff.test.ts 超时)是已有的不稳定测试,与本 PR 无关。

@pomelo-nwu pomelo-nwu added type/bug Something isn't working as expected category/cli Command line interface and interaction scope/non-interactive Non-interactive mode scope/extensions Extension configuration labels Jun 1, 2026
@pomelo-nwu
Copy link
Copy Markdown
Collaborator

pomelo-nwu commented Jun 1, 2026

Stage 4: Real-Scenario Testing — ✅ Passed

Environment: macOS (darwin), Node v22, PR branch ddc8883de1 checked out via gh pr checkout 4673 --detach.

Test 1: Unit test — list-extensions

cd packages/cli && npx vitest run src/gemini.test.tsx -t "list-extensions"

✓ handles --list-extensions before sandbox and app config startup 3ms
Test Files  1 passed (1)
     Tests  1 passed | 23 skipped (24)

Test 2: Extension list regression

cd packages/cli && npx vitest run src/commands/extensions/list.test.ts

✓ should parse the list command
✓ should display message when no extensions are installed
✓ should list installed extensions
✓ should handle errors and exit with code 1
Test Files  1 passed (1)
     Tests  4 passed (4)

Test 3: Real CLI in tmux — --list-extensions exits without TUI

$ tmux new-session -d -s pr4673 -x 200 -y 50
$ tmux send-keys -t pr4673 "DEV=true npx tsx packages/cli/src/gemini.tsx --list-extensions 2>&1; echo EXIT_CODE:\$?" Enter

# tmux capture-pane output:
DEV is set to true, but the React DevTools server is not running.
EXIT_CODE:0

Key observation: The process exited with code 0 and did not render the Qwen Code TUI (no ASCII art banner, no interactive prompt). This is the exact behavioral fix — before this PR, the same command would launch the full interactive session.

CI Status

  • macOS (Node 22): ✅ pass
  • Linux (Node 22): ✅ pass
  • Windows (Node 22): ❌ fail — pre-existing flaky timeouts in crawler.test.ts and gitDiff.test.ts, unrelated to this PR.
中文说明

环境: macOS (darwin), Node v22, PR 分支 ddc8883de1(通过 gh pr checkout 4673 --detach 检出)。

测试 1:单元测试 — list-extensions

新增测试通过,验证 handleList 被调用、process.exit(0) 被调用、sandbox/config 未被加载。

测试 2:扩展列表回归测试

4 个已有测试全部通过,无回归。

测试 3:tmux 真实 CLI 测试

qwen --list-extensions 以 exit code 0 退出,未渲染 Qwen Code TUI(无 ASCII 横幅、无交互式提示符)。这正是本 PR 要修复的行为——修复前同样的命令会启动完整交互会话。

CI 状态

  • macOS / Linux:✅ 通过
  • Windows:❌ 失败——已有的不稳定测试超时(crawler.test.tsgitDiff.test.ts),与本 PR 无关。

Copy link
Copy Markdown
Collaborator

@pomelo-nwu pomelo-nwu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stage 5: Final Decision — ✅ Approved

All gates passed:

  • Stage 1 (Template): All required headings present, bilingual body, linked issue.
  • Stage 2 (Direction): Straightforward bug fix for a documented but non-functional flag. Qwen Code–specific feature, no parity question.
  • Stage 3 (Code Review): Minimal change (4 lines of logic), correct placement, reuses existing handler, good test coverage, removes dead code.
  • Stage 4 (Testing): Unit tests pass, regression tests pass, tmux real-CLI test confirms the fix. Windows CI failure is pre-existing and unrelated.

Recommendation: Approve and merge.

中文说明

所有关卡通过:

  • Stage 1(模板): 所有必需标题存在,中英双语 body,关联 issue。
  • Stage 2(方向): 明确的 bug 修复,修复已文档化但不可用的 CLI 参数。Qwen Code 特有功能,无竞品对齐问题。
  • Stage 3(代码审查): 最小化改动(4 行逻辑代码),放置位置正确,复用已有处理器,测试覆盖良好,删除了死代码。
  • Stage 4(测试): 单元测试通过,回归测试通过,tmux 真实 CLI 测试确认修复有效。Windows CI 失败为已有问题,与本 PR 无关。

建议: 批准并合并。

Copy link
Copy Markdown
Collaborator

@wenshao wenshao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No review findings. Downgraded from Approve to Comment: CI failing: Test (windows-latest, Node 22.x). — qwen3.7-max via Qwen Code /review

Copy link
Copy Markdown
Collaborator

@pomelo-nwu pomelo-nwu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wait a moment

@wenshao
Copy link
Copy Markdown
Collaborator

wenshao commented Jun 1, 2026

✅ Local runtime verification (real qwen CLI in tmux) — PR #4673

结论 / Verdict: 修复有效,--list-extensions / -l 现在打印扩展列表并退出(不再进交互界面),建议合并。 The flag now prints the extension list and exits instead of opening the TUI — recommend merge.

这是 CLI 非交互参数修复,可直接在真实终端复现 before/after。我在隔离沙箱里安装了 dummy extension,用真实构建的 qwen 在 tmux 跑了 main(before)与 PR(after)的对比。

This is a CLI non-interactive flag fix, so I reproduced the before/after directly with the real built qwen in tmux against a sandbox with dummy extensions installed.


Method

  • pr-4673 = current main (1c48e4121) + 2 commits (rebased, 0 behind); deps unchanged; only gemini.tsx (+6/−9) + gemini.test.tsx (+51). The fix adds an early if (argv.listExtensions) { await handleListExtensions(); process.exit(0); } and removes the dead commented-out post-config block. Placement is before the sandbox hop (gemini.tsx ~L503) and auth (~L529).
  • Isolated QWEN_HOME with two dummy extensions (demo-tools 1.2.3, hello-ext 0.9.0); built cli from each branch with node ../../scripts/build_package.js.

Before / After (real terminal, same command qwen --list-extensions)

BEFORE (main) — flag ignored, opens the interactive TUI:

> /tmp/.../run.sh --list-extensions
   ▄▄▄▄▄▄  ...  >_ Qwen Code (v0.17.0)
   ...
>   Type your message or @path/to/file      ← interactive prompt, process does NOT exit
  ? for shortcuts

AFTER (main + PR) — prints the list, exits to the shell prompt:

> /tmp/.../run.sh --list-extensions
✓ demo-tools (1.2.3)
 Path: .../extensions/demo-tools
 Enabled (User): true
 Enabled (Workspace): true
✓ hello-ext (0.9.0)
 Path: .../extensions/hello-ext
 Enabled (User): true
 Enabled (Workspace): true
root@...:~/git/qwen-code-x2#                 ← back at the shell = exited, no TUI

AFTER — exact non-interactive runs (stdout + exit code)

Command (PR build) Result
qwen --list-extensions lists both extensions, exit 0
qwen -l (short alias) byte-identical output, exit 0
qwen extensions list byte-identical output, exit 0 — confirms it reuses the same handleList
qwen --list-extensions with a bare QWEN_HOME (no auth configured) lists solo-ext (2.0.0), exit 0, no auth/theme dialog — proves it exits before auth/sandbox/TUI

Tests & static checks (PR build)

Check Result
gemini.test.tsx -t "list-extensions" (author's targeted) 1 passed
gemini.test.tsx + commands/extensions/list.test.ts 28 passed (2 files)
eslint on gemini.tsx + gemini.test.tsx clean (exit 0)
git diff --check on changed files no whitespace errors
tsc --build (cli typecheck + emit) clean

Side note: the PR description flags a local TS5055 blocking a full build — that's the known stale-packages/core/dist issue. A clean rebuild of core (which clears dist/ first) resolves it; with that, cli builds clean here.


Bottom line: the documented --list-extensions / -l behavior is restored — it prints the same output as qwen extensions list and exits (exit 0) before sandbox/auth/TUI, even with no auth configured, whereas main ignores the flag and drops into the interactive prompt. Targeted + full unit tests, eslint, whitespace and typecheck all green. 👍

@pomelo-nwu pomelo-nwu dismissed their stale review June 1, 2026 08:56

Re-triage complete; all stages pass. Replacing with updated approval.

@he-yufeng he-yufeng force-pushed the fix/list-extensions-flag branch from ddc8883 to cc0b954 Compare June 1, 2026 09:04
Copy link
Copy Markdown
Collaborator

@wenshao wenshao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found. LGTM! ✅ — qwen-latest-series-invite-beta-v38 via Qwen Code /review

@pomelo-nwu pomelo-nwu merged commit 7ee3727 into QwenLM:main Jun 3, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

category/cli Command line interface and interaction scope/extensions Extension configuration scope/non-interactive Non-interactive mode type/bug Something isn't working as expected

Projects

None yet

Development

Successfully merging this pull request may close these issues.

qwen --list-extensions does nothing

3 participants