Skip to content

feat(cli): set OS process title to encode session identity#3713

Closed
yeelam-gordon wants to merge 1 commit into
QwenLM:mainfrom
yeelam-gordon:feature/process-title-runtime-identity
Closed

feat(cli): set OS process title to encode session identity#3713
yeelam-gordon wants to merge 1 commit into
QwenLM:mainfrom
yeelam-gordon:feature/process-title-runtime-identity

Conversation

@yeelam-gordon

Copy link
Copy Markdown
Contributor

What

Set the OS process title on POSIX-like platforms when starting the interactive UI, in the form:

qwen-code session=<short-id> cwd=<basename>

session= carries the first 8 chars of the live session id; cwd= carries the basename of the working directory. Whitespace and = inside either token are replaced with _ so the title remains parseable with naive whitespace splits.

Why

External tools — terminal multiplexers, tab managers, IDE integrations, operators triaging a shared box — need to map a running PID back to its qwen-code session. Today they cannot: ps -ef shows generic node …. Setting process.title makes the mapping trivial without requiring users to launch with --resume.

This mirrors the proctitle helpers in kimi-cli PR #2082.

Scope

In scope (this PR):

  • New helper packages/cli/src/utils/processTitle.ts
  • One call site in startInteractiveUI() next to the existing setWindowTitle()
  • Vitest coverage (22 cases)

Out of scope (intentionally):

Windows behavior

No-op. Node maps process.title to the console window title on Windows, which would race with the existing OSC \x1b]2;…\x07 writers in gemini.tsx and AppContainer.tsx. A future Windows-specific runtime-identity mechanism (named pipe, ETW) can be added without touching this code path.

Tests

npx vitest run src/utils/processTitle.test.ts
# 22 passed (22)

Covers: short session id derivation, format composition with/without cwd, custom base name, trailing-separator normalization, whitespace + = sanitization, Unicode preservation in cwd, dispatch to apply sink on POSIX, no-op on Windows, error swallowing.

Manual verification

On Linux/macOS, after qwen starts:

$ ps -o pid,comm,args -C node | grep qwen-code
12345 node    qwen-code session=a1b2c3d4 cwd=my-project

Set `process.title` on POSIX-like platforms when starting the
interactive UI, in the form `qwen-code session=<short-id> cwd=<basename>`.
This lets external tools (terminal multiplexers, IDE integrations,
operators on a shared box) map a running PID back to its qwen-code
session via plain `ps` / `top` — without the session having been
launched with an explicit `--resume` flag.

Skipped on Windows: Node maps `process.title` to the **console
window title** there, which would conflict with the existing OSC
`\x1b]2;…\x07` writers in `gemini.tsx` and `AppContainer.tsx`.

Mirrors the proctitle bits of kimi-cli PR QwenLM#2082; the runtime.json
sidecar (kimi QwenLM#2082 part 1) and dynamic OSC tab title (kimi QwenLM#2083)
are intentionally out of scope.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@yeelam-gordon

Copy link
Copy Markdown
Contributor Author

Closing — mis-scoped. The intended port was the runtime.json sidecar from kimi-cli #2082, not the OS process title. Reopening with the correct scope shortly.

@yeelam-gordon yeelam-gordon deleted the feature/process-title-runtime-identity branch April 28, 2026 15:08
wenshao pushed a commit that referenced this pull request May 10, 2026
* feat(core): write runtime.json sidecar for active sessions

Port kimi-cli PR #2082 part 1 to qwen-code.

On interactive session start, atomically write a small JSON sidecar at <projectDir>/chats/<sessionId>.runtime.json recording the (pid, session_id, work_dir, hostname, started_at, qwen_version) tuple.

External tools (terminal multiplexers, IDE integrations, status daemons) can map a running PID to its session id and work dir without parsing argv. Write is best-effort: a read-only filesystem must not block UI startup.

OS process title (was #3713) and dynamic OSC tab title (kimi #2083) remain out of scope.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(core): refresh runtime.json on same-PID session swap

Config.startNewSession() reassigns this.sessionId in the same process,
which is reached by /clear, /reset, /new and /resume. Previously the
old <oldId>.runtime.json was left behind, falsely claiming the still-
live PID for a session no longer being served, and no new sidecar was
written for the incoming session.

Centralize the swap by clearing the old sidecar and writing a fresh
one for the new session id from inside startNewSession itself, so all
same-PID transitions are covered. The refresh runs as a fire-and-
forget best-effort; failures must not block the session switch.

Mirrors the post-merge Codex P1 fix on kimi-cli PR #2082 (the source
of the runtime.json sidecar pattern this PR ports).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(core): only refresh runtime.json when this process owns it

Mirrors kimi-cli PR #2082 commit e237951f (Codex P1 r3158754463): a
short-lived non-interactive invocation (qwen --prompt, ACP, etc.) that
runs `/clear` would otherwise call `Config.startNewSession()`, delete
a concurrent shell's runtime.json sidecar (same outgoing session id),
and never write a replacement — leaving the shell discoverable to
nobody.

Add a `runtimeStatusEnabled` flag on Config, flipped on by the
interactive UI bootstrap immediately after the first successful
sidecar write, and gate the swap-time refresh in
`startNewSession()` on it. Non-interactive entry points never reach
the bootstrap, so they won't touch sibling sidecars.

Kimi later reverted the equivalent `write only from shell mode`
guard (commit 7083975a) in favor of writing from every long-lived
mode, but qwen's wire point is already interactive-only, so the
narrower guard is the right shape here.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
xaelistic pushed a commit to xaelistic/qwen-code that referenced this pull request Jun 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant