This is Part 2 of the Codex CLI series. Today, we’ll learn how to control Codex’s capabilities and make your first safe edits.
This post is about speed with control, not automation for its own sake.
Introduction
In the last post, we installed Codex CLI and took our first steps with read-only exploration. Today, we go deeper: learning how to control what Codex can do, understanding the essential commands you will use daily, and making your first actual code edits—safely.
What I learned from using Codex is that the key to productive work is understanding the control mechanisms. Unlike a chatbot that only gives suggestions, Codex can actually change your files and run commands. That power is valuable, but it requires proper guardrails.
Let me show you how to stay in control while getting real work done.
Understanding Security Controls: Permissions and Approvals
This is the most important concept to understand before you let Codex make any changes. Codex uses a security system built on two interconnected ideas: permissions and approvals.
At first, these might seem like the same thing, but understanding the distinction helps you think clearly about how Codex operates and how to stay in control.
Permissions vs Approvals: The Conceptual Difference
Permissions: WHAT Codex Can Do
Permissions define the technical boundaries—what Codex is actually capable of doing in your environment:
- Network Access: Can Codex connect to the internet, external APIs, or package registries?
- File Access Scope: Can Codex only read? Edit workspace files? Edit files anywhere on your system?
- Command Execution: Can Codex run shell commands, install packages, or execute scripts?
Think of permissions as the capabilities Codex has been granted. They are the “can it” question.
Approvals: WHEN Codex Must Ask
Approvals determine the workflow control—when Codex needs to pause and get your explicit consent before taking action:
- Should Codex ask before accessing the network?
- Should Codex ask before editing any file?
- Should Codex proceed autonomously within its granted permissions?
Think of approvals as the checkpoints where you maintain control. They are the “must it ask first” question.
How They Work Together: Three Unified Modes
Here’s what makes Codex’s design elegant: you don’t manage permissions and approvals separately. Instead, you choose a mode that sets both at once.
Each mode is a carefully balanced package of permissions + approval requirements, optimized for different types of work.
You access these modes through either /approvals or /permissions commands—they’re two names for the same menu. Use whichever makes more sense to you in the moment.
1. Read Only Mode: Safe Exploration
# In a Codex session, type:
/approvals
# Then select option 1
Update Model Permissions
› 1. Read Only Codex can read files in the current workspace. Approval is required to edit files or access the internet.
2. Default Codex can read and edit files in the current workspace, and run commands. Approval is required to access the internet or edit other files. (Identical to Agent mode)
3. Full Access Codex can edit files outside this workspace and access the internet without asking for approval. Exercise caution when using.
Press enter to confirm or esc to go back
Permissions granted:
- ✓ Read files in the current workspace
- ✓ Analyze code structure
- ✓ Generate suggestions and explanations
Permissions denied:
- ✗ Cannot edit any files
- ✗ Cannot run any commands
- ✗ Cannot access the internet
Approval requirements:
- Must ask to edit files
- Must ask to access the internet
When to use this:
- First time exploring a new repository
- When you want understanding without any risk
- Reviewing unfamiliar code
- Getting explanations and documentation
- Design discussions and planning sessions
- Code reviews where you only want to understand, not change
My experience: I always start here with new codebases. It is like having a knowledgeable colleague explain the code to you, with zero risk of accidentally changing anything. The name “Read Only” is perfect—Codex literally cannot write, even if it tries.
Example workflow:
You: /approvals
[Select 1 - Read Only]
You: Explain the authentication flow in this app
Codex: [Reads auth.py, models.py, etc. and explains the flow]
You: What happens if login fails?
Codex: [Explains what happens if login fails and in which file this logic is realised]
You: Can you add better error handling?
Codex: Would you like to make the following edits?
[Shows the code changes]
› 1. Yes, proceed (y)
2. Yes, and don't ask again for these files (a)
3. No, and tell Codex what to do differently (esc)
Sometimes Codex requires to have “escalated permissions”, for example, to create new directories or files with shell commands. It will ask you if you want to run the command or prefer “to do differently”.
2. Default Mode: Balanced Control (Agent Mode)
# In a Codex session, type:
/approvals
# Then select option 2
Update Model Permissions
1. Read Only Codex can read files in the current workspace. Approval is required to edit files
or access the internet.
› 2. Default (current) Codex can read and edit files in the current workspace, and run commands. Approval
is required to access the internet or edit other files. (Identical to Agent mode)
3. Full Access Codex can edit files outside this workspace and access the internet without asking
for approval. Exercise caution when using.
Or via /permissions:
/permissions
# Then select option 1 (Default)
Update Model Permissions
› 1. Default (current) Codex can read and edit files in the current workspace, and run commands. Approval
is required to access the internet or edit other files. (Identical to Agent mode)
2. Full Access Codex can edit files outside this workspace and access the internet without asking
for approval. Exercise caution when using.
Permissions granted:
- ✓ Read and edit files in the current workspace
- ✓ Run commands in the workspace
- ✓ Execute local operations (tests, linters, formatters)
Permissions requiring approval:
- ? Must ask before accessing the internet or external APIs
- ? Must ask before editing files outside the current workspace
Approval workflow:
- Proceeds autonomously for in-workspace file edits and command execution
- Stops and asks before network operations or cross-workspace changes
When to use this:
- After you explored a project in Read Only
- For most day-to-day development work (this is the sweet spot)
- When you want efficiency with safety
- Active coding sessions within a single project
- Refactoring, testing, and feature development
My experience: This is my default working mode for 90% of my work. Codex can help efficiently within my project directory—editing files, running tests, refactoring code—but must ask before reaching outside the workspace or accessing the network. It strikes the perfect balance between productivity and safety.
Note: The interface labels this as “identical to Agent mode”—the same permission model Codex uses in its agentic workflows.
Example workflow:
You: /approvals
[Select 2 - Default]
You: Add type hints to all functions in utils.py
Codex: I'll analyze utils.py and add type hints. Here's my plan:
- analyze_data() → add List[Dict] params, Dict return
- format_output() → add str annotations
- validate_input() → add bool return type
[Codex proceeds without asking—it's within workspace permissions]
Codex: Done. I've added type hints to 8 functions.
You: /diff
[Shows exactly what changed in utils.py]
You: Looks good. Now install pytest so we can add tests
Codex: This requires internet access. Should I proceed?
You: Yes
Codex: [Accesses PyPI and installs pytest via pip]
pytest installed successfully.
3. Full Access Mode: Maximum Trust
# In a Codex session, type:
/approvals
# Then select option 3
Or via /permissions:
/permissions
# Then select option 2 (Full Access)
Permissions granted:
- ✓ Edit files anywhere on your system (not limited to workspace)
- ✓ Full network access to any API or service
- ✓ Run any commands without restriction
- ✓ Install packages, modify system configs, access databases
Approval requirements:
- None—Codex proceeds autonomously within these broad permissions
Warning from the interface:
“Exercise caution when using.”
When to use this:
- Multi-project updates that span directories
- Batch operations across multiple repositories
- Tasks requiring frequent network access (CI/CD, deployments)
- Automated maintenance scripts
- System-wide configuration changes
- When you have run the exact workflow many times before
When NOT to use this:
- First time with a new repository or unfamiliar task
- When you are not 100% sure what will happen
- On critical systems without recent backups
- When working with production data or sensitive information
- As your default mode (too risky)
My experience: I use this rarely—maybe 5% of the time. Typically for well-understood batch operations where I need to work across multiple projects or make many network calls. For example, updating dependency versions across all my repos, or running a deployment script that touches multiple systems. Even then, I still review diffs carefully before committing anything.
Example workflow:
You: /approvals
[Select 3 - Full Access]
You: Update all my project READMEs to include the new contribution
guidelines from ~/templates/CONTRIBUTING.md
Codex: I'll scan ~/projects/ for repositories and update each README.
[Codex finds 12 repositories and updates them—no approval needed]
Codex: Updated READMEs in 12 projects.
You: /diff
[Review changes across all 12 projects—critical step!]
You: Also fetch the latest dependency versions from npm and update
package.json files accordingly
Codex: Checking npm for updates...
[Accesses npm registry, updates package.json in all projects]
Updated dependencies in 8 projects. Run npm install to apply.
Critical reminder: Even in Full Access mode, always use /diff to review changes before committing!
Switching Modes Mid-Session
One of Codex’s most powerful features: you can change modes anytime during a session.
# Access the mode selection menu
/approvals
# Or use the alternate name
/permissions
# Select 1, 2, or 3 based on your current needs
Both commands take you to the same place. I use whichever name comes to mind—/approvals when I’m thinking about workflow control, /permissions when I’m thinking about capabilities.
My typical session flow:
# Start conservative: Read Only mode
/approvals → Select 1
[Explore codebase, ask questions, understand structure]
# Ready to make changes: Switch to Default mode
/approvals → Select 2
[Edit files, add features, run tests]
# Need to install a package
Codex: This requires internet access. Should I proceed?
You: Yes
[Single package installed]
# Installing multiple packages, switch to Full Access temporarily
/approvals → Select 3
[Install all dependencies, fetch external data]
# Done with network operations, back to Default
/approvals → Select 2
[Continue regular development with local safety]
Best Practices: Choosing the Right Mode
Start Conservative, Loosen as Needed
New/unfamiliar repository:
Read Only (option 1)
↓ (when ready to make changes)
Default (option 2)
↓ (only when necessary)
Full Access (option 3)
You can always grant more permissions. It is much harder to undo mistakes.
Match the Mode to Your Task
Use Read Only when you want to:
- Understand how a codebase works
- Review someone else’s code
- Plan a refactoring strategy
- Discuss architecture or design
- Learn from examples without risk of changes
Use Default for:
- Regular feature development (95% of coding work)
- Refactoring within a project
- Writing and running tests
- Local debugging and experimentation
- Any work contained within one repository
Use Full Access for:
- Batch updates across multiple projects
- Deployment and CI/CD operations
- System configuration changes
- Network-heavy tasks (many package installs, API calls)
- Automated maintenance scripts you have run before
Check Your Current Mode
The mode menu shows your current state with a visual indicator:
/approvals
# Display shows:
1. Read Only
› 2. Default (current)
3. Full Access
The › arrow and (current) label make it instantly clear where you are.
Pro tip: When something feels off—Codex asking for approval unexpectedly, or proceeding when you expected it to ask—check /approvals. You might be in a different mode than you thought.
Essential Slash Commands
Now that you understand the security model, let’s look at the commands you’ll use daily to work effectively with Codex.
/diff - The Most Important Command
This command shows you a Git-style diff of all changes Codex has made or proposes to make.
/diff
What it shows:
- All modified files with their paths
- Line-by-line changes (deletions in red, additions in green)
- New files that were created
- Files that were deleted
Why this is crucial: Always review diffs before committing. This is your chance to catch unintended changes, verify the logic is correct, and understand exactly what Codex did. Even in Full Access mode, /diff is your safety net.
My workflow:
You: Refactor the config parsing to use dataclasses
Codex: [Makes changes to config.py]
You: /diff
[Carefully review each change]
You: The dataclass looks good, but keep the old from_dict()
method for backward compatibility
Codex: [Updates config.py to preserve from_dict()]
You: /diff
[Confirms the change looks correct]
You: Perfect. This is ready to commit.
Pro tip: Make /diff automatic muscle memory before every commit. My workflow is always: change → diff → review → accept or adjust → commit. No exceptions.
/review - Code Quality Check
This command runs a dedicated code review on your changes.
/review
Select a review preset
› 1. Review against a base branch (PR Style)
2. Review uncommitted changes
3. Review a commit
4. Custom review instructions
What it checks:
- Code quality and style issues
- Potential bugs or edge cases
- Performance concerns
- Best practices for your language/framework
- Documentation gaps
- Test coverage
When to use this:
- Before submitting a pull request
- After making significant changes
- When you want a “second opinion” on your approach
- As a regular code health check
- When learning a new codebase’s patterns
Example:
You: /review followed by 4. Potential bugs or edge cases
In a minute, Codex reviewed my project files and provided full review comments. Next, I ask Codex to address these issues.
What I appreciate: The review is contextual—it understands your project’s coding style, the frameworks you’re using, and suggests improvements that fit naturally into your codebase.
/model - Switch AI Models
Different tasks benefit from different AI models.
/model
Select Model and Effort
Access legacy models by running codex -m <model_name> or in your config.toml
› 1. gpt-5.2-codex (current) Frontier agentic coding model.
2. gpt-5.1-codex-max Codex-optimized flagship for deep and fast reasoning.
3. gpt-5.2 Latest frontier model with improvements across knowledge, reasoning and coding
4. gpt-5.1-codex-mini Optimized for codex. Cheaper, faster, but less capable.
Press enter to select reasoning effort, or esc to dismiss.
What it shows:
- Available models in your Codex installation
- Current model in use
- Reasoning effort options (for models that support it)
When to switch models:
Use faster models for:
- Simple refactoring tasks
- Adding comments or docstrings
- Formatting and style fixes
- Quick questions about code
- Repetitive batch operations
Use more capable models for:
- Complex logic changes or algorithms
- Debugging difficult issues
- Architectural decisions
- Novel problem-solving
- Code that requires deep reasoning
/compact - Clean Up Long Sessions
/compact
What it does:
- Summarizes the conversation history
- Keeps recent context that’s still relevant
- Reduces token usage
- Improves response speed for future messages
When to use this:
- After working on a task for a while
- When responses start slowing down
- Before switching to a completely different topic in the same session
- When you notice Codex losing track of earlier context
Why it helps: Long conversations accumulate context. Compacting maintains what matters while clearing clutter, giving you a faster, more focused Codex.
/resume - Continue Previous Work
Outside of Codex, in your regular terminal:
codex resume
What it does:
- Shows your recent Codex sessions
- Lets you pick one to continue
- Restores full conversation context and history
Why this is brilliant: You can work on a blog post, close Codex, work on Python code in a different session, then resume the blog post session exactly where you left off—including all the conversation history and context.
Example:
$ codex resume
Resume a previous session
Type to search
Updated Branch Conversation
> 1 minute ago - Generate a file named AGENTS.md that serves as a contributor guide for this reposi...
Making Your First Safe Edit
Now let’s put everything together and make an actual code change—safely, with full visibility and control.
Step-by-Step: Your First Edit
I will walk you through a complete workflow from start to finish.
Step 1: Prepare Your Environment
# Navigate to a test project (something non-critical)
cd ~/code/test-project
# Make sure you're on a clean Git branch
git status
git checkout -b codex-test
# Start Codex
codex
Why a new branch? If anything goes wrong, you can easily discard changes without affecting your main branch.
if you did not have any git repository for your project yet, fear not, just type in:
Initialise a git repository for this project with correct .gitignore file
Codex creates .gitignore file and initialise the repository with git initi in no time.
Step 2: Start in Read Only Mode
You: /approvals
[Select 1 - Read Only]
Why start here? Even for simple edits, it’s good practice to first understand the code before changing it.
You: Show me the structure of utils.py and explain what calculate_total does
Codex: [Reads and explains the file structure]
utils.py contains 5 utility functions. calculate_total() takes
a list of item prices and a tax rate, computes the subtotal,
applies tax, and returns the total. Currently, it has no
docstring and no type hints.
You: Perfect. I want to add a docstring with type hints.
Step 3: Switch to Default Mode
You: /approvals
[Select 2 - Default]
The menu now shows:
1. Read Only
› 2. Default (current)
3. Full Access
Perfect. We can edit files in the workspace now.
Step 4: Request the Change
You: Add a comprehensive docstring to calculate_total() with:
- Google-style format
- Parameter descriptions including types
- Return type
- Example usage
- Type hints in the function signature
Why this is a good first edit:
- Small, focused scope
- Easy to verify correctness
- Low risk of breaking anything
- Clear success criteria
- Teaches good documentation practices
Step 5: Review the Proposal
Codex will show you its plan:
Codex: I'll add a Google-style docstring and type hints to
calculate_total() in utils.py. The function signature
will become:
def calculate_total(items: List[float], tax_rate: float) -> float:
And I'll add a comprehensive docstring with args, return
value, and an example. Should I proceed?
Review this carefully: Does the plan match what you wanted? Are the types correct? If yes, proceed. If not, clarify or adjust.
Step 6: Let Codex Make the Change
You: Yes, proceed
Codex: [Edits utils.py]
Done. I've added the docstring and type hints.
Step 7: Review the Diff (Critical Step!)
You: /diff
What you see:
diff --git a/utils.py b/utils.py
index 1234567..abcdef0 100644
--- a/utils.py
+++ b/utils.py
@@ -1,5 +1,24 @@
+from typing import List
+
def calculate_total(items, tax_rate):
+def calculate_total(items: List[float], tax_rate: float) -> float:
+ """Calculate the total cost including tax.
+
+ Computes the sum of all item prices and applies the specified
+ tax rate to calculate the final total.
+
+ Args:
+ items: List of individual item prices
+ tax_rate: Tax rate as a decimal (e.g., 0.08 for 8%)
+
+ Returns:
+ Total cost including tax
+
+ Example:
+ >>> calculate_total([10.0, 20.0, 15.0], 0.08)
+ 48.6
+ """
subtotal = sum(items)
tax = subtotal * tax_rate
return subtotal + tax
Step 8: Verify and Accept
Ask yourself:
- ✓ Does the change match what I requested?
- ✓ Is the docstring accurate and helpful?
- ✓ Are the type hints correct?
- ✓ Did it change anything else unexpectedly?
- ✓ Is the import statement properly added?
- ✓ Would I write this code myself?
If all checks pass:
# Exit Codex
Ctrl+D
# Verify in your editor if you want (optional)
cat utils.py
# Run tests to make sure nothing broke
pytest
# Commit the change
git add utils.py
git commit -m "Add docstring and type hints to calculate_total()"
Congratulations! You just made your first safe edit with Codex CLI, using the full workflow: explore → understand → plan → execute → review → commit.
Interestingly, when you use Ctr+D for exit, you get additional information about your token usage and how to continue with your session later:
Token usage: total=202,814 input=170,501 (+ 1,586,432 cached) output=32,313 (reasoning 4,352)
To continue this session, run codex resume session_hash_id
What If Something Goes Wrong?
Let’s say Codex made a change you’re not happy with:
Option 1: Ask for adjustments
You: The docstring is good, but the example is wrong. Tax on $45
at 8% should be $48.60, not $48.6. Also, use a more realistic
example with actual prices.
Codex: You're right. Let me fix the example:
>>> calculate_total([12.99, 24.99, 8.50], 0.0825)
50.336
You: /diff
[Confirms the fix looks correct]
Option 2: Discard and start over
# In Codex
Ctrl+C # Cancel current operation
# Outside Codex
git checkout utils.py # Discard all changes
codex # Start a fresh session
Option 3: Manual fix
Just edit the file yourself! Codex is a tool to help you, not a requirement. If you can fix it faster manually, do that. The goal is productivity, not using AI for everything.
Building Good Habits
After making your first few edits, here are the habits I recommend developing:
1. Always Review Diffs
Request change → Codex edits → /diff → Review → Accept or Adjust → Commit
Make this automatic. Every single time. No exceptions.
I cannot stress this enough: /diff is your safety net. Use it religiously.
2. Start Conservative with Modes
New/unfamiliar repository:
/approvals → Select 1 (Read Only)
↓ (after understanding the code)
/approvals → Select 2 (Default)
↓ (only when truly needed)
/approvals → Select 3 (Full Access)
You can always grant more permissions. It is much harder to undo mistakes.
3. Check Your Mode When in Doubt
# Something feels off? Codex acting unexpectedly?
/approvals
# The menu shows your current mode clearly:
› 2. Default (current)
# Switch if needed, or Esc to cancel
If Codex is asking for approval when you expected it to proceed (or vice versa), you might be in the wrong mode.
4. Commit Often with Descriptive Messages
# After each logical change
git add .
git commit -m "Add type hints to utils.calculate_total"
# Not this:
git commit -m "codex changes" # Too vague!
Small, frequent commits with good messages make it easy to:
- Roll back specific changes if needed
- Understand the evolution of your code
- Collaborate with others effectively
I also like to use Codex with Cursor, which quickly creates for me commits, and often provides a “second opinion” on the code development.
5. Test After Every Change
If your project has tests:
You: Run the test suite
Codex: Running pytest...
test_utils.py::test_calculate_total PASSED
test_utils.py::test_calculate_total_with_tax PASSED
test_utils.py::test_calculate_total_empty_list PASSED
3 passed in 0.12s ✓
Never skip this step for code changes. Codex is smart, but tests catch mistakes.
6. Use Branches for Experiments
# Before trying something new or risky
git checkout -b experiment-codex-refactor
# If it works great
git checkout main
git merge experiment-codex-refactor
# If it doesn't work
git checkout main
git branch -D experiment-codex-refactor # Discard the experiment
Branches are cheap. Use them liberally to experiment safely.
Practice Exercise
Before moving to Part 3, try this exercise to build confidence:
The Safe Edit Challenge
- Choose a small project (or create a test one)
- Create a branch for Codex experiments:
git checkout -b codex-practice - Start Codex and begin in Read Only:
/approvals→ Select 1 - Explore the code - Ask Codex to explain 2-3 functions
- Switch to Default mode:
/approvals→ Select 2 - Make three small edits:
- Add a docstring to a function
- Fix a typo in a comment
- Add a simple assertion to a test
- Use
/diffafter each change to review what Codex did - Run tests after each change to verify nothing broke
- Commit each change separately with descriptive messages
Goal: Get comfortable with the workflow:
Explore (Read Only) → Plan → Edit (Default) → /diff → Review → Test → Commit
Bonus challenge:
- Try switching to Full Access mode briefly (only if you feel confident and sure about it), then back to Default
- Notice how Codex behaves differently in each mode
- Check
/approvalsfrequently to see which mode you’re in
Success criteria:
- You feel confident switching between modes
/diffbecomes automatic before every commit- You understand when to use each mode
What’s Next
You now understand how to control Codex with permissions and approvals, and how to make safe edits using the essential commands.
In Part 3, we’ll explore practical, real-world workflows:
- Blog writing workflows: Editorial review, front matter consistency, SEO optimization
- Python development workflows: Refactoring with tests, adding type hints, debugging failures
- Multi-file operations: How to coordinate changes across multiple files safely
- Real examples: Step-by-step walkthroughs of complete tasks from start to finish
These workflows will show you how to combine the modes and commands from today into productive patterns you’ll use daily.
Closing Thoughts
The key to productive work with Codex is understanding that you are always in control.
I appreciate how Codex makes the security model transparent and adjustable. When I check /approvals, I see exactly which mode I’m in and what Codex can do. The three-mode system is simple to understand:
- Read Only when I want to explore safely
- Default for everyday work (my go-to mode)
- Full Access only when I need it (rarely)
The separation between permissions (what Codex can do) and approvals (when it must ask) is elegant in concept. But in practice, the unified modes make it even simpler—I just pick the mode that matches my task, and both permissions and approvals are set appropriately.
Start conservative. Review everything with /diff. Build trust gradually through experience. And always remember: Codex is a tool that amplifies your skills and productivity, not a replacement for your judgment.
In the next post, we’ll put these fundamentals to work with real workflows that solve actual problems. I think you will find that once you have these controls in your muscle memory, Codex becomes genuinely useful for daily work—not just a novelty, but a practical productivity multiplier.
Happy coding!
Did you like this post? This is Part 2 of a 4-part series on Codex CLI.