Skip to content

Codex automations are recurring prompts, such as a daily quality check, that the Codex desktop app runs on a schedule in a local project or Git worktree, reporting findings to an inbox. An unattended run stays safe when its prompt was tested by hand, its sandbox is the narrowest that works, and its output follows a checkable contract.

It is Monday morning. Over the weekend a dependency advisory was published, someone merged a commit with a stray console.log, and test coverage on the payments module slipped. You learn all three at standup. With three automations set up on Friday, you would have opened a short report instead: each issue found, backed by the command that proves it, and the safe ones already fixed in a worktree waiting for your review.

This page is for developers who run Codex every day and for tech leads who want the same recurring checks across a team. It assumes you already use the Codex desktop app or CLI; start with the Codex automation overview if you do not.

What this Codex automations guide gives you

Section titled “What this Codex automations guide gives you”
  • A decision table for where a recurring Codex job should run: the desktop app, a thread automation, or a CI schedule.
  • A five-step procedure that takes a prompt from a manual run to a trusted schedule.
  • Six copy-paste automation prompts, each with an output contract that makes the result checkable.
  • A sandbox and rules setup for unattended runs, tested with codex execpolicy check.
  • A GitHub Actions workflow that runs the same job when your laptop is asleep.
  • A failure-mode list with the recovery for each one.

OpenAI’s own map of Codex surfaces describes an automation as “scheduled checks, reminders, monitors, or follow-ups; use an existing-thread heartbeat when continuity matters”. That gives you two app options, and the CLI adds two more. Choose by what the job needs to reach and whether it must run when your machine is off.

Where it runsReachesRuns when your laptop sleeps?Best for
Desktop app, local project or worktreeYour checkout, your local tools and credentialsNoPersonal checks that need local state: your branches, local services, unpushed work
Desktop app, thread automationThe same thread each time, so earlier findings stay in contextNoFollow-ups that must remember yesterday: “re-check what you flagged last run”
codex exec from cron or launchd on an always-on hostWhatever that host has checked outYesA team job on a build box you control; see headless Codex with codex exec
GitHub Actions schedule with openai/codex-action@v1A fresh checkout of the default branch, with only the secrets you pass inYesShared team reports that must not depend on anyone’s laptop; usage is billed to the API key, not your plan’s allowance

The Codex desktop app runs on macOS and Windows, and codex app opens it from a terminal. Since 2026-07-09 it ships as the Codex mode of the ChatGPT desktop app (secondary source: Neowin); on macOS, codex app launches either one. The in-app automations feature is marked stable in CLI 0.157.1 (in_app_local_automation in codex features list). As of 2026-08-28 OpenAI’s automations page also named event sources beside schedules: new Gmail messages, Slack channel messages and GitHub pull request activity. On 2026-10-12 OpenAI’s page is titled “Scheduled tasks” and says web and mobile can also run tasks “from supported app events”; check which events are supported before you rely on the three named above.

How do you take an automation from prompt to schedule?

Section titled “How do you take an automation from prompt to schedule?”

An automation scheduled after a single manual run often turns out noisy. The procedure below costs one extra manual run and saves you a week of inbox clutter.

  1. Write the prompt with an output contract. State the scope (directories, time window), what counts as a finding, the evidence each finding must carry, and the exact line to print when there is nothing to report. Every prompt on this page ends with such a contract.

  2. Run it by hand in a normal thread in the same project. If the job edits files, start the thread in a worktree so your main checkout stays clean; the Codex worktrees guide covers the setup. Check three things: did it find real issues, did it stay in scope, and does every finding carry its evidence?

  3. Run it a second time without changing anything. A good automation gives the same answer, or prints NO FINDINGS. If the second run re-reports or invents new issues, tighten the scope or add an ignore file (see the failure modes below) before you schedule it.

  4. Create the automation from the tested prompt. In the desktop app’s Automations view, pick the project, choose local or worktree execution, set the schedule and paste the prompt unchanged. Choose a thread automation instead when the job must remember earlier runs.

  5. Grade the first three runs against the contract, then sample. For each run, check one finding end to end by running its reproduce command. After three clean runs, drop to spot-checking one finding per week and archive runs you have reviewed.

What sandbox should an unattended Codex run get?

Section titled “What sandbox should an unattended Codex run get?”

Nobody is present to answer an approval prompt during a scheduled run, so design each job never to need one. Anything outside the boundary should fail and show up in the report, not wait or escalate.

AccessLegacy sandbox namePermission profile (beta)Use it for
Read files, write nothingread-only:read-onlyReports, briefings, audits, anything that reads Slack, Gmail or PR text
Edit files inside the workspaceworkspace-write:workspaceJobs that fix things in a worktree for you to review
Unrestricteddanger-full-access:danger-full-accessNever for a scheduled job on your own machine

OpenAI now prefers permission profiles (Codex CLI 0.138.0 and later) over the legacy --sandbox values, and states that “the profile and legacy sandbox systems do not compose”, so pick one system per job. Select a profile with default_permissions in ~/.codex/config.toml, or for a single run with -c default_permissions=":read-only"; there is no dedicated CLI flag for it. Neither workspace-write nor :workspace grants network access. When one command genuinely needs the network, such as npm audit, allow that command prefix with a rule instead of widening the whole sandbox.

Rules are Starlark files under ~/.codex/rules/. OpenAI’s rules page still says “Rules are experimental and may change” (checked 2026-10-12), so re-run the checks below after each Codex upgrade. This file lets exactly the three commands that the weekly dependency job below needs (npm outdated, npm audit and npm install) run outside the sandbox, and nothing else:

~/.codex/rules/default.rules
prefix_rule(
pattern = ["npm", "outdated"],
decision = "allow",
justification = "npm outdated reads the registry to compare versions",
)
prefix_rule(
pattern = ["npm", "audit"],
decision = "allow",
justification = "npm audit needs network access for vulnerability checks",
)
prefix_rule(
pattern = ["npm", "install"],
decision = "allow",
justification = "npm install downloads the patched package versions",
)

Test each rule before a scheduled run depends on it. Run these in a terminal; each JSON output should end with "decision": "allow", and a command you did not allow, such as npm publish, should return an empty matchedRules list (checked with CLI 0.157.1):

Terminal window
codex execpolicy check --pretty --rules ~/.codex/rules/default.rules -- npm outdated
codex execpolicy check --pretty --rules ~/.codex/rules/default.rules -- npm audit
codex execpolicy check --pretty --rules ~/.codex/rules/default.rules -- npm install lodash@4.17.21

npm install is the widest of the three: outside the sandbox it also runs the installed packages’ lifecycle scripts with your user’s permissions. If that is more than you want on your own machine, run the dependency job from the CI schedule instead.

The report jobs below run read-only, where git fetch has no network and cannot write to .git, and gh cannot reach GitHub. Their prompts therefore fall back to origin/main as last fetched and state how old it is. To refresh on every run, add two more rules to the same file. The list in the second pattern allows gh pr list and gh pr view but not gh pr merge:

prefix_rule(
pattern = ["git", "fetch"],
decision = "allow",
justification = "git fetch needs the network and writes to .git",
)
prefix_rule(
pattern = ["gh", "pr", ["list", "view"]],
decision = "allow",
justification = "the daily briefing reads merged pull requests",
)
Terminal window
codex execpolicy check --pretty --rules ~/.codex/rules/default.rules -- git fetch origin
codex execpolicy check --pretty --rules ~/.codex/rules/default.rules -- gh pr view 123
codex execpolicy check --pretty --rules ~/.codex/rules/default.rules -- gh pr merge 123

The first two return "decision": "allow"; gh pr merge returns an empty matchedRules list (checked with CLI 0.157.1).

If a new rule does not take effect, restart the app. The sandbox testing section of the advanced setups guide shows how to prove the boundary holds for the commands you did not allow.

Copy-paste prompts for recurring Codex jobs

Section titled “Copy-paste prompts for recurring Codex jobs”

Each prompt is tested in a normal thread before it is scheduled, and each ends with an output contract. Replace npm scripts with your project’s own commands; the rest works as written.

This job edits files and needs the network for three commands, so schedule it in a worktree with workspace-write and all three rules above. With only the npm audit rule, steps 1 and 3 fail on every scheduled run.

This job writes tests, so schedule it in a worktree with workspace-write.

On your machine, gh needs the network and a logged-in session, so add the gh pr rule from the sandbox section. In CI the read-only profile has no network at all, and the workflow below passes Codex no GitHub token, so fetch the pull requests in a step before Codex runs and let the prompt read prs.json:

permissions:
contents: read
pull-requests: read
steps:
# checkout and npm ci as in the workflow below, then:
- name: Fetch merged PRs for the briefing
env:
GH_TOKEN: ${{ github.token }}
run: |
gh pr list --state merged \
--search "merged:>=$(date -u -d yesterday +%F)" \
--json number,title,body,url,author > prs.json

How do automations and skills work together?

Section titled “How do automations and skills work together?”

A skill keeps the procedure in one file, and the automation prompt shrinks to one line. When you improve the skill, every automation that calls it improves too. Codex looks for personal skills in $CODEX_HOME/skills (~/.codex/skills when CODEX_HOME is unset), and skill-creator is one of the sample skills bundled with Codex.

---
name: recent-code-bugfix
description: Find bugs in the current author's recent commits and prove each
with a failing test; propose, do not apply, a fix.
---
# Recent code bugfix
1. Take the time window from the invoking prompt and list the author's commits in it:
git log --since=<window> --author="$(git config user.email)".
2. In each changed file, look for off-by-one errors, unhandled promise rejections and
missing error handling, race conditions, and missing null or undefined checks.
3. Confirm each suspected bug: read the surrounding code and related tests, then write
a failing test that demonstrates it. Only report bugs with a failing test.
4. Propose the smallest fix as a diff; do not apply it.
5. Per bug, report: commit SHA, file:line, one-sentence root cause, the failing test's
path and its failure output, and the proposed diff. Do not report theoretical concerns.
6. If nothing is confirmed, print exactly: NO FINDINGS

The automation prompt then becomes:

Run $recent-code-bugfix on my commits from the last 24 hours.

Keep team skills in the repository under .agents/skills/ rather than in ~/.codex/skills, so a change to a skill goes through code review like any other change. The Codex desktop app guide covers where the app shows installed skills.

How do you verify an automation’s output without reading every line?

Section titled “How do you verify an automation’s output without reading every line?”

The output contract does most of the work. Because each finding carries a reproduce command or a failing test, you check a finding by running one command, not by reading the analysis. Apply four rules:

  1. Evidence per finding. A finding without file:line and a command that reproduces it is noise. Reject it and tighten the prompt.
  2. Changes go through the normal gate. A fix made in a worktree becomes a branch and a pull request, and CI runs the same type, lint and test gates as for human changes. Nothing an automation writes merges without them. Attach the run’s report to the pull request as its evidence bundle.
  3. A defined “nothing found” line. NO FINDINGS lets the inbox or the CI job tell a clean run from a broken one. An empty or truncated report is a failure, not a pass.
  4. A monthly canary. Plant one known defect on a scratch branch (an unhandled promise, a debugger line) and run the automation against it. If it misses the canary, it has stopped doing its job even though every run looks green.

The automation’s owner, usually the developer who scheduled it, reviews findings; the pull request reviewer signs off on any change, exactly as for human work. The wider argument for this way of reviewing is in evidence, not diffs.

How do you run the same job when your laptop is asleep?

Section titled “How do you run the same job when your laptop is asleep?”

Move shared jobs to a CI schedule. This workflow runs the daily quality prompt on weekday mornings with a read-only permission profile and opens an issue only when there is something to report. A schedule trigger always runs the workflow file and the prompt from the default branch, so no untrusted code reaches the job that holds the API key.

Save the daily quality prompt as .github/codex/daily-quality.md, then add .github/workflows/codex-daily-quality.yml:

