Skip to content

feat(tui): add interactive plan mode and fix compilation - #639

Closed
euxaristia wants to merge 1 commit into
Gitlawb:mainfrom
euxaristia:feat/tui-plan-mode
Closed

feat(tui): add interactive plan mode and fix compilation#639
euxaristia wants to merge 1 commit into
Gitlawb:mainfrom
euxaristia:feat/tui-plan-mode

Conversation

@euxaristia

@euxaristia euxaristia commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

This PR adds interactive, read-only plan mode toggled via /plan in the TUI, allowing the user to view, open, and edit the plan file, and fixes plan command compilation issues (migrating editor spawning to tea.ExecProcess and correcting signature check of planmode.PlanFilePath).

Summary by CodeRabbit

  • New Features

    • Added a read-only planning mode for reviewing and shaping plans without executing changes.
    • Added /plan support for opening the current plan in $VISUAL or $EDITOR.
    • Plan views now prioritize saved session plans and provide clearer fallback messages when no plan is available.
  • Bug Fixes

    • Improved tool access checks and error messages when tools are unavailable in planning modes.

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Adds PermissionModePlan with read-only tool advertisement and mode-specific execution errors. The TUI now routes /plan through plan handling, reads persisted plans when available, falls back to update_plan, and supports editing plans through $VISUAL or $EDITOR.

Changes

Plan mode and TUI plan editing

Layer / File(s) Summary
Plan permission contract and tool gating
internal/agent/types.go, internal/agent/loop.go
Adds the plan permission mode, advertises only planning and permitted read-only tools, and returns plan-specific denial errors for hidden tools.
TUI plan command and editor flow
internal/tui/model.go, internal/tui/plan_command.go, internal/tui/run.go
Routes /plan through plan handling, stores the Bubble Tea program for suspend/resume behavior, prefers persisted plan files, falls back to CurrentPlan(), and opens plans with $VISUAL or $EDITOR.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • Gitlawb/zero#113: Modifies tool advertisement and execution gating for another permission mode.
  • Gitlawb/zero#313: Adds permission-mode branches and constants in the same agent pipeline.
  • Gitlawb/zero#322: Updates the tool-execution flow in internal/agent/loop.go.

Suggested reviewers: gnanam1990, Vasanthdev2004, anandh8x

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: an interactive plan mode in the TUI plus a compilation fix.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 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 `@internal/tui/plan_command.go`:
- Around line 50-53: Update the bare `/plan` handling in the branch checking
`m.permissionMode == agent.PermissionModePlan` so it resets `m.permissionMode`
to `agent.PermissionModeAuto` before appending the current plan, preserving the
documented toggle behavior.
- Line 12: The TUI imports an unavailable planmode package, preventing
compilation. In internal/tui/plan_command.go, correct the import to the existing
package path or restore the internal/planmode package with PlanFilePath,
ReadPlan, and WritePlan implementations matching the command’s usage.

In `@internal/tui/run.go`:
- Line 60: Initialize the model’s program reference before constructing the
Bubble Tea program: update the setup around initialModel.program and
tea.NewProgram so the model receives a non-nil program when it starts, or remove
the under-test guard and rely on the returned tea.ExecProcess 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

Run ID: 352feb84-b16b-454f-999a-7e857405bda9

📥 Commits

Reviewing files that changed from the base of the PR and between 1af5882 and cba508c.

📒 Files selected for processing (5)
  • internal/agent/loop.go
  • internal/agent/types.go
  • internal/tui/model.go
  • internal/tui/plan_command.go
  • internal/tui/run.go

tea "charm.land/bubbletea/v2"

"github.com/Gitlawb/zero/internal/agent"
"github.com/Gitlawb/zero/internal/planmode"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔴 Critical | 🏗️ Heavy lift

Restore the missing planmode package or correct this import.

Current checks fail because github.com/Gitlawb/zero/internal/planmode is not provided by the module. This blocks compilation of the TUI; commit the package implementing PlanFilePath, ReadPlan, and WritePlan, or import the existing package path.

🧰 Tools
🪛 GitHub Check: Security & code health

[failure] 12-12:
could not import github.com/Gitlawb/zero/internal/planmode (invalid package name: "")


[failure] 12-12:
no required module provides package github.com/Gitlawb/zero/internal/planmode; to add it:

🤖 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 `@internal/tui/plan_command.go` at line 12, The TUI imports an unavailable
planmode package, preventing compilation. In internal/tui/plan_command.go,
correct the import to the existing package path or restore the internal/planmode
package with PlanFilePath, ReadPlan, and WritePlan implementations matching the
command’s usage.

Source: Linters/SAST tools

Comment on lines +50 to +53
// No subcommand: toggle plan mode, then surface the current plan.
if m.permissionMode == agent.PermissionModePlan {
m.transcript = reduceTranscript(m.transcript, transcriptAction{kind: actionAppendSystem, text: m.planText()})
return m, nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make bare /plan actually toggle plan mode.

When plan mode is already active, this branch only displays the plan and never exits the mode. That conflicts with the documented /plan toggle behavior and the PR objective. Reset permissionMode to PermissionModeAuto here, or revise the command contract to make /plan view-only.

🤖 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 `@internal/tui/plan_command.go` around lines 50 - 53, Update the bare `/plan`
handling in the branch checking `m.permissionMode == agent.PermissionModePlan`
so it resets `m.permissionMode` to `agent.PermissionModeAuto` before appending
the current plan, preserving the documented toggle behavior.

Comment thread internal/tui/run.go
initialModel.mouseCapture = true
}
program = tea.NewProgram(initialModel, programOpts...)
initialModel.program = program

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu

rg -n -C 3 'tea\.NewProgram\(|initialModel\.program|m\.program|tea\.ExecProcess' internal/tui

Repository: Gitlawb/zero

Length of output: 1613


Initialize program before calling tea.NewProgram
initialModel.program = program happens after tea.NewProgram(initialModel, ...), so the running model still sees m.program == nil. That forces /plan open down the “under test” path and skips launching the editor. Set the field before handing the model to Bubble Tea, or remove the guard and rely on the returned tea.ExecProcess command.

🤖 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 `@internal/tui/run.go` at line 60, Initialize the model’s program reference
before constructing the Bubble Tea program: update the setup around
initialModel.program and tea.NewProgram so the model receives a non-nil program
when it starts, or remove the under-test guard and rely on the returned
tea.ExecProcess command.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant