chakra-ui's codemod layer carries the highest activity risk — 2 functions to address first

Two functions in chakra-ui's codemod package — collectChakraLocalNames and transformer — dominate the critical band with cyclomatic complexity scores of 38 and 48, both touched in the last 30 days.

Stephen Collins ·
oss typescript refactoring code-health
Activity Risk20.63Low
Hottest FunctioncollectChakraLocalNames

Antipatterns Detected

complex_branching5deeply_nested5exit_heavy5god_function5long_function5hub_function1

Key Points

What is a god function and why does it matter in chakra-ui?

A god function is one that accumulates so many responsibilities that it becomes the single point of coordination for a broad slice of the system — in structural terms, it shows up as a combination of high cyclomatic complexity, deep nesting, and high fan-out. The problem is concrete: a god function is difficult to test in isolation because its many paths and callees must all be accounted for, and a change to any one concern inside it risks breaking unrelated behavior. In chakra-ui's codemod package, both `collectChakraLocalNames` and `transformer` carry the god-function pattern, with cyclomatic complexity values of 38 and 48 respectively — meaning any developer modifying either function must reason about dozens of execution paths simultaneously. Five of the top hotspot functions in this snapshot carry this pattern, making it the dominant structural antipattern in the repo's critical band.

How do I reduce cyclomatic complexity in TypeScript?

The most effective technique for high-CC TypeScript functions is extract-method refactoring: identify each logical branch group — a set of conditions that all handle the same concern — and pull it into a named function with a clear contract. A cyclomatic complexity above 15 is a reasonable threshold to start extracting; above 30, like `collectChakraLocalNames` at CC 38 or `transformer` at CC 48, immediate decomposition is warranted. For `transformer` specifically, a concrete first step would be to extract each Button prop migration concern (renaming, variant mapping, size normalization) into separate sub-transformer functions, each independently testable — that alone could reduce the top-level CC by more than half. TypeScript's type system makes this safer than in untyped languages because extracted functions can carry precise input and output types, reducing the risk of introducing new paths during the refactor.

Is chakra-ui actively maintained?

Yes — the "fire" quadrant classification of the two top-ranked functions is direct evidence of active development. Both `collectChakraLocalNames` and `transformer` recorded 1 commit touch in the last 30 days, with the most recent change 29 days ago, and neither is a dormant legacy function. Across 3,043 analyzed functions, 244 fall into the "fire" quadrant, meaning they are both structurally complex and seeing recent commit activity. High structural complexity in the codemod layer and active maintenance are not mutually exclusive — the codemod work appears to be part of a live migration tooling effort, which is itself a signal of ongoing investment in the ecosystem.

How do I reproduce this analysis?

The hotspots CLI is available at github.com/hotspots-dev/hotspots. To reproduce this exact analysis, check out the chakra-ui/chakra-ui repository at commit `155fa13` with `git checkout 155fa13`, then run `hotspots analyze . --mode snapshot --explain-patterns --force` from the repo root. The same command works on any local git repository without additional configuration — no `.hotspotsrc.json` is required to get started.

What does activity-weighted risk mean?

Activity-weighted risk multiplies a function's structural complexity — derived from cyclomatic complexity, nesting depth, and fan-out — by its recent commit frequency, so that functions which are both hard to understand and actively changing score the highest. A function with cyclomatic complexity 80 that hasn't been touched in two years scores much lower than one with CC 20 touched every week, because the complex-but-dormant function has lower near-term regression risk. This prioritization helps teams focus refactoring effort where it reduces the probability of bugs being introduced right now, not just where the code looks complicated in the abstract. In chakra-ui's case, `collectChakraLocalNames` scores 20.63 — the top score in the repo — precisely because its CC of 38 is paired with a recent commit touch, not because it has a known defect history.

At commit 155fa13, the highest activity-weighted risk in chakra-ui doesn’t live in the core styled-system or component primitives — it lives in the codemod tooling. collectChakraLocalNames in packages/codemod/src/utils/chakra-tracker.ts carries an activity-weighted risk score of 20.63, the top score in the repo, with a cyclomatic complexity of 38 and 1 commit touch in the last 30 days — making it a live regression risk, not merely a cleanup item. Across 3,043 analyzed functions, 96 reach the critical band; both top-ranked functions are in the codemod package and are classified as “fire” quadrant, meaning they are structurally complex and actively changing right now.

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
collectChakraLocalNamespackages/codemod/src/utils/chakra-tracker.ts20.638612
transformerpackages/codemod/src/transforms/components/button.ts17.548622
transformerpackages/codemod/src/transforms/theme/theme-tokens.ts17.544577
transformerpackages/codemod/src/transforms/components/pin-input.ts17.228636
transformerpackages/codemod/src/transforms/components/number-input.ts16.027525

Large Repo Analysis

chakra-ui is a large repository. To stay within memory constraints, this analysis used hybrid touch mode: structural complexity — CC, ND, FO — is measured precisely for every function. Git activity is tracked at the function level (via git log -L) only for files with 5 or more commits in the last 30 days; other files use a file-level approximation. Rankings therefore surface functions that are both structurally complex and in the most actively-changing parts of the codebase. Dormant code with high structural complexity will rank lower than it would under a full per-function analysis — to surface it, run hotspots analyze . --per-function-touches on a machine with sufficient memory.

Codemod / Tooling Files in Results

All five of the top-ranked functions live in packages/codemod, a code-transformation tooling package rather than the runtime React component library. Codemod tooling is intentionally complex because it handles AST traversal and migration transforms, and its risk scores reflect that domain complexity rather than product code maintainability. If you want to focus hotspots analysis on the runtime library only, add the following exclude pattern to your .hotspotsrc.json: { "exclude": ["packages/codemod/"] }.

The risk profile for chakra-ui at this snapshot is concentrated rather than spread out. Of the 96 critical-band functions, the two highest scorers share a home: the packages/codemod package. Both carry the full suite of structural antipatterns — complex branching, deep nesting, multiple exit paths, god-function coupling, and excessive length — and both were touched within the last 29 days. That combination is what pushes them into the “fire” quadrant and makes them worth addressing before the codemod tooling ships to consumers.


collectChakraLocalNamespackages/codemod/src/utils/chakra-tracker.ts

This is the structural centre of gravity for the codemod package. With a fan-out of 12 distinct callees, collectChakraLocalNames reaches broadly across the codemod utility layer — changes to its call contract ripple outward to every consumer that depends on accurately resolved Chakra import names. The name suggests it walks an AST or module graph to collect local binding names for Chakra-UI symbols, a task that inherently branches on import styles, aliasing, re-exports, and namespace patterns.

The metrics tell a pointed story. A cyclomatic complexity of 38 means 38 independent execution paths through a single function — each path is a required test case and a potential regression surface. A max nesting depth of 6 compounds that: reasoning about the outermost branches requires holding six levels of context simultaneously, well past the ND 4+ threshold that signals readability breakdown. The function also flags as exit_heavy, meaning multiple return paths are scattered through those nested branches, which raises the cost of achieving meaningful test coverage. With 1 commit touch in the last 30 days (29 days ago), this is not dormant legacy code — it is actively changing.

The external signals here are sparse: one total commit, one author in the last 90 days, no bug-linked commits or reverts. That absence of historical defect signal is worth noting — the risk is structural, not an established bug history. But a single-author, high-complexity function with active churn is a knowledge-concentration risk: if that author is unavailable when a regression surfaces, the blast radius is high and the debugging surface is enormous.

Recommendation: Apply extract-method refactoring to decompose collectChakraLocalNames by import pattern type — one handler per recognized import shape (named imports, namespace imports, aliased re-exports, etc.). Each extracted function should carry its own unit tests. Targeting a post-refactor CC below 15 per extracted unit is a realistic first milestone and would eliminate the god-function and deeply-nested antipatterns in a single pass.


transformerpackages/codemod/src/transforms/components/button.ts

If collectChakraLocalNames is the highest-risk function by activity-weighted score, transformer is the highest by raw structural complexity. At a cyclomatic complexity of 48 — 10 points above its stablemate — it holds 48 independent execution paths through a single transform function. Its fan-out of 22 is the largest in the top hotspots list, meaning it calls into 22 distinct functions, making it a hub that coordinates the full surface of the Button component migration. Its activity-weighted risk score of 17.53 puts it firmly in the critical band.

