teachyou.ai academy
← All posts
Codex

OpenAI Codex Terminal Workflow: Tips for Power Users

Pramod Dutta · May 16, 2026 · 15 min read

Why the terminal is where Codex actually shines

Most people meet OpenAI Codex through a chat window or an IDE sidebar, type a request, wait for a diff, and click accept. That works, but it leaves a lot of value on the table. The terminal version of Codex is a different animal. It runs in your shell, reads your actual file tree, executes commands, runs your test suite, and reports back with real exit codes instead of vibes. Once you start treating Codex CLI as a scriptable teammate rather than a chatbot, your whole workflow changes shape.

The gap between "I used Codex a little" and "I run half my day through Codex" is almost entirely about knowing the flags, the config file, and the shell habits that make the tool disappear into your muscle memory. This article is a practical rundown of exactly that: the terminal patterns, approval modes, sandbox settings, and shortcuts that separate a casual user from someone who has genuinely rebuilt their workflow around an agentic coding CLI. None of this requires a new mental model of programming — it requires learning the tool the way you'd learn any serious CLI, with attention to flags, config precedence, and the boring plumbing that makes automation reliable.

Installing and getting your first session right

Before optimizing anything, get the basics solid. Codex CLI installs via npm or a platform package, and the first session sets defaults you'll be fighting or leaning on for months.

npm install -g @openai/codex
codex --version
codex auth login

Once authenticated, launch it inside a project directory rather than your home folder. Codex scopes its understanding of "the repo" to wherever you started it, and it will walk up looking for a git root. Starting from the wrong directory is the single most common reason people complain that "Codex doesn't understand my project" — it was never given the project.

cd ~/code/my-service
codex

From here you get an interactive REPL-like session. Type a task, Codex reads relevant files, proposes a plan or a diff, and asks for approval depending on your sandbox mode (more on that below). The first thing power users do differently: they don't accept the default approval mode for every project. A quick throwaway script and a production payments service should not run under the same trust level.

Approval modes: the setting that actually matters most

Codex CLI has a small number of approval/sandbox modes, and picking the right one per task is the highest-leverage decision you'll make. Roughly:

  • Suggest / read-only mode — Codex can read files and propose changes but cannot execute anything or write to disk without your explicit yes on each action. Good for unfamiliar codebases or your first day on a new repo.
  • Auto-edit mode — Codex can edit files directly but still asks before running shell commands that could have side effects (installing packages, deleting files, hitting the network).
  • Full-auto / workspace-write mode — Codex can edit files and run commands inside a sandboxed workspace without asking every time, but it's still boxed in: no network by default, and writes are constrained to the project directory.

You select these with a flag or inside the session:

codex --approval-mode suggest
codex --approval-mode auto-edit
codex --full-auto

The trick power users lean on: start a risky or exploratory task in suggest mode, watch what Codex proposes for the first two or three steps, and once you trust the direction, bump the session to full-auto rather than babysitting every file write for the rest of the run. You can usually change the mode mid-session with a slash-style command rather than restarting, which saves the context Codex has already built about your repo.

/mode full-auto

Don't default every project to full-auto out of impatience. The sandbox is there because agentic tools occasionally do something you didn't ask for — a stray rm, an unwanted git push, a dependency bump you didn't want. Full-auto in a sandboxed, network-disabled workspace is safe by design; full-auto with network and outside a git-tracked directory is where things go wrong.

It's worth building a mental checklist for choosing a mode instead of picking one out of habit: How reversible is this change? Is the directory under version control? Does the task plausibly need to touch anything outside the project folder? A quick one-line CSS tweak and a database migration script both technically qualify as "small tasks," but only one of them deserves full-auto without a second thought. Power users get fast at this triage precisely because they've been burned once by skipping it — an unattended dependency upgrade that quietly bumped a major version, or a "cleanup" pass that deleted a config file nobody remembered was load-bearing. The five seconds spent picking the right mode is cheaper than the ten minutes spent reconstructing what happened after the wrong one.

Config file: stop repeating yourself on every launch

If you're typing the same flags every session, you're doing it wrong. Codex reads a config file, typically at ~/.codex/config.toml, and project-level overrides if present. This is where power users park their defaults instead of memorizing flag combinations.

# ~/.codex/config.toml
model = "o4-mini"
approval_mode = "auto-edit"
sandbox = "workspace-write"

[history]
persist = true
max_entries = 5000

[shell]
default_shell = "zsh"

A few settings worth calling out:

  • model — you can pin a faster, cheaper model for routine edits and reach for a stronger one only when a task actually needs deeper reasoning, either by overriding per-session or keeping two profiles.
  • sandbox — controls filesystem and network boundaries. workspace-write is the sane default for almost everyone; reserve unrestricted network access for tasks that genuinely need to fetch packages or hit an API.
  • history.persist — keeps a durable log of past sessions so you can grep back through what Codex actually did last week, which matters more than people expect once you're running it daily.

