Skip to content

Plan Mode: read-only, iterative planning (Shift+Tab) + configurable planner - #4769

Closed
thomast8 wants to merge 1502 commits into
openai:mainfrom
thomast8:feature/plan-shortcut
Closed

Plan Mode: read-only, iterative planning (Shift+Tab) + configurable planner#4769
thomast8 wants to merge 1502 commits into
openai:mainfrom
thomast8:feature/plan-shortcut

Conversation

@thomast8

@thomast8 thomast8 commented Oct 5, 2025

Copy link
Copy Markdown

Closes #4118

What

  • Adds Plan Mode to the TUI so users can request a plan before making any changes.
  • While Plan Mode is on, Enter submits a read-only planning turn and keeps the composer in planning mode for iterative refinement.
  • Introduces a dedicated planner model/effort selection via /plan-model.
  • Renders update_plan tool calls as a checklist in the transcript.

Why

  • Addresses the need for a safe, dedicated planning phase that does not mutate the system until the user explicitly exits planning and asks to execute.
  • Keeps planning steps visible and editable, making it easy to converge on the right approach before running any commands or applying patches.

How (technical summary)

  • TUI – composer: adds plan_mode and a Shift+Tab (BackTab) toggle. Enter in plan mode calls a planning path instead of sending a normal turn. Composer remains in plan mode across submissions and is blocked while a task is running.
  • TUI – chat flow: request_plan_turn temporarily switches to a read-only sandbox and (optionally) a planner model/effort for the planning turn, then restores the prior context. It prompts the model to record a concise plan via update_plan.
  • Rendering: PlanUpdate events are displayed as a checkbox list (pending, in_progress, completed) with an optional explanation.
  • Config: adds/stores planner model and reasoning effort; exposes /plan-model to adjust them.
  • Docs & tests: README section on planning; unit tests cover toggling, persistence across submissions, and blocked entry during active tasks.

How to use (high level)

  • Toggle Plan Mode: press Shift+Tab in the composer.
  • Submit a plan request: type your goal and press Enter.
  • Iterate: refine and press Enter again; the model updates the plan (rendered in the transcript).
  • Choose planner: type /plan-model to pick a model and reasoning effort.
  • Implement: press Shift+Tab to exit Plan Mode and ask Codex to start with step 1.

Notes on contributing

  • I reviewed docs/contributing.md and kept the change focused with tests and docs updates. This PR links to and closes the tracked issue.

Verification steps

  • Build/run: cargo test -p codex-tui then codex.
  • In the CLI: Shift+Tab → type "Add dark mode toggle" → Enter → see a plan in the transcript. Shift+Tab to exit Plan Mode, then ask: "Start with step 1".
  • During planning turns, no file modifications or exec should occur; only plan updates should stream.

jif-oai and others added 30 commits September 18, 2025 16:27
Unify the animation in a single code and add the CTRL + . in the
onboarding
Only emit a task finished when the compaction comes from a `/compact`
<img width="931" height="438" alt="Screenshot 2025-09-16 at 4 25 19 PM"
src="https://github.com/user-attachments/assets/ccfb8df1-feaf-45b4-8f7f-56100de916d5"
/>
Fix some small references issue. No behavioural change. Just making the
code cleaner
openai#3850)

### Why Use `tokio::sync::Mutex`

`std::sync::Mutex` are not _async-aware_. As a result, they will block
the entire thread instead of just yielding the task. Furthermore they
can be poisoned which is not the case of `tokio` Mutex.
This allows the Tokio runtime to continue running other tasks while
waiting for the lock, preventing deadlocks and performance bottlenecks.

In general, this is preferred in async environment
Adds `/review` action in TUI

<img width="637" height="370" alt="Screenshot 2025-09-17 at 12 41 19 AM"
src="https://github.com/user-attachments/assets/b1979a6e-844a-4b97-ab20-107c185aec1d"
/>
…penai#3874)

Previous to this PR, both of these functions take a single `cwd`:


https://github.com/openai/codex/blob/71038381aa0f51aa62e1a2bcc7cbf26a05b141f3/codex-rs/core/src/seatbelt.rs#L19-L25


https://github.com/openai/codex/blob/71038381aa0f51aa62e1a2bcc7cbf26a05b141f3/codex-rs/core/src/landlock.rs#L16-L23

whereas `cwd` and `sandbox_cwd` should be set independently (fixed in
this PR).

Added `sandbox_distinguishes_command_and_policy_cwds()` to
`codex-rs/exec/tests/suite/sandbox.rs` to verify this.
…s in order (openai#3881)

Incidentally, we had a test for this in
`accepts_multiple_commands_with_allowed_operators()`, but it was
verifying the bad behavior. Oops!
Currently, we change the tool description according to the sandbox
policy and approval policy. This breaks the cache when the user hits
`/approvals`. This PR does the following:
- Always use the shell with escalation parameter:
- removes `create_shell_tool_for_sandbox` and always uses unified tool
via `create_shell_tool`
- Reject the func call when the model uses escalation parameter when it
cannot.
Move to using test helper method everywhere.
Hopefully fixes incorrectly showing ^J instead of Shift+Enter in the key
hints occasionally.
We currently get information about rate limits in the response headers.
We want to forward them to the clients to have better transparency.
UI/UX plans have been discussed and this information is needed.
### /limits: show rate limits graph

<img width="442" height="287" alt="image"
src="https://github.com/user-attachments/assets/3e29a241-a4b0-4df8-bf71-43dc4dd805ca"
/>

### Warning on close to rate limits:

<img width="507" height="96" alt="image"
src="https://github.com/user-attachments/assets/732a958b-d240-4a89-8289-caa92de83537"
/>

Based on openai#3965
Adds the following options:

1. Review current changes
2. Review a specific commit
3. Review against a base branch (PR style)
4. Custom instructions

<img width="487" height="330" alt="Screenshot 2025-09-20 at 2 11 36 PM"
src="https://github.com/user-attachments/assets/edb0aaa5-5747-47fa-881f-cc4c4f7fe8bc"
/>

---

\+ Adds the following UI helpers:

1. Makes list selection searchable
2. Adds navigation to the bottom pane, so you could add a stack of
popups
3. Basic custom prompt view
Unify cargo versions at root
The only file to watch is the cargo.toml
All the others come from just fix + a few manual small fix

The set of rules have been taken from the list of clippy rules
arbitrarily while trying to optimise the learning and style of the code
while limiting the loss of productivity
defaults to 60sec, overridable with MCP_TOOL_TIMEOUT or on a per-server
basis in the config.
no intended functional change, just simplifying the code.
Backtracking multiple times could drop earlier turns. We now derive the
active user-turn positions from the transcript on demand (keying off the
latest session header) instead of caching state. This keeps the replayed
context intact during repeated edits and adds a regression test.
Adds a "View Stack" to the bottom pane to allow for pushing/popping
bottom panels.

`esc` will go back instead of dismissing.

Benefit: We retain the "selection state" of a parent panel (e.g. the
review panel).
Add redundant closure clippy rules and let Codex fix it by minimising
FQP
gpeal and others added 28 commits October 3, 2025 17:15
…vers (openai#4689)

The `experimental_use_rmcp_client` flag is still useful to:
1. Toggle between stdio clients
2. Enable oauth beacuse we want to land
modelcontextprotocol/rust-sdk#469,
openai#4677, and binary signing before we
enable it by default

However, for no-auth http servers, there is only one option so we don't
need the flag and it seems to be working pretty well.
## Summary
- ensure the issue deduplicator workflow ignores the current issue when
listing potential duplicates

## Testing
- not run (workflow change)

------
https://chatgpt.com/codex/tasks/task_i_68e03244836c8320a4aa22bfb98fd291
Include information about the action and SDK
fixes an issue when terminals change their color scheme, e.g. dark/light
mode, the composer wouldn't update its background color.
Co-authored-by: rakesh <rakesh@openai.com>
It's present on the event, add it to the final result as well.
# External (non-OpenAI) Pull Request Requirements

Before opening this Pull Request, please read the dedicated
"Contributing" markdown file or your PR may be closed:
https://github.com/openai/codex/blob/main/docs/contributing.md

If your PR conforms to our contribution guidelines, replace this text
with a detailed and high quality description of your changes.
We truncate the output of exec commands to not blow the context window.
However, some cases we weren't doing that. This caused reports of people
with 76% context window left facing `input exceeded context window`
which is weird.
In the past, we were treating `input exceeded context window` as a
streaming error and retrying on it. Retrying on it has no point because
it won't change the behavior. In this PR, we surface the error to the
client without retry and also send a token count event to indicate that
the context window is full.

<img width="650" height="125" alt="image"
src="https://github.com/user-attachments/assets/c26b1213-4c27-4bfc-90f4-51a270a3efd5"
/>
## Summary
This PR is an alternative approach to openai#4711, but instead of changing our
storage, parses out shell calls in the client and reserializes them on
the fly before we send them out as part of the request.

What this changes:
1. Adds additional serialization logic when the
ApplyPatchToolType::Freeform is in use.
2. Adds a --custom-apply-patch flag to enable this setting on a
session-by-session basis.

This change is delicate, but is not meant to be permanent. It is meant
to be the first step in a migration:
1. (This PR) Add in-flight serialization with config
2. Update model_family default
3. Update serialization logic to store turn outputs in a structured
format, with logic to serialize based on model_family setting.
4. Remove this rewrite in-flight logic.

## Test Plan
- [x] Additional unit tests added
- [x] Integration tests added
- [x] Tested locally
Remove codex-level workingDirectory
Throw on turn.failed in `run()`
Cleanup readme
When truncating output, add a hint of the total number of lines
## Summary
- replace manual event polling loops in several core test suites with
the shared wait_for_event helpers
- keep prior assertions intact by using closure captures for stateful
expectations, including plan updates, patch lifecycles, and review flow
checks
- rely on wait_for_event_with_timeout where longer waits are required,
simplifying timeout handling

## Testing
- just fmt


------
https://chatgpt.com/codex/tasks/task_i_68e1d58582d483208febadc5f90dd95e
## Summary
Updates tool config for gpt-5-codex

## Test Plan
- [x] Ran locally
- [x]  Updated unit tests
- Add PlanRequested flow for Shift+Tab; block during tasks and keep text.
- Default planning to gpt-5 with high effort; make plan model/effort configurable.
- Add /plan-model selector with two-step model/effort UI and persistence.
- Core config: add plan_model + plan_model_reasoning_effort; add persistence helper.
- App protocol/profile structs updated to expose planning model settings.
- Footer hint shows Shift+Tab; snapshots updated; tests added/updated.
- Replace planning prompt with concise Plan-Only Mode instructions.

Refs: feature/plan-shortcut
@thomast8 thomast8 closed this Oct 5, 2025
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 5, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Subject: Missing “Analysis / Plan” Button Without Code Generation in Codex