oh-my-openagent's event and hooks layer carries the highest activity risk — 5 functions to address first

src/plugin/event.ts and the claude-code-hooks directory dominate oh-my-openagent's critical risk tier, with cyclomatic complexity up to 90 and max nesting depth of 8–9 across actively changing functions.

Stephen Collins ·
oss typescript refactoring code-health

Antipatterns Detected

complex_branching5deeply_nested5god_function5long_function5exit_heavy3

Key Points

What is a god function and why does it matter in oh-my-openagent?

A god function is one that does too many things at once — it handles too many responsibilities, calls too many other functions, and branches across too many conditions to be understood or changed safely in isolation. In oh-my-openagent, every one of the top 5 hotspots is flagged as a god function, including `createEventHandler` which calls 62 distinct functions and `executePreToolUseHooks` which nests 9 levels deep. When a god function is also actively changing — as all five are — the risk of an unintended regression with each commit is high because there is no clean boundary around what a change might affect.

How do I reduce cyclomatic complexity in TypeScript?

The most direct technique is extract-method refactoring: identify each independent conditional branch or loop body and move it into a named function with a clear single responsibility, so the original function becomes a flat orchestrator. In TypeScript specifically, discriminated unions and exhaustive switch statements can replace deeply nested if-else chains, making the branching both shallower and type-safe.

Is oh-my-openagent actively maintained?

The activity data strongly suggests yes — all five top hotspots carry recent commit activity levels between 16.93 and 18.68, indicating recent and repeated commit activity across the event plugin and hooks layer. A recent commit activity that high means these files are not dormant; they are being changed frequently enough that structural complexity in them is a present-tense risk.

How do I reproduce this analysis?

Run the Hotspots CLI against the oh-my-openagent repository at commit 85e7a24 to reproduce the exact scores and rankings shown here.

What does activity-weighted risk mean?

Complexity × recent commit frequency — functions that are hard to understand AND actively changing are the highest priority for refactoring.

At commit 85e7a24, oh-my-openagent’s highest structural risk is concentrated in two subsystems: the event plugin (src/plugin/event.ts) and the claude-code-hooks layer (src/hooks/claude-code-hooks/). The anonymous top-level function in event.ts carries an activity risk score of 19.74 with a recent commit activity of 18.68 — meaning it is not just complex (CC 90, ND 8) but is being actively committed against right now, which transforms what might otherwise be a static cleanup note into a live regression risk. Across 3,389 total functions, 395 are rated critical and every one of the top 5 hotspots lands in the “fire” quadrant, signaling that complexity and commit churn are co-located rather than spread evenly across the codebase.

The table below ranks functions by activity-weighted risk — a score that multiplies structural complexity by recent commit frequency. A function that is both hard to understand (high cyclomatic complexity) and actively changing is a higher priority than one that is complex but untouched. CC = cyclomatic complexity (independent execution paths); ND = max nesting depth; FO = fan-out (distinct callees).

Top 5 Hotspots

FunctionFileRiskCCNDFO
<anonymous>src/plugin/event.ts19.790855
createEventHandlersrc/plugin/event.ts19.443862
executePreToolUseHookssrc/hooks/claude-code-hooks/pre-tool-use.ts19.236911
executePostToolUseHookssrc/hooks/claude-code-hooks/post-tool-use.ts18.942716
formatFullSessionsrc/tools/background-task/full-session-format.ts18.123718

Hotspot Analysis

<anonymous> — src/plugin/event.ts

This anonymous function sits at the top level of the event plugin file, suggesting it likely serves as the module’s primary initialization or dispatch entry point — the kind of scope that wires together event registration, routing, and plugin lifecycle in a single block. A cyclomatic complexity of 90 means there are roughly 90 independent execution paths to reason about and test; a max nesting depth of 8 indicates those paths are deeply interleaved rather than flat. With a fan-out of 55 and a recent commit activity of 18.68, this function is both broadly coupled — touching 55 distinct callees — and under active churn, meaning every recent commit to this file risks touching logic that branches in 90 different directions.

Recommendation: Before any refactoring, write characterization tests that exercise the dominant event paths so regressions surface immediately. Then apply extract-method refactoring to pull distinct event-type handlers into named, independently testable functions, reducing the anonymous scope to an orchestrator with single-digit CC.

createEventHandler — src/plugin/event.ts

Based on its name and file location, createEventHandler likely constructs and returns a configured handler for plugin events — a factory-style function responsible for assembling the logic that responds to agent events. Its CC of 43 and ND of 8 indicate that handler construction involves substantial conditional branching nested at least 8 levels deep, while a fan-out of 62 — the highest of any function in the top 5 — means it calls out to 62 distinct functions, giving it the widest blast radius in the codebase. With a recent commit activity of 18.25 and activity risk of 19.39, it is being changed nearly as frequently as the anonymous function above it in the same file, compounding the regression surface.

Recommendation: Audit the 62 callees to identify which are genuinely required at construction time versus which could be deferred or injected; reducing fan-out through dependency injection or lazy initialization will shrink the blast radius of future changes and make the construction logic testable in isolation.

executePreToolUseHooks — src/hooks/claude-code-hooks/pre-tool-use.ts

This function almost certainly runs before any tool invocation in the claude-code agent lifecycle, acting as a gate that evaluates and executes registered pre-tool-use hooks — a critical control point for intercepting or modifying tool calls. Its CC of 36 and ND of 9 — the deepest nesting in the entire top 5 — suggest the hook evaluation logic branches heavily on tool type, hook configuration, or execution context, with conditions nested 9 levels deep. The exit_heavy pattern alongside these values means there are also multiple early-return paths, each of which represents a branch that must be independently covered by tests; the recent commit activity of 17.96 confirms this gating logic is still evolving.

Recommendation: Flatten the nesting by extracting each distinct hook-evaluation concern (e.g., per-tool-type dispatch, condition checks, abort paths) into dedicated functions, and add tests that explicitly cover each early-exit path before making further changes.

Patterns Found

Antipatterns detected across the top functions in this snapshot:

PatternOccurrences
complex_branching5
deeply_nested5
god_function5
long_function5
exit_heavy3

These labels belong to two tiers — Tier 1 (structural): complex_branching, deeply_nested, exit_heavy, long_function, god_function. Tier 2 (relational/temporal): hub_function, cyclic_hub, middle_man, neighbor_risk, stale_complex, churn_magnet, shotgun_target, volatile_god.

Key Takeaways

  • src/plugin/event.ts contains two of the top three hotspots — the anonymous function (CC 90, FO 55) and createEventHandler (CC 43, FO 62) — and both have recent commit activity levels above 18, making this file the single highest-priority refactoring target in the repo right now.
  • executePreToolUseHooks and executePostToolUseHooks both carry the exit_heavy pattern alongside nesting depths of 9 and 7 respectively; add characterization tests covering every early-exit path in these functions before the next commit touches either file.
  • Fan-out of 62 on createEventHandler is the widest coupling in the top 5 — map its callees before refactoring to understand the full blast radius, since changes to this factory function can ripple into 62 distinct downstream functions.

Reproduce This Analysis

git clone https://github.com/code-yeongyu/oh-my-openagent
cd oh-my-openagent
git checkout 85e7a24e265aa4c2e60ae63abef138a0b80856e7
hotspots analyze . --mode snapshot --explain-patterns --force

To run the same analysis on your own codebase, run hotspots analyze . --mode snapshot in any local git repo — no configuration required.

Hotspots highlights structural and activity risk — not “bad code.” Findings are a prioritization aid, not a bug predictor. Editorial policy →

Run this on your own codebase

Hotspots runs locally in under a minute — no account, no data leaves your machine.

macOS
$ brew install Stephen-Collins-tech/tap/hotspots
Linux / cargo
$ cargo install hotspots-cli
Run in any repo
$ hotspots analyze .
★ Star on GitHub

Related Analyses