All articles
case study · intermediate ·

Reprompt: prompt refinement inside Codex

How a manual ChatGPT cleanup loop became a Codex interceptor that narrows the gap between rough intent and executable agent work.

codexprompt-engineeringtooling
Resources
Reporavikanchikare/codex-reprompt
Upstreamopenai/codex
SurfaceTUI-only interceptor on /reprompt
Default refinero4-mini via the Responses API
Configuration~/.codex/config.toml + ~/.codex/reprompt/<profile>.toml

Why prompt refinement came first

Most Codex runs do not begin as crisp task specs. They start as rough intent: a dictated thought, a half-formed constraint, a few files that seem relevant, and an outcome that is obvious to the person asking but not yet explicit in the prompt.

That gap matters. The failure mode is letter over spirit: the model honors the literal instruction while missing the goal. “Make it shorter” can cut the one finding the reader needed. “Make it more professional” can polish the prose while leaving the actual ask buried.

The fix is to state the goal, not just repeat the instruction with more force. A useful prompt says what to do and why the result matters. That turns refinement into an intent checkpoint before the coding agent spends tokens, opens files, or edits the repo.

The starting workflow was manual. A rough request went into ChatGPT first, followed by a short refiner prompt:

manual-refiner-prompt.md markdown
- Use action verbs.
- Keep the wording direct, clear, and concise.
- Correct grammar and clarify intent.
- Refine the wording while preserving the original user intent.
- Do not solve the task; only improve the task definition.
- Do not add irrelevant content; only correct and refine the provided text.
- Respond in a single markdown block.

The rewritten prompt was not the final authority. Reading it back exposed missing constraints, muddled scope, and places where the literal instruction could diverge from the intended result. After that review, the refined task moved into Codex for execution.

The problem was the tool boundary. Refinement lived in ChatGPT; execution lived in Codex. Reprompt started from a simple question: what if the refinement step lived inside the coding workflow itself?

Why a skill was not enough

The first attempt to get “rewrite-only” behavior out of Codex was a skill. It worked sometimes. It did not hold up.

A skill provides guidance, not a hard execution boundary. Five problems showed up immediately:

  • Skills cannot reliably stop Codex from solving the task when the model reads the user request as executable work.
  • Skills cannot disable tools — file edits, shell, tests, browser actions all stay live.
  • Skills depend on trigger quality. They may not load, or they may load alongside stronger instructions that override them.
  • “Rewrite only” conflicts with the model’s default bias to act on user requests.
  • Grounding the prompt requires light project exploration, which can drift into task execution.

A skill can shape behavior. It cannot guarantee enforcement. For strict rewrite-only behavior the right design is a dedicated layer that sits outside the agent loop, owns the rewrite step end-to-end, and never gets handed the tools that would let it act.

What Reprompt does

Reprompt is a Codex setting that intercepts user input before the main agent runs. It uses the existing ChatGPT or API-key authentication, calls a configured refiner model, grounds the request in the local repository, and rewrites the prompt into a clearer, more structured task.

The refiner does not just clean up grammar. It turns a rough request into a task definition that names the goal, preserves the user’s intent, and adds project grounding where the repository can supply it. The user still approves the result before the main agent sees it.

Initial Codex prompt before refinement

When the user submits, Reprompt fires first. It reads the working directory, pulls in recent conversation turns, expands @file and $skill mentions, and asks the refiner model for a structured rewrite.

Reprompt overlay showing the refined prompt with rules and reasoning

The overlay is the load-bearing UI element. It shows the original prompt, the refined version, the rules that were applied, a tip, and the model’s reasoning. The user can accept, iterate, skip, or cancel — keyboard-only, no mouse, no tab-out.

Once accepted, Codex executes against the refined prompt. The refined version is what the agent sees in its history; the original is preserved only for context.

Codex executing the refined prompt with a structured plan

How it works

The fork adds roughly 3,400 lines, almost entirely concentrated in codex-rs/tui/src/reprompt/. Core Codex logic is largely untouched.

TUI-level capture

When /reprompt is enabled, every user submission that meets the min_length threshold gets passed through the refinement pipeline before reaching the main agent loop.

Repo-aware context build

The refiner sees a cached project tree (depth 4, ~2000 chars), the most recent conversation turns, content-matched relevant files, and any extracted skills, plugins, or apps from session state.

Structured Responses API call

A single call to the configured model (default o4-mini) at /responses, using a JSON schema that returns refinedPrompt, appliedRules, taskType, reasoning, tips, and a wasSubstantiveChange flag.

Overlay before commit

If the change is substantive, the overlay opens. If not, the original prompt passes through untouched. Auto-accept after 15s by default; the timer is configurable.

The refinement call is a separate, stateless request. It does not have tools, it does not have shell, it cannot edit files. The only thing it can produce is text shaped by the JSON schema. That shape is the enforcement that a skill could not give.

What can be configured

Reprompt has two configuration surfaces. The main ~/.codex/config.toml holds defaults; named profiles in ~/.codex/reprompt/<name>.toml override per task type.

~/.codex/config.toml toml
[reprompt]
enabled = true
model = "o4-mini"
profile_name = "default"
min_length = 20             # skip short messages
context_turns = 4           # prior turns to include
auto_accept_delay = "15s"
show_diff = false

# Grounding controls
include_relevant_files = true
relevant_files_max_count = 8
relevant_files_max_chars = 600
include_project_structure = true
project_structure_max_depth = 4
project_structure_max_chars = 2000
project_structure_cache_ttl_secs = 30

# Safety
redact_secrets = true
redact_high_entropy = true
redaction_entropy_threshold = 4.5

Profiles add a system_prompt, an optional task_type tag (bugfix, feature, refactor, security, analysis, review), and rule lists that are grouped by task type. The seven shipped profiles are None, bugfix, concise, default, docs, refactor, and security.

Selecting a reprompt profile

Switching profile is a /reprompt command away. The slash-picker also exposes /reprompt-insights for retrospective coaching — a tool that scans past refinements and surfaces recurring ways the user under-specifies tasks.

Slash command picker showing /reprompt and /review

Why this shape

Four design choices held up across iterations.

The refiner is its own model call. Mixing refinement into the main agent’s system prompt re-creates the skill problem — the model decides whether to obey. A separate call with a separate model and a JSON schema gives a hard contract.

The overlay is a checkpoint, not a silent rewrite. A refiner can introduce its own letter-over-spirit error. Showing the original and refined prompt side by side keeps the human in the loop before the executable task enters the agent history.

Grounding is bounded by character budgets, not file counts. Files vary wildly in size. Capping by characters keeps the refiner’s context predictable across repositories.

Profiles, not prompt templates. A bugfix needs an investigation order and a regression check. A refactor needs scope preservation. A security review needs threat-modeling questions. Encoding those as task-typed rule lists is more legible than maintaining seven different system prompts.

Takeaways

Prompt refinement is an intent checkpoint

The first pass is not about clever wording. It gives the user a chance to reread the task, catch letter-over-spirit gaps, and state the goal before tools run.

Skills give guidance, not enforcement

A skill cannot disable tools or stop a model that interprets the user request as executable work. Hard boundaries belong in the wrapper, not in instructions.

Refinement is a different job from execution

Treating prompt rewriting as its own model call — with its own system prompt, its own model, and structured output — keeps the planner from leaking into the doer.

Grounding beats verbosity

A short prompt with the right file path, the right symbol, and the right task type produces better runs than a long prompt that asks the agent to figure out the rest.

The tool ships as a fork rather than a plugin because the boundary it needs lives below the slash-command surface. Skills, hooks, and config do not currently expose a “before-the-agent-runs” hook in upstream Codex. Until they do, the fork is the smallest place to put a layer that has to run first and has to run every time.