Skip to content

feat(terminal): add cursor style setting (bar/block/underline)#908

Open
roberto-fernandino wants to merge 22 commits into
crynta:mainfrom
roberto-fernandino:feat/terminal-cursor-style
Open

feat(terminal): add cursor style setting (bar/block/underline)#908
roberto-fernandino wants to merge 22 commits into
crynta:mainfrom
roberto-fernandino:feat/terminal-cursor-style

Conversation

@roberto-fernandino

@roberto-fernandino roberto-fernandino commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds a Cursor style setting in General → Terminal settings
  • Options: Bar (default), Block, Underline — matching VS Code's terminal cursor styles
  • Persisted via the preferences store and applied live to all open terminals
  • Default remains bar so existing users see no change

Test plan

  • Open Settings → General → Terminal → change Cursor style to Block
  • Verify terminal cursor changes to a full-cell block immediately
  • Change to Underline and verify underline cursor appears
  • Revert to Bar and verify thin bar cursor appears
  • Restart the app and confirm the chosen style persists

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added an Agents sidebar/tab with a dedicated panel, counts, and navigation support.
    • Added terminal tab indicators that can reflect the active agent, plus a new terminal tab switch command group.
    • Added a setting to choose the terminal cursor style and a toggle to show or hide the Agents tab.
  • Bug Fixes

    • Improved agent status handling so finished sessions return to idle more consistently.
    • Updated shortcut and navigation behavior for smoother sidebar and tab switching.

Roberto and others added 22 commits June 26, 2026 13:07
feat(tabs): select tabs by index within active space
…dow-shortcut

feat(shortcuts): add ai toggle mini shortcut
…nd-palette

feat: terminals in command-palette
Adds a new keyboard shortcut (Cmd+Shift+G by default) that switches the
sidebar to the Files/explorer view. Pairs naturally with Cmd+G (source
control) so the user can toggle between them without touching the mouse.

The shortcut uses cycleSidebarView("explorer") — same pattern as pane.source
uses for source-control — and is fully configurable in Settings > Shortcuts.
Also exposed as "Show Files sidebar" in the command palette.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tcut

feat(shortcuts): add configurable shortcut to show Files sidebar
Documents and enforces the mandatory workflow: branch → commit →
dual PR (fork + upstream cross-fork) → merge fork → back to main.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New "Agents" sidebar tab lists every Claude Code, Codex, Gemini,
  OpenCode and Cursor agent running in terminals, with status badges
  (working / needs input) and one-click navigation to the terminal tab
- Terminal tabs whose agent is detected by the backend now show that
  tool's logo (Claude, Gemini, Codex/OpenCode, or robotic fallback)
  instead of the generic terminal icon
- "Show Agents sidebar tab" toggle in Settings > General (default on);
  disabling it falls back to the Files view
- Merged upstream additions: Codex/Gemini notification hooks,
  per-agent notification bell, jump-to-attention shortcut

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…-and-logos

feat(sidebar): Agents tab + agent logos in terminal tabs
When an agent process starts (claude, codex, etc.) it was immediately
shown as "working" even though it was just sitting at its idle prompt.

Added "idle" as a third AgentStatus. The "started" signal now sets idle;
only the explicit "working" signal (fired when the agent begins executing
a task) promotes it to working. The sidebar badge count excludes idle
sessions so the badge only lights up during real activity.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fix(agents): show idle status when agent is at prompt, not working
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…efault

feat(ai): open AI panel by default on startup
- "finished" signal now sets status back to "idle" instead of "waiting"
  so the badge only lights up on genuine attention requests, not routine
  task completions
- Added a useEffect in App.tsx: when the active tab becomes a terminal
  that has a waiting agent, reset it to idle — the user is already
  looking at it so the notification is no longer relevant; covers all
  nav paths (tab click, keyboard shortcut, notification bell, agents panel)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…on-focus

fix(agents): clear needs-input when tab focused; finished resets to idle
Ctrl+C interrupts Claude Code without firing a finished signal, leaving
the status permanently stuck on "working". Extend the tab-focus effect
to reset any non-idle status (waiting or working) to idle when the user
navigates to the terminal. If the agent is genuinely still running, the
backend will fire the next working signal and promote it back immediately.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ck-on-interrupt

fix(agents): reset working status to idle when terminal tab is focused
…working status

