feat(ui): add customizable status line with /statusline command#2923
feat(ui): add customizable status line with /statusline command#2923
Conversation
Allow users to configure a custom shell command to display in the UI footer status line.
📋 Review SummaryThis PR introduces a customizable status line feature that allows users to display custom information in the UI footer by executing a read-only shell command periodically. The implementation includes a new React hook ( 🔍 General Feedback
🎯 Specific Feedback🔴 Critical
🟡 High
🟢 Medium
🔵 Low
✅ Highlights
|
Code Coverage Summary
CLI Package - Full Text ReportCore Package - Full Text ReportFor detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run. |
Rewrite the status line feature (originally by Gemini 3.1 Pro) to align
with the upstream design:
- Settings: change from plain string to object `{ type, command, padding? }`
- Hook: event-driven with 300ms debounce instead of 5s polling; pass
structured JSON context (session, model, tokens, vim) via stdin;
generation counter to ignore stale exec callbacks; EPIPE guard on stdin
- Footer: render status line as dedicated row with dimColor + truncate;
suppress "? for shortcuts" hint when status line is active
- Add `/statusline` slash command that delegates to a statusline-setup agent
- Add `statusline-setup` built-in agent with PS1 conversion instructions
- Remove unrelated changes (whitespace, formatting, package-lock, test file)
- Fix copyright headers (Google LLC → Qwen)
- Fix config path references (~/.qwen-code → ~/.qwen)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a user-configurable “status line” in the CLI footer by executing a configured shell command and displaying its output, plus a /statusline helper command backed by a new built-in subagent to guide setup.
Changes:
- Extend settings schemas to support
ui.statusLine(type/command/padding). - Add a CLI
useStatusLinehook and render an extra footer row when configured. - Add
/statuslineslash command and a new built-instatusline-setupsubagent (and update subagent tests).
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/vscode-ide-companion/schemas/settings.schema.json | Adds JSON schema for ui.statusLine configuration. |
| packages/cli/src/config/settingsSchema.ts | Registers ui.statusLine in the CLI settings schema metadata. |
| packages/cli/src/ui/hooks/useStatusLine.ts | New hook that runs the configured command (stdin JSON) and returns display text/padding. |
| packages/cli/src/ui/components/Footer.tsx | Renders an additional footer row for the custom status line; integrates the new hook. |
| packages/cli/src/ui/commands/statuslineCommand.ts | New /statusline command that prompts creation of a statusline-setup subagent. |
| packages/cli/src/services/BuiltinCommandLoader.ts | Registers the new built-in /statusline command. |
| packages/core/src/subagents/builtin-agents.ts | Adds built-in statusline-setup subagent with instructions for configuring the setting. |
| packages/core/src/subagents/subagent-manager.test.ts | Updates expectations to include the new built-in subagent. |
| packages/cli/src/ui/utils/TableRenderer.tsx | Formatting-only change. |
| packages/cli/src/ui/utils/MarkdownDisplay.tsx | Formatting-only change. |
| packages/cli/src/commands/channel/pidfile.test.ts | Whitespace cleanup in tests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The hand-edited schema didn't match the auto-generated output. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
useStatusLine hook requires SettingsContext, which was missing from the test render wrapper, causing all Footer tests to crash. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Validate padding is finite number >= 0 instead of blind cast - Initialize prevStateRef with current values to prevent double exec on mount - Kill previous child process before starting new one; kill on unmount - Fix agent prompt: settings path is ui.statusLine, not root-level - Fix agent prompt: remove multi-cat examples, stdin can only be read once - Update Footer left-section comment to reflect new behavior Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
When vim mode is toggled off, vimMode stays the same but the status line should stop including vim data. Use effectiveVim (undefined when disabled) as the tracked value instead of raw vimMode. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Set cwd to config.getTargetDir() so commands like pwd/git run in the correct workspace directory - Strip only trailing newline instead of trim() to preserve intentional leading/trailing whitespace in command output - Match footer's marginLeft/marginRight on the status line row so it aligns with the rest of the footer content Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The settings parser uses stripJsonComments + JSON.parse, which does not support trailing commas. Changed the config example from jsonc to json and removed trailing commas so users can copy-paste safely. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Use echo "$input" instead of echo $input for proper shell variable quoting, consistent with the script file example. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
PS1 \n should be removed or replaced with a space since the status line only displays the first line of stdout. Also added a guideline that commands must produce exactly one line of output. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Footer comment now accurately states only the "? for shortcuts" hint is suppressed, not all left-section items - Docs now note that Windows uses cmd.exe by default and suggest wrapping commands with bash -c or using a bash script Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Inline shell snippets need sh -c to execute via pipe, matching how child_process.exec() runs the configured command. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
"Use the Agent tool with subagent_type" is more direct than "Create an Agent", reducing ambiguity for the model. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ustomization # Conflicts: # packages/cli/src/ui/components/Footer.tsx
Add the missing ui.statusLine setting to the settings.md reference table with a link to the status-line feature documentation.
1. Summary
Allow users to configure a custom shell command to display context-aware information in the status line area beneath the footer.
1.1 Architecture
1.2 How it works
1.3 Configuration
The command receives structured JSON via stdin:
{ "session_id": "abc-123", "cwd": "/home/user/project", "model": { "id": "qwen-3-235b" }, "context_window": { "context_window_size": 131072, "last_prompt_token_count": 45000 }, "vim": { "mode": "INSERT" } }1.4 /statusline command
Users can run /statusline to launch a setup agent that reads their shell PS1 and auto-generates a statusLine config.
2. Changes
ui({ type, command, padding? })3. Test plan
3.1 Quick start
3.2 Manual test checklist
ui.statusLineconfig above, launch CLIcat | jq -r '.cwd'/model, select different modelsleep 10 && echo done/statusline/statuslinein CLIui.statusLinefrom settings, restartui.statusLine3.3 Unit tests
4. Comparison with Claude Code upstream
This implementation follows the upstream Claude Code status line design, adapted for qwen-code's architecture. Key differences:
4.1 Intentional simplifications
cost,rate_limits,workspace.added_dirs,worktree,remote,output_style,version— these can be added incrementally as the corresponding systems are ported<Ansi>component for colored output; we usedimColorfor nowstatusLineTextin global AppState for cross-component access; we keep it local to the hook since only Footer consumes it4.2 Potential follow-ups
workspace,cost,versionfields to stdin JSON<Ansi>component for colored status line outputuseStatusLinehookstatuslineCommand