Repository navigation
Inbox: connect Qwen Code and tag its sessions - #2271
Merged
Merged
Conversation
Qwen Code joins the agents plannotator inbox connects: qwen mcp add -s user (0.0.8 or later, QWEN_HOME honoured), its settings.json guarded so a run never leaves it broken, the note in QWEN.md (or its context.fileName), the harness panel and a glyph. The stdio shim sends as Qwen's current session, read from Qwen's session registry on every call so /clear and /resume move it. The connect snippet follows NonoElRobot's fork (c6a02a0). Co-Authored-By: Claude <noreply@anthropic.com>
# Conflicts: # apps/hook/server/inbox-mcp-shim.ts # packages/core/inbox-types.ts
qwen mcp add and remove write every MCP server back with $VAR and ${VAR}
filled in, so a token kept in the environment landed in settings.json and
the old guard did not notice. Plannotator now edits the file itself, as
JSON with comments: only its own entry changes, every comment stays, and a
file that does not parse or is read-only is left as it is.
Qwen's session client is named qwen-cli-mcp-client-<server>, so a Qwen
session with no registry record now keeps its session id. qwen runs in the
home folder, QWEN_HOME is read from Qwen's .env files too and is not
trimmed, a relative QWEN_HOME is left to the person, and a record with a
malformed kind is read as a terminal session, as Qwen reads it.
- Uninstall, Settings off and the connect run check and remove the entry in the file the record names, not the one QWEN_HOME names now. A run or Settings on under a new QWEN_HOME moves the entry (out of the old file first); an old file that cannot be written keeps the entry and its record, said once. No false "removed outside". - json-edit: a CRLF line comment keeps its \r on the line ending; a one-line empty object keeps its comment on add. - Test: the shared JSON writer renames a new file over the old one and keeps its mode.
# Conflicts: # apps/hook/server/inbox-command.ts
A run that finds QWEN_HOME differs from the recorded home touches neither settings file: it says once where Qwen Code is connected and that turning it on in Settings → Agents moves it (report.elsewhere, also in the band). Settings → Agents shows the recorded file. Turning Qwen Code on in Settings under the new home adds the entry there first (a relative QWEN_HOME, another program named qwen, a settings.json that does not parse or is read-only: refused, nothing changed), then removes the recorded one; when the old one cannot be removed (read-only, no longer parses) the new entry is taken back out, so only the recorded one is left.
- Settings → Agents shows Qwen Code off, state "elsewhere", when its entry is in another QWEN_HOME: "Connected in <file>. Turn on to move it here." The switch sends on, which runs the add-first move with rollback. - The "connected in another folder" line is said once per pair of places (a run from the matching shell keeps it said; Settings clears it), and a run whose QWEN_HOME matches drops the other shell's line from the band. - Places compare by real path, case-folded on macOS and Windows; an absolute QWEN_HOME is normalized (a trailing slash). - A run reads the recorded file first: an entry removed by hand there is removed outside, never "connected in …". - A rollback that fails is said, and its entry kept on the record as a stray that uninstall removes.
…ugh Settings and uninstall Two homes that differ only by case are two folders on a case-sensitive volume; the real path already gives the case on disk where case is ignored. A stray entry stays recorded when Settings turns Qwen Code on or off, uninstall keeps an agent's record while one of its entries is left, and the band's move line goes once Settings acts.
…d test runs on Windows A second entry the person replaced with their own is theirs: named once, never touched, no longer recorded; one they removed is nothing to do. The uninstall test makes the main removal fail with a duplicate key instead of a read-only folder, which Windows ignores. A move out of a changed file never takes the stray entry instead (tested).
backnotprop
added a commit
to utpalsinghdev/plannotator
that referenced
this pull request
Oct 31, 2026
Keeps both the host-recovery checks and the Qwen Code uninstall work (backnotprop#2271-backnotprop#2275). The Qwen extension action uses the new references form.
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Qwen Code joins the Inbox the same way Gemini CLI does, and its sessions get a real identity.
plannotator inboxadds aplannotator-inboxentry to Qwen Code'ssettings.jsonitself. It does not runqwen mcp add: that command writes every MCP server back with its${VAR}values filled in, so a token the person keeps in their environment would end up in the file. Aqwenon PATH is still asked its--version, so a program that only shares the name is left alone. It runs in the home folder, so Qwen never touches the working folder's.qwen/settings.json. Qwen Code shows up in Settings → Agents, in the Connected band and in the "Connect an agent" picker, with its own icon.QWEN_HOME. Read as Qwen reads it: the environment first, then~/.qwen/.envor~/.env.~is expanded, and the value is not trimmed. A relativeQWEN_HOMEnames a different folder in each project, so Qwen Code is then left to connect by hand. A~/.qwenfolder without the CLI is also listed as "connect it by hand".settings.jsonmay hold comments. Plannotator keeps every comment and adds or removes only its own entry. A file that is not valid JSON, or is read-only, is left byte for byte as it was, and the terminal says why. Add then remove gives the file back exactly. Uninstall uses the same edit. Every write is a new file renamed over the old one, keeping the file's mode. A CRLF file keeps CRLF, also next to a comment.QWEN_HOMEnames now (QWEN_HOMEset in one shell and not in another).QWEN_HOME. A run that starts with a differentQWEN_HOMEtouches neither file. It says once per change of home, in the terminal and the band, where Qwen Code is connected. A run from the matching shell does not reset that, and it removes the other shell's line from its band. Settings → Agents shows Qwen Code off there: "Connected in ~/.qwen/settings.json. Turn on to move it here." Only that switch moves it: the entry is added in the new home first, then removed from the old file. A relativeQWEN_HOME, another program namedqwen, or a newsettings.jsonthat does not parse or is read-only is refused, and nothing changes. If the old entry cannot be removed, the new one is taken back out, so only one entry is ever left. If even that fails, the message says so and the new entry is recorded too, so uninstall removes both. That second entry stays recorded when Settings later turns Qwen Code on or off, and uninstall keeps the record until every entry is gone. Once Settings has moved it, the band stops saying to move it. One folder spelled two ways (a symlink,/tmpand/private/tmp, a trailing slash) counts as one place. Plannotator never ignores case itself: on a disk that ignores case, the real path already gives the case on disk, and on a case-sensitive disk (Linux)qwenandQwenare two folders. An entry removed by hand counts as removed outside, never as "connected in …".~/.qwen/QWEN.md, or in the file named bycontext.fileName. This reuses the Gemini logic.qwen-cli-mcp-client-<server name>, or the olderqwen-code-mcp-client) or fromQWEN_CODE_SESSION_ID. On every call it reads Qwen's session record for its parent process, so after/clearor/resumethe messages carry the new session id, not the stale one from the environment. With no record, the environment id is used. Qwen sessions can now be tagged and addressed. Replies do not wake Qwen yet; Inbox: replies go into running Qwen Code sessions #2274 adds that.Why
The owner asked for full Qwen Code support in the Inbox (2026-10-27). This is the first half. The wake comes in #2274, stacked on this one.
Changes for existing users
qwenon PATH get aplannotator-inboxentry in~/.qwen/settings.json(or$QWEN_HOME/settings.json) on their nextplannotator inbox.PLANNOTATOR_INBOX_CONNECT=0turns this off, andplannotator uninstallremoves it.agents.jsonat its start and writes it at its end (up to 30 s later), so a Settings switch made in that window can be overwritten. Left as is.Credit
The "Connect an agent" panel for Qwen Code, its spaced-path test, and the idea of writing the
settings.jsonentry instead of usingqwen mcp addcome from NonoElRobot's fork (commit c6a02a0), adapted to the current code. Thank you, NonoElRobot.How it was tested
packages/server/inbox-agents-qwen.test.ts(40 tests) uses a fakeqwenand a scratch home. It covers:${GITHUB_TOKEN}keeps that text, not the token (this test fails on the oldqwen mcp addcode);QWEN_HOMEfrom the environment and from.env, and a relative one;qwenalways run in the home folder;settings.jsonand a read-only one, both left byte-identical;QWEN_HOMEthat differs from the add: a run changes nothing and says it once; uninstall and Settings off act on the recorded file; Settings on moves it, and the old file comes back byte for byte;QWEN_HOME, anotherqwen), and an old file that is broken or read-only: both files and the record stay as they were;uninstall.test.tschecks that a record is kept while one of its entries is left. It makes the removal fail with a duplicate key, which works on every platform, including Windows.inbox-agents-settings.test.tsgoes through the same HTTP route the UI uses. The row reads "elsewhere" and is off. Turning it on into a settings.json with a trailing comma is refused, and the old entry survives byte for byte. Once that file is fixed, turning it on moves the entry.agentsSettings.test.tsx(DOM) checks the line, and that the switch sendsreach: true.json-edit.test.tscovers JSON with comments: insert after a trailing comment (also in a CRLF file), cut next to one, a comment in a one-line empty object, refuse trailing commas.inbox-agents.test.tschecks that the shared JSON writer renames a new file over the old one and keeps its mode (an in-place write fails it).inbox-agent-notes.test.tscovers the QWEN.md target,context.fileNameandQWEN_HOME.inbox-cli.test.tscovers the shim: the real client name, environment ids, a record swapped by/clear, bad and shared records, no record, precedence, and an end-to-end shim that follows/clear.qwenwas never run, and the real~/.qwenwas never read.--versionline, and that the shim's parent process really is the Qwen process.