Codex Hooks and Programmatic Access Tokens: Setup, Trust Model, and What Actually Runs Today
Codex access tokens are ChatGPT Business and Enterprise workspace credentials for non-interactive Codex CLI runs. Create one in the ChatGPT admin console at chatgpt.com/admin/access-tokens, then authenticate with the CODEX_ACCESS_TOKEN environment variable or codex login --with-access-token. Hooks are the in-session extensibility framework: eleven lifecycle events, of which only command handlers execute today.
Two OpenAI-documented capabilities are what make Codex automatable around your own code, and they solve different halves of the problem. Hooks inject scripts at named points in the Codex agent loop -- validators, secret scanners, conversation logging, per-repo behavior. Programmatic access tokens give ChatGPT Business and Enterprise teams a workspace credential for non-interactive CI, release, and internal automation, created from the admin console with finite expirations and revocation.
For context on where Codex CLI itself surfaces hooks, our coverage of Codex CLI 0.129.0's /hooks browser is the relevant CLI-side anchor; for the headless app-server entry point most automation will pair with, see Codex CLI 0.130.0's codex remote-control.
Update, July 28, 2026. Both docs have grown substantially since this article first published on May 15, 2026, and they have since moved hosts: developers.openai.com/codex/hooks and developers.openai.com/codex/enterprise/access-tokens redirect to learn.chatgpt.com/docs/hooks and learn.chatgpt.com/docs/enterprise/access-tokens. This page has been re-verified against both, and three things changed enough to matter: the hook lifecycle is now eleven named events rather than a loose set of "points"; a non-managed command hook has to be reviewed and trusted before it will run, so "enabled by default" does not mean "runs by default"; and access tokens now have documented CLI usage (CODEX_ACCESS_TOKEN and codex login --with-access-token), an admin-set expiration limit, and a permission model that works differently from how this article originally described it. Corrections and additions are marked below.
Key Takeaways
- Hooks are an extensibility framework, not a single feature. They inject scripts at eleven named lifecycle events, from
SessionStartthroughStop. - Enabled by default is not the same as trusted. A non-managed command hook is skipped until you review and trust it in
/hooks; trust is recorded against the hook's hash, so editing a hook re-arms the review. - Only
type: "command"handlers execute today.promptandagenthandlers are parsed but skipped, and theasyncoption is parsed without asynchronous hooks being supported yet. - Hooks are a guardrail, not an enforcement boundary. Hosted tools such as
WebSearchnever hit the local hook path, and the docs say so explicitly. - Enterprise-managed hooks are defined inline in
requirements.toml, and admins can pin thehooksfeature on or off there regardless of local config. - Access tokens authenticate non-interactive Codex CLI and app-server runs with a ChatGPT workspace identity. Business and Enterprise workspaces only, created at
chatgpt.com/admin/access-tokens. - Use
CODEX_ACCESS_TOKENfor ephemeral runs,codex login --with-access-tokenfor a persistent local login. Copy the token at creation; you cannot view it again. - A token carries its creator's access. The workspace permission governs who may create tokens, not what a token may do -- you narrow it by owner, expiration, and the runner's permission profile.
What Hooks Actually Do
The official Hooks docs describe an extensibility framework, not a single feature. The patterns called out:
- Logging and analytics. Forward agent activity to internal observability systems for review, audit, or quality scoring.
- Block pasted API keys. Pre-prompt hooks that scan input for credentials and refuse to forward them to the model.
- Persistent memories. Hooks that read and write durable state across runs, materializing repo-specific or directory-specific behavior.
- Validation at turn stop. Run a validator (typecheck, lint, custom rule) when the agent finishes a turn and surface failures.
- Directory-based prompting. Customize behavior per repo or per directory so the agent treats different parts of a codebase with different policies.
Hooks are enabled by default. Codex discovers them next to active config layers, either as a hooks.json file or as inline hooks tables inside config.toml; installed plugins can bundle their own through a plugin manifest. In practice the four locations that matter are ~/.codex/hooks.json, ~/.codex/config.toml, <repo>/.codex/hooks.json, and <repo>/.codex/config.toml. Matching hooks from every source run -- a higher-precedence layer does not replace a lower one -- and multiple matching command hooks for the same event launch concurrently, so one hook cannot stop another from starting. Project-local hooks load only when the project's .codex/ layer is trusted.
To turn hooks off entirely, set hooks = false under [features] in config.toml. hooks is the canonical feature key; codex_hooks still works as a deprecated alias.
The Eleven Lifecycle Events
Earlier versions of this article described hook points loosely. The current doc names all eleven, which is what you actually configure against:
| Event | When it fires | What it is for |
|---|---|---|
SessionStart | Session begins: startup, resume, clear, or compact | Load conventions or session notes as developer context |
SessionEnd | Main thread ends (not for subagents) | Save final notes, clean up. Advisory only, 1s default timeout |
SubagentStart | A subagent starts | Apply per-subagent policy by agent_type |
SubagentStop | A subagent finishes | Ask Codex to continue the subagent with a reason |
UserPromptSubmit | Before a prompt is sent to the model | Scan input for credentials; inject extra context |
PreToolUse | Before a tool call | Block or rewrite the call |
PermissionRequest | Codex is about to ask for approval | Auto-approve, deny, or defer to the normal prompt |
PostToolUse | After a supported tool produces output | Review output, run checks |
PreCompact / PostCompact | Around context compaction | Persist or restore state across a compaction |
Stop | The turn stops | Run validators (typecheck, lint, custom rules) |
Every command hook receives one JSON object on stdin with at least session_id, transcript_path, cwd, hook_event_name, and model. Most turn-scoped events also carry permission_mode, whose documented values are default, acceptEdits, plan, dontAsk, and bypassPermissions.
Correction: Configured Is Not the Same as Trusted
The original version of this article said hooks are enabled by default and left it there. That is incomplete in a way that matters for anyone planning a rollout. Codex lists configured hooks before deciding which can run, and a non-managed command hook must be reviewed and trusted before it runs. Trust is recorded against the hook definition's current hash, so a new or edited hook is flagged for review and skipped until trusted. If hooks need review at startup, Codex prints a warning pointing you at /hooks.
The practical consequence: you cannot ship a security hook to a team by dropping it in a repo and assuming it is active. Either the developers trust it, or it arrives through a managed source. For one-off automation that already vets hook sources outside Codex, --dangerously-bypass-hook-trust runs enabled hooks without persisted trust for that invocation.
Known Caveats Today
The docs are explicit about a gap between what the framework parses and what currently runs:
- Only
type: "command"handlers execute.promptandagenthandlers are parsed in config but skipped at runtime. asyncis parsed but not supported. Asynchronous command hooks are not available yet.- Not every tool path is covered.
PreToolUseandPostToolUsesee shell commands (matched asBash), unified exec,apply_patch(also matchingEditandWrite), MCP tools by theirmcp__server__toolname, and other local function tools. Hosted tools such asWebSearchdo not use the local hook path at all, andwrite_stdindoes not re-runPreToolUsefor a command that already passed it. - Some output fields are parsed but inert.
suppressOutputis parsed and not yet implemented;continue,stopReason, andsuppressOutputare not supported onPreToolUseorPermissionRequest, and returning them there marks the hook run as failed while the tool call continues.
The docs put the conclusion plainly: treat tool hooks as a useful guardrail, not a complete enforcement boundary. If you are designing a security or compliance posture around hooks, build for command handlers today and architect so additional handler types can plug in without re-doing the integration.
Enterprise Enforcement via requirements.toml
The enterprise lever is requirements.toml, where admins define managed hooks inline under a hooks table. That split is deliberate: the requirements file enforces the configuration while the actual scripts arrive through MDM or another device-management system. Managed hooks are trusted by policy and cannot be disabled from the user hook browser.
Two switches are worth knowing. To enforce managed hooks even for users who turned hooks off locally, pin [features].hooks = true in requirements.toml alongside the hooks table. Admins can force hooks off across the org the same way, with [features].hooks = false.
What Programmatic Access Tokens Solve
Hooks are the in-loop extensibility surface. Access tokens are the "is this Codex run actually you?" surface. Per the official access-tokens docs, Codex access tokens are ChatGPT workspace credentials scoped to Codex permissions that authenticate trusted non-interactive local workflows, including Codex CLI and app-server-based automation, with a ChatGPT workspace identity.
Concretely, that's the difference between an automated codex exec job depending on a developer's browser sign-in versus running under a credential the workspace issued and can revoke. The docs name the workflows:
codex execjobs that run from trusted automation- Local scripts that need repeatable, non-interactive Codex CLI runs
- Trusted app-server-based automation
- Enterprise workflows where usage should be associated with a ChatGPT workspace user instead of an API organization key
The docs are also clear about when not to reach for one: if a Platform API key works for your automation, keep using API key auth. And if what you actually want is to trigger a published ChatGPT workspace agent from your own system, that needs a Workspace Agent access token, which is a different credential.
How Do You Use a Codex Access Token?
Two documented paths, and which one you want depends on whether the credential should persist on the machine.
For ephemeral automation, put the token in an environment variable and run Codex CLI normally:
export CODEX_ACCESS_TOKEN="<access-token>"
codex exec --json "review this repository and summarize the top risks"
For a persistent local login, pipe the token into codex login:
printf '%s' "$CODEX_ACCESS_TOKEN" | codex login --with-access-token
codex exec "summarize the last release diff"
codex login --with-access-token stores an agent identity credential in Codex CLI auth storage. If you would rather not persist credentials on the machine, use the environment variable instead.
codex app-server can use the same credential through either path to authenticate its OpenAI requests. One caveat the docs call out and that is easy to get wrong: that credential is separate from client-to-app-server transport authentication. A remote WebSocket connection needs its own bearer or capability token, and you should not reuse the Codex access token as the transport token.
Where Is the Codex Admin Console?
Access tokens live at chatgpt.com/admin/access-tokens. Three separate controls govern them, and they sit in different places:
| Control | Where | What it does |
|---|---|---|
| Allow users to create access tokens | Workspace Settings, Permissions and roles, Access tokens section | Turns on token creation for allowed members |
| Access token expiration limit | Workspace Settings, Permissions and roles, Codex Local section | Caps the longest expiration a member may choose. Applies to new tokens only; existing tokens keep theirs |
| Allow members to use Codex Local | Workspace Settings, Permissions and roles, Codex Local section | Gates local use in the ChatGPT desktop app, Codex CLI, and IDE extension |
Creating a token is a short flow: open the Access tokens page, select Create, give it a descriptive name (the docs use release-ci and nightly-docs-check as examples), and choose an expiration. The docs recommend a finite window such as 7, 30, 60, or 90 days; the shortest custom expiration is one day, and if you pick No expiration you are expected to rotate on a schedule instead. Copy the token immediately -- you cannot view it again after closing the modal.
If the Access tokens page returns 404 or forbidden, that is the permission, not a bug: ask a workspace owner or admin to confirm your role includes token creation, and that Codex Local is enabled if your workflow needs it.
To rotate, the documented order is create the replacement, update the secret in the runner or secret manager, smoke-test with the new token, then revoke the old one. Owners and admins can revoke any workspace token; a member with the permission can revoke only tokens they created.
Correction: What the Permission Model Actually Says
An earlier version of this article read the docs' permission separation as meaning an automation token is a fresh, narrower permission surface that you provision per job. Re-checking the current doc, that is wrong, and it is wrong in the direction that makes a security design too optimistic.
What the doc actually says is that the workspace access token permission controls token creation, and that it "doesn't change a member's seat type, built-in workspace role, or local runtime permission profile." Separately, the token "represents the ChatGPT workspace user who created it, so runs can use that user's access and appear in workspace governance data." There is no per-token permission scoping documented. A token is closer to a long-lived stand-in for its creator than to a narrowly-scoped service credential.
That changes the design advice. You narrow a Codex access token by three levers, none of which is the token itself:
- Owner. Create the token under an identity whose workspace access already matches the job. Do not mint a CI token from a broadly-privileged admin account.
- Expiration. Prefer a finite window, and use the workspace expiration limit to stop members choosing forever.
- The runner. The local permission profile on the machine executing
codex execis what bounds what the run can touch. That is where least privilege actually lives.
The docs' own risk list points the same way: a leaked token lets anyone start local runs as the token creator, and shared identities make audit trails hard to interpret, so tokens should be created for a specific workflow owner and used only on trusted runners. Public CI and forked pull requests are named explicitly as places tokens get exposed.
Token Hygiene
The docs spell out the standard list, and it's worth quoting in working form:
- Store tokens in a secret manager. Never inline them in a script.
- Keep tokens out of logs (including CI logs, especially failed-build artifacts).
- Rotate on a schedule. Don't let any single token outlive its useful lifetime.
- Prefer finite expirations over indefinite ones.
- Tie tokens to the narrowest workflow that needs them; don't share one token across unrelated automations.
How a Reader Uses This
Two concrete shapes:
Pattern 1: Secret-Scan Hook + CI Token
A platform team that wants developers to use Codex but is worried about leaked credentials:
- Author a
UserPromptSubmithook that scans prompts for high-confidence credential patterns (API keys, OAuth refresh tokens, SSH private keys) before they reach the model. - Enforce it as a managed hook in
requirements.toml, and pin[features].hooks = truethere so it stays active even for developers who turned hooks off locally. Managed hooks skip the trust-review step that would otherwise leave a repo-local copy inert. - Provision a programmatic access token for the CI job that runs nightly
codex execvalidation against the main branch, created by the identity that should own that job rather than by an admin. - Bound the job on the runner, not on the token: a token carries its creator's workspace access, so the CI machine's permission profile and expiration limit are the real controls. Keep it on a trusted runner -- never one that builds forked pull requests.
Pattern 2: Per-Repo Memory + Validation
A team with multiple repos that want different agent behavior in each:
- Put a
<repo>/.codex/hooks.jsonin each repo with aSessionStarthook that loads repo-specific prompts and policies. Note the prerequisite: project-local hooks load only when that project's.codex/layer is trusted, and each hook still needs a one-time trust review. - Add a
Stophook that runs the repo's preferred validator (typecheck, lint, test) and surfaces failures back to the agent. - Add a
SessionEndhook that writes the day's work to a memory file so the next session resumes with context. Budget for its timeout:SessionEnddefaults to 1 second and supports a maximum of 3. - Resolve hook commands from the git root rather than a relative
.codex/hooks/...path -- Codex may be started from a subdirectory. - None of this requires programmatic tokens. This is all interactive-session extensibility.
When to Reach for Access Tokens Instead of Just Hooks
| You want to... | Hooks | Access tokens |
|---|---|---|
| Modify in-session behavior (validators, scanners, memory) | Yes | No |
| Enforce org-wide rules across interactive sessions | Yes (via requirements.toml) | No |
| Run Codex from a CI pipeline | Maybe (hooks still apply) | Yes -- needed for non-interactive auth |
Run scheduled codex exec jobs as a service | No | Yes |
| Audit which automation ran which Codex action | No | Yes -- usage ties back to workspace |
How This Fits With the Recent Codex Surface Expansion
OpenAI has been moving Codex onto more surfaces and into more workflows. The pattern across recent months:
- April 16, 2026: Mac computer use, browser comment mode, thread automations -- Codex on more surfaces.
- May 7, 2026: Codex CLI 0.129.0 --
/hooksbrowser in the CLI to inspect lifecycle hooks. - May 9, 2026: Codex CLI 0.130.0 --
codex remote-controlfor headless operation. - Now: Hooks framework and programmatic access tokens documented as the official automation surface.
The earlier releases shipped the CLI-level affordances (lifecycle hooks, headless entry point). This is the part where OpenAI tells developers how the automation surface is intended to be used, with enterprise-grade auth attached.
Caveats
- Handler-type gap. Only
type: "command"handlers run today;promptandagenthandlers are parsed but skipped, andasyncis parsed without asynchronous hooks being supported. Don't design critical paths around handler types that aren't executing yet. - Tool-path coverage. Hooks intercept shell, unified exec,
apply_patch, MCP tools, and other local function tools, but not hosted tools such asWebSearch. The docs' own framing: a useful guardrail, not a complete enforcement boundary. - Trust gate. A non-managed command hook does nothing until it is reviewed and trusted, and editing it re-arms the review. Only managed sources are trusted by policy.
- Business/Enterprise only. Access tokens require a ChatGPT Business or Enterprise workspace. Individual Pro/Plus users do not get them.
- No per-token scoping. A token carries its creator's workspace access. If you need a credential whose permissions differ from a human's, this is not that credential -- and if a Platform API key would do the job, the docs say to use one.
FAQ
See structured FAQ in the schema header for question-level details: what hooks do, which handlers run today, whether hooks run without being trusted, how enterprise enforcement works, what access tokens are, how to use one in CI, where the admin console is, and how the permission model actually works.
Sources
- Codex Hooks docs: https://learn.chatgpt.com/docs/hooks (re-verified 2026-08-04;
https://developers.openai.com/codex/hooksredirects here) - Codex Access tokens docs: https://learn.chatgpt.com/docs/enterprise/access-tokens (re-verified 2026-08-04;
https://developers.openai.com/codex/enterprise/access-tokensredirects here) - ChatGPT admin console, Access tokens: https://chatgpt.com/admin/access-tokens
- Codex changelog: https://learn.chatgpt.com/docs/changelog (
https://developers.openai.com/codex/changelogredirects here)
Every hook event, handler-type limitation, permission control, and expiration figure above comes from the two docs listed first, each re-fetched and checked on 2026-08-04. Codex hooks and access tokens were first flagged in a May 2026 OpenAI Developers post on X; that post is not cited here and nothing on this page rests on it, because x.com returns HTTP 402 to automated requests and a claim sourced only there cannot be re-checked.
Read next
Keep building the workspace playbookCodex CLI 0.129.0 Adds Modal Vim Composer, Redesigned Resume/Fork Picker, and a `/hooks` Browser
OpenAI shipped Codex CLI 0.129.0 on May 7, 2026. The release brings modal Vim editing to the TUI composer via `/vim`, a redesigned resume/fork picker with raw scrollback and workspace-aware `/diff`, a new `/hooks` browser with before/after compaction support, expanded plugin management with workspace sharing and access controls, theme-aware status lines, and Codex Apps auth surfaced through Guardian. Plus a long bug-fix list across Linux/Windows sandboxes, MCP, and TUI input handling.
Codex CLI 0.130.0 Adds `remote-control`, Richer Plugin Sharing Metadata, and Better App-Server Thread Paging
OpenAI shipped Codex CLI 0.130.0 in May 2026. The release adds a new `codex remote-control` command for starting a headless, remotely controllable app-server, improves app-server clients with paging options for large threads (unloaded/summary/full turn items), expands plugin sharing with link metadata and discoverability controls, adds Bedrock auth support for AWS console-login credentials from `aws login` profiles, and fixes several app-server/thread reliability issues.
Codex CLI vs Claude Code vs Cursor: 2026 Architecture Deep-Dive (Sandboxing, Context, Plugins, Scheduling)
Codex CLI, Claude Code, and Cursor all reach for the same outcome -- an AI agent that ships code -- with three different architectures. Codex enforces safety at the OS kernel layer. Claude Code uses application-layer hooks for programmable governance. Cursor builds the agent into a visual IDE with a marketplace of plugins. The right one depends less on which model you prefer and more on which architecture matches your security posture, your composition needs, and your team shape.
Frequently Asked Questions
What did OpenAI ship for Codex automation?
Two capabilities, both documented on OpenAI-owned surfaces. Hooks are an extensibility framework that injects scripts into the Codex agent loop at eleven named lifecycle events -- session start and end, prompt submission, tool calls, permission requests, context compaction, and turn stop. Programmatic access tokens are ChatGPT Business and Enterprise workspace credentials, created in the ChatGPT admin console, that authenticate non-interactive Codex CLI and app-server runs, with finite expirations and revocation.
What are Codex hooks?
Hooks are an extensibility framework for Codex. You inject scripts into the agentic loop at eleven lifecycle events: SessionStart, SessionEnd, SubagentStart, SubagentStop, PreToolUse, PermissionRequest, PostToolUse, PreCompact, PostCompact, UserPromptSubmit, and Stop. Hooks are enabled by default and configured in a hooks.json file or in inline hooks tables in config.toml, at the user, project, or plugin layer. A /hooks slash command in the CLI inspects sources, reviews changes, trusts hooks, or disables them.
What hook handlers actually run today?
Per the official docs, only type command handlers run today; prompt and agent handlers are parsed but skipped, and the async option is parsed but asynchronous command hooks are not supported yet. Hosted tools such as WebSearch do not use the local hook path at all, and the docs say to treat tool hooks as a useful guardrail rather than a complete enforcement boundary.
Do Codex hooks run automatically once configured?
No. Hooks are enabled by default as a feature, but a non-managed command hook must be reviewed and trusted before it runs. Codex records trust against the hook definition's current hash, so a new or edited hook is marked for review and skipped until you trust it in /hooks. Managed hooks from system, MDM, cloud, or requirements.toml sources are trusted by policy and cannot be disabled from the user hook browser.
How are enterprise hooks managed?
Enterprise-managed hooks are defined inline under a hooks table in requirements.toml, which is useful when admins want to enforce the configuration while delivering the scripts through MDM. To enforce managed hooks even for users who turned hooks off locally, admins pin the hooks feature flag to true in requirements.toml alongside the hooks table. Admins can also force hooks off the same way.
What are Codex programmatic access tokens?
Codex access tokens are ChatGPT workspace credentials scoped to Codex permissions that authenticate non-interactive local workflows, including Codex CLI and app-server automation. They are currently supported for ChatGPT Business and Enterprise workspaces. Use them for codex exec jobs, repeatable local scripts, trusted app-server automation, and enterprise workflows where usage should tie back to a workspace user rather than an API organization key.
How do you use a Codex access token in CI?
Two documented paths. For ephemeral automation, put the token in the CODEX_ACCESS_TOKEN environment variable and run Codex CLI normally. For a persistent local login, pipe the token into codex login --with-access-token, which stores an agent identity credential in Codex CLI auth storage. The codex app-server can use the same credential, but the docs say not to reuse a Codex access token as the WebSocket transport token.
Where is the Codex admin console for access tokens?
Access tokens live at chatgpt.com/admin/access-tokens. The permission that governs them is in Workspace Settings, Permissions and roles, under the Access tokens section as Allow users to create access tokens. The maximum expiration members may choose is set separately as Access token expiration limit in the Codex Local section of the same page. If the tokens page returns 404 or forbidden, the permission is not enabled for your role.
How are access-token permissions managed?
The workspace access token permission controls who may create tokens; it does not scope what a token can do. A token represents the ChatGPT workspace user who created it, so runs use that user's access and appear in workspace governance data. The separate Allow members to use Codex Local permission gates local client use. You narrow a token by choosing its owner, its expiration, and the runner's own permission profile -- not by scoping the token itself.