Find a file
Shaojin Wen 68c9032cd5
feat(autofix): direct takeover of maintainer-fork PRs (#7213)
* feat(autofix): direct takeover of maintainer-fork PRs

Maintainer-approved v2: many maintainers work from personal forks, and
adoption-snapshotting breaks their local workflow. A fork PR is now
directly manageable when three live conditions hold — the takeover
label, 'Allow edits from maintainers' (org-owned forks cannot enable
it; adoption remains their path), and a fork author who holds write+
RIGHT NOW (the same live-privilege rule as the comment command, so an
ex-member's fork can never summon secret-bearing runs).

Plumbing:
- Scan: fork takeover candidates are admitted per candidate (allow-
  edits + no-skip filtered in jq; the author's live write+ gate is one
  permission call each — a rare set); every matrix target now carries
  its head repo.
- Address: prepare fetches the fork branch (origin has no copy) and
  checks out FETCH_HEAD with hooks already severed; the eligibility
  gate re-verifies takeover + allow-edits + author write+ live; the
  report step pushes back to the fork via the allow-edits grant.
- Triggers: fork pull_request label events carry NO secrets, so the
  route notes them and the next scheduled scan engages (≤10m); the
  comment command now toggles fork PRs too (write+ senders only — fork
  authors stay silently dropped) and refuses only when allow-edits is
  missing, with the actionable ask. The scan posts a first-pickup
  engage ack (identity-verified, deduped on any existing ack, ic.json
  re-fetched so the same scan counts under the fresh window key) —
  closing the fork/manual-label ack gap and anchoring the round
  window.

Behavioral coverage: fork-candidate admission jq (allow-edits, skip,
in-repo exclusion, tsv rows), eligibility across
fork+takeover+allow-edits+write / no-allow-edits / read-author, the
toggle's fork split (refusal vs managed), plus plumbing pins (fork
fetch/push forms, head_repo threading, first-pickup ack dedup).
60/60 + 12/12.

* fix(autofix): strip stray patch-artifact quotes after two fi keywords

Two inserted blocks ended 'fi"' — the quotes balanced against each
other inside the same script, so bash -n stayed green while runtime
would have lexed 'fi' as a command word and swallowed the span between
them (the fork head-repo resolution tail and the engage-ack block)
into one string. Removed both, and pinned the artifact class in the
suite: a lone fi/done/esac followed by a quote now fails the tests.
61/61 + 12/12.

* fix(autofix): author-filtered, re-armable first-pickup engage ack

Reverse-audit findings on the scan-side ack:

- Dedup was a raw grep over ic.json — a forged human comment carrying
  the engaged marker would have suppressed the real ack (and with it
  the window anchor). Dedup now selects bot-authored engaged acks via
  jq, same author rule as the window key itself.
- Fork PRs get NO ack job (label events carry no secrets), so the
  documented re-arm gesture — remove and re-add the label to reset the
  round window — silently kept the old window: any historical ack
  blocked a fresh one. When a bot ack already exists, the scan now
  compares it against the takeover label's latest application time
  (issue events, fetched only in that rare case); a newer application
  posts a fresh ack, resetting window and cap as documented.

Coverage: verbatim jq replays for both selections (forged-marker and
released-marker exclusion, label-name filter, sort|last) plus the
lexicographic re-arm gate pin. 61/61 + 12/12.

* fix(autofix): review round 1 — ack ordering, dry-run, ghost-engage gate

Addresses the maintainer review on #7213 (all findings confirmed):

- Critical: the first-pickup ack read ic.json BEFORE the per-PR fetch —
  the first takeover candidate killed the whole scan step (missing file
  under -eo pipefail; every in-repo label-forced scan regressed), and
  later candidates dedup'd against the PREVIOUS PR's comments (bot PR
  ahead → fresh ack every 10min → window reset → cap never binds). The
  block now sits directly AFTER the fetch; its post-ack re-fetch keeps
  the downstream MARKERS/window-key reads fresh. A contract pin asserts
  the fetch precedes the first ack-timestamp read.
- Medium: the ack now honors DRY_RUN (log only, window key untouched).
- Medium: the command refused forks only for missing allow-edits — a
  below-write fork author was a silent ghost engagement (label sticks,
  no ack, nothing ever manages it). The command now mirrors the scan's
  author write+ gate with an actionable bilingual refusal. Found while
  fixing it: PR_INFO never fetched maintainerCanModify (or author), so
  EVERY fork toggle refused regardless of allow-edits — the test stub
  carried the field and masked the gap. Both engage-side fork gates are
  now also scoped to 'add': release is never blocked.
- Low: the two new paginated jq reads are slurped (add-merged) so >100
  comments/events cannot scramble the timestamp comparisons; replays
  now feed two concatenated page-documents. Fork fetch pins
  refs/heads/ (tag shadowing); HEAD_REPO_FULL guards each component
  (deleted fork = owner XOR name empty); fork-rotation caveat
  documented; forced-path refusal mentions the scheduled fork path.
- Security caveat adopted: prepare proves fork push access with a
  --dry-run push right after checkout (allow-edits rides the
  classic-PAT grant only) and discards gracefully instead of 403ing
  after a full agent round.

61/61 + 12/12; YAML parses; every run block passes bash -n.

* fix(autofix): fork targets keep base/branch invariants + 3 hardening follow-ups

Blocking (yiliang114): the last fork elif ends the eligibility ladder
for every eligible fork, so the LIVE_BASE/LIVE_BRANCH re-checks were
unreachable for exactly the PR class the loop fetches and pushes — a
labeled fork retargeted off main (or head-renamed) between scan and
address would have had conflicts resolved against the wrong base. The
base/branch invariants now sit ABOVE the fork chain (comment explains
why the order is load-bearing), with replay cases pinning a
retargeted and a renamed fork to the discard path.

Follow-ups from the same review, all adopted:
- PR_LIVE re-reads headRepositoryOwner/headRepository; a fork renamed
  or transferred since the scan discards at the live re-check (moved
  or unresolved, fail-closed) instead of fetching and token-pushing a
  stale path. The replay's fork fixture now carries its head repo and
  the harness provides the matrix HEAD_REPO to compare against.
- The fork fetch failure (force-push/rename race) discards through the
  standard no-action path instead of a red run.
- The first-pickup engage ack defers to the in-repo label event's
  DEDICATED ack job within a 3-minute grace after the label lands, so
  a concurrent ack job is never double-posted (which would shift the
  round-window anchor); a failed ack job is still healed by the next
  scan, and forks (no ack job) keep immediate pickup. Events are read
  once, before the branch split.

Both hooks-order regex windows widened to span the new fork-arm guards
(the assertions are about order; one hooksPath site genuinely covers
both checkout arms). 61/61 + 12/12.

* test: raise timeout ceiling for I/O-bound tests flaky under CI contention

The self-hosted CI runners are heavily oversubscribed (core runs
maxThreads: 16), and a recurring class of tests blows vitest's 5s
default timeout purely under that contention — not from any logic
fault. Observed repeatedly across unrelated PRs (#7213, #7219, and
noted in prior sessions):

- packages/core/src/utils/shell-ast-parser-lazy.test.ts — fully
  mocked, but the dynamic import + async coordination exceeds 5s when
  16 threads contend.
- packages/cli/src/serve/workspace-registration-store.test.ts —
  tempdir round-trip.
- packages/core/src/extension/github.test.ts > extractFile — its
  waitForFileData helper polled a FIXED 1_000 setImmediate turns, which
  elapse in <100ms while the tar extraction I/O is still catching up,
  throwing 'Timed out waiting for extracted data'.

Fixes:
- testTimeout: 15000 in the core and cli vitest configs — 3x the
  default. Assertions still fail instantly; only the timeout ceiling
  grows, so this masks no logic bug (a real hang still fails, just
  later, and the job timeout still bounds it).
- waitForFileData now polls a real ~10s wall-clock budget
  (2_000 x 5ms) instead of a fixed iteration count, so a slow
  extraction is awaited rather than raced. Stays under the 15s ceiling.

These are the deterministic root-cause fixes for the flake class the
autofix loop and CI Failure Patrol were papering over with reruns.

---------

Co-authored-by: wenshao <wenshao@example.com>
2026-07-19 12:49:55 +00:00
.github feat(autofix): direct takeover of maintainer-fork PRs (#7213) 2026-07-19 12:49:55 +00:00
.husky Sync upstream Gemini-CLI v0.8.2 (#838) 2025-10-23 09:27:04 +08:00
.qwen fix(ci): consolidate issue triage ownership (#7180) 2026-07-19 10:58:40 +00:00
.vscode Merge branch 'main' into feat/sandbox-config-improvements 2026-03-06 14:38:39 +08:00
docs fix(cli): allow goal controls during active loops (#7202) 2026-07-19 11:29:52 +00:00
docs-site Hide internal docs from docs site (#4357) 2026-06-01 15:55:14 +08:00
eslint-rules pre-release commit 2025-07-22 23:26:01 +08:00
integration-tests feat(web-shell): add a workspace Goals page, and stop losing /goal on daemon resume (#6561) 2026-07-18 08:52:07 +00:00
packages fix(cli): show mode indicator alongside steering hint during streaming (#7219) 2026-07-19 12:08:12 +00:00
patches feat(cli): mouse text selection and copy in VP mode (#6937) 2026-07-17 08:04:07 +00:00
scripts feat(autofix): direct takeover of maintainer-fork PRs (#7213) 2026-07-19 12:49:55 +00:00
.dockerignore fix(cli): skip stdin read for ACP mode 2026-03-27 11:47:01 +00:00
.editorconfig pre-release commit 2025-07-22 23:26:01 +08:00
.gitattributes feat(installer): add standalone hosted install and uninstall flow (#3828) 2026-05-21 11:57:10 +08:00
.gitignore feat(web-shell): auto-post visual previews (screenshots + flow GIFs) on PRs (#6880) 2026-07-15 06:48:52 +00:00
.npmrc chore: remove google registry 2025-08-08 20:45:54 +08:00
.nvmrc chore(deps): upgrade ink 6.2.3 → 7.0.2 + bump Node engine to 22 (#3860) 2026-05-11 17:29:50 +08:00
.prettierignore feat(acp): support /cd command in ACP sessions (#5903) 2026-06-27 14:47:40 +00:00
.prettierrc.json pre-release commit 2025-07-22 23:26:01 +08:00
.yamllint.yml feat(desktop): Add desktop app package with Qwen ACP SDK integration (#3778) 2026-06-11 21:57:20 +08:00
AGENTS.md fix(serve): Harden multi-workspace ownership guards (#7005) 2026-07-16 17:29:10 +00:00
CHANGELOG.md chore(release): v0.20.0 (#7211) 2026-07-19 07:35:40 +00:00
CLAUDE.md docs: rewrite CLAUDE.md to point to AGENTS.md as authoritative source (#5138) 2026-06-15 15:23:26 +08:00
CONTRIBUTING.md revert: remove local PR verification gate (#7031) 2026-07-16 11:24:38 +00:00
Dockerfile chore(deps): upgrade ink 6.2.3 → 7.0.2 + bump Node engine to 22 (#3860) 2026-05-11 17:29:50 +08:00
esbuild.config.js fix(cli): add bootstrap fast paths (#6188) 2026-07-02 22:28:11 +00:00
eslint.config.js Add harness infrastructure for web-shell package (#6517) 2026-07-09 08:11:58 +00:00
eslint.legacy-filenames.mjs feat(serve): add workspace persisted transcript reader (#6740) 2026-07-12 10:39:05 +00:00
LICENSE Sync upstream Gemini-CLI v0.8.2 (#838) 2025-10-23 09:27:04 +08:00
Makefile feat: update docs 2025-12-22 21:11:33 +08:00
package-lock.json chore(release): v0.20.0 (#7211) 2026-07-19 07:35:40 +00:00
package.json chore(release): v0.20.0 (#7211) 2026-07-19 07:35:40 +00:00
README.md docs: Revamp README for clarity and focus (#5257) 2026-06-18 10:27:16 +08:00
SECURITY.md fix: update security vulnerability reporting channel 2026-02-24 14:22:47 +08:00
tsconfig.json # 🚀 Sync Gemini CLI v0.2.1 - Major Feature Update (#483) 2025-09-01 14:48:55 +08:00
vitest.config.ts feat(channel): add QQ Bot (QQ机器人) channel adapter (#5202) 2026-06-19 06:32:52 +08:00

npm version License Node.js Version Downloads

QwenLM%2Fqwen-code | Trendshift

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.

Qwen Code

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.