Depending on tabs (not tabsRef) caused the effect to re-run on every tab
title update. While the agent was working and the user was already on the
terminal tab, the next title change re-ran the effect and reset working→idle,
breaking real-time status display. Switching to tabsRef means the effect only
fires when activeId actually changes (true navigation), not on content updates.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a terminalCursorStyle preference that lets users choose between
bar, block, and underline cursor shapes in the terminal, matching VS
Code's terminal cursor style options. Defaults to bar (previous
hardcoded value).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Introduces an Agents sidebar panel displaying active agent sessions with idle/working/waiting status tracking. Adds terminal cursor style as a persisted preference applied live to xterm instances. Extends the command palette with terminal tab switching and a files sidebar command. Adds ai.toggleMini and sidebar.files keyboard shortcuts. Scopes tab-index selection to the active space via a new pickTabBySpaceIndex helper. Wires agent icon decorations into TabBar through Header.

Changes

Agents Panel and Status Lifecycle

Layer / File(s) Summary
AgentStatus type, store init, and metadata
src/modules/agents/lib/types.ts, src/modules/agents/store/agentStore.ts, src/modules/agents/components/AgentNotificationsBridge.tsx, src/modules/agents/components/NotificationBell.tsx, src/modules/agents/lib/agentIcon.tsx, src/modules/agents/lib/format.ts
Adds "idle" to AgentStatus, initializes sessions as idle, fixes "finished" signal to set idle after maybeTriggerManagedReview, updates StatusRow idle label, and adds opencode/cursor to icon and display-name lookups.
AgentsPanel component
src/modules/agents-panel/AgentsPanel.tsx, src/modules/agents-panel/index.ts
New component with StatusBadge, tabTitleFor, session list rendering, empty state, and PanelHeader with count badge; exported via module index.
Sidebar agents view: type, rail, and panel hook
src/modules/sidebar/types.ts, src/modules/sidebar/SidebarRail.tsx, src/modules/sidebar/useSidebarPanel.ts
Extends SidebarViewId with "agents", adds showAgentsTab/agentCount props to SidebarRail with RoboticIcon item, and updates useSidebarPanel to gate agents view restore and fall back to explorer when agents tab is disabled.
agentsByTabId plumbing through Header → TabBar → TabIcon
src/modules/header/Header.tsx, src/modules/tabs/TabBar.tsx
Threads agentsByTabId: Map<number, string> through Header props into TabBar and down to TabIcon, which renders AgentIcon for terminal tabs found in the map.
showAgentsTab preference
src/modules/settings/store.ts, src/settings/sections/GeneralSection.tsx
Adds showAgentsTab to Preferences, default, load, persist, and cross-window mapping; adds a Switch row in GeneralSection.
App.tsx agents wiring
src/app/App.tsx
Reads useAgentStore sessions, builds agentsByTabId, passes showAgentsTab to useSidebarPanel, renders AgentsPanel in the sidebar agents branch, resets non-idle agent sessions on terminal tab switch, and provides agentCount to SidebarRail.

Terminal Cursor Style Preference

Layer / File(s) Summary
TerminalCursorStyle store and settings UI
src/modules/settings/store.ts, src/settings/sections/GeneralSection.tsx
Adds TerminalCursorStyle type, TERMINAL_CURSOR_STYLES metadata, extends Preferences, wires load/persist/cross-window mapping, and adds Cursor style Select row in GeneralSection.
applyCursorStyle in renderer pool and session hook
src/modules/terminal/lib/rendererPool.ts, src/modules/terminal/lib/useTerminalSession.ts
Uses prefs.terminalCursorStyle at xterm init, adds applyCursorStyle export to update all pooled slots, and adds a useEffect in useTerminalSession to apply it on preference change.

Navigation, Shortcuts, and Command Palette

Layer / File(s) Summary
New shortcuts and space-scoped tab selection
src/modules/shortcuts/shortcuts.ts, src/modules/tabs/lib/useTabs.ts, src/modules/tabs/lib/pickTabBySpaceIndex.test.ts
Adds ai.toggleMini and sidebar.files shortcut IDs and bindings, introduces pickTabBySpaceIndex helper, extends selectByIndex with optional spaceId, and tests the helper.
Command palette: Terminals group and files sidebar
src/modules/command-palette/commands.ts
Adds "Terminals" to COMMAND_GROUPS, extends CommandPaletteActionContext with toggleFilesExplorer/terminalTabs/switchTab, generates per-terminal-tab commands, and adds Show Files sidebar command.
App.tsx navigation wiring
src/app/App.tsx, src/modules/ai/components/AiStatusBarControls.tsx, src/modules/ai/store/chatStore.ts
Wires toggleMini with hasComposer guard, updates sidebar.files handler to cycle to explorer, passes spaceId to selectByIndex, adds terminal tab palette context, and flips chatStore initial panelOpen to true.

Tooling and Workflow

Layer / File(s) Summary
PR workflow skill and pnpm bump
.claude/skills/terax-pr-workflow/SKILL.md, package.json
Defines a new fork+upstream dual-PR workflow skill for Claude automation and bumps pnpm from 11.5.0 to 11.9.0.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • crynta/terax-ai#569: Modifies the same rendererPool.ts + useTerminalSession.ts pipeline to persist and apply a terminal appearance preference across all active slots (font weight vs cursor style here).
  • crynta/terax-ai#810: Adds a prop to the same HeaderTabBar prop chain for a different feature (drag-to-reorder), touching the same component interfaces expanded by agentsByTabId here.
  • crynta/terax-ai#881: Introduces the same pickTabBySpaceIndex space-scoped tab selection and selectByIndex spaceId extension incorporated in this PR.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title uses conventional commits and accurately summarizes the main change: a terminal cursor style setting.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/modules/agents/store/agentStore.ts (1)

33-49: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Filter idle sessions before driving the active-agent UI.

handleSignal(..., "finished") now leaves sessions in the store as "idle", but App.tsx still feeds every session into agentsByTabId and AgentsPanel. Completed runs will keep a tab icon and stay in the sidebar until the PTY exits.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/modules/agents/store/agentStore.ts` around lines 33 - 49, The agent store
leaves finished sessions in state as "idle", but the active-agent UI still
treats every session as active. Update the session-to-UI mapping in App.tsx (the
agentsByTabId/AgentsPanel path) to exclude sessions whose status is "idle" so
only running sessions drive the tab icon and sidebar, while keeping the existing
store behavior in agentStore.start and handleSignal unchanged.
🧹 Nitpick comments (1)
src/modules/terminal/lib/useTerminalSession.ts (1)

911-914: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Hoist this global preference fanout out of useTerminalSession.

Each mounted terminal hook now subscribes to terminalCursorStyle, but applyCursorStyle() already scans the shared pool. Because hidden tabs stay mounted, one settings change reruns the same pool walk once per terminal tab. A single store subscription near the pool or app bootstrap avoids that multiplier. As per path instructions, src/**/*.{ts,tsx}: "Watch for performance regressions: wasted re-renders, extra IPC round-trips, eager work that should be lazy" and "Tabs are kept mounted and hidden on switch".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/modules/terminal/lib/useTerminalSession.ts` around lines 911 - 914, The
cursor-style fanout in useTerminalSession is causing duplicate work because
every mounted terminal hook subscribes to terminalCursorStyle and re-runs
applyCursorStyle() even though it already walks the shared pool. Move the store
subscription and effect out of useTerminalSession and hoist it to a single place
near the terminal pool or app bootstrap so the style change is handled once per
update. Keep applyCursorStyle as the shared pool updater, and ensure the new
subscription still triggers it when the preference changes.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.claude/skills/terax-pr-workflow/SKILL.md:
- Line 34: The workflow currently uses a bare TypeScript check command instead
of the project’s pnpm-based script. Update the SKILL.md instructions to use pnpm
check-types in place of npx tsc --noEmit, and keep the guidance aligned with the
established pnpm-only workflow so it references the project’s standard
type-check command.
- Line 74: Remove the robot emoji from the PR body template in the skill
documentation so it follows the no-emojis convention. Update the template text
in SKILL.md by editing the PR template section that includes the “Generated with
[Claude Code]” line, and ensure the final PR body content contains only plain
text with no emoji characters.
- Line 3: The skill description in SKILL.md still uses an em-dash, which
violates the repository convention. Update the description text to remove the
em-dash and replace it with plain ASCII punctuation while preserving the
meaning, and ensure the rest of the skill content remains unchanged. Use the
description field in SKILL.md as the target location for this cleanup.