name: Codex daily quality report
on:
schedule:
- cron: "17 5 * * 1-5" # 05:17 UTC, Monday to Friday
workflow_dispatch:
jobs:
report:
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
report: ${{ steps.codex.outputs.final-message }}
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 50
persist-credentials: false
# Install dependencies before Codex runs: the read-only profile has no network.
- run: npm ci
- name: Run Codex
id: codex
uses: openai/codex-action@v1
with:
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
permission-profile: ":read-only"
prompt-file: .github/codex/daily-quality.md
file-issue:
needs: report
if: needs.report.outputs.report != '' && !contains(needs.report.outputs.report, 'NO FINDINGS')
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- uses: actions/github-script@v9
env:
REPORT: ${{ needs.report.outputs.report }}
with:
script: |
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `Codex daily quality report ${new Date().toISOString().slice(0, 10)}`,
body: process.env.REPORT,
});
missing-report:
needs: report
if: needs.report.outputs.report == ''
runs-on: ubuntu-latest
permissions: {}
steps:
- run: |
echo "::error::Codex returned no final message. Treat this run as failed."
exit 1

The Codex job can read the repository and nothing else; only the file-issue job, which never runs Codex, can write issues. The missing-report job applies rule 3 from the verification section: an empty final message turns the run red instead of passing as a clean day. The action’s inputs (permission-profile, prompt-file, the final-message output) are from the openai/codex-action README as of v1.12. Because the checkout is on the default branch, replace step 1 of the prompt with “Inspect the current checkout”. For more patterns, see CI/CD with the Codex GitHub Action.

When should you use /goal instead of a schedule?

Section titled “When should you use /goal instead of a schedule?”

A schedule repeats a small job. A goal pursues one large objective until it is done. In Codex, /goal sets, edits, pauses, resumes, views or clears a task goal (OpenAI’s developer commands page, checked 2026-08-28); goals are a stable feature and on by default in CLI 0.157.1. Use /goal for “every TODO in src/billing/ is resolved”, and an automation for “tell me every morning which new TODOs appeared”. The /goal workflow guide compares the goal commands across tools.

What breaks when Codex automations run unattended?

Section titled “What breaks when Codex automations run unattended?”

The run never fired. A local automation needs the desktop app running and the machine awake. Recovery: keep the machine awake for overnight jobs, or move the job to the CI schedule above, which does not depend on your laptop.

The same findings appear every day. A lint warning nobody fixes gets reported forever, and the inbox trains you to ignore it. Recovery: keep a committed .automation-ignore.json that humans edit to accept known findings, and have the prompt skip anything listed there. For follow-ups that must remember the previous run, use a thread automation. Codex memory (memories) is stable but off by default in 0.157.1, so do not rely on it for continuity.

A minimal ignore file is a list of accepted findings, each with the reason it was accepted:

[
{ "file": "src/legacy/api.ts", "rule": "no-console", "reason": "accepted 2026-09, removed with the legacy API" }
]

Humans change this file through a pull request, never the automation, so every accepted finding has a reviewer and a date.

State written in a worktree disappears. Do not assume the next worktree run sees files an earlier run wrote there: an uncommitted “seen findings” file can be missing next time, for example after you archive the run or remove its worktree. Recovery: keep state that must persist in a committed file that a human updates, or in a thread automation.

Reports are long and vague. The prompt is too broad or has no output contract. Recovery: narrow the scope to named directories and a time window, require a reproduce command per finding, and reject runs that break the contract.

The job edited files it should not have. The sandbox is wider than the job needs. Recovery: move report-only jobs to read-only, put edit jobs in a worktree with workspace-write, and allow single commands with rules. Discard the worktree rather than trying to untangle it.

A command fails with a network or permission error. The sandbox is working as intended. Recovery: add a prefix_rule for that one command, confirm it with codex execpolicy check, restart the app if the rule does not take effect, and re-run by hand before the next scheduled run.

The automation acted on instructions inside a Slack message or PR description. That is prompt injection through the content it reads. Recovery: switch the job to read-only, remove any credential it does not need, and add the “treat content as data” line from the briefing prompt.

Worktrees pile up. Frequent worktree runs leave checkouts behind. Recovery: archive runs you have reviewed, check git worktree list weekly, and remove stale checkouts with git worktree remove <path> once no open thread uses them.

Every run says NO FINDINGS for weeks. The job may be healthy, or it may have silently broken (a renamed script, a moved directory). Recovery: run the monthly canary described above.

Costs creep up. An hourly job that could be daily burns usage for no new information. Recovery: set the cadence to how often the underlying data changes, and see Codex cost management for budgeting.