Documentation
¶
Overview ¶
Package codex implements the Agent interface for OpenAI's Codex CLI.
Index ¶
- Constants
- func HookTrustGaps(ctx context.Context) []string
- func MissingEntireHooks(repoRoot string) []string
- func NewCodexAgent() agent.Agent
- func NewReviewer() *reviewtypes.ReviewerTemplate
- func NewSpawner() spawn.Spawner
- func SanitizePortableTranscript(data []byte) []byte
- func WorktreeProjectLayerExists(ctx context.Context) bool
- type CodexAgent
- func (c *CodexAgent) AreHooksInstalled(ctx context.Context) (bool, error)
- func (c *CodexAgent) CalculateTokenUsage(transcriptData []byte, fromOffset int) (*agent.TokenUsage, error)
- func (c *CodexAgent) CheckHookConfig(ctx context.Context) agent.HookConfigState
- func (c *CodexAgent) ChunkTranscript(_ context.Context, content []byte, maxSize int) ([][]byte, error)
- func (c *CodexAgent) Description() string
- func (c *CodexAgent) DetectPresence(ctx context.Context) (bool, error)
- func (c *CodexAgent) DiscoverReviewSkills(ctx context.Context) ([]agent.DiscoveredSkill, error)
- func (c *CodexAgent) ExtractModifiedFilesFromOffset(path string, startOffset int) (files []string, currentPosition int, err error)
- func (c *CodexAgent) ExtractPrompts(sessionRef string, fromOffset int) ([]string, error)
- func (c *CodexAgent) FormatResumeCommand(sessionID string) string
- func (c *CodexAgent) GenerateText(ctx context.Context, prompt string, model string) (string, error)
- func (c *CodexAgent) GetSessionDir(_ string) (string, error)
- func (c *CodexAgent) GetSessionID(input *agent.HookInput) string
- func (c *CodexAgent) GetTranscriptPosition(path string) (int, error)
- func (c *CodexAgent) HookConfigRelPath() string
- func (c *CodexAgent) HookNames() []string
- func (c *CodexAgent) InjectionEvent() agent.EventType
- func (c *CodexAgent) InstallHooks(ctx context.Context, force bool) (int, error)
- func (c *CodexAgent) IsPreview() bool
- func (c *CodexAgent) LaunchCmd(ctx context.Context, initialPrompt string) (*exec.Cmd, error)
- func (c *CodexAgent) Name() types.AgentName
- func (c *CodexAgent) OwnsEffectiveHookDiagnostics()
- func (c *CodexAgent) ParseHookEvent(_ context.Context, hookName string, stdin io.Reader) (*agent.Event, error)
- func (c *CodexAgent) ProtectedDirs() []string
- func (c *CodexAgent) ReadSession(input *agent.HookInput) (*agent.AgentSession, error)
- func (c *CodexAgent) ReadTranscript(sessionRef string) ([]byte, error)
- func (c *CodexAgent) ReassembleTranscript(chunks [][]byte) ([]byte, error)
- func (c *CodexAgent) RenderContextInjection(inj agent.ContextInjection) ([]byte, error)
- func (c *CodexAgent) ResolveRestoredSessionFile(sessionDir, agentSessionID string, transcript []byte) (string, error)
- func (c *CodexAgent) ResolveSessionFile(sessionDir, agentSessionID string) string
- func (c *CodexAgent) SanitizeTranscriptForStorage(data []byte) []byte
- func (c *CodexAgent) SessionEndBudget() time.Duration
- func (c *CodexAgent) Type() types.AgentType
- func (c *CodexAgent) UninstallHooks(ctx context.Context) error
- func (c *CodexAgent) WriteHookResponse(message string) error
- func (c *CodexAgent) WriteSession(_ context.Context, session *agent.AgentSession) error
- type DiscoveredHooksPath
- type HookConfigInspection
- type HookDiagnostics
- type HookDiscovery
- type HookDiscoveryState
- type HookEntry
- type HookEventSpec
- type HookEvents
- type HookFileState
- type HookTrustInspection
- type HooksFile
- type MatcherGroup
- type UnresolvedHookDiscoveryError
- type WorktreeHooksPath
Constants ¶
const ( HookNameSessionStart = "session-start" HookNameSessionEnd = "session-end" HookNameUserPromptSubmit = "user-prompt-submit" HookNameStop = "stop" HookNamePreToolUse = "pre-tool-use" HookNamePostToolUse = "post-tool-use" HookNameSubagentStart = "subagent-start" HookNameSubagentStop = "subagent-stop" )
Codex hook names — these become subcommands under `entire hooks codex`
const HooksFileName = "hooks.json"
HooksFileName is the hooks config file used by Codex.
const SessionEndTimeoutSec = 3
SessionEndTimeoutSec is the timeout Entire configures for Codex's SessionEnd hook. Codex clamps SessionEnd handlers to SESSION_END_MAX_TIMEOUT_SEC = 3 (codex-rs/hooks/src/events/session_end.rs) and prints a "clamping SessionEnd hook timeout" warning on every startup when a config asks for more, so requesting exactly the ceiling gets the longest run available without nagging the user. Every other Codex hook keeps the standard 30s that addHook applies.
Variables ¶
This section is empty.
Functions ¶
func HookTrustGaps ¶ added in v0.6.2
HookTrustGaps returns the snake_case event labels declared in the hooks.json Codex discovers that don't have a matching approval entry in the user's Codex config.toml. Matching parses the full `<hooks.json>:<event>:<group>:<handler>` key, accepts any valid indexes, and compares canonicalized hook paths.
This is the structural form of the trust check: we don't recompute Codex's hook hash, we only look at key presence. That misses the "command changed but key is still there" case (status = Modified), but Codex's own startup warning catches those — our purpose here is to surface fresh additions like "you trusted three hooks last month but a new PostToolUse arrived" inside our SessionStart welcome.
Returns nil when:
- .codex/hooks.json doesn't exist (entire isn't installed in this repo)
- The authoritative hook location can't be resolved
- The checkout has no local .codex project layer
- The user's config.toml can't be read
- Every declared event already has a state entry
func MissingEntireHooks ¶ added in v0.6.2
MissingEntireHooks reports the managed Codex events that are not present in a repository-local hooks file. It is kept as a compatibility helper for callers that only need the drift list; diagnostics use HookConfigInspection.
func NewCodexAgent ¶
NewCodexAgent creates a new Codex agent instance.
func NewReviewer ¶ added in v0.6.1
func NewReviewer() *reviewtypes.ReviewerTemplate
NewReviewer returns the AgentReviewer for codex.
Argv shape: codex exec --skip-git-repo-check --json -. Prompt is piped via stdin (the trailing "-" tells codex to read from stdin). Stdout is newline-delimited JSON envelopes (one event per line); no chrome filter needed — each line is parsed directly into an Event.
func NewSpawner ¶ added in v0.7.0
NewSpawner returns a Spawner for codex's non-interactive review/investigate mode.
func SanitizePortableTranscript ¶ added in v0.5.4
SanitizePortableTranscript strips encrypted history fragments that cannot be replayed when Entire reconstructs a Codex rollout outside its original session context.
func WorktreeProjectLayerExists ¶ added in v0.10.3
WorktreeProjectLayerExists reports whether the current checkout has a valid local .codex project directory.
Types ¶
type CodexAgent ¶
type CodexAgent struct {
CommandRunner agent.TextCommandRunner
}
CodexAgent implements the Agent interface for OpenAI's Codex CLI.
func (*CodexAgent) AreHooksInstalled ¶
func (c *CodexAgent) AreHooksInstalled(ctx context.Context) (bool, error)
AreHooksInstalled reports whether Codex is wired up to Entire in this repo.
It requires only the core events, not everything InstallHooks writes today. The two questions are different: this one decides whether Codex is listed as an installed agent (`entire status`, the review and investigate pickers), and answering it with the full set would drop Codex out of all of them the moment a release adds an event — every existing install predates the addition. Drift against today's set is part of hook-config inspection, which `entire doctor` reports with the fix (`entire enable`).
A missing config file is an answer, not a failure: that file is where the state lives, so its absence means no hooks. Anything that stops us reading the answer — an unreadable file, malformed config — is returned as an error, since "we could not tell" and "there are none" are different things to a caller deciding whether hooks can be left alone.
func (*CodexAgent) CalculateTokenUsage ¶
func (c *CodexAgent) CalculateTokenUsage(transcriptData []byte, fromOffset int) (*agent.TokenUsage, error)
CalculateTokenUsage computes token usage from the transcript starting at the given line offset. Codex reports cumulative total_token_usage, so we compute the delta between the last token_count at/before the offset and the last token_count after the offset.
func (*CodexAgent) CheckHookConfig ¶ added in v0.10.3
func (c *CodexAgent) CheckHookConfig(ctx context.Context) agent.HookConfigState
CheckHookConfig reports whether the current checkout's Codex hook configuration is absent, current, or needs installation.
func (*CodexAgent) ChunkTranscript ¶
func (c *CodexAgent) ChunkTranscript(_ context.Context, content []byte, maxSize int) ([][]byte, error)
ChunkTranscript splits a JSONL transcript at line boundaries.
func (*CodexAgent) Description ¶
func (c *CodexAgent) Description() string
Description returns a human-readable description.
func (*CodexAgent) DetectPresence ¶
func (c *CodexAgent) DetectPresence(ctx context.Context) (bool, error)
DetectPresence checks if Codex is configured in the repository.
func (*CodexAgent) DiscoverReviewSkills ¶ added in v0.6.1
func (c *CodexAgent) DiscoverReviewSkills(ctx context.Context) ([]agent.DiscoveredSkill, error)
DiscoverReviewSkills walks codex's on-disk skill layout looking for review-adjacent skills. Returns (nil, nil) when HOME is unreadable or the directories are missing — discovery is best-effort.
Codex exposes skills as <root>/<name>/SKILL.md (same frontmatter shape as Claude). Three roots contribute, mirroring codex's own injected skills catalog:
- ~/.codex/skills/<name>/ → user skills ($name)
- ~/.codex/plugins/cache/<m>/<p>/<v>/skills/<name>/ → plugin skills ($p:name)
- ~/.codex/superpowers/skills/<name>/ → superpowers ($superpowers:name)
Skills are emitted in codex's dollar invocation form ($name / $plugin:name) — the literal token a user types to invoke the skill in the codex CLI — so the review prompt names skills exactly the way codex's skill system expects, loading the real SKILL.md rather than relying on a loose description match.
func (*CodexAgent) ExtractModifiedFilesFromOffset ¶
func (c *CodexAgent) ExtractModifiedFilesFromOffset(path string, startOffset int) (files []string, currentPosition int, err error)
ExtractModifiedFilesFromOffset extracts files modified since a given line offset.
func (*CodexAgent) ExtractPrompts ¶
func (c *CodexAgent) ExtractPrompts(sessionRef string, fromOffset int) ([]string, error)
ExtractPrompts returns user prompts from the transcript starting at the given offset.
func (*CodexAgent) FormatResumeCommand ¶
func (c *CodexAgent) FormatResumeCommand(sessionID string) string
FormatResumeCommand returns the command to resume a Codex session.
func (*CodexAgent) GenerateText ¶ added in v0.5.6
GenerateText sends a prompt to the Codex CLI and returns the raw text response.
func (*CodexAgent) GetSessionDir ¶
func (c *CodexAgent) GetSessionDir(_ string) (string, error)
GetSessionDir returns the directory where Codex stores session transcripts. Codex stores transcripts under CODEX_HOME/sessions/YYYY/MM/DD/.
func (*CodexAgent) GetSessionID ¶
func (c *CodexAgent) GetSessionID(input *agent.HookInput) string
GetSessionID extracts the session ID from hook input.
func (*CodexAgent) GetTranscriptPosition ¶
func (c *CodexAgent) GetTranscriptPosition(path string) (int, error)
GetTranscriptPosition returns the current line count of a Codex rollout transcript.
func (*CodexAgent) HookConfigRelPath ¶ added in v0.10.6
func (c *CodexAgent) HookConfigRelPath() string
HookConfigRelPath implements agent.HookConfigLocator.
func (*CodexAgent) HookNames ¶
func (c *CodexAgent) HookNames() []string
HookNames returns the hook verbs Codex supports.
func (*CodexAgent) InjectionEvent ¶ added in v0.7.7
func (c *CodexAgent) InjectionEvent() agent.EventType
InjectionEvent reports that Codex injects model context at TurnStart (its user-prompt-submit hook). Codex hosts Claude-compatible hooks, so it consumes the same hookSpecificOutput.additionalContext shape.
func (*CodexAgent) InstallHooks ¶
InstallHooks installs Codex hooks in .codex/hooks.json.
func (*CodexAgent) IsPreview ¶
func (c *CodexAgent) IsPreview() bool
IsPreview returns true because this is a new integration.
func (*CodexAgent) LaunchCmd ¶ added in v0.6.1
LaunchCmd builds an exec.Cmd for `codex "<initialPrompt>"`. Stdio is wired to the caller's TTY so the agent runs foreground and the user interacts normally. The call site is expected to Run() and wait. Hooks inherit the parent environment.
func (*CodexAgent) Name ¶
func (c *CodexAgent) Name() types.AgentName
Name returns the agent registry key.
func (*CodexAgent) OwnsEffectiveHookDiagnostics ¶ added in v0.10.3
func (c *CodexAgent) OwnsEffectiveHookDiagnostics()
OwnsEffectiveHookDiagnostics keeps Codex's discovered-file state out of the generic current-worktree freshness report.
func (*CodexAgent) ParseHookEvent ¶
func (c *CodexAgent) ParseHookEvent(_ context.Context, hookName string, stdin io.Reader) (*agent.Event, error)
ParseHookEvent translates a Codex hook into a normalized lifecycle Event. Returns nil if the hook has no lifecycle significance.
func (*CodexAgent) ProtectedDirs ¶
func (c *CodexAgent) ProtectedDirs() []string
ProtectedDirs returns directories that Codex uses for config/state.
func (*CodexAgent) ReadSession ¶
func (c *CodexAgent) ReadSession(input *agent.HookInput) (*agent.AgentSession, error)
ReadSession reads a session from Codex's storage (JSONL rollout file).
func (*CodexAgent) ReadTranscript ¶
func (c *CodexAgent) ReadTranscript(sessionRef string) ([]byte, error)
ReadTranscript reads the raw JSONL transcript bytes for a session.
func (*CodexAgent) ReassembleTranscript ¶
func (c *CodexAgent) ReassembleTranscript(chunks [][]byte) ([]byte, error)
ReassembleTranscript concatenates JSONL chunks with newlines.
func (*CodexAgent) RenderContextInjection ¶ added in v0.7.7
func (c *CodexAgent) RenderContextInjection(inj agent.ContextInjection) ([]byte, error)
RenderContextInjection renders the Claude-style additionalContext payload Codex injects into the model context at user-prompt-submit.
func (*CodexAgent) ResolveRestoredSessionFile ¶ added in v0.5.4
func (c *CodexAgent) ResolveRestoredSessionFile(sessionDir, agentSessionID string, transcript []byte) (string, error)
ResolveRestoredSessionFile returns the canonical Codex rollout path for a restored session so `codex resume <id>` can rediscover it.
func (*CodexAgent) ResolveSessionFile ¶
func (c *CodexAgent) ResolveSessionFile(sessionDir, agentSessionID string) string
ResolveSessionFile returns the path to a Codex session transcript file. Codex provides the transcript path directly in hook payloads as an absolute path. When only a session ID is available, callers recover it from the sessions/YYYY/MM/DD/rollout-...-<session-id>.jsonl layout.
func (*CodexAgent) SanitizeTranscriptForStorage ¶ added in v0.10.0
func (c *CodexAgent) SanitizeTranscriptForStorage(data []byte) []byte
SanitizeTranscriptForStorage implements agent.TranscriptSanitizer. Codex rollouts embed encrypted reasoning payloads and compaction blobs that are bound to the originating session, so Entire strips them from its stored copy while leaving Codex's own rollout file untouched.
func (*CodexAgent) SessionEndBudget ¶ added in v0.10.1
func (c *CodexAgent) SessionEndBudget() time.Duration
SessionEndBudget implements agent.SessionEndBudgeter. Codex runs SessionEnd inside its shutdown sequence under a hard cap; see the interface docs.
func (*CodexAgent) Type ¶
func (c *CodexAgent) Type() types.AgentType
Type returns the agent type identifier.
func (*CodexAgent) UninstallHooks ¶
func (c *CodexAgent) UninstallHooks(ctx context.Context) error
UninstallHooks removes Entire hooks from Codex hooks.json.
func (*CodexAgent) WriteHookResponse ¶
func (c *CodexAgent) WriteHookResponse(message string) error
WriteHookResponse outputs a JSON hook response to stdout. Codex reads the systemMessage field and displays it to the user.
func (*CodexAgent) WriteSession ¶
func (c *CodexAgent) WriteSession(_ context.Context, session *agent.AgentSession) error
WriteSession writes a session to Codex's storage (JSONL rollout file).
type DiscoveredHooksPath ¶ added in v0.10.3
type DiscoveredHooksPath struct {
// contains filtered or unexported fields
}
DiscoveredHooksPath identifies the read-only project hooks file Codex is expected to load. It is intentionally distinct from WorktreeHooksPath.
func (DiscoveredHooksPath) Path ¶ added in v0.10.3
func (p DiscoveredHooksPath) Path() string
Path returns the discovered hooks file's absolute path.
type HookConfigInspection ¶ added in v0.10.3
type HookConfigInspection struct {
State HookFileState
Missing []string
Declared []string
Current bool
CoreInstalled bool
Err error
}
HookConfigInspection is the single parsed view used by Codex presence, freshness, missing-hook, and doctor reporting.
func InspectHookConfig ¶ added in v0.10.3
func InspectHookConfig(ctx context.Context) HookConfigInspection
InspectHookConfig resolves and parses the hooks file Codex discovers.
type HookDiagnostics ¶ added in v0.10.3
type HookDiagnostics struct {
Discovery HookDiscovery
WorktreeHooks WorktreeHooksPath
Worktree HookConfigInspection
Discovered HookConfigInspection
Trust HookTrustInspection
WorktreePathErr error
}
HookDiagnostics keeps current-checkout ownership separate from the read-only file Codex discovers.
func InspectHookDiagnostics ¶ added in v0.10.3
func InspectHookDiagnostics(ctx context.Context) HookDiagnostics
InspectHookDiagnostics collects the local and effective Codex hook state without creating, rewriting, or removing either file.
func InspectHookDiagnosticsLightweight ¶ added in v0.10.3
func InspectHookDiagnosticsLightweight(ctx context.Context) HookDiagnostics
InspectHookDiagnosticsLightweight collects only the checks safe to run from Codex's SessionStart hook. It avoids freshness probes and platform-specific command checks, which can delay the agent startup path.
func (HookDiagnostics) PathsDiffer ¶ added in v0.10.3
func (d HookDiagnostics) PathsDiffer() bool
PathsDiffer reports whether current-checkout mutation and Codex discovery refer to different hook files.
type HookDiscovery ¶ added in v0.10.3
type HookDiscovery struct {
State HookDiscoveryState
DiscoveredHooks DiscoveredHooksPath
Diagnostic error
// contains filtered or unexported fields
}
HookDiscovery describes the hooks file Codex is expected to discover. It is diagnostic-only and carries no write target, migration path, or lock path.
func ResolveHookDiscovery ¶ added in v0.10.3
func ResolveHookDiscovery(ctx context.Context) HookDiscovery
ResolveHookDiscovery performs read-only discovery of the hook file Codex is expected to load for the current checkout.
func (HookDiscovery) ProjectLayerExists ¶ added in v0.10.3
func (d HookDiscovery) ProjectLayerExists() bool
ProjectLayerExists reports whether the current checkout has a valid local .codex directory Codex can use to construct its project config layer.
type HookDiscoveryState ¶ added in v0.10.3
type HookDiscoveryState uint8
HookDiscoveryState distinguishes a resolved Codex hook source from a layout whose behavior Entire cannot safely infer.
const ( HookDiscoveryUnresolved HookDiscoveryState = iota HookDiscoveryResolved )
type HookEntry ¶
type HookEntry struct {
Type string `json:"type"`
Command string `json:"command"`
Timeout int `json:"timeout,omitempty"`
}
HookEntry represents a single hook command in the config.
type HookEventSpec ¶ added in v0.10.3
type HookEventSpec struct {
Event string
Label string
Verb string
Timeout int
Managed bool
Core bool
JSONWarning bool
}
HookEventSpec is the shared Codex event metadata used by installation, trust inspection, and the Codex integration tests.
func HookEventSpecs ¶ added in v0.10.3
func HookEventSpecs() []HookEventSpec
HookEventSpecs returns a copy so callers cannot mutate the canonical table.
type HookEvents ¶
type HookEvents struct {
SessionStart []MatcherGroup `json:"SessionStart,omitempty"`
SessionEnd []MatcherGroup `json:"SessionEnd,omitempty"`
UserPromptSubmit []MatcherGroup `json:"UserPromptSubmit,omitempty"`
Stop []MatcherGroup `json:"Stop,omitempty"`
PreToolUse []MatcherGroup `json:"PreToolUse,omitempty"`
PostToolUse []MatcherGroup `json:"PostToolUse,omitempty"`
SubagentStart []MatcherGroup `json:"SubagentStart,omitempty"`
SubagentStop []MatcherGroup `json:"SubagentStop,omitempty"`
}
HookEvents contains the hook configurations by event type.
type HookFileState ¶ added in v0.10.3
type HookFileState uint8
HookFileState distinguishes Entire's installation from unrelated user configuration, malformed JSON, and a file that cannot be inspected.
const ( HookFileAbsent HookFileState = iota HookFileUserOnly HookFileEntire HookFileMalformed )
type HookTrustInspection ¶ added in v0.10.3
HookTrustInspection is a structural view of Codex's local approval records. It never computes or copies trusted hashes.
func InspectHookTrust ¶ added in v0.10.3
func InspectHookTrust(ctx context.Context) HookTrustInspection
InspectHookTrust reports declared events and whether the user's Codex config contains approval records for them. Known is false when config.toml cannot be read, so callers do not mistake an unavailable trust check for active hooks.
type HooksFile ¶
type HooksFile struct {
Hooks HookEvents `json:"hooks"`
}
HooksFile represents the .codex/hooks.json structure.
type MatcherGroup ¶
MatcherGroup groups hooks under an optional matcher pattern.
type UnresolvedHookDiscoveryError ¶ added in v0.10.3
type UnresolvedHookDiscoveryError struct {
Reason string
}
UnresolvedHookDiscoveryError explains why Entire will not guess which hook file Codex loads for a Git layout.
func (*UnresolvedHookDiscoveryError) Error ¶ added in v0.10.3
func (e *UnresolvedHookDiscoveryError) Error() string
type WorktreeHooksPath ¶ added in v0.10.3
type WorktreeHooksPath struct {
// contains filtered or unexported fields
}
WorktreeHooksPath identifies the hooks file owned by the current checkout. It is intentionally distinct from DiscoveredHooksPath.
func ResolveWorktreeHooksPath ¶ added in v0.10.3
func ResolveWorktreeHooksPath(ctx context.Context) (WorktreeHooksPath, error)
ResolveWorktreeHooksPath resolves the hooks file owned by the current checkout, independently of the file Codex discovers.
func (WorktreeHooksPath) Path ¶ added in v0.10.3
func (p WorktreeHooksPath) Path() string
Path returns the current checkout's hooks file path.