feat(editor): show git blame for current line in status bar#910
feat(editor): show git blame for current line in status bar#910roberto-fernandino wants to merge 25 commits into
Conversation
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>
…tyle feat(terminal): add cursor style setting (bar/block/underline)
…pboard) Resolves conflicts between fork additions (showAgentsTab, cursor style) and upstream additions (defaultWorkspaceEnv, sidebar collapsed persistence, native clipboard on Linux). Both sides preserved. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When editing a file, the status bar now shows who last committed the current cursor line and how long ago, e.g. "Roberto (2 days ago)". Adds a git_blame Tauri command (git blame -L line,line --porcelain), cursor tracking via a CodeMirror updateListener, debounced blame fetching (300ms), and a relative-time display in the status bar footer. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
📝 WalkthroughWalkthroughAdds a Rust git-blame backend command surfaced through a debounced editor cursor callback into the status bar. Introduces an Agents sidebar tab/panel with agent session tracking (new "idle" status), terminal cursor-style preference, command palette terminal-switching support, and several shortcut/UI tweaks. ChangesGit Blame Feature
Agents Sidebar Feature
Terminal & Settings Wiring
PR Workflow Documentation
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/app/App.tsx (1)
334-346: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winStale blame response can land on the wrong tab.
handleEditorCursorChangeschedules a 300ms-debouncednative.gitBlame(...)call, but the resolved.then(setBlameInfo)/.catchnever re-checks that the originating tab is still active. Since editor tabs stay mounted (not unmounted) on switch, if the user switches tabs while a request for the previous tab is in flight, that stale result overwritesblameInfofor whatever tab is now active.Compounding this, the cleanup effect at lines 341-345 only clears
blameInfowhen leaving editor tabs entirely — switching between two editor tabs leaves the old tab's author/time displayed until the new tab happens to fire a cursor event.As per path instructions, "Tabs are kept mounted and hidden on switch... so do not accept logic that assumes unmount-on-switch."
🛡️ Proposed fix: guard against stale async results and clear on every tab switch
+ const activeIdRef = useRef(activeId); + activeIdRef.current = activeId; + useEffect(() => { setActiveSearchAddon( activeLeafId !== null ? (searchAddons.current.get(activeLeafId) ?? null) : null, ); setActiveEditorHandle(editorRefs.current.get(activeId) ?? null); - const tab = tabsRef.current.find((t) => t.id === activeId); - if (!tab || tab.kind !== "editor") { - if (blameDebounceRef.current) clearTimeout(blameDebounceRef.current); - setBlameInfo(null); - } + if (blameDebounceRef.current) clearTimeout(blameDebounceRef.current); + setBlameInfo(null); }, [activeId, activeLeafId]);if (blameDebounceRef.current) clearTimeout(blameDebounceRef.current); blameDebounceRef.current = setTimeout(() => { - native.gitBlame(cwd, filePath, line).then(setBlameInfo).catch(() => { - setBlameInfo(null); - }); + native.gitBlame(cwd, filePath, line) + .then((info) => { + if (id === activeIdRef.current) setBlameInfo(info); + }) + .catch(() => { + if (id === activeIdRef.current) setBlameInfo(null); + }); }, 300);Note: clearing unconditionally on every tab switch means a brief "no blame" flash until the new tab's first cursor event fires — acceptable trade-off versus showing the wrong author.
Also applies to: 908-928
🤖 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 334 - 346, The blame state update is stale across tab switches: handleEditorCursorChange’s debounced native.gitBlame result can resolve after the user has switched tabs, and the current useEffect only clears blameInfo when leaving editor tabs entirely. Update the App.tsx logic around handleEditorCursorChange and the activeId/activeLeafId effect to either guard the async setBlameInfo/catch path with the originating tab id or active tab check, and clear blameInfo on every tab switch so hidden mounted editor tabs cannot overwrite the currently visible tab’s blame data.Source: Path instructions
🧹 Nitpick comments (1)
.claude/skills/terax-pr-workflow/SKILL.md (1)
34-34: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winReplace
npx tsc --noEmitwithpnpm check-types.The project mandates
pnpmexclusively and definespnpm check-typesas the type-check command in its quality bar. Usingnpxcontradicts thepnpm onlyconvention and creates a rug-pull risk (RP1). As per coding guidelines, pnpm only, never npm/npx/yarn.Also applies to: 129-129
🤖 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 docs still use npx tsc --noEmit, which conflicts with the pnpm-only convention. Update the affected command in SKILL.md to use pnpm check-types instead, and make the same replacement at the additional referenced location so all type-check guidance points to the project’s standard command.Sources: Coding guidelines, Linters/SAST tools
🤖 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 90: The PR body template contains an emoji, which violates the project’s
no-emoji rule. Update the generated attribution text in SKILL.md to plain text
only, using the existing “Generated with Claude Code” wording without any emoji
or special symbols, and keep the change localized to the template content.
- Line 3: The skill description in SKILL.md contains em dashes, which violate
the project’s punctuation rules. Update the description text to use hyphens or
commas instead, and make sure the wording in the skill’s description remains
equivalent while removing every em dash from that entry.
In `@src-tauri/src/modules/git/operations.rs`:
- Around line 1150-1201: Refactor blame_line so the porcelain parsing is moved
into a pure helper, such as parse_blame_porcelain, and keep blame_line focused
on the run_git I/O and exit-code handling. Extract the text.lines()
author/timestamp loop into that helper using GitBlameLineInfo as the return
value, then add unit tests directly against the parser with fixture strings
covering valid output, malformed output, missing author-time, and the "Not
Committed Yet" filter.
In `@src/modules/ai/store/chatStore.ts`:
- Line 242: The default for `panelOpen` in `chatStore` now causes the AI panel
to open on every startup, ignoring the user’s previous choice. Update the
`chatStore` state handling so `panelOpen` is persisted and restored across
launches, and keep the in-memory default from forcing it open unless a saved
value is available.
In `@src/modules/editor/EditorPane.tsx`:
- Around line 238-245: Switching editor tabs leaves stale blameInfo because the
current cursor listener in EditorPane only updates on selection changes; reset
or refresh it whenever activeId changes so the status bar reflects the newly
active file immediately. Update the logic around EditorPane and the
onCursorChangeRef/updateListener flow to either clear blame state on every
activeId switch or read the active editor’s current cursor position and invoke
the existing callback right away.
In `@src/modules/tabs/TabBar.tsx`:
- Around line 626-636: The TabIcon rendering path is returning the agent brand
mark before the private-tab incognito state is checked, so private terminal tabs
can lose their privacy indicator. Update TabIcon so the tab.private branch takes
precedence over the agent lookup/AgentIcon branch, keeping the incognito icon
visible for private tabs even when an agent is detected.
---
Outside diff comments:
In `@src/app/App.tsx`:
- Around line 334-346: The blame state update is stale across tab switches:
handleEditorCursorChange’s debounced native.gitBlame result can resolve after
the user has switched tabs, and the current useEffect only clears blameInfo when
leaving editor tabs entirely. Update the App.tsx logic around
handleEditorCursorChange and the activeId/activeLeafId effect to either guard
the async setBlameInfo/catch path with the originating tab id or active tab
check, and clear blameInfo on every tab switch so hidden mounted editor tabs
cannot overwrite the currently visible tab’s blame data.
---
Nitpick comments:
In @.claude/skills/terax-pr-workflow/SKILL.md:
- Line 34: The workflow docs still use npx tsc --noEmit, which conflicts with
the pnpm-only convention. Update the affected command in SKILL.md to use pnpm
check-types instead, and make the same replacement at the additional referenced
location so all type-check guidance points to the project’s standard command.
🪄 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: 3ac4b4e6-2c60-42a0-bda7-03f1432857ef
📒 Files selected for processing (32)
.claude/skills/terax-pr-workflow/SKILL.mdsrc-tauri/src/lib.rssrc-tauri/src/modules/git/commands.rssrc-tauri/src/modules/git/operations.rssrc-tauri/src/modules/git/types.rssrc/app/App.tsxsrc/app/components/WorkspaceSurface.tsxsrc/modules/agents-panel/AgentsPanel.tsxsrc/modules/agents-panel/index.tssrc/modules/agents/components/AgentNotificationsBridge.tsxsrc/modules/agents/components/NotificationBell.tsxsrc/modules/agents/lib/agentIcon.tsxsrc/modules/agents/lib/format.tssrc/modules/agents/lib/types.tssrc/modules/agents/store/agentStore.tssrc/modules/ai/components/AiStatusBarControls.tsxsrc/modules/ai/lib/native.tssrc/modules/ai/store/chatStore.tssrc/modules/command-palette/commands.tssrc/modules/editor/EditorPane.tsxsrc/modules/editor/EditorStack.tsxsrc/modules/header/Header.tsxsrc/modules/settings/store.tssrc/modules/shortcuts/shortcuts.tssrc/modules/sidebar/SidebarRail.tsxsrc/modules/sidebar/types.tssrc/modules/sidebar/useSidebarPanel.tssrc/modules/statusbar/StatusBar.tsxsrc/modules/tabs/TabBar.tsxsrc/modules/terminal/lib/rendererPool.tssrc/modules/terminal/lib/useTerminalSession.tssrc/settings/sections/GeneralSection.tsx
| @@ -0,0 +1,130 @@ | |||
| --- | |||
| 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. | |||
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Remove em-dashes from skill description.
The project prohibits em dashes in all files. Replace with hyphens or commas. As per coding guidelines, do not use em dashes anywhere, including code, comments, commits, and docs.
🧰 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] 129: [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 contains em dashes, which violate the project’s punctuation rules.
Update the description text to use hyphens or commas instead, and make sure the
wording in the skill’s description remains equivalent while removing every em
dash from that entry.
Source: Coding guidelines
| ## Test plan | ||
| - [ ] item | ||
|
|
||
| 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Remove emoji from PR body template.
The project prohibits emojis in all files. Replace with plain text, e.g., [Generated with Claude Code]. As per coding guidelines, do not use 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] 129: [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 90, The PR body template
contains an emoji, which violates the project’s no-emoji rule. Update the
generated attribution text in SKILL.md to plain text only, using the existing
“Generated with Claude Code” wording without any emoji or special symbols, and
keep the change localized to the template content.
Source: Coding guidelines
| pub fn blame_line( | ||
| registry: &WorkspaceRegistry, | ||
| cwd: &str, | ||
| path: &str, | ||
| line: u32, | ||
| workspace: &WorkspaceEnv, | ||
| ) -> Result<Option<GitBlameLineInfo>> { | ||
| if line == 0 { | ||
| return Ok(None); | ||
| } | ||
| let dir = canonical_dir(registry, cwd, workspace)?; | ||
| if !registry.is_authorized(&dir.local_path) { | ||
| return Err(GitError::PathOutsideWorkspace(dir.local_path)); | ||
| } | ||
| ensure_git_available(&dir.workspace)?; | ||
|
|
||
| let line_spec = format!("{},{}", line, line); | ||
| let output = run_git( | ||
| &dir.workspace, | ||
| Some(&dir.git_path), | ||
| ["blame", "-L", &line_spec, "--porcelain", "--", path], | ||
| DEFAULT_TIMEOUT_SECS, | ||
| )?; | ||
|
|
||
| if output.exit_code != Some(0) { | ||
| return Ok(None); | ||
| } | ||
|
|
||
| let text = String::from_utf8_lossy(&output.stdout); | ||
| let mut author: Option<String> = None; | ||
| let mut timestamp: Option<i64> = None; | ||
|
|
||
| for line_text in text.lines() { | ||
| if let Some(name) = line_text.strip_prefix("author ") { | ||
| author = Some(name.to_string()); | ||
| } else if let Some(ts) = line_text.strip_prefix("author-time ") { | ||
| if let Ok(t) = ts.trim().parse::<i64>() { | ||
| timestamp = Some(t); | ||
| } | ||
| } | ||
| if author.is_some() && timestamp.is_some() { | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| Ok(match (author, timestamp) { | ||
| (Some(a), Some(t)) if a != "Not Committed Yet" => { | ||
| Some(GitBlameLineInfo { author: a, timestamp: t }) | ||
| } | ||
| _ => None, | ||
| }) | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Extract the porcelain parser into a pure function and add a test for it.
The parsing logic (lines 1178-1200) is sound, but it's fused to the run_git IO call, so it can't be unit-tested without shelling out to a real git process. TERAX.md's quality bar requires a test that locks the invariant for any git-subsystem change, and none is included for this parser (e.g. malformed porcelain output, "Not Committed Yet" filtering, missing author-time).
Splitting the text.lines() loop into a standalone fn parse_blame_porcelain(text: &str) -> Option<GitBlameLineInfo> keeps blame_line as the thin IO orchestrator and makes the parsing trivially testable with fixture strings.
As per coding guidelines, "A change to a core subsystem (terminal/shell spawn, workspace auth, git, fs, IPC or AI tool surface) needs a test that locks the invariant," and "new or changed logic lives in pure, dependency-light functions (functional core)."
♻️ Suggested split
fn parse_blame_porcelain(text: &str) -> Option<GitBlameLineInfo> {
let mut author: Option<String> = None;
let mut timestamp: Option<i64> = None;
for line_text in text.lines() {
if let Some(name) = line_text.strip_prefix("author ") {
author = Some(name.to_string());
} else if let Some(ts) = line_text.strip_prefix("author-time ") {
if let Ok(t) = ts.trim().parse::<i64>() {
timestamp = Some(t);
}
}
if author.is_some() && timestamp.is_some() {
break;
}
}
match (author, timestamp) {
(Some(a), Some(t)) if a != "Not Committed Yet" => Some(GitBlameLineInfo { author: a, timestamp: t }),
_ => None,
}
}Then blame_line just calls Ok(output.exit_code == Some(0)).then(|| parse_blame_porcelain(&String::from_utf8_lossy(&output.stdout))).flatten()) (or an equivalent if), and a #[cfg(test)] module can exercise parse_blame_porcelain directly with porcelain fixtures.
🤖 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-tauri/src/modules/git/operations.rs` around lines 1150 - 1201, Refactor
blame_line so the porcelain parsing is moved into a pure helper, such as
parse_blame_porcelain, and keep blame_line focused on the run_git I/O and
exit-code handling. Extract the text.lines() author/timestamp loop into that
helper using GitBlameLineInfo as the return value, then add unit tests directly
against the parser with fixture strings covering valid output, malformed output,
missing author-time, and the "Not Committed Yet" filter.
Source: Coding guidelines
| toggleMini: () => set((s) => ({ mini: { open: !s.mini.open } })), | ||
|
|
||
| panelOpen: false, | ||
| panelOpen: true, |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '--- chatStore.ts outline ---\n'
ast-grep outline src/modules/ai/store/chatStore.ts --view expanded || true
printf '\n--- search panelOpen usages ---\n'
rg -n "panelOpen" src/modules src/App.tsx
printf '\n--- chatStore.ts relevant slice ---\n'
sed -n '1,340p' src/modules/ai/store/chatStore.tsRepository: crynta/terax-ai
Length of output: 244
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '--- chatStore.ts outline ---'
ast-grep outline src/modules/ai/store/chatStore.ts --view expanded || true
echo
echo '--- search panelOpen usages ---'
rg -n "panelOpen" src/modules src/App.tsx
echo
echo '--- chatStore.ts relevant slice ---'
sed -n '1,340p' src/modules/ai/store/chatStore.tsRepository: crynta/terax-ai
Length of output: 2158
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '--- chatStore.ts around panelOpen ---'
sed -n '100,290p' src/modules/ai/store/chatStore.ts
echo
echo '--- search for persisted panelOpen / hydration ---'
rg -n "panelOpen|persist|hydrateSessions|set\\(\\{ panelOpen|openPanel\\(|closePanel\\(" src/modules/ai src/modules/statusbar src/modulesRepository: crynta/terax-ai
Length of output: 16797
AI panel now opens on every launch
panelOpen is still in-memory, so changing the default to true makes the docked AI surface start open on every app launch instead of respecting the user's last state. Persist this flag if that state should stick.
🤖 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/store/chatStore.ts` at line 242, The default for `panelOpen`
in `chatStore` now causes the AI panel to open on every startup, ignoring the
user’s previous choice. Update the `chatStore` state handling so `panelOpen` is
persisted and restored across launches, and keep the in-memory default from
forcing it open unless a saved value is available.
| EditorView.updateListener.of((update) => { | ||
| if (!update.selectionSet) return; | ||
| const cb = onCursorChangeRef.current; | ||
| if (!cb) return; | ||
| const pos = update.state.selection.main.head; | ||
| const lineInfo = update.state.doc.lineAt(pos); | ||
| cb(lineInfo.number, pos - lineInfo.from + 1); | ||
| }), |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Clear blameInfo on editor-tab switches. Switching between two mounted editor tabs leaves the previous file’s blame in the status bar until the new tab emits a cursor move. Reset it on every activeId change, or refresh from the active editor’s current cursor when focus moves.
🤖 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/editor/EditorPane.tsx` around lines 238 - 245, Switching editor
tabs leaves stale blameInfo because the current cursor listener in EditorPane
only updates on selection changes; reset or refresh it whenever activeId changes
so the status bar reflects the newly active file immediately. Update the logic
around EditorPane and the onCursorChangeRef/updateListener flow to either clear
blame state on every activeId switch or read the active editor’s current cursor
position and invoke the existing callback right away.
| export function TabIcon({ | ||
| tab, | ||
| agentsByTabId, | ||
| }: { | ||
| tab: Tab; | ||
| agentsByTabId?: Map<number, string>; | ||
| }) { | ||
| const agent = tab.kind === "terminal" ? agentsByTabId?.get(tab.id) : undefined; | ||
| if (agent) { | ||
| return <AgentIcon agent={agent} size={14} className="shrink-0" />; | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Agent icon silently overrides the private-tab incognito indicator.
The new agent-icon branch returns before the tab.private check further down, so a private terminal running a detected coding agent loses its incognito icon entirely in favor of the agent brand mark. Since the private icon is the only visual cue that a tab is in private/incognito mode, this is a small but real regression for that feature.
Proposed fix: keep the private indicator in front
const agent = tab.kind === "terminal" ? agentsByTabId?.get(tab.id) : undefined;
- if (agent) {
+ if (agent && !(tab.kind === "terminal" && tab.private)) {
return <AgentIcon agent={agent} size={14} className="shrink-0" />;
}📝 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.
| export function TabIcon({ | |
| tab, | |
| agentsByTabId, | |
| }: { | |
| tab: Tab; | |
| agentsByTabId?: Map<number, string>; | |
| }) { | |
| const agent = tab.kind === "terminal" ? agentsByTabId?.get(tab.id) : undefined; | |
| if (agent) { | |
| return <AgentIcon agent={agent} size={14} className="shrink-0" />; | |
| } | |
| export function TabIcon({ | |
| tab, | |
| agentsByTabId, | |
| }: { | |
| tab: Tab; | |
| agentsByTabId?: Map<number, string>; | |
| }) { | |
| const agent = tab.kind === "terminal" ? agentsByTabId?.get(tab.id) : undefined; | |
| if (agent && !(tab.kind === "terminal" && tab.private)) { | |
| return <AgentIcon agent={agent} size={14} className="shrink-0" />; | |
| } |
🤖 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/tabs/TabBar.tsx` around lines 626 - 636, The TabIcon rendering
path is returning the agent brand mark before the private-tab incognito state is
checked, so private terminal tabs can lose their privacy indicator. Update
TabIcon so the tab.private branch takes precedence over the agent
lookup/AgentIcon branch, keeping the incognito icon visible for private tabs
even when an agent is detected.
Summary
git_blameTauri command that runsgit blame -L <line>,<line> --porcelainfor the current cursor lineEditorPanevia a CodeMirrorupdateListenerextension"Author (X time ago)"in the status bar footer when editing a file in a git repoTest plan
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes