Of vercel/hyper’s 1,129 analyzed functions, 45 are rated critical — and the two highest-priority first-party hotspots are both in the ‘fire’ quadrant, meaning they are structurally complex AND actively changing simultaneously. The anonymous UI reducer in lib/reducers/ui.ts carries an activity risk of 16.02 with a recent commit velocity of 15.19 and a cyclomatic complexity of 69, making every commit to that file a live regression risk. configToPlugin in app/config/migrate.ts adds a nesting depth of 7 to the mix, compounding the structural exposure. Hyper is Vercel’s open-source terminal emulator built on Electron and web technologies.
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
| Function | File | Risk | CC | ND | FO |
|---|---|---|---|---|---|
parse | bin/rimraf-standalone.js | 16.8 | 84 | 4 | 16 |
expand$1 | bin/rimraf-standalone.js | 16.5 | 25 | 6 | 18 |
<anonymous> | lib/reducers/ui.ts | 16.0 | 69 | 3 | 19 |
<anonymous> | bin/rimraf-standalone.js | 15.7 | 29 | 5 | 7 |
configToPlugin | app/config/migrate.ts | 15.3 | 22 | 7 | 11 |
Codemod / Tooling Files in Results
Three of the top five hotspots — parse, expand$1, and an anonymous function — all reside in bin/rimraf-standalone.js, which is a vendored, standalone bundle of the rimraf file-deletion utility. These functions score highly because the file is co-located with the project’s bin directory and receives activity from surrounding commits, but the complexity belongs to rimraf’s internals, not to hyper’s own logic. To exclude this file from future analyses, add the following to your .hotspotsrc.json: { "exclude": ["bin/rimraf-standalone.js"] }. This will surface hyper’s first-party hotspots without vendored noise competing for the top positions.
Hotspot Analysis
<anonymous> — lib/reducers/ui.ts
This anonymous function in the UI reducers directory is almost certainly the root reducer — or a large branch of it — responsible for handling the full range of UI state transitions in hyper’s Redux-style state layer. A cyclomatic complexity of 69 means there are at least 69 independent execution paths through it, each a required test case and a potential bug surface. With a fan-out of 19, it calls into 19 distinct functions, meaning changes here can ripple broadly across the UI layer; the exit-heavy and god_function patterns confirm it is doing far too many things in one place. At activity risk 16.02 and a recent commit velocity of 15.19 in the ‘fire’ quadrant, this is not a theoretical concern — it is a live regression risk right now.
Recommendation: Before the next commit touches this file, write characterization tests that cover the highest-traffic state transitions, then extract logical groupings of action handlers into dedicated sub-reducers to bring CC below 20 per unit. The fan-out of 19 is your map for where those sub-reducers should live.
configToPlugin — app/config/migrate.ts
From its name and path, configToPlugin likely handles the transformation of legacy configuration entries into the plugin format used by hyper’s config migration system — a critical path that runs when users upgrade. A nesting depth of 7 is a strong refactoring signal on its own (the threshold for concern is ND 4+), and combined with a cyclomatic complexity of 22 and 11 distinct callees (fan-out), the function is both hard to reason about and broadly coupled. As a fire-quadrant function with activity risk 15.28 and a recent commit velocity of 14.37, it is being actively changed while carrying this structural load.
Recommendation: Flatten the deeply nested conditional logic by extracting each migration case into a named handler function — this directly reduces both ND and CC. Given the fan-out of 11, add integration-level tests for the migration pipeline before refactoring to avoid silent breakage downstream.
Patterns Found
Antipatterns detected across the top functions in this snapshot:
| Pattern | Occurrences |
|---|---|
complex_branching | 4 |
exit_heavy | 4 |
god_function | 4 |
long_function | 4 |
deeply_nested | 3 |
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
- The anonymous reducer in lib/reducers/ui.ts has a cyclomatic complexity of 69 and a fan-out of 19 — write characterization tests before the next commit lands there, not after.
- configToPlugin in app/config/migrate.ts has a max nesting depth of 7; extract each migration case into a named function to reduce both ND and the risk of silent regressions during config upgrades.
- Exclude bin/rimraf-standalone.js via .hotspotsrc.json to prevent vendored rimraf complexity from drowning out hyper’s 45 genuinely critical first-party functions.
Reproduce This Analysis
git clone https://github.com/vercel/hyper
cd hyper
git checkout 2a7bb18259d975f27b30b502af1be7576f6f5656
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 →