AI Catchup

Codex Hooks and Programmatic Access Tokens: Setup, Trust Model, and What Actually Runs Today

By 15 min read

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 SessionStart through Stop.
  • 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. prompt and agent handlers are parsed but skipped, and the async option is parsed without asynchronous hooks being supported yet.
  • Hooks are a guardrail, not an enforcement boundary. Hosted tools such as WebSearch never hit the local hook path, and the docs say so explicitly.
  • Enterprise-managed hooks are defined inline in requirements.toml, and admins can pin the hooks feature 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_TOKEN for ephemeral runs, codex login --with-access-token for 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:

EventWhen it firesWhat it is for
SessionStartSession begins: startup, resume, clear, or compactLoad conventions or session notes as developer context
SessionEndMain thread ends (not for subagents)Save final notes, clean up. Advisory only, 1s default timeout
SubagentStartA subagent startsApply per-subagent policy by agent_type
SubagentStopA subagent finishesAsk Codex to continue the subagent with a reason
UserPromptSubmitBefore a prompt is sent to the modelScan input for credentials; inject extra context
PreToolUseBefore a tool callBlock or rewrite the call
PermissionRequestCodex is about to ask for approvalAuto-approve, deny, or defer to the normal prompt
PostToolUseAfter a supported tool produces outputReview output, run checks
PreCompact / PostCompactAround context compactionPersist or restore state across a compaction
StopThe turn stopsRun 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. prompt and agent handlers are parsed in config but skipped at runtime.
  • async is parsed but not supported. Asynchronous command hooks are not available yet.
  • Not every tool path is covered. PreToolUse and PostToolUse see shell commands (matched as Bash), unified exec, apply_patch (also matching Edit and Write), MCP tools by their mcp__server__tool name, and other local function tools. Hosted tools such as WebSearch do not use the local hook path at all, and write_stdin does not re-run PreToolUse for a command that already passed it.
  • Some output fields are parsed but inert. suppressOutput is parsed and not yet implemented; continue, stopReason, and suppressOutput are not supported on PreToolUse or PermissionRequest, 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 exec jobs 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:

ControlWhereWhat it does
Allow users to create access tokensWorkspace Settings, Permissions and roles, Access tokens sectionTurns on token creation for allowed members
Access token expiration limitWorkspace Settings, Permissions and roles, Codex Local sectionCaps the longest expiration a member may choose. Applies to new tokens only; existing tokens keep theirs
Allow members to use Codex LocalWorkspace Settings, Permissions and roles, Codex Local sectionGates 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 exec is 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:

  1. Author a UserPromptSubmit hook that scans prompts for high-confidence credential patterns (API keys, OAuth refresh tokens, SSH private keys) before they reach the model.
  2. Enforce it as a managed hook in requirements.toml, and pin [features].hooks = true there 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.
  3. Provision a programmatic access token for the CI job that runs nightly codex exec validation against the main branch, created by the identity that should own that job rather than by an admin.
  4. 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:

  1. Put a <repo>/.codex/hooks.json in each repo with a SessionStart hook 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.
  2. Add a Stop hook that runs the repo's preferred validator (typecheck, lint, test) and surfaces failures back to the agent.
  3. Add a SessionEnd hook that writes the day's work to a memory file so the next session resumes with context. Budget for its timeout: SessionEnd defaults to 1 second and supports a maximum of 3.
  4. Resolve hook commands from the git root rather than a relative .codex/hooks/... path -- Codex may be started from a subdirectory.
  5. 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...HooksAccess tokens
Modify in-session behavior (validators, scanners, memory)YesNo
Enforce org-wide rules across interactive sessionsYes (via requirements.toml)No
Run Codex from a CI pipelineMaybe (hooks still apply)Yes -- needed for non-interactive auth
Run scheduled codex exec jobs as a serviceNoYes
Audit which automation ran which Codex actionNoYes -- 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:

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; prompt and agent handlers are parsed but skipped, and async is 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 as WebSearch. 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

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.

Keep building the workspace playbook

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.

Get the weekly AI Catchup

Tools, practices, and what matters, in your inbox every week.