feature (desktop):warp style wd nav and terminal path visualization#286
feature (desktop):warp style wd nav and terminal path visualization#286
Conversation
|
Warning Rate limit exceeded@AviPeltz has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 20 minutes and 19 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (1)
WalkthroughThis PR introduces a directory navigation feature for the terminal. It adds a tRPC procedure to list directory contents, a new DirectoryNavigator UI component with breadcrumb navigation in a popover, state management for tracking the pane's current working directory, cwd extraction from OSC-7 escape sequences, and a new Popover UI component. Changes
Sequence DiagramsequenceDiagram
participant User
participant DirectoryNavigator as DirectoryNavigator<br/>(UI)
participant TabsStore as TabsStore
participant Terminal as Terminal<br/>(Component)
participant TerminalEmulator as Terminal<br/>(Emulator)
participant Backend as Backend<br/>(tRPC)
User->>DirectoryNavigator: Click/interact with navigator
DirectoryNavigator->>Backend: Call listDirectory(dirPath)
Backend-->>DirectoryNavigator: Return directory contents
DirectoryNavigator->>User: Display breadcrumbs & subdirs
User->>DirectoryNavigator: Select directory to navigate
DirectoryNavigator->>Terminal: Send cd command
Terminal->>TerminalEmulator: Execute cd command
TerminalEmulator-->>TerminalEmulator: Output with OSC-7 escape seq
TerminalEmulator-->>Terminal: Emit data event
Terminal->>Terminal: Parse OSC-7 via parseCwd()
Terminal->>Terminal: Extract cwd from OSC-7
Terminal->>Terminal: Update terminalCwd state
Terminal->>TabsStore: Call updatePaneCwd(paneId, cwd, true)
TabsStore->>TabsStore: Update pane.cwd & cwdConfirmed
TabsStore-->>DirectoryNavigator: State updated
DirectoryNavigator->>DirectoryNavigator: Re-render with new cwd
DirectoryNavigator->>User: Update displayed path
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (1 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 |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🚀 Preview Deployment🔗 Preview Links
Preview updates automatically with new commits |
Keep renderToolbar approach for DirectoryNavigator and venv tags while adopting main's improved button styling. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Resolved conflicts: - agent-setup.ts: removed prompt customization, kept PATH setup - Terminal.tsx: merged pane metadata updates with tab auto-title - store.ts: combined all pane update functions - types.ts: use shared types, keep all store actions - tabs-types.ts: added venvs/cwd fields to shared Pane type - package.json: merged exports and dependencies - terminal-manager.ts: accepted deletion from main - bun.lock: regenerated 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
apps/desktop/src/lib/trpc/routers/terminal/terminal.ts (1)
219-226: Consider distinguishing error types for better UX.The catch block returns a generic "Unable to read directory" message. Consider differentiating between permission denied (
EACCES), not found (ENOENT), and not a directory (ENOTDIR) to provide more actionable feedback in the UI.- } catch { + } catch (err) { + const error = err as NodeJS.ErrnoException; + let message = "Unable to read directory"; + if (error.code === "ENOENT") message = "Directory not found"; + else if (error.code === "EACCES") message = "Permission denied"; + else if (error.code === "ENOTDIR") message = "Not a directory"; + return { currentPath: dirPath, parentPath: null, items: [], - error: "Unable to read directory", + error: message, }; }apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/DirectoryNavigator.tsx (1)
127-127: Improve event type specificity.The event parameter type
Eventis too broad. TheonOpenAutoFocusprop from Radix UI expects a more specific event type. Consider using the proper event type from Radix UI's type definitions orReact.FocusEvent.Apply this diff:
- onOpenAutoFocus={(e: Event) => e.preventDefault()} + onOpenAutoFocus={(e) => e.preventDefault()}TypeScript will infer the correct type from the Radix UI prop definition.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
apps/desktop/src/lib/trpc/routers/terminal/terminal.ts(2 hunks)apps/desktop/src/main/lib/agent-setup.ts(1 hunks)apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsx(2 hunks)apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/DirectoryNavigator.tsx(1 hunks)apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx(9 hunks)apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/parseCwd.ts(1 hunks)apps/desktop/src/renderer/stores/tabs/store.ts(1 hunks)apps/desktop/src/renderer/stores/tabs/types.ts(1 hunks)apps/desktop/src/shared/tabs-types.ts(1 hunks)packages/ui/src/components/popover.tsx(1 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
apps/desktop/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)
For Electron interprocess communication, ALWAYS use tRPC as defined in
src/lib/trpc
Files:
apps/desktop/src/main/lib/agent-setup.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsxapps/desktop/src/shared/tabs-types.tsapps/desktop/src/lib/trpc/routers/terminal/terminal.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/DirectoryNavigator.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/parseCwd.tsapps/desktop/src/renderer/stores/tabs/types.tsapps/desktop/src/renderer/stores/tabs/store.ts
apps/desktop/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)
apps/desktop/**/*.{ts,tsx}: Please use alias as defined intsconfig.jsonwhen possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary
Files:
apps/desktop/src/main/lib/agent-setup.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsxapps/desktop/src/shared/tabs-types.tsapps/desktop/src/lib/trpc/routers/terminal/terminal.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/DirectoryNavigator.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/parseCwd.tsapps/desktop/src/renderer/stores/tabs/types.tsapps/desktop/src/renderer/stores/tabs/store.ts
**/*.{ts,tsx,js,jsx,json}
📄 CodeRabbit inference engine (AGENTS.md)
Use Biome for code formatting and linting, running at root level for speed
Files:
apps/desktop/src/main/lib/agent-setup.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsxapps/desktop/src/shared/tabs-types.tsapps/desktop/src/lib/trpc/routers/terminal/terminal.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/DirectoryNavigator.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/parseCwd.tsapps/desktop/src/renderer/stores/tabs/types.tsapps/desktop/src/renderer/stores/tabs/store.tspackages/ui/src/components/popover.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Avoid
anytype and prioritize type safety in TypeScript code
Files:
apps/desktop/src/main/lib/agent-setup.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsxapps/desktop/src/shared/tabs-types.tsapps/desktop/src/lib/trpc/routers/terminal/terminal.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/DirectoryNavigator.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/parseCwd.tsapps/desktop/src/renderer/stores/tabs/types.tsapps/desktop/src/renderer/stores/tabs/store.tspackages/ui/src/components/popover.tsx
apps/desktop/src/main/lib/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Implement IPC handlers accepting object parameters (not positional parameters) in apps/desktop/src/main/lib/*.ts files
Files:
apps/desktop/src/main/lib/agent-setup.ts
**/components/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/components/**/*.{ts,tsx}: Structure project folders as one folder per component with PascalCase naming (ComponentName/ComponentName.tsx + index.ts barrel export)
Co-locate component dependencies (utils, hooks, constants, config, tests, stories) next to the file using them
Use one component per file (no multi-component files)
Files:
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/DirectoryNavigator.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/parseCwd.tspackages/ui/src/components/popover.tsx
apps/desktop/src/renderer/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Call IPC methods from renderer process using window.ipcRenderer.invoke with type-safe object parameters
Files:
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/DirectoryNavigator.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/parseCwd.tsapps/desktop/src/renderer/stores/tabs/types.tsapps/desktop/src/renderer/stores/tabs/store.ts
packages/ui/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use React + TailwindCSS v4 + shadcn/ui for UI components in
packages/ui
Files:
packages/ui/src/components/popover.tsx
🧠 Learnings (2)
📚 Learning: 2025-11-24T21:33:13.267Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-11-24T21:33:13.267Z
Learning: Applies to apps/desktop/**/*.{ts,tsx,js,jsx} : For Electron interprocess communication, ALWAYS use tRPC as defined in `src/lib/trpc`
Applied to files:
apps/desktop/src/lib/trpc/routers/terminal/terminal.ts
📚 Learning: 2025-12-12T05:45:09.672Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T05:45:09.672Z
Learning: Applies to packages/ui/**/*.{ts,tsx} : Use React + TailwindCSS v4 + shadcn/ui for UI components in `packages/ui`
Applied to files:
packages/ui/src/components/popover.tsx
🧬 Code graph analysis (5)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsx (1)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/DirectoryNavigator.tsx (1)
DirectoryNavigator(11-208)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx (1)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/parseCwd.ts (1)
parseCwd(21-36)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/DirectoryNavigator.tsx (1)
packages/ui/src/components/popover.tsx (3)
Popover(46-46)PopoverTrigger(46-46)PopoverContent(46-46)
apps/desktop/src/renderer/stores/tabs/store.ts (1)
apps/cli/src/lib/storage/lowdb-adapter.ts (1)
set(162-172)
packages/ui/src/components/popover.tsx (1)
packages/ui/src/lib/utils.ts (1)
cn(4-6)
🪛 ast-grep (0.40.0)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/parseCwd.ts
[warning] 11-14: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(
${ESC}\\]7;file://[^/]*((?:/[^${BEL}${ESC}]*)*)(?:${BEL}|${ESC}\\\\),
"g",
)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
(regexp-from-variable)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Deploy Admin
- GitHub Check: Deploy Web
- GitHub Check: Deploy Docs
- GitHub Check: Build
🔇 Additional comments (22)
apps/desktop/src/main/lib/agent-setup.ts (1)
180-181: LGTM!The minimal PS1 prompt with emerald coloring aligns well with the new toolbar-based path visualization. The ANSI escape sequence syntax is correct.
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/parseCwd.ts (2)
11-15: Static analysis false positive - constants are not user input.The ast-grep warning about "variable input" is a false positive since
ESCandBELare compile-time constants (\x1band\x07), not user-controlled values.The nested quantifier
(?:/[^${BEL}${ESC}]*)*has theoretical ReDoS potential, but terminal buffer sizes provide practical bounds. Consider using a non-greedy match if performance issues arise with large buffers.
21-35: LGTM!The parsing logic correctly handles multiple OSC 7 sequences by returning the last (most recent) match, and the
decodeURIComponentfallback gracefully handles malformed percent-encoded paths.apps/desktop/src/shared/tabs-types.ts (1)
24-24: LGTM!The optional nullable type appropriately distinguishes between "not yet determined" (undefined), "explicitly unavailable" (null), and "valid path" (string). The comment clearly documents the OSC 7 source.
apps/desktop/src/renderer/stores/tabs/types.ts (1)
58-58: LGTM!The method signature correctly matches the implementation and aligns with the
Pane.cwdtype definition.apps/desktop/src/renderer/stores/tabs/store.ts (1)
441-450: Implementation follows established patterns.The guarded update pattern is consistent with
markPaneAsUsedandsetNeedsAttention. However, since the store usespersistmiddleware, thecwdvalue will be persisted across sessions. Consider whether stale cwd paths after app restart could cause issues for DirectoryNavigator.apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsx (1)
130-155: LGTM!The
renderToolbarintegration cleanly separates the DirectoryNavigator (left) from pane actions (right). The emptytitle=""correctly defers to the custom toolbar. Thepane.cwdmay beundefinedinitially, but DirectoryNavigator handles this gracefully by showing "Terminal" as the fallback label.apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx (3)
70-73: LGTM!The effect correctly synchronizes local
terminalCwdstate to the pane store. Dependencies are accurate.
75-85: LGTM!The
useCallbackwith ref pattern correctly avoids stale closures in the main effect while allowing the cwd parser to be called from multiple code paths.
226-233: Good: Initial scrollback is parsed for cwd.Parsing the initial scrollback for OSC 7 sequences ensures the cwd is populated even when reattaching to an existing terminal session.
packages/ui/src/components/popover.tsx (5)
1-4: LGTM!Imports are clean and appropriate for a shadcn/ui-style Popover wrapper.
6-10: LGTM!Clean wrapper component following shadcn/ui conventions.
12-16: LGTM!Clean wrapper component following shadcn/ui conventions.
40-44: LGTM!Clean wrapper component following shadcn/ui conventions.
46-46: LGTM!Export statement is clean and complete.
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/DirectoryNavigator.tsx (7)
1-4: LGTM!Imports are clean and follow the coding guidelines for tRPC usage and path aliases.
6-9: LGTM!Interface is well-defined with appropriate types.
11-29: LGTM!Good use of conditional query enabling to avoid unnecessary backend calls. The state management is clean and follows the guideline to prefer local state over effects.
54-92: LGTM!The path manipulation logic is well-structured. The special handling for home directory paths (showing
~) provides a better user experience. Edge cases like root path are handled correctly.
94-107: LGTM!Good UX pattern to show a non-interactive state when the current working directory hasn't been confirmed yet via OSC-7.
127-127: Consider accessibility impact of preventing auto-focus.Preventing auto-focus with
onOpenAutoFocusmay impact keyboard navigation users. Verify that this is intentional and doesn't break the keyboard accessibility flow for directory navigation.If this is meant to prevent focus stealing while the user is typing in the terminal, consider documenting this decision or exploring alternative solutions that maintain keyboard accessibility.
113-207: LGTM!The popover UI provides an intuitive directory navigation experience with breadcrumbs, directory listing, and clear actions. The UX patterns (hover states, separate "cd" actions, "Navigate here" button) are well thought out.
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx (1)
44-85: Avoid pushingcwd=nullinto the pane store on initial mount (can clobber existing pane cwd).
updatePaneCwd(paneId, terminalCwd, cwdConfirmed)runs even whenterminalCwdis stillnull(before the seeding effect sets it). If the pane already had a cwd (e.g., from a prior attach), this can clear it.Suggested tweak:
useEffect(() => { - updatePaneCwd(paneId, terminalCwd, cwdConfirmed); + if (terminalCwd === null) return; + updatePaneCwd(paneId, terminalCwd, cwdConfirmed); }, [terminalCwd, cwdConfirmed, paneId, updatePaneCwd]);
♻️ Duplicate comments (1)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/DirectoryNavigator.tsx (1)
44-54: Don’t close the popover / clearbrowsePathwhenwriteMutationfails.This is the same issue previously flagged:
writeMutation.mutate(...)has noonSuccess/onError, so the UI closes even if the write fails.const handleNavigateToDir = useCallback( (path: string) => { - writeMutation.mutate({ - paneId, - data: `cd ${shellEscape(path)}\n`, - }); - setIsOpen(false); - setBrowsePath(null); + writeMutation.mutate( + { paneId, data: `cd ${shellEscape(path)}\n` }, + { + onSuccess: () => { + setIsOpen(false); + setBrowsePath(null); + }, + onError: (error) => { + console.error("Failed to navigate to directory:", error); + // TODO: show toast + }, + }, + ); }, [paneId, writeMutation], );
🧹 Nitpick comments (1)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx (1)
87-99:updateCwdRefindirection: please sanity-check it’s needed and won’t hide dependency bugs.Using a ref to call
updateCwdFromDatafrom inside the big terminal setup effect avoids adding it to the dependency list, but also makes it easier to miss future changes (e.g., ifupdateCwdFromDatastarts depending on props/state). If you keep the ref pattern, I’d at least add a brief comment noting it must remain dependency-free (as it is today).Also applies to: 220-247
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsx(2 hunks)apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/DirectoryNavigator.tsx(1 hunks)apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx(9 hunks)apps/desktop/src/renderer/stores/tabs/store.ts(1 hunks)apps/desktop/src/renderer/stores/tabs/types.ts(1 hunks)apps/desktop/src/shared/tabs-types.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- apps/desktop/src/shared/tabs-types.ts
- apps/desktop/src/renderer/stores/tabs/store.ts
- apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsx
- apps/desktop/src/renderer/stores/tabs/types.ts
🧰 Additional context used
📓 Path-based instructions (6)
apps/desktop/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)
For Electron interprocess communication, ALWAYS use tRPC as defined in
src/lib/trpc
Files:
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/DirectoryNavigator.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
apps/desktop/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)
apps/desktop/**/*.{ts,tsx}: Please use alias as defined intsconfig.jsonwhen possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary
Files:
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/DirectoryNavigator.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
**/*.{ts,tsx,js,jsx,json}
📄 CodeRabbit inference engine (AGENTS.md)
Use Biome for code formatting and linting, running at root level for speed
Files:
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/DirectoryNavigator.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Avoid
anytype and prioritize type safety in TypeScript code
Files:
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/DirectoryNavigator.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
**/components/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/components/**/*.{ts,tsx}: Structure project folders as one folder per component with PascalCase naming (ComponentName/ComponentName.tsx + index.ts barrel export)
Co-locate component dependencies (utils, hooks, constants, config, tests, stories) next to the file using them
Use one component per file (no multi-component files)
Files:
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/DirectoryNavigator.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
apps/desktop/src/renderer/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Call IPC methods from renderer process using window.ipcRenderer.invoke with type-safe object parameters
Files:
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/DirectoryNavigator.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
🧬 Code graph analysis (1)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx (1)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/parseCwd.ts (1)
parseCwd(21-36)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Deploy API
- GitHub Check: Deploy Admin
- GitHub Check: Deploy Docs
- GitHub Check: Deploy Web
- GitHub Check: Deploy Marketing
- GitHub Check: Build
🔇 Additional comments (3)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx (2)
143-146: CWD parsing on streamed data and queued data looks consistent.Updating cwd on both live stream chunks and flushed pending events prevents missing OSC-7 updates during attach/startup.
Also applies to: 227-230
239-246: OSC-7 parsing correctly extracts the latest sequence. TheparseCwd()implementation iterates through all OSC-7 sequences in the scrollback and returns the last (most recent) one (seeparseCwd.tsline 19-35), which correctly reflects the current prompt's working directory per shell emission patterns. No changes needed.apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/DirectoryNavigator.tsx (1)
66-69: [Rewritten comment]
[Classification tag]
| > | ||
| {buttonLabel} | ||
| </span> | ||
| </button> | ||
| </PopoverTrigger> | ||
| <PopoverContent | ||
| align="start" | ||
| className="w-72 p-0" | ||
| onOpenAutoFocus={(e: Event) => e.preventDefault()} | ||
| > | ||
| {/* Breadcrumb navigation */} | ||
| <div className="flex items-center gap-0.5 border-b border-border px-2 py-1.5 overflow-x-auto hide-scrollbar"> | ||
| {pathSegments.map((segment, idx) => ( | ||
| <div key={segment.path} className="flex items-center shrink-0"> | ||
| {idx > 0 && ( | ||
| <HiChevronRight className="size-3 text-muted-foreground/50 mx-0.5" /> | ||
| )} | ||
| <button | ||
| type="button" | ||
| onClick={() => handleBrowseDir(segment.path)} | ||
| className="text-xs text-muted-foreground hover:text-foreground transition-colors px-1 py-0.5 rounded hover:bg-accent/50" | ||
| > | ||
| {segment.name} | ||
| </button> | ||
| </div> | ||
| ))} | ||
| </div> | ||
|
|
||
| {/* Directory list */} | ||
| <div className="max-h-64 overflow-y-auto"> | ||
| {/* Parent directory */} | ||
| {directoryData?.parentPath && ( | ||
| <button | ||
| type="button" | ||
| onClick={handleNavigateUp} | ||
| className="flex w-full items-center gap-2 px-2 py-1.5 text-sm hover:bg-accent/50 transition-colors" | ||
| > | ||
| <HiFolderOpen className="size-4 text-muted-foreground" /> | ||
| <span className="text-muted-foreground">..</span> | ||
| </button> | ||
| )} | ||
|
|
||
| {isLoading ? ( | ||
| <div className="px-2 py-3 text-sm text-muted-foreground text-center"> | ||
| Loading... | ||
| </div> | ||
| ) : directories.length === 0 ? ( | ||
| <div className="px-2 py-3 text-sm text-muted-foreground text-center"> | ||
| No subdirectories | ||
| </div> | ||
| ) : ( | ||
| directories.map((item) => ( | ||
| <div key={item.path} className="flex items-center group"> | ||
| <button | ||
| type="button" | ||
| onClick={() => handleBrowseDir(item.path)} | ||
| className="flex flex-1 min-w-0 items-center gap-2 px-2 py-1.5 text-sm hover:bg-accent/50 transition-colors" | ||
| > | ||
| <HiFolder className="size-4 shrink-0 text-muted-foreground" /> | ||
| <span className="truncate">{item.name}</span> | ||
| </button> | ||
| <button | ||
| type="button" | ||
| onClick={() => handleNavigateToDir(item.path)} | ||
| className="px-2 py-1.5 text-xs text-muted-foreground hover:text-foreground opacity-0 group-hover:opacity-100 transition-opacity" | ||
| title="Navigate here" | ||
| > | ||
| cd | ||
| </button> | ||
| </div> | ||
| )) | ||
| )} | ||
| </div> | ||
|
|
||
| {/* Navigate to current browse path */} | ||
| {browsePath && browsePath !== currentCwd && ( | ||
| <div className="border-t border-border p-2"> | ||
| <button | ||
| type="button" | ||
| onClick={() => handleNavigateToDir(browsePath)} | ||
| className="w-full rounded bg-primary/10 px-2 py-1.5 text-sm text-primary hover:bg-primary/20 transition-colors" | ||
| > | ||
| Navigate here | ||
| </button> | ||
| </div> | ||
| )} | ||
| </PopoverContent> | ||
| </Popover> | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * Escape a path for safe use in shell commands | ||
| */ | ||
| function shellEscape(path: string): string { | ||
| if (/[^a-zA-Z0-9._\-/~]/.test(path)) { | ||
| return `'${path.replace(/'/g, "'\\''")}'`; | ||
| } | ||
| return path; | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Component folder structure doesn’t match repo guidelines (one folder per component + barrel export).
Per **/components/**/*.{ts,tsx} guidelines: please move to .../Terminal/DirectoryNavigator/DirectoryNavigator.tsx and add an index.ts barrel export, then update imports accordingly. As per coding guidelines, ...
Description
Related Issues
Type of Change
Testing
Screenshots (if applicable)
Additional Notes
Summary by CodeRabbit
Release Notes
New Features
UI Updates
✏️ Tip: You can customize this high-level summary in your review settings.