Both collectChakraLocalNames and transformer share the same structural antipattern fingerprint: complex branching, deep nesting (ND 6), exit-heavy control flow, god-function coupling, and excessive length. In transformer, the fan-out of 22 is the more alarming signal — a change to any one of those 22 callees, or a new Button prop variant that requires a new branch, forces a developer to navigate a function that already has 48 paths. Like its sibling, the external signals show no prior bug-linked commits or reverts, so the risk is forward-looking: the next change to this function is the one most likely to introduce a regression.

Recommendation: Decompose transformer by migration concern. A codemod transformer for a single component should not need CC 48; that complexity suggests it is handling prop renaming, variant mapping, size normalization, and possibly JSX restructuring all in one body. Splitting those concerns into focused sub-transformers — each testable in isolation — would reduce fan-out to a coordination layer and bring individual path counts into a range where coverage is achievable.


transformerpackages/codemod/src/transforms/theme/theme-tokens.ts

The third-ranked function shares an activity-weighted score of 17.5 with the button transformer and is structurally distinct in one key way: a fan-out of 77 — more than three times the next highest in the top five. Where transformer in button.ts is a hub by virtue of coordination complexity, this function calls into 77 distinct callees, making it the broadest dependency surface in the critical band. Its cyclomatic complexity of 44 and max nesting depth of 5 confirm the full antipattern suite: complex branching, deep nesting, exit-heavy control flow, god-function coupling, and excessive length.

Recommendation: Prioritize extracting the fan-out before addressing the branching. At FO 77, the first step is identifying which callees belong to coherent theme-token concerns (color, typography, spacing, etc.) and grouping them behind dedicated sub-transformer functions. Reducing the coordination surface will make the remaining branching complexity tractable.


transformerpackages/codemod/src/transforms/components/pin-input.ts

Fourth by risk score at 17.2, the pin-input transformer has CC 28, ND 6, and FO 36. Its nesting depth matches the button transformer’s ND 6 — the deepest in the top five — and its fan-out of 36 places it as the second broadest callee surface. Like the other codemod transformers, it carries the full structural antipattern fingerprint and was active within the same recent commit window. Its lower CC (28 vs. 48 in button.ts) reflects a narrower migration surface, but ND 6 still means six levels of nested context to hold while reasoning about any branch.

Recommendation: Apply the same decompose-by-concern approach as the button transformer: identify each distinct prop migration (renaming, event handler changes, slot restructuring) and extract it into a named sub-transformer. Each extracted unit should have ND ≤ 3 as a post-refactor target.


transformerpackages/codemod/src/transforms/components/number-input.ts

The fifth function rounds out a pattern that is consistent across all four codemod transformers: CC 27, ND 5, FO 25, activity-weighted risk 16.0. Its structural profile is the most moderate in the top five, but it still carries the full antipattern set. Given the repetition of function name and file structure across the codemod package, these four transformers are strong candidates for a shared refactoring pass — a common sub-transformer interface would allow each to delegate to focused concern handlers while keeping the coordination logic thin and independently testable.


Key Takeaways

  • Decompose collectChakraLocalNames first. With an activity-weighted risk score of 20.63, CC 38, ND 6, and a commit touch 29 days ago, it is the single highest-priority refactoring target in the repo. Extract per-import-pattern handlers, each with independent tests, to bring CC below 15 per unit.
  • Audit transformer before the next codemod release. CC 48 and FO 22 in a single Button transform function means 48 paths through a 22-callee hub — the next prop addition or variant change runs a high regression risk. Decompose by migration concern before expanding coverage.
  • The codemod package is the active risk zone, not the core React layer. All five hotspots are transformer functions in packages/codemod. Structural debt is concentrated in tooling, not in the component primitives consumers depend on. A shared decompose-by-concern refactoring pass across the four transformer functions would address the pattern systematically.

Patterns Found

Antipatterns detected across the top functions in this snapshot:

PatternOccurrences
complex_branching5
deeply_nested5
exit_heavy5
god_function5
long_function5
hub_function1

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.

Reproduce This Analysis

git clone https://github.com/chakra-ui/chakra-ui
cd chakra-ui
git checkout 155fa1388825debedcf2017b2a51b85d179fc701
hotspots analyze . --mode snapshot --explain-patterns --force --hybrid-touches 5

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