Skip to content

feat(cli): allow entering edit mode from CLI#12716

Open
foxfirecodes wants to merge 2 commits intogitbutlerapp:masterfrom
foxfirecodes:lew/cli-edit-mode
Open

feat(cli): allow entering edit mode from CLI#12716
foxfirecodes wants to merge 2 commits intogitbutlerapp:masterfrom
foxfirecodes:lew/cli-edit-mode

Conversation

@foxfirecodes
Copy link
Contributor

@foxfirecodes foxfirecodes commented Mar 7, 2026

this PR was written by Claude Code with assistance and review from myself

🧢 Changes

this PR introduces a new edit-mode subcommand that lets you enter edit mode via the CLI. this is meant to mirror the current functionality in the GUI where you can right click on a commit and click "Edit commit" to enter edit mode.

☕️ Reasoning

while i do enjoy using the GUI, i would like to be able to allow my AI agents to use edit mode directly, and sometimes its just easier to use a CLI. seeing as the functionality was all there and simply missing a dedicated command to interact with it, i took the opportunity to implement this.

the reason why i named this edit-mode instead of edit is to avoid conflicts with the existing hidden edit subcommand

the structure of both the code & the output is meant to align with what already exists in the resolve mode command. i did not extract shared code between the resolve and edit-mode commands but if you want me to do that i can do so, most of the code is basically the same. that being said the actual amount of code involved is pretty small to begin with.

there is a small frontend change here as well to solve what seemed to me to be a race condition. if you exit edit mode (or resolve mode) from the CLI, sometimes the app would show errors like this:

errors

it seems that the app would sometimes receive the worktree_changes event before it had unmounted the EditMode UI due to the mode changing, resulting in the error message above. im open to suggestions on a better solution, but this seems like a reasonable approach for a simple race condition like this

Copilot AI review requested due to automatic review settings March 7, 2026 00:09
@vercel
Copy link

vercel bot commented Mar 7, 2026

@foxfirecodes is attempting to deploy a commit to the GitButler Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new legacy-only but edit-mode CLI subcommand to enter/inspect/finish/cancel edit mode (mirroring the desktop UI “Edit commit” flow), plus a small desktop-side mitigation for an edit-mode exit race.

Changes:

  • Introduces edit-mode CLI command with status|finish|cancel [--force], wiring it through args parsing, command dispatch, and metrics.
  • Updates legacy status to show edit-mode status and delegate to resolve status when the edited commit is conflicted.
  • Adds CLI tests + updates CLI reference docs; adds a frontend guard against a worktree-changes/edit-mode race.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
crates/but/tests/but/command/mod.rs Registers new legacy edit_mode test module.
crates/but/tests/but/command/edit_mode.rs Adds CLI tests covering enter/status/finish/cancel flows.
crates/but/src/utils/metrics.rs Emits metrics event for the new EditMode subcommand.
crates/but/src/lib.rs Dispatches Subcommands::EditMode to legacy handler.
crates/but/src/command/legacy/status/mod.rs Improves edit-mode status handling (fallback to resolve status if conflicted).
crates/but/src/command/legacy/resolve.rs Exposes conflict helpers for reuse by edit-mode flow.
crates/but/src/command/legacy/mod.rs Exposes new legacy edit_mode module.
crates/but/src/command/legacy/edit_mode.rs Implements the but edit-mode command behavior and output.
crates/but/src/command/help.rs Adds edit-mode to grouped help list (shown only if subcommand exists).
crates/but/src/args/mod.rs Adds EditMode clap subcommand + wires args module.
crates/but/src/args/metrics.rs Adds EditMode to metrics command-name enum.
crates/but/src/args/edit_mode.rs Defines edit-mode subcommands and flags.
crates/but/skill/references/reference.md Documents but edit-mode usage + workflow.
apps/desktop/src/lib/mode/modeService.ts Catches a specific edit-mode exit race during worktree change event handling.

Comment on lines +148 to +152
// listener was unsubscribed. Silently ignore that specific race.
const message = error instanceof Error ? error.message : String(error);
if (!message.includes("Expected to be in edit mode")) {
throw error;
}
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

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

This error handling relies on a substring match ("Expected to be in edit mode") to detect the race. That’s brittle to future backend error-message changes and can mask legitimate failures if the message ever changes format. Consider switching to a structured error signal (e.g. backend error code/type) or proactively checking operating_mode before invoking; at minimum, when this condition is hit, set finished = true and/or call unsubscribe() immediately so repeated worktree_changes events don’t keep triggering failing invokes.