Project-level config (a .codex/config.toml inside the repo, or equivalent per your installed version) lets you override model or sandbox behavior per project — useful when one repo needs network access for its test suite and another absolutely should not have it.

It's also worth keeping a written AGENTS.md or equivalent instructions file at the root of any repo you use Codex on regularly. Codex CLI looks for this kind of project-level guidance file automatically, and it's the natural place to put the things you'd otherwise repeat in every prompt: which package manager the repo uses, how to run the test suite, which directories are generated output and should never be hand-edited, and any house style rules ("prefer named exports," "no default exports," "migrations go through the db/migrate script, never edited by hand"). Five minutes spent writing this file once saves you from retyping the same constraints in every session for the life of the project, and it means a fresh session picks up the same guardrails a session from last month had.

# AGENTS.md
- Package manager: pnpm (not npm, not yarn)
- Test: pnpm test -- --run
- Lint: pnpm lint --fix
- Never hand-edit files under /generated or /dist
- Database migrations: pnpm db:migrate:new "<name>", never edit old migration files
- Prefer small, composable functions over large ones with many branches

Prompting patterns that work better from a terminal

Chat-window prompting habits don't transfer cleanly to a CLI agent that can see your whole file tree and run commands. A few patterns consistently produce better runs:

  1. Point at files explicitly. Instead of "fix the bug in the auth flow," say "look at src/auth/session.ts and src/auth/middleware.ts, the token refresh logic in session.ts line ~80 is the suspect." Codex CLI can search the repo itself, but giving it a starting point cuts down on wasted exploration turns.
  2. Ask for a plan before a diff on anything nontrivial. A one-line "outline your plan first, don't edit yet" instruction turns a shotgun edit into a reviewable sequence of steps.
  3. Reference command output, not just code. Paste a failing test's stderr or a stack trace directly into the prompt. Codex CLI treats this as ground truth far better than a vague description of "it's broken."
  4. Batch related asks. Rather than five separate one-line requests, describe the full unit of work — "add the endpoint, add a test, update the OpenAPI spec" — in one prompt so Codex can sequence the work instead of re-deriving context each time.

A prompt that works well in practice:

Read tests/payments/webhook_test.py and see why test_signature_mismatch
is failing. Run the test first to confirm, show me the traceback,
then propose a fix. Don't touch other test files.

That single instruction gives Codex a target, a verification step, and an explicit boundary — three things that separate a clean single-pass fix from a multi-turn back-and-forth.

One more habit worth adopting: tell Codex what "done" looks like, not just what to change. "Fix the failing test" is ambiguous about whether you want the test loosened, the implementation fixed, or both examined for which one is actually wrong. "Fix the implementation so the existing test passes without modifying the test itself" removes an entire category of lazy-fix behavior where the model quietly weakens an assertion instead of solving the underlying bug. The more precisely you can state the acceptance criteria in the prompt itself, the less you'll need to catch in review afterward.

Wiring Codex into your shell and scripts

The terminal-native part of Codex CLI really pays off when you stop treating it as an interactive-only tool and start calling it from scripts, aliases, and CI-adjacent tooling.

Non-interactive, single-shot invocation is the building block:

codex exec "run the linter, fix any autofixable issues, and summarize what changed" --full-auto

The exec (or equivalent non-interactive) subcommand runs a task headlessly and exits, which makes it pipeable and scriptable. A few shell aliases that regular users end up reaching for:

alias cxf='codex --approval-mode auto-edit'
alias cxs='codex --approval-mode suggest'
alias cxreview='codex exec "review the current git diff for bugs and style issues, do not edit files"'

That cxreview alias is worth building yourself even if you don't copy it verbatim — a read-only review pass on your working diff before you commit is one of the highest-value five-second habits you can add to a daily loop.

You can also pipe context into Codex directly:

git diff | codex exec "review this diff for security issues, be specific about line numbers"

Combine this with git log to give Codex historical context on a file before asking it to modify it:

git log -p --follow -- src/billing/invoice.py | tail -200 | codex exec "given this file's recent history, what's the safest way to add proration support?"

This same exec pattern is what makes Codex usable as a build step rather than just an interactive tool. A package.json script, a Makefile target, or a pre-commit hook can all shell out to codex exec the same way they'd shell out to any other CLI:

# Makefile
.PHONY: review
review:
	git diff --cached | codex exec "review this staged diff, flag anything risky, be terse" --approval-mode suggest
# package.json script
"scripts": {
  "codex:review": "git diff | codex exec 'review this diff for bugs' --approval-mode suggest"
}

Because exec mode prints to stdout and exits with a real status code, you can also gate on it — for instance, failing a pre-push hook if Codex's review flags something and you haven't addressed it, though most teams treat this as an advisory signal rather than a hard gate, at least until they've built enough trust in the output to make it a blocker.

Managing context and session state like a pro

