Please give us a hook for custom compaction

Open 💬 9 comments Opened Feb 16, 2026 by thom-heinrich

What variant of Codex are you using?

CLI

What feature would you like to see?

Please give us a hook to add custom compaction solutions to codex.. like:

Token amount xxx is reached —> fires —> my custom compaction does its job —> injects and uses as context for continuation..

This is already possible if you build custom interfaces, but it would be a huge QoL for the vanilla CLI…

Additional information

_No response_

View original on GitHub ↗

9 Comments

wbdb · 5 months ago

<img width="895" height="323" alt="Image" src="https://github.com/user-attachments/assets/c8ef47f0-e342-47a3-a3f6-ed2f7e1f99a2" />

https://developers.openai.com/codex/config-reference/

Maybe some of this will help you. Perhaps by instructions?

QIANSUIMINGMINGMING · 4 months ago

I have the same need, and the concrete blocker is a structured persist workflow.

My setup:

  • I keep durable project state in .agent-doc/
  • I use Codex hooks like SessionStart and Stop
  • I also have a manual persist skill that writes findings, next actions, decisions, and state snapshots to disk

What is still missing is a deterministic hook immediately before compaction.

Why Stop is not enough:

  • Stop only runs on clean session end
  • compaction can happen in the middle of an active session, before I want to stop
  • once compaction has happened, some of the high-value transient context is already gone
  • manual "watch token usage and persist early" workarounds are approximate, not reliable

The exact feature that would solve this for me is something like a PreCompact hook with payload fields such as:

  • cwd
  • session_id
  • thread_id
  • reason (auto vs manual)
  • current context/token usage if available
  • timestamp

Then I could run something like:

python3 ~/.claude/scripts/pre-compact-persist.py

or a more general persist command that checkpoints .agent-doc/ before Codex summarizes the context.

This would make a big difference for:

  • multi-hour coding sessions
  • planner/executor workflows
  • external memory systems
  • structured project state that lives on disk rather than only in model context

So +1 from a real workflow perspective: this is not just "more hooks would be nice", it is the missing piece that makes durable custom memory and structured persistence reliable in Codex.

joshua-bone · 3 months ago

+1 PLEASE give us better compaction options

I routinely run into compaction error loops where I have to discard my whole thread.

itscheems · 3 months ago

Follow-up after tightening the fork patch:

  • Stop-hook compaction is only honored when the payload explicitly declares hookSpecificOutput.hookEventName = "Stop" together with action = "compact".
  • CodexErr::Interrupted is treated as a real turn abort; interrupted compaction no longer falls through into continuation scheduling.
  • If a Stop hook requests both compaction and continuation, compaction uses the mid-turn initial-context reinjection path so the resumed request keeps fresh developer/context state.
  • Repeated block + compact Stop-hook continuations in the same turn are now guarded by a turn-scoped latch, so compaction still runs at most once per turn.

So the current contract is:

  • narrow Stop-only extension
  • at-most-once compaction per turn, including repeated continuations
  • best-effort for non-interruption failures
  • interruption aborts the turn
  • block + compact continuation preserves the normal mid-turn context baseline
ElninoZhong · 2 months ago

Adding an implementation-oriented field report from Codex CLI 0.124.0 and the current main branch source.

Codex already has a solid hook runtime shape for this feature. The current hook engine discovers handlers from hooks.json and [hooks] in config.toml, supports command handlers, matcher groups, timeouts, hook start/completion events, and event-specific parsers for:

  • SessionStart
  • UserPromptSubmit
  • PreToolUse
  • PermissionRequest
  • PostToolUse
  • Stop

The gap is that none of those events is tied directly to the compaction lifecycle. SessionStart and UserPromptSubmit can inject context, and Stop can ask Codex to continue, but there is no stable event that says either:

  1. Codex is about to compact this thread, let external persistence capture state or provide compaction guidance.
  2. Codex has just compacted this thread, here is the new summary / metadata, let external persistence reinject or update state exactly once.

Without that lifecycle event, external memory systems have to infer compaction by watching rollout logs, token usage, or other internal artifacts. That is workable for experiments but brittle as a plugin or long-running workflow contract.

A minimal design that seems to fit the existing hook architecture:

PreCompact

Run before compaction starts. The input could mirror the common hook fields already used elsewhere:

  • session_id
  • turn_id
  • cwd
  • transcript_path
  • model
  • permission_mode
  • trigger: manual or auto
  • optional token metadata if already available: current input tokens, context window, threshold

Useful output semantics:

  • Plain stdout or hookSpecificOutput.additionalContext can be included in the compaction input.
  • JSON parse failures should be surfaced as hook failures but avoid corrupting the compaction path.
  • If blocking is supported at all, it should be conservative and probably require an explicit reason, similar to the existing blocking contracts.

PostCompact or ContextCompacted

Run after compaction succeeds. The input could include:

  • common fields above
  • trigger
  • compact_summary or a stable summary reference
  • optional pre/post token counts if available

Useful output semantics:

  • additionalContext should be recorded as model context for the next turn exactly once, similar to the existing SessionStart / UserPromptSubmit context injection path.
  • It should not require external tools to tail JSONL rollout files or infer which turn owns the compaction.

Implementation-wise, this looks like an incremental extension rather than a new subsystem:

  • Add the new event names to HookEventsToml in codex-rs/config/src/hook_config.rs.
  • Add generated command input/output schemas under codex-rs/hooks/schema/generated.
  • Add event modules beside session_start.rs, user_prompt_submit.rs, and stop.rs.
  • Add preview/run methods in the hook registry and call them from codex-rs/core/src/hook_runtime.rs around the existing compaction flow.
  • Add core tests similar to codex-rs/core/tests/suite/hooks.rs that verify no-hook behavior is unchanged, configured hooks receive stable stdin JSON, and additional context reaches the next model request once.

The main product value is not only custom summaries. It gives users a supported persistence boundary for long-running threads: save important state before compaction, observe the compacted state after compaction, and reinject durable context without relying on internal log formats.

Happy to help refine the contract or test cases if maintainers think this direction matches the intended hook model.

szybnev · 2 months ago

+1 for explicit PreCompact / PostCompact lifecycle hooks. My main use case is deterministic project-state persistence before Codex rewrites context: save decisions, current plan, changed files, and next steps to a project memory/doc, then optionally reinject a short durable summary after compaction.

Stop / UserPromptSubmit hooks are not a reliable substitute because compaction can happen mid-session, before the user is ready to stop or manually persist state.

oxysoft · 2 months ago

Indexed this hook ticket in the umbrella tracker: #21753

Goal: collect the scattered Codex hook requests and bugs into one parity matrix for Full Claude Code Hook Parity (29+), while preserving this issue as the detailed thread for its specific behavior.

robertvitali · 18 days ago

Is this being prioritized / on the roadmap?

Concrete use case: a companion hook that preserves external task-tracker context across compaction. Today PreCompact/PostCompact are lifecycle-only (no injection channel), and SessionStart(compact) only fires on resume — so after an in-place auto-compaction there's no first-class way to re-inject saved context into the continuing session. The current options are the rollout-log-scraping + next-UserPromptSubmit reinjection pattern (#19061) or a PostToolUse additionalContext shim — both best-effort and coupled to internal log shapes.

A deterministic post-compaction injection point (as requested here) would remove the need for those workarounds. Any maintainer signal on whether this is planned? Happy to help test.

bogorad · 18 days ago

Ideally so that something like https://github.com/Opencode-DCP/opencode-dynamic-context-pruning is possible. In opencode I hardly ever hit compaction thanks to it.