In `@src/app/App.tsx`:
- Around line 399-415: Do not reset agent lifecycle state in the App tab-switch
effect: the logic in App.tsx useEffect that iterates over useAgentStore sessions
and calls setStatus(..., "idle") on activeId change is clearing real
running/waiting state. Remove or narrow this behavior so tab visibility only
acknowledges notifications, and if any status update is still needed, scope it
to the focused leaf and only for waiting states rather than all non-idle
sessions.
- Around line 1179-1184: The panel row click wiring in App’s AgentsPanel is
using setActiveId directly, but these rows need the leaf-aware activation path
to keep the header and split-pane state in sync across spaces. Update the
AgentsPanel usage so row clicks call activateAgentTarget instead of setActiveId,
and make sure the panel receives the existing callback that knows how to focus
the owning leaf for an agent session. Keep the change localized to the
App/AgentsPanel wiring to avoid broader regressions in global navigation state.

In `@src/modules/ai/components/AiStatusBarControls.tsx`:
- Around line 172-174: The IconBtn in AiStatusBarControls should toggle the mini
chat window instead of always opening it. Update the button’s click handler to
switch between the open and close actions based on miniOpen, using the existing
openMini/closeMini logic (or a shared toggle handler) so it matches the title
text and the ai.toggleMini shortcut.

In `@src/modules/sidebar/useSidebarPanel.ts`:
- Around line 60-62: The lazy initialization in useSidebarPanel is restoring
sidebarView from the pre-hydration default, which can briefly reopen the agents
view before preferences are loaded. Update the sidebarView initialization and
the related syncing logic in useSidebarPanel/readSidebarView so the initial
state does not come from the stale showAgentsTab default, and only apply the
persisted view once preferences are ready; also adjust the later effect around
the same sidebar state handling to avoid the visible flash.

---

Outside diff comments:
In `@src/modules/agents/store/agentStore.ts`:
- Around line 33-49: The agent store leaves finished sessions in state as
"idle", but the active-agent UI still treats every session as active. Update the
session-to-UI mapping in App.tsx (the agentsByTabId/AgentsPanel path) to exclude
sessions whose status is "idle" so only running sessions drive the tab icon and
sidebar, while keeping the existing store behavior in agentStore.start and
handleSignal unchanged.

---

Nitpick comments:
In `@src/modules/terminal/lib/useTerminalSession.ts`:
- Around line 911-914: The cursor-style fanout in useTerminalSession is causing
duplicate work because every mounted terminal hook subscribes to
terminalCursorStyle and re-runs applyCursorStyle() even though it already walks
the shared pool. Move the store subscription and effect out of
useTerminalSession and hoist it to a single place near the terminal pool or app
bootstrap so the style change is handled once per update. Keep applyCursorStyle
as the shared pool updater, and ensure the new subscription still triggers it
when the preference changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 841ca7e7-fddf-4eff-9a13-415158d9fec4

📥 Commits

Reviewing files that changed from the base of the PR and between 3f4d680 and d292c64.

📒 Files selected for processing (26)
  • .claude/skills/terax-pr-workflow/SKILL.md
  • package.json
  • src/app/App.tsx
  • src/modules/agents-panel/AgentsPanel.tsx
  • src/modules/agents-panel/index.ts
  • src/modules/agents/components/AgentNotificationsBridge.tsx
  • src/modules/agents/components/NotificationBell.tsx
  • src/modules/agents/lib/agentIcon.tsx
  • src/modules/agents/lib/format.ts
  • src/modules/agents/lib/types.ts
  • src/modules/agents/store/agentStore.ts
  • src/modules/ai/components/AiStatusBarControls.tsx
  • src/modules/ai/store/chatStore.ts
  • src/modules/command-palette/commands.ts
  • src/modules/header/Header.tsx
  • src/modules/settings/store.ts
  • src/modules/shortcuts/shortcuts.ts
  • src/modules/sidebar/SidebarRail.tsx
  • src/modules/sidebar/types.ts
  • src/modules/sidebar/useSidebarPanel.ts
  • src/modules/tabs/TabBar.tsx
  • src/modules/tabs/lib/pickTabBySpaceIndex.test.ts
  • src/modules/tabs/lib/useTabs.ts
  • src/modules/terminal/lib/rendererPool.ts
  • src/modules/terminal/lib/useTerminalSession.ts
  • src/settings/sections/GeneralSection.tsx