Long sessions accumulate a lot of context, and Codex CLI's usefulness depends heavily on how well that context stays relevant. A few habits keep sessions productive instead of bloated:

  • Start a fresh session per unrelated task. Don't drag a session that's been debugging a flaky test into an unrelated feature request — stale context biases the model toward solutions shaped by the last problem, not the current one.
  • Use `/clear` or equivalent to reset context without leaving the terminal, when you're staying in the same repo but switching tasks completely.
  • Checkpoint with git, not with memory. Before letting Codex run a multi-step full-auto task, commit or stash your current state. If the run goes sideways, git diff and git checkout -- . are your actual undo button, not "ask Codex to revert."
git add -A && git commit -m "checkpoint before codex full-auto run"
codex --full-auto "refactor the queue consumer to use the new retry policy"
# if it goes wrong:
git reset --hard HEAD~1
  • Grep your own history. If persistent history is enabled, grep through the session log directory the same way you'd grep shell history. It's often faster to find "what did I ask Codex last time about the rate limiter" this way than to re-derive it from memory.

Debugging Codex itself: verbose output and logs

When a session behaves unexpectedly — hangs, times out, or seems to ignore an instruction — the terminal gives you diagnostics a chat UI never would.

codex --verbose
codex --log-level debug

Verbose mode surfaces the actual tool calls Codex is making: which files it opened, which shell commands it ran, and the raw exit codes. This is invaluable when a task partially succeeds — you can see exactly which step failed instead of guessing from the summary.

If a session seems to be looping (asking to run the same failing command repeatedly), that's usually a sign the underlying issue is either a missing dependency or a permissions problem the sandbox is silently blocking. Checking the sandbox and network settings first saves a lot of time compared to rephrasing the prompt five different ways.

codex --sandbox workspace-write --network-access

Only enable --network-access for the specific session that needs it (installing a package, hitting an internal API for a schema) and drop back to the default afterward. Leaving broad network access on as a permanent default defeats the purpose of sandboxing in the first place.

A related troubleshooting step people skip: check which config actually loaded before assuming the tool is broken. Global config, project config, and whatever flags you typed all stack together, and it's easy to forget you left an override in your shell history or a stray .codex/config.toml in a parent directory. When behavior seems inconsistent between two repos, diffing the effective config is almost always faster than re-reading the prompt for the tenth time looking for ambiguity that isn't there.

codex config show   # or the equivalent flag in your installed version, prints the merged config

If a session seems to have amnesia about something you told it three prompts ago, that's usually a context window issue rather than a bug — long sessions eventually push earlier instructions out of the effective context, which is a strong argument for keeping the durable rules in AGENTS.md rather than relying on them staying "remembered" mid-conversation.

Multi-file refactors and large tasks without losing control

Codex CLI can genuinely handle multi-file changes, but power users break large tasks into checkpointed stages rather than one giant ask, for the same reason you wouldn't want a junior engineer to touch forty files in a single unreviewed commit.

A pattern that scales well:

1. First, just list every file that imports the old `LegacyLogger` class.
   Don't change anything yet.
2. Now update LegacyLogger's own definition to the new interface.
   Run the existing tests for that file only.
3. Now update the callers one directory at a time, starting with src/api/.
   After each directory, run the relevant test suite before moving on.

This turns one large, risky refactor into a sequence of small, verifiable steps, each with its own pass/fail signal. It also means if step 3 goes wrong on the third directory, you've only got a small diff to git reset, not the whole refactor.

For genuinely large migrations, combine this with a scratch branch:

git checkout -b codex/logger-migration
codex --approval-mode auto-edit
# work through staged prompts above
git diff main --stat   # sanity check scope before opening a PR

Bringing it together: a realistic power-user daily loop

Put together, a terminal-first Codex workflow looks less like "chat with an AI" and more like a disciplined engineering habit:

  • Config file holds sane defaults (model, sandbox, approval mode) so every session starts right.
  • New unrelated task → new session, old session context discarded.
  • Anything touching more than a couple of files → plan first, diff second, full-auto only after the plan is sound.
  • Git commit or stash before any full-auto multi-step run, so rollback is one command away.
  • A review alias (cxreview or similar) runs against the diff before every commit, catching issues before a human reviewer has to.
  • Verbose/debug flags are the first move when something looks wrong, not the fifth.

None of this is exotic. It's the same discipline experienced engineers already apply to any powerful CLI tool — know the flags, trust but verify, keep an undo path, and don't let convenience erode the safety rails you set up on day one. The difference with Codex is that the "teammate" on the other end can read, write, and execute across your whole repo, so the habits matter more, not less.

If you want to go deeper than a single article can cover — sandbox internals, scripting Codex into CI pipelines, structuring multi-agent workflows, and building repeatable prompt templates for your own codebase — that's exactly what we walk through hands-on in the OpenAI Codex CLI Tutorial course on teachyou.ai. It's built for exactly the kind of terminal-first, automation-minded workflow this article describes, with real repos and real refactors instead of toy examples.

OpenAI Codex Terminal Workflow: Tips for Power Users · TeachYou Academy