Skip to content

[WIP] feat(plan): support opening and modifying current plan in editor #20050

Closed
Adib234 wants to merge 1 commit into
mainfrom
adibakm/support-editing-files-editor
Closed

[WIP] feat(plan): support opening and modifying current plan in editor #20050
Adib234 wants to merge 1 commit into
mainfrom
adibakm/support-editing-files-editor

Conversation

@Adib234

@Adib234 Adib234 commented Feb 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Details

Related Issues

How to Validate

Pre-Merge Checklist

  • Updated relevant documentation and README (if needed)
  • Added/updated tests (if needed)
  • Noted breaking changes (if any)
  • Validated on required platforms/methods:
    • MacOS
      • npm run
      • npx
      • Docker
      • Podman
      • Seatbelt
    • Windows
      • npm run
      • npx
      • Docker
    • Linux
      • npm run
      • npx
      • Docker

@Adib234 Adib234 self-assigned this Feb 23, 2026
@Adib234 Adib234 requested a review from a team as a code owner February 23, 2026 18:06
@Adib234 Adib234 marked this pull request as draft February 23, 2026 18:06
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @Adib234, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly improves the user experience by allowing direct interaction with the plan file using external editors. It integrates a new command and keybinding to facilitate this, ensuring that any modifications made externally are reloaded and acknowledged within the CLI. This change provides greater control and flexibility for users to refine their plans before final approval, streamlining the development workflow.

Highlights

  • External Plan Editing: Introduced the ability for users to open and modify the current plan file in an external editor directly from the CLI, enhancing flexibility during the plan approval process.
  • New Command and Keybinding: Added a new command plan.openInEditor with a default keybinding of Ctrl+X to trigger the external editor functionality.
  • Dynamic UI Updates: The ExitPlanModeDialog now reloads the plan content after external editing and displays an 'extraFooterActions' shortcut for the editor.
  • IDE Integration and Fallback: The openFileInEditor utility supports integrated IDE diffing (if available) and falls back to external GUI or terminal editors, with improved handling for Vim/Neovim.
  • Plan Modification Tracking: The system now tracks whether the plan was modified by the user in an external editor, and this information is passed to onApprove and onFeedback callbacks, and reflected in the LLM content.
Changelog
  • packages/cli/src/config/keyBindings.ts
    • Added OPEN_PLAN_IN_EDITOR command to the Command enum.
    • Assigned Ctrl+X as the default keybinding for OPEN_PLAN_IN_EDITOR.
    • Provided a description for the OPEN_PLAN_IN_EDITOR command.
  • packages/cli/src/ui/components/AskUserDialog.tsx
    • Added extraFooterActions optional prop to AskUserDialogProps interface.
    • Passed extraFooterActions to the DialogFooter component.
  • packages/cli/src/ui/components/ExitPlanModeDialog.test.tsx
    • Imported openFileInEditor for testing external editor functionality.
    • Mocked openFileInEditor and IdeClient methods.
    • Updated onApprove and onFeedback calls to include the new planModified boolean parameter.
    • Added a new test case to verify opening the editor with Ctrl+X, reloading the plan, and submitting with planModified set to true.
  • packages/cli/src/ui/components/ExitPlanModeDialog.tsx
    • Imported useCallback, useMemo, coreEvents, openFileInEditor, IdeClient, debugLogger, isValidEditorType, useSettings, useKeypress, KeypressPriority, Command, and keyMatchers.
    • Updated ExitPlanModeDialogProps to include planModified in onApprove and onFeedback signatures.
    • Modified PlanContentState to include a reload function.
    • Refactored usePlanContent to manage plan content state with a nonce for reloading and exposed a reload function.
    • Added isModified state to track external plan modifications.
    • Implemented performOpenInEditor and handleOpenInEditor callbacks to open the plan in an external editor and reload if modified.
    • Implemented syncIde callback to resolve IDE diff status on approval or cancellation.
    • Integrated useKeypress to listen for the OPEN_PLAN_IN_EDITOR command (Ctrl+X) and trigger handleOpenInEditor.
    • Updated onSubmit and onCancel handlers to call syncIde and pass the isModified flag to onApprove and onFeedback.
    • Added extraFooterActions prop to AskUserDialog to display the 'Ctrl+X to open in editor' shortcut.
  • packages/cli/src/ui/components/snapshots/ExitPlanModeDialog.test.tsx.snap
    • Updated all snapshots to include 'Ctrl+X to open in editor' in the dialog footer.
  • packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx
    • Modified onApprove and onFeedback callbacks to ExitPlanModeDialog to pass the planModified boolean.
  • packages/cli/src/ui/components/shared/DialogFooter.tsx
    • Added extraActions optional string array prop to DialogFooterProps interface.
    • Incorporated extraActions into the displayed footer parts.
  • packages/core/src/tools/exit-plan-mode.test.ts
    • Added a test case to verify that the LLM content includes a 'Note: The user modified the plan file in an external editor.' when planModified is true.
  • packages/core/src/tools/exit-plan-mode.ts
    • Modified the llmContent generation for both approved and rejected plans to include a note if planModified is true.
  • packages/core/src/tools/tools.ts
    • Added an optional planModified boolean property to the ToolExitPlanModeConfirmationPayload interface.
  • packages/core/src/utils/editor.ts
    • Introduced OpenFileIdeClient and OpenFileInEditorOptions interfaces to decouple editor utility from IdeClient.
    • Exported isValidEditorType function.
    • Refactored hasValidEditorCommandAsync to use Promise.allSettled for more robust command existence checks.
    • Removed redundant execAsync declaration.
    • Added openFileInEditor function to handle opening files in external editors, supporting IDE integration with fallback to GUI or terminal editors.
    • Implemented specific handling for Vim/Neovim to prevent E138 errors by adding -i NONE.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-cli gemini-cli Bot added area/core Issues related to User Interface, OS Support, Core Functionality 🔒 maintainer only ⛔ Do not contribute. Internal roadmap item. labels Feb 23, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