Suggested change
// listener was unsubscribed. Silently ignore that specific race.
const message = error instanceof Error ? error.message : String(error);
if (!message.includes("Expected to be in edit mode")) {
throw error;
}
// listener was unsubscribed. Silently ignore that specific race,
// and stop listening so we don't keep invoking a failing command.
const message = error instanceof Error ? error.message : String(error);
if (message.includes("Expected to be in edit mode")) {
finished = true;
unsubscribe();
return;
}
throw error;

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings March 7, 2026 00:17
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings March 7, 2026 01:03
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated no new comments.

@Byron Byron added the CLI The command-line program `but` label Mar 7, 2026
@Byron
Copy link
Collaborator

Byron commented Mar 7, 2026

Thanks a lot for contributing!

Could you squash commits to two maybe, one for the CLI changes, and one for the frontend fix?
Then it would probably also be good to get feedback from @krlvi on the CLI API side of things. It feels like we want to find a more succinct name for all the new interaction.

@codex review

Copy link
Contributor

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 237d3b4564

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +149 to +150
const message = error instanceof Error ? error.message : String(error);
if (!message.includes("Expected to be in edit mode")) {
Copy link
Contributor

Choose a reason for hiding this comment

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

P2 Badge Read object error messages before race-condition filtering

This filter only inspects error.message when the thrown value is an Error instance, but our backend invoke path can throw plain object-shaped errors (e.g. ReduxError), in which case String(error) becomes "[object Object]". That means the intended "Expected to be in edit mode" race gets rethrown instead of ignored, so the UI still surfaces the same error when edit mode is exited from another client. Please extract message from object errors before falling back to String(error).

Useful? React with 👍 / 👎.

@foxfirecodes foxfirecodes changed the title allow entering edit mode from CLI feat(cli): allow entering edit mode from CLI Mar 7, 2026
Copilot AI review requested due to automatic review settings March 7, 2026 04:37
@foxfirecodes
Copy link
Contributor Author

foxfirecodes commented Mar 7, 2026

squashed and updated the frontend to use parseError to be more resilient! also cleaned up some logic in the status command. im pretty happy w where this is at, i do agree that there may be a more succinct name we could use for this interaction than edit-mode. i would use but edit if it wasnt already a thing

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.

let mode = gitbutler_operating_modes::operating_mode(ctx);
if let gitbutler_operating_modes::OperatingMode::Edit(_metadata) = mode {
if let gitbutler_operating_modes::OperatingMode::Edit(metadata) = mode {
// In edit mode, show the conflict resolution status
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

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

The comment here says edit mode always shows the conflict resolution status, but show_edit_mode_status() now conditionally shows either resolve status (for conflicted commits) or edit-mode status (for non-conflicted commits). Updating the comment would prevent confusion when reading this early-return path.

Suggested change
// In edit mode, show the conflict resolution status
// In edit mode, show either conflict resolution status (for conflicted commits)
// or the general edit-mode status for non-conflicted commits.

Copilot uses AI. Check for mistakes.

fn current_branch_name(env: &Sandbox) -> anyhow::Result<String> {
let repo = env.open_repo()?;
repo.rev_parse_single("HEAD")
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

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

repo.rev_parse_single("HEAD")? is only used for its error side-effect, but its return value is ignored. Consider assigning it to _ (or removing it) so it’s clear this is an intentional validation step and avoids an “unused result” warning if warnings are tightened in tests.

Suggested change
repo.rev_parse_single("HEAD")
let _ = repo
.rev_parse_single("HEAD")

Copilot uses AI. Check for mistakes.
.assert()
.success()
.stderr_eq(str![""]);

Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

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

The new behavior where but status in edit mode shows edit-mode status (or resolve status for conflicted commits) isn’t exercised in these tests. Adding an assertion that plain but status succeeds after entering edit mode would help catch regressions in the status/operating-mode integration.

Suggested change
env.but("status")
.assert()
.success()
.stderr_eq(str![""]);

Copilot uses AI. Check for mistakes.
this is a new subcommand to allow you to enter and exit edit mode via
the CLI just like you can in the GUI
in certain situations it's possible for the desktop app to receive a
worktree_update event BEFORE EditMode has unmounted (and the listener
has been unsubscribed). this results in an eroneous error message about
expecting to be in edit mode
@Byron Byron requested a review from krlvi March 7, 2026 08:08
@Byron
Copy link
Collaborator

Byron commented Mar 7, 2026

Thanks a lot!

Then I'd think that @krlvi would be able to review this PR and/or give product-related directions.

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

Labels

CLI The command-line program `but`

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants