Skip to content

bug: Codex hooks (PreToolUse/PostToolUse) are largely ineffective — 91% skipped, PostToolUse HTTP never reaches daemon #241

Description

@Maple0517

Context

After #206 landed (implemented via #207, #209, #211, #212, #213, #215, #218, #230), I've been running Codex with the hooks enabled for a day. The hooks are well-implemented and fire correctly, but I'm seeing some gaps in how they interact with Codex's actual usage patterns. Wanted to share the observations in case they're useful.

What I observed

~/.gortex/cache/hook-decisions.jsonl (64 entries, all from Bash):

Decision Count %
skipped_non_symbol 58 91%
probed_miss 3 5%
probed_hit 2 3%
timed_out 1 2%

Meanwhile, query-log.jsonl shows 64 successful MCP tool calls (search_symbols: 15, smart_context: 15, search_text: 34) across 8 sessions. The agent is using graph tools effectively — it's just being guided by AGENTS.md rather than the hooks.

PreToolUse: Bash command classifier doesn't match Codex's search patterns

Codex wraps everything in Bash. The hook parses tool_input.command to detect grep/find/cat, then checks if the pattern looks like a symbol name via classifyGrepPattern. But Codex tends to use multi-keyword |-separated patterns:

grep -rn "ai-redesign|Phase 5|entity_links|world-map" .
grep -rn "place_edges|location_edge|normalize" .

These contain |, multi-word phrases, and non-identifier tokens, so classifyGrepPattern returns NonSymbol and the hook passes through silently. This is by design for Claude Code's dedicated Grep tool (where patterns are typically single identifiers), but Codex's usage pattern is quite different.

I'm not sure what the right fix is here — maybe splitting |-separated patterns and probing each segment? Or falling back to search_text for non-symbol patterns? The current classifyBashCommandclassifyGrepPattern pipeline is solid for its original use case; it just doesn't align well with how Codex uses Bash.

PostToolUse: daemon HTTP endpoint not available by default

posttooluse.go calls queryGortex(port, path) which hits http://localhost:{port}/api/graph/symbol-at etc. But the daemon only listens on a unix socket by default — the HTTP endpoint requires --http-addr. On my setup, port 8765 happens to be occupied by another process, so all PostToolUse graph lookups silently fail.

Looking at the daemon logs, I can see zero HTTP API requests from hooks, which confirms the calls never reach the daemon.

I wonder if it would make sense to have PostToolUse fall back to the unix socket (same as probeViaDaemon in probe.go) when HTTP isn't available, or perhaps add a reachability check before attempting the HTTP calls?

Side note: binary freshness

I noticed the Homebrew-installed v0.58.3 binary was built ~2 hours before #218 merged, so the MCP read PreToolUse matcher (^mcp__gortex__(read_file|get_editing_context)$) isn't in my running binary. Not a code issue — just a packaging timing thing. Thought worth mentioning for context.

Happy to help investigate or test any fixes. The hook infrastructure is solid — the gaps seem to be in Codex-specific pattern matching and daemon connectivity.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions