Codex CLI Multi-Directory Workflows: Coordinating Cross-Repo Changes with --add-dir, Writable Roots, and Permission Profiles
Codex CLI Multi-Directory Workflows: Coordinating Cross-Repo Changes with –add-dir, Writable Roots, and Permission Profiles
Real-world product work rarely fits inside a single directory. A feature ticket that touches a React frontend, a FastAPI backend, and a shared types package requires coordinated edits across three separate trees — often three separate Git repositories. Codex CLI’s default workspace-write sandbox restricts writes to the current working directory 1, which is exactly the safety boundary you want until it becomes the thing blocking your agent from finishing the job.
This article covers every mechanism Codex CLI provides for safe multi-directory access: the --add-dir flag, writable_roots in config.toml, the newer permission profiles with :project_roots, and AGENTS.md hierarchical loading across directory boundaries.
The Problem: One Workspace, Many Repos
Consider a typical polyrepo layout:
~/code/
acme-frontend/ # Next.js app
acme-api/ # FastAPI service
acme-shared/ # Shared TypeScript types + Python models
You launch Codex from acme-api/ and ask it to add a new endpoint together with the corresponding frontend component and shared type definition. Under the default workspace-write sandbox, Codex can read files anywhere the OS allows, but it can only write inside ~/code/acme-api/ 1. Any attempt to create a file in acme-frontend/ or acme-shared/ is blocked by the sandbox before the patch reaches the filesystem.
The naive escape hatch — --sandbox danger-full-access — removes all filesystem restrictions 2. That is a sledgehammer when you need a scalpel. The safer approach is to widen the writable boundary just enough.
–add-dir: The CLI Flag for Ad-Hoc Multi-Directory Access
The --add-dir flag grants additional directories write access alongside the main workspace 3. It can be repeated for multiple paths:
codex --cd ~/code/acme-api \
--add-dir ~/code/acme-frontend \
--add-dir ~/code/acme-shared \
"Add a GET /users/:id endpoint, the shared User type, and the frontend UserProfile component"
Key behaviours:
- Does not change the working directory. The agent’s
cwdremainsacme-api/. The additional directories are mounted as writable roots within the sandbox 3. - Each path must exist before Codex starts. Non-existent paths are silently ignored.
- Scope narrowly. Granting write access to
/homeor/etcdefeats the purpose of sandboxing 4. - Works with
codex exectoo. Non-interactive automation can pass--add-diridentically, enabling CI scripts that span repositories.
flowchart LR
subgraph Sandbox["workspace-write sandbox"]
CWD["acme-api/ (cwd)"]
FE["acme-frontend/ (--add-dir)"]
SHARED["acme-shared/ (--add-dir)"]
end
READONLY[".git/ directories (always read-only)"]
BLOCKED["Everything else (blocked)"]
CWD -->|write| Sandbox
FE -->|write| Sandbox
SHARED -->|write| Sandbox
Sandbox -.->|read-only| READONLY
Sandbox -.->|denied| BLOCKED
Platform-Specific Sandbox Enforcement
The writable-root boundary is enforced by platform-native mechanisms, not just prompt instructions 5:
- macOS: Seatbelt SBPL profiles enumerate each writable path explicitly.
- Linux: Bubblewrap bind-mounts only the specified directories as read-write.
- Windows: DACL grants restrict token access to the listed paths.
This means an agent cannot circumvent the restriction by running mv or ln -s — the kernel-level sandbox blocks it.
writable_roots in config.toml: Persistent Multi-Directory Access
If you routinely work across the same set of directories, baking them into your configuration avoids repetitive flags:
# ~/.codex/config.toml
sandbox_mode = "workspace-write"
[sandbox_workspace_write]
writable_roots = [
"/Users/you/code/acme-frontend",
"/Users/you/code/acme-shared",
]
network_access = false
The writable_roots array accepts absolute paths 6. They are merged with the current working directory at startup — any directory in the list becomes writable for every session launched under this configuration.
Project-Scoped Configuration
For team-shared setups, place the configuration in the project’s .codex/config.toml:
# ~/code/acme-api/.codex/config.toml
[sandbox_workspace_write]
writable_roots = [
"../acme-frontend",
"../acme-shared",
]
Relative paths are resolved from the project root 7. This approach commits the multi-directory boundary into the repository, so every team member gets the same access scope without remembering flags.
Permission Profiles: Fine-Grained Filesystem Control
Codex v0.124+ introduced named permission profiles that replace the flat sandbox_mode + writable_roots pattern with a richer policy language 8. Profiles let you define per-path access levels, deny specific file patterns, and scope permissions relative to detected project roots.
# ~/.codex/config.toml
default_permissions = "polyrepo"
[permissions.polyrepo.filesystem]
":project_roots" = { "." = "write", "**/*.env" = "none", "**/.git/**" = "read" }
"/Users/you/code/acme-frontend" = "write"
"/Users/you/code/acme-shared" = "write"
glob_scan_max_depth = 3
[permissions.polyrepo.network]
enabled = false
The :project_roots placeholder is resolved dynamically based on project_root_markers (defaulting to [".git", ".hg", ".sl"]) 9. This means you can define a single profile that works across any project without hardcoding paths for the primary workspace.
Denying Sensitive Paths
The "none" access level prevents both reads and writes, which is useful for ensuring the agent never touches secrets files even when the parent directory is writable:
[permissions.polyrepo.filesystem]
":project_roots" = { "." = "write" }
"**/*.env" = "none"
"**/.env.local" = "none"
"**/secrets/**" = "none"
Built-In Profiles
Codex ships three built-in profiles 8:
| Profile | Behaviour |
|---|---|
:read-only |
No writes, no command execution |
:workspace |
Writes within detected project roots |
:danger-no-sandbox |
Unrestricted access |
Custom profiles (without the leading colon) layer on top of these defaults.
AGENTS.md Across Directory Boundaries
When Codex operates across multiple directories, each directory can carry its own AGENTS.md. Codex concatenates instruction files from the project root downward to the current working directory 10, but --add-dir directories have their own project roots and their own AGENTS.md hierarchies.
Practical Pattern: Polyrepo AGENTS.md
Place a root-level AGENTS.md in each repository describing its conventions:
~/code/acme-api/AGENTS.md → Python/FastAPI conventions
~/code/acme-frontend/AGENTS.md → TypeScript/Next.js conventions
~/code/acme-shared/AGENTS.md → Shared type generation rules
When Codex works across all three via --add-dir, it discovers and loads each repository’s AGENTS.md independently. The agent sees the combined context and can respect per-repository conventions — using pytest for the backend and vitest for the frontend, for instance.
The Override Mechanism
AGENTS.override.md at any level temporarily replaces the base AGENTS.md at that level without deleting it 10. This is particularly useful in polyrepo setups where you want to inject cross-cutting instructions:
~/code/acme-api/AGENTS.override.md
# Cross-Repo Sprint Rules (temporary)
When modifying shared types in acme-shared/, always update the
corresponding Pydantic model in acme-api/models/ AND the Zod
schema in acme-frontend/schemas/.
Remove the override file to restore normal guidance.
Worked Example: End-to-End Feature Across Three Repos
# Launch Codex with all three repos writable
codex --cd ~/code/acme-api \
--add-dir ~/code/acme-frontend \
--add-dir ~/code/acme-shared \
--sandbox workspace-write
Inside the session:
You: Add a "user preferences" feature:
1. Shared type UserPreferences in acme-shared/types/
2. GET/PUT /users/:id/preferences endpoints in acme-api/
3. PreferencesPanel component in acme-frontend/components/
4. Tests for all three
Codex reads the AGENTS.md from each repository, generates the shared type first (since both downstream repos depend on it), then creates the API endpoints and frontend component. The sandbox allows writes to all three directories but blocks any attempt to modify files outside them.
Reviewing Changes Across Repos
After the agent finishes, review changes per repository:
cd ~/code/acme-shared && git diff
cd ~/code/acme-api && git diff
cd ~/code/acme-frontend && git diff
Each repository maintains its own Git history. Codex does not attempt cross-repo commits — that remains a human decision 11.
Non-Interactive Automation with codex exec
The --add-dir flag works identically in non-interactive mode 12, enabling CI pipelines that span repositories:
codex exec \
--cd ~/code/acme-api \
--add-dir ~/code/acme-frontend \
--add-dir ~/code/acme-shared \
--sandbox workspace-write \
"Update all OpenAPI client stubs from the latest acme-api spec"
Combine with --output-schema for structured reporting:
codex exec \
--cd ~/code/acme-api \
--add-dir ~/code/acme-frontend \
--output-schema '{"type":"object","properties":{"files_changed":{"type":"array","items":{"type":"string"}},"repos_affected":{"type":"array","items":{"type":"string"}}}}' \
"Synchronise shared types and regenerate all downstream stubs"
Known Limitations and Caveats
-
Diff panel scope. The TUI diff panel currently shows changes relative to the primary
cwdrepository. Changes in--add-dirdirectories may not appear in the inline diff viewer 11. Usegit diffin each repo after the session. -
Linux –add-dir bug (pre-v0.122). Versions before v0.122 had a bug where
--add-dirdid not correctly propagate to the Bubblewrap sandbox on some Linux distributions. The workaround was to usewritable_rootsinconfig.tomlinstead 13. This has been addressed in subsequent releases. -
AGENTS.md size limit. Combined instruction files across all directories are capped at
project_doc_max_bytes(32 KiB by default) 10. With three verbose AGENTS.md files, you may hit this limit. Keep instructions concise or raise the cap. -
No cross-repo Git operations. Codex treats each repository’s
.git/directory as read-only 5. The agent cannot create branches or commits spanning multiple repos. Orchestrate that from your shell or CI script. -
Context window pressure. Reading files from three repositories consumes context rapidly. Consider using
/compactproactively or configuringmodel_auto_compact_token_limitwhen working across large codebases 14.
Decision Framework
flowchart TD
A["Need writes outside cwd?"] -->|No| B["Default workspace-write is fine"]
A -->|Yes| C["Same dirs every session?"]
C -->|No| D["Use --add-dir flags"]
C -->|Yes| E["Add writable_roots to config.toml"]
E --> F["Need per-path deny rules?"]
F -->|Yes| G["Use permission profiles"]
F -->|No| H["writable_roots array is sufficient"]
D --> I["Need CI automation?"]
I -->|Yes| J["Pass --add-dir to codex exec"]
I -->|No| K["Interactive session with --add-dir"]
Summary
Codex CLI provides a graduated set of tools for multi-directory work, from the quick --add-dir flag for ad-hoc sessions, through persistent writable_roots for habitual patterns, to full permission profiles for enterprise-grade filesystem policies. The key principle: widen the sandbox boundary just enough for the task, never more.
For polyrepo teams, the combination of per-repo AGENTS.md files, project-scoped .codex/config.toml with relative writable_roots, and AGENTS.override.md for cross-cutting sprint rules creates a configuration surface that scales from solo developer to large engineering organisation without sacrificing the safety guarantees that make agent-assisted development trustworthy.
Citations
-
Sandbox — Codex Concepts, OpenAI Developers — workspace-write mode restricts writes to the primary workspace directory. ↩ ↩2
-
Sandbox — Codex Concepts, OpenAI Developers —
danger-full-accessremoves all filesystem and network restrictions. ↩ -
Features — Codex CLI, OpenAI Developers —
--add-dirgrants additional directories write access alongside the main workspace. ↩ ↩2 -
Command line options — Codex CLI, OpenAI Developers — safety guidance on scoping writable directories narrowly. ↩
-
Sandbox — Codex Concepts, OpenAI Developers — platform-native enforcement via Seatbelt, Bubblewrap, and Windows DACL. ↩ ↩2
-
Configuration Reference — Codex, OpenAI Developers —
sandbox_workspace_write.writable_rootsaccepts an array of absolute paths. ↩ -
Config basics — Codex, OpenAI Developers — project-scoped
.codex/config.tomlconfiguration layering. ↩ -
Advanced Configuration — Codex, OpenAI Developers — named permission profiles with filesystem and network policies. ↩ ↩2
-
Advanced Configuration — Codex, OpenAI Developers —
:project_rootsplaceholder andproject_root_markersconfiguration. ↩ -
Custom instructions with AGENTS.md — Codex, OpenAI Developers — hierarchical AGENTS.md discovery and
project_doc_max_byteslimit. ↩ ↩2 ↩3 -
Multi-repo support — GitHub Issue #11956, openai/codex — diff panel limitations and cross-repo change review. ↩ ↩2
-
Non-interactive mode — Codex, OpenAI Developers —
codex execsupports the same flags as interactive mode. ↩ -
–add-dir write access bug — GitHub Issue #18448, openai/codex — Linux sandbox propagation bug and
writable_rootsworkaround. ↩ -
Context compaction — Codex, OpenAI Developers —
model_auto_compact_token_limitconfiguration for managing context window pressure. ↩