feat(cli-component): Enhance CLI interface with new components and ESLint configuration#3
Conversation
|
Warning Review limit reached
More reviews will be available in 33 minutes. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, 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 include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThis PR introduces a command menu system to the CLI application, enabling users to invoke slash commands (e.g., ChangesCommand Menu Feature
Sequence DiagramssequenceDiagram
participant User
participant useCommandMenu
participant getFilteredCommands
participant CommandMenu as CommandMenu UI
User->>useCommandMenu: Type text starting with /
useCommandMenu->>getFilteredCommands: Extract query from /text
getFilteredCommands-->>useCommandMenu: Return filtered commands
useCommandMenu->>useCommandMenu: Show menu, reset selection to 0
User->>useCommandMenu: Press Up/Down arrow
useCommandMenu->>useCommandMenu: Update selectedIndex, scroll viewport
User->>useCommandMenu: Press Enter on command
useCommandMenu->>useCommandMenu: Resolve command at selectedIndex, close menu
sequenceDiagram
participant User
participant InputBar
participant CommandMenu
participant Command as Command Action
participant Renderer
User->>InputBar: Press Enter on selected command
InputBar->>CommandMenu: Resolve selected command
alt Command has action
InputBar->>Command: Call action(ctx) with exit callback
Command->>Renderer: ctx.exit() destroys renderer
else Command is value
InputBar->>InputBar: Insert command value + space into textarea
end
InputBar->>InputBar: Close command menu
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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: 3
🧹 Nitpick comments (3)
packages/cli/src/components/command-menu/use-command-menu.ts (1)
37-37: ⚡ Quick winFix comment typos.
Minor typos in comments:
- Line 37: "caracter" should be "character"
- Line 49: "caller, handles" should be "caller handles" (remove comma)
📝 Proposed fixes
- // jump back to top of list when the user types a new caracter + // jump back to top of list when the user types a new character- // resolve a command at a specific index (returns the command, caller, handles execution) + // resolve a command at a specific index (returns the command; caller handles execution)Also applies to: 49-49
🤖 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 `@packages/cli/src/components/command-menu/use-command-menu.ts` at line 37, In useCommandMenu update the inline comments to fix typos: change "caracter" to "character" in the comment about jumping back to the top of the list, and remove the stray comma so "caller, handles" becomes "caller handles"; locate these comments inside the useCommandMenu implementation and edit the comment text accordingly.packages/cli/src/components/command-menu/index.tsx (1)
19-26: ⚡ Quick winSingle source of truth for the filtered list.
CommandMenurecomputesgetFilteredCommands(query)even thoughuseCommandMenualready derivesfilteredCommandsfrom the samecommandQueryand uses that list to driveselectedIndex, keyboard navigation, andresolveCommand. The two lists are equivalent today only becausequery === commandQuery; any future change to filtering inputs (or passing a differentquery) would silently desync the highlighted/executed index from what is rendered. Consider passing the already-computed list down as a prop instead of refiltering here.🤖 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 `@packages/cli/src/components/command-menu/index.tsx` around lines 19 - 26, CommandMenu is re-running getFilteredCommands(query) despite useCommandMenu already providing the canonical filtered list (filteredCommands derived from commandQuery), which can cause desyncs; update the component to accept the precomputed filtered list as a prop (e.g. add filteredCommands to CommandMenuProps) and use that prop instead of calling getFilteredCommands inside CommandMenu, and ensure callers (the hook or parent that uses useCommandMenu) pass useCommandMenu.filteredCommands so selectedIndex, keyboard navigation, and resolveCommand remain in sync with the rendered list.packages/cli/src/components/input-bar.tsx (1)
100-121: ⚡ Quick winMove
onSubmitRef.currentassignment out of the render phase.React guidance discourages mutating refs during render (except lazy init), since concurrent rendering can make ref mutations unpredictable; update
onSubmitRef.currentfrom an effect (or useuseEffectEventon React 19.2+) so the textarea handler always points at the committed/latest closure.♻️ Move assignment into an effect
- onSubmitRef.current = () => { - if (disabled) return - - if (showCommandMenu) { - const command = resolveCommand(selectedIndex) - handleCommand(command) - return - } - - handleSubmit() - } + useEffect(() => { + onSubmitRef.current = () => { + if (disabled) return + + if (showCommandMenu) { + const command = resolveCommand(selectedIndex) + handleCommand(command) + return + } + + handleSubmit() + } + }, [disabled, showCommandMenu, selectedIndex, resolveCommand, handleCommand, handleSubmit])🤖 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 `@packages/cli/src/components/input-bar.tsx` around lines 100 - 121, The current code sets onSubmitRef.current during render which mutates a ref in the render phase; move the assignment into an effect so the ref update happens after commit (or use useEffectEvent on React 19.2+). Specifically, stop assigning onSubmitRef.current = () => { ... } during render and instead place that whole assignment inside a useEffect (or create an effect-safe event via useEffectEvent) so the textarea.onSubmit handler (wired in the existing useEffect that reads textareRef.current) always calls the latest closure; make sure the effect captures disabled, showCommandMenu, selectedIndex, resolveCommand, handleCommand and handleSubmit dependencies or uses refs for stable access.
🤖 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 `@packages/cli/src/components/command-menu/use-command-menu.ts`:
- Around line 50-53: The resolveCommand function uses the comma operator so
setShowCommandMenu(false) only runs when filteredCommands[index] is truthy;
change it to always close the menu before returning the command. Update
resolveCommand to call setShowCommandMenu(false) unconditionally (e.g., as a
separate statement) and then return filteredCommands[index] (which may be
undefined). Ensure you modify the resolveCommand function (referenced by name)
and keep filteredCommands usage intact.
In `@packages/cli/src/components/input-bar.tsx`:
- Around line 74-80: The call to command.action currently ignores returned
promises, causing unhandled rejections; update the invocation of command.action
so you capture its return value and handle async rejections: call
command.action({ exit: () => renderer.destroy() }), store the result, and if
it's a Promise attach .catch(err => { /* log and surface error to user (e.g.
console.error or render a message in the UI) */ }) (or await it if the
surrounding function can be made async), ensuring renderer.destroy() still runs
when exit() is invoked; keep textarea.insertText when command.action is absent.
In `@packages/cli/src/index.tsx`:
- Around line 26-29: The CLI disables Ctrl+C by setting exitOnCtrlC: false on
createCliRenderer, which prevents the universal interrupt from cleaning up;
either set exitOnCtrlC: true when constructing the renderer (in the
createCliRenderer call) or add a process SIGINT/SIGTERM handler that always
calls renderer.destroy() (ensure the handler references the same renderer
instance created in packages/cli/src/index.tsx and mirrors the cleanup already
invoked by ctx.exit() -> renderer.destroy() in input-bar.tsx).
---
Nitpick comments:
In `@packages/cli/src/components/command-menu/index.tsx`:
- Around line 19-26: CommandMenu is re-running getFilteredCommands(query)
despite useCommandMenu already providing the canonical filtered list
(filteredCommands derived from commandQuery), which can cause desyncs; update
the component to accept the precomputed filtered list as a prop (e.g. add
filteredCommands to CommandMenuProps) and use that prop instead of calling
getFilteredCommands inside CommandMenu, and ensure callers (the hook or parent
that uses useCommandMenu) pass useCommandMenu.filteredCommands so selectedIndex,
keyboard navigation, and resolveCommand remain in sync with the rendered list.
In `@packages/cli/src/components/command-menu/use-command-menu.ts`:
- Line 37: In useCommandMenu update the inline comments to fix typos: change
"caracter" to "character" in the comment about jumping back to the top of the
list, and remove the stray comma so "caller, handles" becomes "caller handles";
locate these comments inside the useCommandMenu implementation and edit the
comment text accordingly.
In `@packages/cli/src/components/input-bar.tsx`:
- Around line 100-121: The current code sets onSubmitRef.current during render
which mutates a ref in the render phase; move the assignment into an effect so
the ref update happens after commit (or use useEffectEvent on React 19.2+).
Specifically, stop assigning onSubmitRef.current = () => { ... } during render
and instead place that whole assignment inside a useEffect (or create an
effect-safe event via useEffectEvent) so the textarea.onSubmit handler (wired in
the existing useEffect that reads textareRef.current) always calls the latest
closure; make sure the effect captures disabled, showCommandMenu, selectedIndex,
resolveCommand, handleCommand and handleSubmit dependencies or uses refs for
stable access.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 7f21eb59-61de-4fef-905c-34c6c4ddeec4
📒 Files selected for processing (12)
eslint.config.mjspackages/cli/package.jsonpackages/cli/src/components/border.tsxpackages/cli/src/components/command-menu/commands.tsxpackages/cli/src/components/command-menu/filter-commands.tspackages/cli/src/components/command-menu/index.tsxpackages/cli/src/components/command-menu/types.tspackages/cli/src/components/command-menu/use-command-menu.tspackages/cli/src/components/header.tsxpackages/cli/src/components/input-bar.tsxpackages/cli/src/components/status-bar.tsxpackages/cli/src/index.tsx
This pull request introduces a new interactive command menu to the CLI, along with several UI improvements and supporting utilities. The main changes include adding the command menu component and its supporting logic, updating the input bar to integrate command selection, and enhancing the CLI's overall appearance with a header and status bar. There are also updates to ESLint configuration and type dependencies to support React code.
Command Menu Feature and UI Enhancements:
CommandMenucomponent, command definitions, filtering logic, keyboard navigation, and type definitions. This allows users to trigger commands via the input bar with/and navigate/execute them interactively. (packages/cli/src/components/command-menu/commands.tsx,filter-commands.ts,index.tsx,types.ts,use-command-menu.ts) [1] [2] [3] [4] [5]InputBarcomponent to integrate the command menu, handle command execution, and manage input state, including support for keyboard navigation and command actions. (packages/cli/src/components/input-bar.tsx)Headercomponent with stylized ASCII art and aStatusBarcomponent for improved CLI appearance. (packages/cli/src/components/header.tsx,status-bar.tsx) [1] [2]EmptyBorder,SplitBorder) for consistent UI styling. (packages/cli/src/components/border.tsx)packages/cli/src/index.tsx)Tooling and Dependency Updates:
@types/reacttodevDependenciesto support React type checking in the CLI package. (packages/cli/package.json)eslint-plugin-react-hooksplugin and enabled rules for React hooks best practices. (eslint.config.mjs) [1] [2] [3]Summary by CodeRabbit
New Features
/new,/agents,/models,/sessions,/theme,/login,/logout,/upgrade,/usage,/exit)Chores