@@ -0,0 +1,112 @@
---
name: terax-pr-workflow
description: Use this skill whenever making ANY change to this repository — features, fixes, shortcuts, refactors, anything. It enforces the mandatory branch → commit → dual-PR (fork + upstream) → merge-fork → back-to-main workflow. Trigger on phrases like "create a PR", "add a feature", "fix this", "push this", "open a pull request", or any task that involves committing and shipping code changes.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove em-dash from skill description.

The description field contains an em-dash, which violates the project convention: "Do not use em-dash anywhere, including code, comments, commits, and docs." As per coding guidelines, no em-dashes anywhere.

🧰 Tools
🪛 SkillSpector (2.3.7)

[warning] 34: [RP1] null: npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Remediation: Pin the version: npx @scope/server@1.2.3

(MCP Rug Pull (RP1))


[warning] 111: [RP1] null: npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Remediation: Pin the version: npx @scope/server@1.2.3

(MCP Rug Pull (RP1))

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.claude/skills/terax-pr-workflow/SKILL.md at line 3, The skill description
in SKILL.md still uses an em-dash, which violates the repository convention.
Update the description text to remove the em-dash and replace it with plain
ASCII punctuation while preserving the meaning, and ensure the rest of the skill
content remains unchanged. Use the description field in SKILL.md as the target
location for this cleanup.

Source: Coding guidelines

Implement the feature/fix. Type-check before committing:

```bash
npx tsc --noEmit

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use pnpm check-types instead of npx tsc --noEmit.

The project defines pnpm check-types as the frontend type-check command. Using bare npx tsc bypasses pnpm, the project's package manager, and any project-level TypeScript configuration that check-types may wrap. This is inconsistent with the established workflow and could drift if the check-types script is updated. As per coding guidelines, pnpm only, never npm/npx/yarn.

🧰 Tools
🪛 SkillSpector (2.3.7)

[warning] 34: [RP1] null: npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Remediation: Pin the version: npx @scope/server@1.2.3

(MCP Rug Pull (RP1))


[warning] 111: [RP1] null: npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Remediation: Pin the version: npx @scope/server@1.2.3

(MCP Rug Pull (RP1))

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.claude/skills/terax-pr-workflow/SKILL.md at line 34, The workflow currently
uses a bare TypeScript check command instead of the project’s pnpm-based script.
Update the SKILL.md instructions to use pnpm check-types in place of npx tsc
--noEmit, and keep the guidance aligned with the established pnpm-only workflow
so it references the project’s standard type-check command.

Source: Coding guidelines

## Test plan
- [ ] item
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove emoji from PR template.

The PR body template includes a robot emoji, which violates the project convention: "Do not use emojis anywhere." As per coding guidelines, no emojis anywhere.

🧰 Tools
🪛 SkillSpector (2.3.7)

[warning] 34: [RP1] null: npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Remediation: Pin the version: npx @scope/server@1.2.3

(MCP Rug Pull (RP1))


[warning] 111: [RP1] null: npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Remediation: Pin the version: npx @scope/server@1.2.3

(MCP Rug Pull (RP1))

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.claude/skills/terax-pr-workflow/SKILL.md at line 74, Remove the robot emoji
from the PR body template in the skill documentation so it follows the no-emojis
convention. Update the template text in SKILL.md by editing the PR template
section that includes the “Generated with [Claude Code]” line, and ensure the
final PR body content contains only plain text with no emoji characters.

Source: Coding guidelines

Comment thread src/app/App.tsx
Comment on lines +399 to +415

// When the user NAVIGATES to a terminal tab, reset any non-idle agent status
// back to idle — they are looking at it so notifications are moot, and
// Ctrl+C won't fire a finished signal so "working" would otherwise get stuck.
// Uses tabsRef (not tabs) so this only fires on activeId change, not on every
// tab title update (which would kill real-time "working" display).
useEffect(() => {
const tab = tabsRef.current.find((t) => t.id === activeId);
if (!tab || tab.kind !== "terminal") return;
const store = useAgentStore.getState();
for (const s of Object.values(store.sessions)) {
if (s.tabId === activeId && s.status !== "idle") {
store.setStatus(s.leafId, "idle");
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activeId]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Do not clear agent status on tab switch.

This rewrites real lifecycle state as a visibility side effect: a running or waiting agent in the active tab becomes idle, which drops it from agentCount and the panel, and split tabs clear sibling leaves too. Keep acknowledgement separate, or at least scope this to the focused leaf and waiting. As per path instructions, focus on regressions from local fixes and the right abstraction boundary.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/App.tsx` around lines 399 - 415, Do not reset agent lifecycle state
in the App tab-switch effect: the logic in App.tsx useEffect that iterates over
useAgentStore sessions and calls setStatus(..., "idle") on activeId change is
clearing real running/waiting state. Remove or narrow this behavior so tab
visibility only acknowledges notifications, and if any status update is still
needed, scope it to the focused leaf and only for waiting states rather than all
non-idle sessions.

