MemoryLake
Back to all articles
TutorialNovember 10, 2026·10 min read

Codex Hooks Need Review — Why a Changed Hook Stops Running Until You Trust It Again, and How a SessionStart Hook Feeds Project Context Into Every Session (2026)

You start Codex and a warning appears: hooks need review, open /hooks. Or nothing appears at all, and you only notice later that the script you set up to load your project notes, block a risky command, or log each session simply didn't run.

Both come from the same rule. OpenAI's hooks documentation says: "Non-managed hooks must be reviewed and trusted before they run." Codex doesn't trust a hook once and forget about it. It trusts a specific version of it. When the hook changes, the trust no longer applies, and Codex skips the hook until you review it again.

That matters for hooks that give Codex context, like a script that loads project conventions every time a session starts. If that hook is skipped, the session starts without the context you expected, unless you catch the startup warning.

This guide covers what hooks are in Codex, why a hook gets marked for review, how to review and trust hooks, why project hooks may not load at all, how plugin hooks are handled, and how to use a SessionStart hook to feed project context into each session without overloading it.

What hooks are in Codex

OpenAI's documentation describes hooks as "an extensibility framework for Codex". They let you run scripts or MCP tools at set points in a conversation.

The documentation lists examples, including scanning prompts to block accidentally pasted API keys, running a validation check when a turn stops, and one that's directly about memory: "Summarize chats to create persistent memories automatically".

Hooks attach to events. A few of the main ones:

  • SessionStart runs when a session starts, including after compaction.
  • PreToolUse and PostToolUse run around tool calls.
  • PreCompact and PostCompact run around compaction.
  • UserPromptSubmit runs when you send a prompt.
  • Stop runs when a turn stops.

Codex finds hooks in hooks.json files or in inline [hooks] tables in config.toml. The documentation names the four most useful locations: ~/.codex/hooks.json, ~/.codex/config.toml, and the same two files under <repo>/.codex/. Enabled plugins can also bundle hooks.

If more than one source has hooks, Codex loads all matching ones. OpenAI says higher-precedence layers "don't replace lower-precedence hooks".

Why a hook gets marked for review

The review section of OpenAI's documentation explains the mechanism in two sentences. "Before a non-managed hook can run, Codex requires you to review and trust the exact hook definition. Codex records trust against the hook's current hash, so new or changed hooks are marked for review and skipped until trusted."

The key words are exact and hash. Codex isn't asking whether you trust a file path or a script name. It's asking whether you trust this exact definition. So any of these can put a hook back into review:

  • You added a new hook. It has never been trusted.
  • You edited a hook. A changed definition has a different hash.
  • A teammate changed a project hook. If the repo's .codex/hooks.json changed in a pull, the new version needs your review.

When hooks need review at startup, the documentation says Codex "prints a warning that tells you to open /hooks". Until you do, those hooks are skipped.

That's the part that's easy to miss. A skipped hook doesn't stop the session. If the hook was loading context, the session simply starts without it.

How to review and trust hooks

In the CLI, /hooks is the place to manage them. OpenAI's documentation says you can use it "to inspect hook sources, review new or changed hooks, trust hooks, or disable individual non-managed hooks".

In the desktop app, plugin hooks can be reviewed by selecting Review hooks in the composer, or by opening Settings > Hooks.

When you review, look at what the hook runs and where it gets its input. Trust is the decision that lets a script run inside your sessions, so it's worth reading the command before approving it, especially for project hooks you didn't write.

Two kinds of hooks don't go through this review:

  • Managed hooks. Hooks from system, MDM, cloud, or requirements.toml sources "are marked as managed, trusted by policy, and can't be disabled from the user hook browser".
  • One-off bypass. For automation that already vets hook sources elsewhere, Codex has a --dangerously-bypass-hook-trust flag that runs enabled hooks without persisted trust for that invocation. As the name says, it's for narrow cases.

Hooks are on by default. You can turn them off entirely by setting hooks = false under [features] in config.toml.

Why project hooks may not load at all

Sometimes a project hook doesn't appear for review, because Codex never loaded it. That's about project trust, not hook trust.

OpenAI's hooks documentation says: "Project-local hooks load only when the project .codex/ layer is trusted." Its config basics page adds that if you mark a project as untrusted, Codex "skips project-scoped .codex/ layers, including project-local config, hooks, and rules". User and system hooks still load.

So there are two gates for a hook in your repo:

  1. The project has to be trusted, so Codex reads <repo>/.codex/.
  2. The hook itself has to be trusted, at its current hash.

If you cloned a repo that ships hooks and nothing happens, check the first gate before the second.

Plugin hooks and updates

Plugins can bring their own hooks. By default, Codex looks for hooks/hooks.json inside the plugin, and a plugin manifest can point somewhere else. OpenAI says plugin hooks "use the same trust-review flow as other non-managed hooks".

There's one detail specific to plugins. The documentation says: "If a plugin update changes a bundled script, Codex requires a new review even if the hook definition stays the same."

So a plugin update can put its hooks back into review even when nothing in your own configuration changed. If a plugin hook stops running after an update, /hooks is the first place to look.

How a SessionStart hook feeds project context into a session

For context, SessionStart is the event to look at first. It runs when a session begins, and what it returns is added for the model to see.

OpenAI's documentation says that for SessionStart, "Plain text on stdout is added as extra developer context." A hook can also return JSON with an additionalContext field, and "That additionalContext text is added as extra developer context."

The event tells your hook how the session started. The source field can be startup, resume, clear, compact, or fork. You can match on that to load different context in different cases.

The compact case is the one to know for long tasks. The documentation says that after Codex compacts a root session, SessionStart hooks that match compact "run before the next model request". That includes automatic compaction in the middle of a turn. So a hook can restate the few facts a long task can't afford to lose right after a summary replaces the earlier conversation. Our guide to GPT-6.1 Sol's 500k context in Codex covers compaction in more detail.

One timing detail: OpenAI notes that SessionStart hooks can run before an MCP server is ready. If that happens, they don't block the session.

Keep the context short

A SessionStart hook can feed context into every session, which makes it tempting to feed in a lot. The documentation sets a limit and explains why.

By default, Codex limits each hook-output message the model sees to roughly 2,500 tokens. If a hook returns more, Codex saves the full text to a file and gives the model a shorter preview with the file path. OpenAI calls this spilling.

You can raise the threshold with additionalContextLimit on the handler, but the documentation warns against relying on it: "Context from multiple hooks and plugins adds up and can degrade model performance. Raising additionalContextLimit increases that risk."

It also flags a privacy point. Because oversized output can be written to disk, it says to avoid returning secrets or other sensitive data in hook output.

So a good SessionStart hook loads a short, current summary of what matters, not a whole document. For conventions that don't change, AGENTS.md is the standard place. Our guide to stopping Codex from skipping your AGENTS.md rules covers how those files load.

What people try first

Assuming the hook is broken. It may simply be waiting for review after a change.

Re-trusting without reading. Review exists because hooks run scripts in your sessions.

Editing the hook while debugging and forgetting to re-trust. Every edit changes the hash.

Looking for project hooks in an untrusted project. Codex skips the project's .codex/ layer there.

Feeding a whole document through SessionStart. Large output is spilled to disk and only a preview reaches the model.

The Fix: Get your context hook running again

Step 1: Open /hooks and review what's pending

Start Codex and open /hooks. Look for hooks marked for review, read what each one runs, and trust the ones you expect. In the desktop app, use Review hooks or Settings > Hooks for plugin hooks.

Step 2: Check the project gate

If a repo hook doesn't appear at all, confirm the project is trusted. Codex loads <repo>/.codex/ only for trusted projects.

Step 3: Make the SessionStart hook short and stable

Have the hook return a brief summary through additionalContext, and match compact as well as startup so the summary comes back after compaction. Keep the hook definition stable so it doesn't fall back into review every time you tweak it.

Setting this up in MemoryLake

A SessionStart hook is a delivery mechanism. It decides when context reaches a session, not what that context is or where it's kept. If the summary it loads lives in one repo's scripts or one machine's files, it's only as current as whoever last edited it, and only available where that hook runs. Our guide to Codex memories v2 covers the local memory Codex keeps on your machine.

MemoryLake is a memory layer for keeping that project context in one place you maintain, available to the assistants you connect, such as ChatGPT, Claude Code, and Codex.

You write the entries yourself, in your own words. Nothing is read out of, written to, or deleted from your hooks, your hooks.json or config.toml files, your AGENTS.md files, your Codex sessions, your Codex memories, or any vendor's store. Hook review, trust, and SessionStart work the way OpenAI describes them.

Step 1: Create an API key

Sign in and generate a key from the dashboard. The key belongs to your MemoryLake workspace and is separate from your OpenAI account.

The MemoryLake console showing the API keys screen, where a new key is created and copied for use in an agent
The MemoryLake console showing the API keys screen, where a new key is created and copied for use in an agent

Step 2: Upload your first memories

Start with the short summary you'd want a session to begin with: the project's goal, current decisions, and constraints. One decision per entry, so you can update one without rewriting the rest.

The MemoryLake workspace with the first documents uploaded, listing each file as it becomes searchable memory
The MemoryLake workspace with the first documents uploaded, listing each file as it becomes searchable memory

Step 3: Connect your AI & agents

Connect Codex and any other assistants you use. The same entries are available across sessions and tools, and you update them in one place.

The MemoryLake integrations screen listing the AI clients and agent frameworks that can be connected to the memory layer
The MemoryLake integrations screen listing the AI clients and agent frameworks that can be connected to the memory layer

What this changes in practice

The first difference is fewer silent gaps. The context you rely on isn't only in a script that might be waiting for review.

The second is a stable hook. When the summary lives elsewhere, the hook definition changes less often, so it falls back into review less often.

The third is consistency across tools. The same decisions are available in Codex and in the other assistants you connect.

Best practices for Codex hooks

Expect review after every change. Trust is tied to the hook's current hash.

Read before you trust. Hooks run scripts inside your sessions.

Trust the project first. Repo hooks don't load in untrusted projects.

Recheck after plugin updates. A changed bundled script needs a new review.

Match compact in SessionStart. It restores essentials right after compaction.

Keep hook output short. Large output is spilled to disk, and context adds up.

Leave secrets out of hook output. Oversized output can be written to disk.

Conclusion

Hooks need review means Codex found new or changed hooks that haven't been trusted at their current version. OpenAI's documentation says Codex records trust against each hook's hash, so new or changed hooks are skipped until you trust them in /hooks. Plugin hooks follow the same rule, and a plugin update that changes a bundled script needs a new review. Project hooks also need a trusted project before they load at all.

The hook most worth getting right is SessionStart. Its output is added as developer context when a session starts, and a hook that matches compact runs again after compaction. Keep that context short, keep the hook stable, and check /hooks whenever something you expected in a session isn't there.

Frequently asked questions

What does hooks need review mean in Codex?

It means there are new or changed hooks that haven't been trusted. Codex skips them until you review and trust them in /hooks.

Why did my Codex hook stop running?

If you or someone else changed it, its hash changed, so Codex marked it for review. It also won't load if the project isn't trusted.

How do I trust a hook in Codex?

Open /hooks in the CLI to review and trust it. In the desktop app, use Review hooks or Settings > Hooks for plugin hooks.

Do managed hooks need review?

No. Hooks from system, MDM, cloud, or requirements.toml sources are trusted by policy.

Why do plugin hooks need review again after an update?

OpenAI says that if a plugin update changes a bundled script, Codex requires a new review even if the hook definition stays the same.

What does a SessionStart hook do?

It runs when a session starts. Plain text on stdout, or additionalContext in JSON, is added as extra developer context.

Can a SessionStart hook run after compaction?

Yes. SessionStart hooks that match compact run before the next model request after Codex compacts a root session.

How do I turn hooks off in Codex?

Set hooks = false under [features] in config.toml.