The pull request introduces a useful feature for editing plans in an external editor. The implementation correctly handles both IDE-integrated diffs and external terminal/GUI editors. However, there are a few issues regarding UI state management and correctness of the modification detection that should be addressed to ensure a robust user experience and accurate feedback to the LLM.

Comment thread packages/cli/src/ui/components/ExitPlanModeDialog.tsx
Comment thread packages/cli/src/ui/components/ExitPlanModeDialog.tsx
Comment thread packages/cli/src/ui/components/ExitPlanModeDialog.tsx
Comment thread packages/cli/src/ui/components/ExitPlanModeDialog.tsx Outdated
Comment thread packages/core/src/utils/editor.ts Outdated
@Adib234

Adib234 commented Feb 23, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for working on this! I've reviewed the PR and have a few pieces of feedback, primarily regarding React state management and child process execution.

Blocking the Event Loop

In packages/core/src/utils/editor.ts, the fallback for terminal editors (when not using GUI spawn) uses spawnSync wrapped inside a Promise:

const result = spawnSync(command, args, {
  stdio: 'inherit',
  shell: process.platform === 'win32',
});

Even though this is inside a Promise, spawnSync is synchronous and will block the Node.js event loop completely while the external editor is open. This will cause the entire CLI UI to freeze and stall any background tasks. This should be refactored to use an asynchronous spawn with appropriate event listeners for the close and error events.

Bypassing spawnAsync Rule

The code imports spawn and spawnSync directly from node:child_process. The Gemini CLI Strict Development Rules explicitly state:

"Ensure all shell operations use spawnAsync from packages/core/src/utils/shell-utils.ts for consistent error handling and promise management."

Note: I realize that spawnAsync in shell-utils.ts is currently typed with SpawnOptionsWithoutStdio and tries to capture stdout/stderr, which makes it incompatible with interactive editors that require stdio: 'inherit'. If spawnAsync cannot be reasonably modified to support interactive stdio, you might need to use the native asynchronous spawn directly. Please avoid spawnSync at all costs. Consider adding a comment or expanding spawnAsync's capabilities if you do use native spawn.

Potential Unmounted Component State Update

In packages/cli/src/ui/components/ExitPlanModeDialog.tsx, within performOpenInEditor:

const result = await openFileInEditor(...)
if (result.modified) {
  setIsModified(true);
  planState.reload();
}

Because openFileInEditor can take a long time (the user is interacting with an editor), there is a risk that the ExitPlanModeDialog component unmounts before the promise resolves (e.g. if a CLI exit signal is received). Calling setIsModified or planState.reload on an unmounted component will result in a React state update warning. You should use an isMounted ref to verify the component is still mounted before applying these state updates.

@github-actions

github-actions Bot commented Feb 23, 2026

Copy link
Copy Markdown

Size Change: +6.68 kB (+0.03%)

Total Size: 25.8 MB

Filename Size Change
./bundle/gemini.js 25.3 MB +6.68 kB (+0.03%)
ℹ️ View Unchanged
Filename Size
./bundle/node_modules/@google/gemini-cli-devtools/dist/client/main.js 221 kB
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/_client-assets.js 227 kB
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/index.js 11.5 kB
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/types.js 132 B
./bundle/sandbox-macos-permissive-open.sb 890 B
./bundle/sandbox-macos-permissive-proxied.sb 1.31 kB
./bundle/sandbox-macos-restrictive-open.sb 3.36 kB
./bundle/sandbox-macos-restrictive-proxied.sb 3.56 kB
./bundle/sandbox-macos-strict-open.sb 4.82 kB
./bundle/sandbox-macos-strict-proxied.sb 5.02 kB

compressed-size-action

@Adib234

Adib234 commented Feb 23, 2026

Copy link
Copy Markdown
Contributor Author

/gemini review

Comment thread packages/core/src/utils/shell-utils.ts Fixed

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new feature allowing users to open the current plan in an external editor using the Ctrl + X keyboard shortcut. The changes involve updating keyboard shortcut documentation, defining a new OPEN_PLAN_IN_EDITOR command and its default key binding, and integrating this functionality into the ExitPlanModeDialog. The ExitPlanModeDialog now supports opening the plan file in an external editor (or IDE if configured), reloads the plan content if modified, and passes a planModified flag to the approval/feedback handlers. The UI's dialog footer has been enhanced to display this new shortcut. Additionally, the core editor utilities have been updated to support openFileInEditor with logic to detect file modifications and handle both GUI and terminal editors, and the exit-plan-mode tool now includes a note in the LLM content if the plan was modified by the user in an external editor.

@Adib234 Adib234 force-pushed the adibakm/support-editing-files-editor branch from 5c9c385 to 0a48828 Compare February 24, 2026 19:34
| Show warning when trying to move focus away from shell input. | `Tab (no Shift)` |
| Move focus from Gemini to the active shell. | `Tab (no Shift)` |
| Move focus from the shell back to Gemini. | `Shift + Tab` |
| Open the current plan in an external editor. | `Ctrl + X` |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@scidomino please advise on the shortcut here

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

is there a way for us to reuse packages/core/src/scheduler/tool-modifier.ts instead of duplicating?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/core Issues related to User Interface, OS Support, Core Functionality 🔒 maintainer only ⛔ Do not contribute. Internal roadmap item. size/l A large sized PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants