OpenAI Codexcodex-cli 0.154 · macOS, Linux, WSL, Windows
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
26 small wins to finish your pathNext lesson

Rules: what may leave the sandbox

Lesson 4 ended with a question: what about the one command that genuinely needs to leave the boundary? A rule is how you name it, and only it.

Rules live in a .rules file inside a rules/ folder next to a config layer, for example ~/.codex/rules/default.rules. They are experimental, and the docs say so.

python
prefix_rule(
    pattern = ["gh", "pr", "view"],
    decision = "prompt",
    justification = "Viewing PRs is allowed with approval",
    match = [
        "gh pr view 7888",
        "gh pr view --repo openai/codex",
    ],
    not_match = [
        "gh pr --repo openai/codex view 7888",
    ],
)

Read it in four parts. The pattern is an exact command prefix. The decision is what happens when it matches. The justification is what you will be shown when it does. And the two lists are inline tests: examples that should match, and examples that should not.

Those test lists are the point

A rule is a security boundary written as a string match, which is exactly the kind of thing that is wrong in a way nobody notices. The not_match example above is the lesson: gh pr --repo x view 7888 does not match, because the pattern has to be an exact prefix and the flag moved.

Write the awkward cases into not_match as you think of them. It is the cheapest review your rules will ever get.

The decisions

DecisionWhat it does
allowThe default. The command may run
promptAsk before running it
forbiddenBlock it without asking

When more than one rule matches, Codex applies the most restrictive decision. So a forbidden rule cannot be undone by a broader allow, which is the behaviour you want from a deny list.

How wide to make a pattern
Prefer narrow prefixes. ["gh", "pr", "view"] is a rule about reading pull requests. ["gh"] is a rule about anything the GitHub CLI can do, including closing and merging.
Try it yourself
  • Write a rule for the one command your workflow needs outside the sandbox.
  • Add a not_match line for the version of that command you would not want allowed.

You understood something today that you didn't yesterday.