Source: Path instructions

Comment thread src/app/App.tsx
Comment on lines +1179 to +1184
) : sidebarView === "agents" ? (
<AgentsPanel
sessions={agentSessions}
tabs={tabs}
onSelectTab={setActiveId}
/>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Use activateAgentTarget for panel row clicks.

agentSessions spans all spaces and multiple leaves per tab, but these rows only call setActiveId, so cross-space clicks leave the header on the wrong space and split-pane clicks cannot focus the owning leaf. Pass the existing leaf-aware activation callback through the panel instead. As per path instructions, focus on blast radius and global regressions from local UI wiring.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/App.tsx` around lines 1179 - 1184, The panel row click wiring in
App’s AgentsPanel is using setActiveId directly, but these rows need the
leaf-aware activation path to keep the header and split-pane state in sync
across spaces. Update the AgentsPanel usage so row clicks call
activateAgentTarget instead of setActiveId, and make sure the panel receives the
existing callback that knows how to focus the owning leaf for an agent session.
Keep the change localized to the App/AgentsPanel wiring to avoid broader
regressions in global navigation state.

Source: Path instructions

Comment on lines 172 to 174
<IconBtn
title={miniOpen ? "Mini-window open" : "Open conversation"}
title={`${miniOpen ? "Close" : "Open"} AI chat window (${fmtShortcut("⇧", MOD_KEY, "I")})`}
onClick={openMini}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make this button actually toggle the mini window.

Line 173 advertises "Close AI chat window" when miniOpen is true, but Line 174 still calls openMini, so this control never performs the close action and now disagrees with the ai.toggleMini shortcut.

Suggested fix
-  const openMini = useChatStore((s) => s.openMini);
+  const toggleMini = useChatStore((s) => s.toggleMini);
...
-        onClick={openMini}
+        onClick={toggleMini}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<IconBtn
title={miniOpen ? "Mini-window open" : "Open conversation"}
title={`${miniOpen ? "Close" : "Open"} AI chat window (${fmtShortcut("⇧", MOD_KEY, "I")})`}
onClick={openMini}
<IconBtn
title={`${miniOpen ? "Close" : "Open"} AI chat window (${fmtShortcut("⇧", MOD_KEY, "I")})`}
onClick={toggleMini}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/modules/ai/components/AiStatusBarControls.tsx` around lines 172 - 174,
The IconBtn in AiStatusBarControls should toggle the mini chat window instead of
always opening it. Update the button’s click handler to switch between the open
and close actions based on miniOpen, using the existing openMini/closeMini logic
(or a shared toggle handler) so it matches the title text and the ai.toggleMini
shortcut.

Comment on lines +60 to +62
const [sidebarView, setSidebarViewState] = useState<SidebarViewId>(() =>
readSidebarView(showAgentsTab),
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Do not restore the agents view from the pre-hydration default.

usePreferencesStore boots with showAgentsTab: true, so this lazy initializer can reopen "agents" on first paint for users who disabled it and had that view stored. The later effect fixes it, but only after a visible flash.

Also applies to: 121-125

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/modules/sidebar/useSidebarPanel.ts` around lines 60 - 62, The lazy
initialization in useSidebarPanel is restoring sidebarView from the
pre-hydration default, which can briefly reopen the agents view before
preferences are loaded. Update the sidebarView initialization and the related
syncing logic in useSidebarPanel/readSidebarView so the initial state does not
come from the stale showAgentsTab default, and only apply the persisted view
once preferences are ready; also adjust the later effect around the same sidebar
state handling to avoid the visible flash.

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