Health Report: zed

2026-02-01T20:50:35.580409Z 1y history
49Health Score
Declining
-0.06 pts/mo
1666
Files Analyzed
438
Hotspot Files
23
Critical Issues
10.5%
Duplication

Quick Insights

Key findings from the analysis - prioritized by impact

Technical Debt Hotspot

Found 23 critical and 66 high-priority debt items. These are areas where the team has explicitly noted problems. Consider scheduling time to address the most impactful items.

Low Cohesion Classes

Detected 9 classes with low cohesion (LCOM > 50). These classes may be doing too many unrelated things. Consider splitting them into more focused components.

Code Duplication

10.5% of code is duplicated across 721 clone groups. Bugs fixed in one location may need fixing in others. Consider extracting shared functionality.

Active Development

46325 commits across 5012 files.

Attention Needed

Health score of 49 suggests significant technical debt. Consider allocating dedicated time for refactoring and debt reduction.

Executive Summary

The Zed codebase scores 48.5 out of 100 (grade F) across 1,666 analyzed files, and is on a slow but statistically significant decline (slope -0.056, R-squared 0.55) over the past year. The primary driver of this decline is coupling, which has fallen from 48 to 34 -- the steepest drop of any component (slope -0.44, correlation 0.87). Complexity is pegged at 0 throughout the entire observation window, with an average cyclomatic complexity of 54.3 per file that saturates the metric floor. These two components alone -- coupling at weight 1.0 and complexity at score 0 -- make recovery mathematically difficult without targeted intervention.

The trajectory is declining. Each major feature push (Agent panel in May 2025, WSL/MCP in August 2025, subagent/permissions in January 2026) has ratcheted coupling down by 5-10 points with no sustained recovery. The only meaningful improvement occurred in October 2025 during a search rewrite that briefly lifted coupling from 39 to 44, but those gains were immediately reversed. Cohesion (76) and duplication (69) have been stable, providing a floor, but they cannot offset the coupling and complexity erosion.

The top risks are: (1) a 118-component dependency cycle spanning 28 crates including gpui, editor, language, agent_ui, and task -- this mega-cycle prevents independent testing and reasoning about core subsystems; (2) 257 files with a bus factor of 1, including security-critical files like tool_permissions.rs (1,083 lines, single owner) and core infrastructure like gpui/platform/mac/keyboard.rs (1,500 lines, single owner); and (3) five god-class files (thread_view.rs, lsp_store.rs, element.rs, workspace.rs, git_panel.rs) each scoring above 0.99 on the hotspot index, combining extreme complexity with the highest churn rates in the project.

The path forward requires a two-track approach: break the 118-component dependency cycle by extracting shared trait definitions into interface crates (targeting editor-to-agent_ui and editor-to-debugger_ui edges first), and decompose the top 5 god classes into focused sub-modules. Coupling is the only component with a strong negative trend and high weight -- stabilizing it would halt the overall score decline. In parallel, knowledge transfer for bus-factor-1 files in production code paths should begin immediately to reduce personnel risk.

Recommendations

Prioritized actions to improve code health

Critical - Address Soon
Break the 118-component dependency cycle

A single cyclic dependency spans 118 files across 28 crates (editor: 26 files, gpui: 14, agent_ui: 10, debugger_ui: 10, language: 8). This prevents independent testing and reasoning about core subsystems. Start by identifying and removing the 3-5 cross-crate edges that sustain the cycle -- the editor-to-agent_ui, editor-to-debugger_ui, and language_model-to-client edges are the most likely candidates. Extract shared trait definitions into small interface crates that do not depend back on their consumers.

Address bus-factor-1 files in security and core infrastructure

257 files have a single contributor. The highest-risk are: crates/agent/src/tool_permissions.rs (1,083 lines, Richard Feldman, security-critical), crates/gpui/src/platform/mac/keyboard.rs (1,500 lines, single owner, core input handling), crates/editor/src/split.rs (3,497 lines, Cole Miller), and crates/dev_container/src/lib.rs (1,824 lines, KyleBarton, entire crate). Begin immediate knowledge transfer through pair programming or code review rotation for these files.

Decompose the top 5 god classes

thread_view.rs (complexity 265.9, 132 commits), lsp_store.rs (complexity 356.5, 62 commits), element.rs (complexity 328.5, 71 commits), workspace.rs (complexity 251.5, 66 commits), and git_panel.rs (complexity 210.9, 79 commits) each score above 0.99 on the hotspot index. These files combine extreme complexity with the highest churn in the codebase. Split each into focused sub-modules: rendering vs. state management vs. event handling. This directly addresses both the complexity (score 0) and coupling problems.

Fix known production bugs left unresolved

Several acknowledged bugs sit in production code paths: (1) path_key.rs ordering bug masked by a sort workaround, (2) worktree.rs abs_path bug with trailing slashes causing silent path matching failures, (3) edit_file_tool.rs broken under remoting (canonicalize uses local filesystem), (4) shell_builder.rs build_no_quote method described as 'should not exist' with infrastructure 'broken beyond repair', (5) 64x memory amplification workaround in worktree.rs that has been 'temporary' for over a year. These carry correctness and stability risk.

Important - Plan For
Extract shared abstractions for language model providers

18 clone groups (~1,200 duplicated lines) across 10 provider files in crates/language_models/src/provider/. Temporal coupling confirms all providers change together (strength 0.43-0.67). Extract a generic ApiKeyProvider trait or shared ProviderState struct to eliminate ~800-1,000 lines and reduce bug-fix divergence risk where fixes applied to one provider are missed in others.

Extract shared abstractions for git hosting providers

14 clone groups (~1,450 duplicated lines) across 6 git hosting provider files. Group 4 alone spans all 6 providers with 309 lines of type-2 clones. Create a HostingProviderBase struct or macro for common URL patterns and permalink construction. Estimated savings: ~900 lines.

Stabilize the agent subsystem architecture

The agent subsystem shows the most architectural strain: thread.rs at 5.48x relative churn, thread_store.rs at 12.07x, an entire module (active_thread.rs, 148 commits) built and deleted, and 17 hotspot files in agent_ui alone. The acp_thread/connection.rs file is temporally coupled to 4 separate crates. The rapid feature iteration (subagents, message queuing, tool permissions) is outpacing the design. Pause feature work long enough to stabilize abstractions before the next feature push.

Introduce shared settings schema and layered keymaps

Settings changes require triple-writes to default.json, page_data.rs, and vscode_import.rs (temporal coupling 0.36-0.52). Keymap changes require triple-writes across 3 platform files (coupling 0.96-1.00). Generate page_data.rs and vscode_import mappings from the canonical default.json. Adopt a layered keymap format (base + platform delta) to eliminate mandatory triple-edits.

Reduce theme default_colors.rs duplication

33 identical 63-line StaticColorScaleSet initializations in crates/theme/src/default_colors.rs (2,079 duplicated lines, the single largest clone group). Replace with a data-driven array of color definitions and a single constructor function, or use a macro. Estimated savings: ~1,900 lines.

Maintenance - Keep Doing
Monitor coupling trend monthly

Coupling is the only component with a strong negative trend (slope -0.44) and the highest weight. Each feature push has ratcheted it down without recovery. Establish a coupling budget: any PR that introduces a new cross-crate dependency should justify it and identify a compensating removal. Target: halt the decline and stabilize at or above 40 within 6 months.

Reduce cyclomatic complexity in highest-scoring files

Complexity scores 0 with average cyclomatic complexity of 54.3 per file. The worst offenders are project_panel.rs (369.4), lsp_store.rs (356.5), element.rs (328.5), and thread_view.rs (265.9). Target reducing complexity in these files by 50% through extraction of nested logic into helper functions. Even moving the average from 54 to 40 would begin lifting the complexity score off 0.

Resolve self-cycles in language model providers and core modules

11 self-cycles (length 1) exist in language model provider files (open_ai, x_ai, vercel, open_router, ollama, mistral, lmstudio) plus collab/rpc, gpui/taffy, util/schemars, and language/proto. These are low-effort fixes that improve the structural graph and signal architectural intent.

Track and reduce SATD accumulation

824 SATD markers (density 0.61 per 1K lines) with a slowly declining score (slope -0.09). 377 requirement TODOs suggest features are shipped with acknowledged incomplete implementations. Establish a policy of resolving or triaging SATD items within 2 release cycles of their introduction. Prioritize the 89 high-priority items, particularly the BUG-category markers in non-test production code.

Assign maintainers to highly fragmented core files

editor.rs (160 contributors, top owner at 10.4%), workspace.rs (105 contributors, top owner at 10.8%), element.rs (101 contributors, top owner at 12.5%), and git_panel.rs (64 contributors, top owner at 11.7%) have no clear ownership. Diffuse responsibility increases defect risk. Designate 1-2 maintainers per file with review authority to ensure architectural consistency.

Key Findings

Coupling is in freefall. The coupling score dropped from 48 to 34 over 12 months (slope -0.44, correlation 0.87), hitting its all-time low in January 2026. A 118-component dependency cycle spanning 28 crates (gpui, editor, language, agent_ui, task, and 23 others) is the root cause. Four import cycles exist in total, but this mega-cycle dominates.

Complexity is bottomed out at 0. Average cyclomatic complexity is 54.3 per file across 1,664 files, with the worst offender project_panel.rs at 369.4. The complexity score has been 0 for the entire year. With a weight of 1.0, this is the single largest drag on the overall grade.

Five god classes dominate hotspot risk. thread_view.rs (score 0.997, 132 commits, complexity 265.9), lsp_store.rs (0.993, complexity 356.5), element.rs (0.992, complexity 328.5), workspace.rs (0.992, 66 commits), and git_panel.rs (0.991, 79 commits) each exceed 0.99 on the hotspot index. These 5 files represent the highest concentration of combined churn and complexity in the project.

257 files have a bus factor of 1. Critical single-owner files include crates/agent/src/tool_permissions.rs (1,083 lines, security-critical), crates/editor/src/split.rs (3,497 lines), crates/dev_container/src/lib.rs (1,824 lines, entire crate single-owned), and crates/gpui/src/platform/mac/keyboard.rs (1,500 lines). Max Brunsfeld owns 90-97% of the language, multi_buffer, worktree, and lsp crates -- the largest knowledge silo in the project.

10.5% code duplication (51,191 lines) with high-risk clusters. Language model providers share 18 clone groups (~1,200 duplicated lines) across 10 provider files. Git hosting providers duplicate ~1,450 lines across 6 files. Theme default colors have 33 identical 63-line blocks (2,079 lines). Bug-fix divergence risk is highest in the provider files, where a fix applied to one provider is likely missed in the others.

The agent subsystem is under architectural strain. thread.rs has 5.48x relative churn, thread_store.rs has 12.07x relative churn, and active_thread.rs (148 commits) was built and entirely deleted. The agent_ui crate has 17 hotspot files. Temporal coupling analysis shows acp_thread/connection.rs is coupled to files in 4 separate crates, meaning any protocol change cascades across the entire agent stack.

Known bugs are left unresolved in production paths. The path_key.rs ordering bug is masked by a sort workaround. The worktree.rs abs_path bug causes silent path matching failures with trailing slashes. The edit_file_tool.rs is broken under remoting. The shell_builder.rs is described as 'broken beyond repair'. A 64x memory amplification workaround in worktree.rs has been 'temporary' for over a year.

Settings require triple-write updates. Every new setting requires synchronized changes to assets/settings/default.json, crates/settings_ui/src/page_data.rs, and crates/settings/src/vscode_import.rs (temporal coupling strength 0.36-0.52). Platform keymaps require triple-writes across Linux, macOS, and Windows files (coupling strength 0.96-1.00, 24-25 co-changes). Both patterns indicate missing shared schemas or code generation.

Hotspots

Files with both high complexity and frequent changes - highest risk for bugs

The hotspot analysis reveals 438 files with elevated risk, of which 89 are Critical (score >= 0.8) and 39 score above 0.9. Hotspots concentrate heavily in a few crates: agent_ui (17 files >= 0.7), project (15), gpui (14), and editor (10). This clustering indicates systemic architectural pressure rather than isolated tech debt. The single most dangerous file is crates/agent_ui/src/acp/thread_view.rs with a score of 0.997, combining the highest churn in the codebase (132 commits) with extreme complexity (265.9 avg). Five mega-hotspot files -- thread_view.rs, lsp_store.rs, element.rs, workspace.rs, and git_panel.rs -- each score above 0.99 and represent god-class-level risk where both complexity and change frequency are in the 99th percentile. The language_models/src/provider/ directory is a notable secondary pattern: seven provider files appear as hotspots, all with low complexity but high churn, suggesting a repeated pattern of adapting to upstream API changes that would benefit from a shared abstraction layer.

438
Hotspot Files
1.0
Highest Risk
0.63
Average Risk

Risk Landscape

Files in the upper-right are both complex and frequently changed -- the most likely sources of bugs. Bubble size reflects overall risk score. Green is low risk, yellow moderate, red high.

FileLangRiskChangesComplexity

Low Cohesion Classes

Classes doing too many unrelated things - candidates for splitting

Cohesion has been remarkably stable, declining only slightly from 77 to 76 (slope -0.017, moderate correlation 0.55). Across 4635 analyzed classes, the average LCOM is 2.3, which is acceptable. However, the Editor class dominates the worst cases with CBO of 1027 and 829 across two modules, plus WMC of 3499 and 2723 respectively. EditorElement has CBO 619, LspStore has CBO 506, and Project has CBO 428. These few mega-classes are severely low-cohesion, but they are not getting worse and the overall average remains stable.

ClassFileLanguageLCOMWMCCBO

Architectural Smells

Structural problems that make the codebase harder to change safely

61 architectural smells across 1,666 components, with 22 critical and 25 high severity issues.

Dominant Cycle: 118 Components Across 28 Crates

The most severe finding is a single cyclic dependency spanning 118 files across 28 crates. The heaviest participants are editor (26 files), gpui (14 files), agent_ui (10 files), debugger_ui (10 files), language (8 files), and ai_onboarding (8 files). This mega-cycle means none of these crates can be tested, built, or reasoned about independently. The cycle passes through core infrastructure (gpui, language, client), UI layers (editor, agent_ui, debugger_ui, picker), and domain logic (task, dap, edit_prediction), indicating that abstraction boundaries between these layers have collapsed. Breaking this cycle should be the top architectural priority. The most likely seams to cut are: (1) editor depending on debugger_ui or agent_ui -- these should flow the other direction or through traits; (2) ai_onboarding depending on agent_ui and client simultaneously; (3) language_model and client forming a bidirectional dependency through telemetry.

There are also 11 self-cycles (length 1), mostly in language_models providers (open_ai, x_ai, vercel, open_router, ollama, mistral, lmstudio) plus collab/rpc, gpui/taffy, util/schemars, and language/proto. These likely represent files that re-export and consume their own definitions through module-level circular references. They are low-effort fixes.

God Module: gpui.rs (893 fan-in, 45 fan-out)

crates/gpui/src/gpui.rs has 893 incoming dependencies, making it the single largest coupling bottleneck in the codebase. Any change to its public API ripples across nearly every crate. Its instability is 0.05 (very stable), which is appropriate for a framework root, but its sheer fan-in means even safe refactors carry high coordination cost. Consider whether gpui.rs re-exports too many internal details -- narrowing its public surface would reduce coupling without changing architecture.

Central Connectors: High Fan-In AND Fan-Out

Ten modules are flagged as central connectors (high fan-in and fan-out simultaneously), making them single points of failure:

  • crates/editor/src/editor.rs: 139 in, 64 out -- the worst ratio. This module both receives and creates dependencies aggressively. It is also in the 118-component cycle. Splitting editor.rs into focused sub-modules (rendering, keybindings, LSP integration) would reduce its connector role.
  • crates/language/src/language.rs: 237 in, 29 out -- a core abstraction that everything depends on while itself depending on 29 other modules.
  • crates/client/src/client.rs: 65 in, 11 out -- networking hub.
  • crates/gpui/src/gpui.rs: 893 in, 45 out -- discussed above.
  • crates/language_model/src/language_model.rs: 64 in, 14 out.
  • crates/task/src/task.rs: 51 in, 12 out.
  • crates/multi_buffer/src/multi_buffer.rs: 35 in, 11 out.
  • crates/acp_thread/src/acp_thread.rs: 23 in, 13 out.
  • crates/agent/src/agent.rs: 13 in, 23 out.
  • crates/gpui/src/platform/windows.rs: 25 in, 16 out.

Hub Modules: Extreme Fan-In

25 modules are flagged as hubs (exceeding the threshold of 20 total connections). Beyond gpui.rs, the notable hubs by fan-in are: agent_ui/ui.rs (271), language/language.rs (237), util/serde.rs (208), gpui/platform/windows/util.rs (200), settings_content/workspace.rs (192), extension_api/settings.rs (191), collab/db/tables/project.rs (190), editor/editor.rs (139), and collections/collections.rs (133). Most of these are stable (low instability) which is correct -- heavily depended-on modules should be stable. The risk is that changes to any of them are expensive.

Unstable Dependencies

14 unstable dependency smells, all medium severity. The pattern is that stable, high fan-in modules depend on modules with significantly higher instability. The agent_ui/ui.rs module (271 fan-in, instability 0.03) depends on four sub-modules (acp_onboarding_modal, agent_notification, claude_code_onboarding_modal, end_trial_upsell) with instability 0.72. This means a stable, widely-used module depends on volatile modules, violating the Stable Dependencies Principle. Similarly, gpui.rs depends on app.rs (instability 0.84) and gpui_macros (instability 0.70). These should be restructured so dependency arrows point toward stability.

Recommended Actions

  1. Map the 118-component cycle in detail and identify the 3-5 cross-crate edges that, if removed, would break the cycle. The editor-to-debugger_ui and editor-to-agent_ui edges are the most likely candidates.
  2. Extract traits/interfaces from editor.rs to reduce its 64 outgoing dependencies. Sub-modules should depend on editor abstractions, not the other way around.
  3. Fix the 11 self-cycles in language_models providers and core modules -- these are low-effort, high-signal improvements.
  4. Audit agent_ui/ui.rs re-exports -- with 271 fan-in it should not depend on volatile onboarding sub-modules directly. Invert those dependencies or use trait objects.
  5. Narrow the public API surface of gpui.rs to reduce its 893 fan-in over time.
61
Total Smells
12
Cyclic Dependencies
25
Hub Dependencies
14
Unstable Dependencies
TypeSeverityFiles InvolvedSuggestion
Cyclic DependencyCriticalcrates/gpui/src/taffy.rsBreak the cycle by introducing an interface or restructuring the dependency direction
Cyclic DependencyCriticalcrates/collab/src/rpc.rsBreak the cycle by introducing an interface or restructuring the dependency direction
Cyclic DependencyCriticalcrates/util/src/schemars.rsBreak the cycle by introducing an interface or restructuring the dependency direction
Cyclic DependencyCriticalcrates/language/src/proto.rsBreak the cycle by introducing an interface or restructuring the dependency direction
Cyclic DependencyCriticalcrates/gpui/examples/window.rs, ...//platform/windows/directx_renderer.rs, ...//src/platform/windows/direct_write.rs, ...//platform/windows/destination_list.rs, crates/gpui/src/platform/windows.rs, crates/gpui/src/platform/windows/util.rs, crates/cloud_api_client/src/websocket.rs, .../ud_api_client/src/cloud_api_client.rs, crates/client/src/test.rs, crates/gpui_macros/src/gpui_macros.rs, crates/gpui/examples/tab_stop.rs, crates/gpui/src/styled.rs, .../s/language_model/src/fake_provider.rs, crates/client/src/telemetry.rs, crates/task/src/task_template.rs, crates/task/src/debug_format.rs, crates/task/src/static_source.rs, crates/task/src/task.rs, crates/dap/src/registry.rs, crates/gpui/examples/text.rs, .../ge/src/syntax_map/syntax_map_tests.rs, crates/language/src/syntax_map.rs, crates/language/src/language_registry.rs, crates/language/src/diagnostic_set.rs, crates/language/src/toolchain.rs, crates/language/src/task_context.rs, ...//integration/db_tests/buffer_tests.rs, crates/agent/src/outline.rs, crates/language/src/language_settings.rs, crates/language/src/language.rs, .../es/workspace/src/persistence/model.rs, crates/language_model/src/api_key.rs, ...//language_model/src/language_model.rs, crates/agent_ui/src/context.rs, crates/gpui/src/keymap.rs, crates/gpui/examples/input.rs, .../s/agent_ui/src/ui/onboarding_modal.rs, .../i/src/ui/model_selector_components.rs, crates/agent_ui/src/ui/mention_crease.rs, .../s/agent_ui/src/ui/hold_for_default.rs, crates/client/src/user.rs, crates/client/src/client.rs, .../ding/src/agent_api_keys_onboarding.rs, .../nboarding/src/young_account_banner.rs, .../ai_onboarding/src/plan_definitions.rs, ...edit_prediction_onboarding_content.rs, .../s/ai_onboarding/src/ai_upsell_card.rs, .../src/agent_panel_onboarding_content.rs, .../ng/src/agent_panel_onboarding_card.rs, .../es/ai_onboarding/src/ai_onboarding.rs, .../s/agent_ui/src/ui/end_trial_upsell.rs, .../rc/ui/claude_code_onboarding_modal.rs, .../agent_ui/src/ui/agent_notification.rs, .../ent_ui/src/ui/acp_onboarding_modal.rs, crates/agent_ui/src/ui.rs, crates/dap/src/adapters.rs, crates/dap/src/dap.rs, ...//src/session/running/variable_list.rs, .../c/session/running/stack_frame_list.rs, crates/agent/src/db.rs, .../es/command_palette/src/persistence.rs, .../ings_ui/src/components/input_field.rs, crates/ui_input/src/ui_input.rs, crates/picker/src/popover_menu.rs, .../r/src/highlighted_match_with_paths.rs, crates/picker/src/head.rs, crates/picker/src/picker.rs, crates/buffer_diff/src/buffer_diff.rs, crates/multi_buffer/src/transaction.rs, crates/multi_buffer/src/path_key.rs, .../ulti_buffer/src/multi_buffer_tests.rs, crates/multi_buffer/src/multi_buffer.rs, .../s/editor/src/selections_collection.rs, crates/editor/src/scroll/autoscroll.rs, crates/editor/src/actions.rs, crates/editor/src/scroll.rs, crates/editor/src/inlays/inlay_hints.rs, crates/editor/src/inlays.rs, crates/editor/src/hover_popover.rs, crates/editor/src/hover_links.rs, .../es/feature_flags/src/feature_flags.rs, crates/editor/src/element.rs, .../on_types/src/edit_prediction_types.rs, crates/editor/src/code_context_menus.rs, crates/editor/src/split.rs, crates/editor/src/signature_help.rs, .../lab/tests/integration/editor_tests.rs, .../ediction/src/edit_prediction_tests.rs, crates/editor/src/tasks.rs, crates/editor/src/split_editor_view.rs, crates/editor/src/rust_analyzer_ext.rs, crates/editor/src/movement.rs, crates/editor/src/mouse_context_menu.rs, crates/editor/src/lsp_ext.rs, crates/editor/src/lsp_colors.rs, .../s/editor/src/linked_editing_ranges.rs, crates/editor/src/jsx_tag_auto_close.rs, crates/diagnostics/src/items.rs, crates/editor/src/indent_guides.rs, .../tor/src/highlight_matching_bracket.rs, crates/editor/src/clangd_ext.rs, .../es/editor/src/bracket_colorization.rs, crates/editor/src/editor.rs, crates/tasks_ui/src/modal.rs, crates/tasks_ui/src/tasks_ui.rs, ...//debugger_ui/src/new_process_modal.rs, .../ui/src/session/running/module_list.rs, .../ebugger_ui/src/tests/inline_values.rs, crates/debugger_ui/src/debugger_panel.rs, .../s/debugger_ui/src/tests/dap_logger.rs, .../ger_ui/src/session/running/console.rs, crates/debugger_ui/src/attach_modal.rs, crates/debugger_ui/src/tests.rs, crates/scheduler/src/scheduler.rs, crates/gpui/src/platform_scheduler.rs, crates/assets/src/assets.rs, crates/gpui/src/app.rs, crates/gpui/src/gpui.rsBreak the cycle by introducing an interface or restructuring the dependency direction
Cyclic DependencyCritical.../nguage_models/src/provider/open_ai.rsBreak the cycle by introducing an interface or restructuring the dependency direction
Cyclic DependencyCritical...//language_models/src/provider/x_ai.rsBreak the cycle by introducing an interface or restructuring the dependency direction
Cyclic DependencyCritical.../anguage_models/src/provider/vercel.rsBreak the cycle by introducing an interface or restructuring the dependency direction
Cyclic DependencyCritical.../ge_models/src/provider/open_router.rsBreak the cycle by introducing an interface or restructuring the dependency direction
Cyclic DependencyCritical.../anguage_models/src/provider/ollama.rsBreak the cycle by introducing an interface or restructuring the dependency direction
Cyclic DependencyCritical.../nguage_models/src/provider/mistral.rsBreak the cycle by introducing an interface or restructuring the dependency direction
Cyclic DependencyCritical.../guage_models/src/provider/lmstudio.rsBreak the cycle by introducing an interface or restructuring the dependency direction
Central ConnectorCriticalcrates/task/src/task.rsDecompose into smaller components with single responsibility; extract interfaces for consumers
Central ConnectorCriticalcrates/multi_buffer/src/multi_buffer.rsDecompose into smaller components with single responsibility; extract interfaces for consumers
Central ConnectorCriticalcrates/client/src/client.rsDecompose into smaller components with single responsibility; extract interfaces for consumers
Central ConnectorCriticalcrates/editor/src/editor.rsDecompose into smaller components with single responsibility; extract interfaces for consumers
Central ConnectorCriticalcrates/gpui/src/platform/windows.rsDecompose into smaller components with single responsibility; extract interfaces for consumers
Central ConnectorCriticalcrates/acp_thread/src/acp_thread.rsDecompose into smaller components with single responsibility; extract interfaces for consumers
Central ConnectorCriticalcrates/language/src/language.rsDecompose into smaller components with single responsibility; extract interfaces for consumers
Central ConnectorCritical...//language_model/src/language_model.rsDecompose into smaller components with single responsibility; extract interfaces for consumers
Central ConnectorCriticalcrates/gpui/src/gpui.rsDecompose into smaller components with single responsibility; extract interfaces for consumers
Central ConnectorCriticalcrates/agent/src/agent.rsDecompose into smaller components with single responsibility; extract interfaces for consumers
Hub DependencyHighcrates/dap/src/dap.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHighcrates/html_to_markdown/src/markdown.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHighcrates/fuzzy/src/fuzzy.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHighcrates/project/src/lsp_store.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHighcrates/collab/src/rpc.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHighcrates/extension_api/src/http_client.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHighcrates/settings_content/src/workspace.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHigh.../dit_prediction/src/edit_prediction.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHighcrates/editor/src/element.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHigh.../ommand/src/assistant_slash_command.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHighcrates/gpui/examples/text.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHighcrates/picker/src/picker.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHighcrates/agent_ui/src/ui.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHighcrates/settings_content/src/theme.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHighcrates/collab/src/db/tables/project.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHighcrates/edit_prediction_cli/src/git.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHighcrates/collab/src/db/tables/extension.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHighcrates/util/src/serde.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHighcrates/extension_api/src/settings.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHighcrates/extension/src/types/lsp.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHigh.../es/feature_flags/src/feature_flags.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHighcrates/fs/src/fs.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHighcrates/gpui/src/platform/windows/util.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHighcrates/sum_tree/src/sum_tree.rsConsider splitting this component into smaller, more focused modules
Hub DependencyHighcrates/collections/src/collections.rsConsider splitting this component into smaller, more focused modules
Unstable DependencyMediumcrates/agent_ui/src/ui.rs, .../ent_ui/src/ui/acp_onboarding_modal.rsIntroduce an interface in the stable component that the unstable component implements (Dependency Inversion)
Unstable DependencyMediumcrates/agent_ui/src/ui.rs, .../agent_ui/src/ui/agent_notification.rsIntroduce an interface in the stable component that the unstable component implements (Dependency Inversion)
Unstable DependencyMediumcrates/agent_ui/src/ui.rs, .../rc/ui/claude_code_onboarding_modal.rsIntroduce an interface in the stable component that the unstable component implements (Dependency Inversion)
Unstable DependencyMediumcrates/agent_ui/src/ui.rs, .../s/agent_ui/src/ui/end_trial_upsell.rsIntroduce an interface in the stable component that the unstable component implements (Dependency Inversion)
Unstable DependencyMedium.../ommand/src/assistant_slash_command.rs, .../ommand/src/extension_slash_command.rsIntroduce an interface in the stable component that the unstable component implements (Dependency Inversion)
Unstable DependencyMediumcrates/client/src/client.rs, crates/client/src/telemetry.rsIntroduce an interface in the stable component that the unstable component implements (Dependency Inversion)
Unstable DependencyMediumcrates/client/src/client.rs, crates/client/src/user.rsIntroduce an interface in the stable component that the unstable component implements (Dependency Inversion)
Unstable DependencyMediumcrates/dap/src/dap.rs, crates/dap/src/adapters.rsIntroduce an interface in the stable component that the unstable component implements (Dependency Inversion)
Unstable DependencyMediumcrates/gpui/src/gpui.rs, crates/gpui/src/app.rsIntroduce an interface in the stable component that the unstable component implements (Dependency Inversion)
Unstable DependencyMediumcrates/gpui/src/gpui.rs, crates/gpui_macros/src/gpui_macros.rsIntroduce an interface in the stable component that the unstable component implements (Dependency Inversion)
Unstable DependencyMediumcrates/language/src/language.rs, crates/language/src/language_settings.rsIntroduce an interface in the stable component that the unstable component implements (Dependency Inversion)
Unstable DependencyMedium...//language_model/src/language_model.rs, crates/client/src/telemetry.rsIntroduce an interface in the stable component that the unstable component implements (Dependency Inversion)
Unstable DependencyMediumcrates/multi_buffer/src/multi_buffer.rs, .../ulti_buffer/src/multi_buffer_tests.rsIntroduce an interface in the stable component that the unstable component implements (Dependency Inversion)
Unstable DependencyMediumcrates/multi_buffer/src/multi_buffer.rs, crates/multi_buffer/src/path_key.rsIntroduce an interface in the stable component that the unstable component implements (Dependency Inversion)

Dependency Structure

Import graph analysis - cycles, bottlenecks, and instability

The dependency graph contains 1,666 nodes and 4,819 edges (avg degree 5.79) with 4 import cycles. The dominant structural risk is a massive 253-file cycle spanning 44 crates, with ui (61 files), project (42), and editor (39) as the heaviest participants. This mega-cycle means these crates cannot be built, tested, or reasoned about independently. Two smaller 2-file cycles exist between context_server/transport/http.rs and http_client.rs, and between gpui/executor.rs and scheduler.rs. A 7-file cycle links agent_ui, agent_servers, and agent crates. gpui.rs is the most central file by a wide margin (PageRank 0.039, betweenness 0.108, fan-in 803), which is appropriate for a framework root, but its fan-out of 42 is high for such a foundational file -- changes to its dependencies ripple widely. editor.rs has the highest fan-out in the codebase (54 outgoing edges) combined with high fan-in (121) and betweenness (0.055), making it the most change-sensitive non-framework file. project.rs is similarly exposed (fan-out 39, fan-in 168, betweenness 0.031). Several bottleneck files have high betweenness relative to their PageRank: vim/test.rs (betweenness 0.057, only 12 dependents) acts as a test-infrastructure chokepoint, ui/components.rs (betweenness 0.028, fan-out 44 vs fan-in 4) is a fragile re-export hub, and gpui/platform.rs (betweenness 0.023, fan-out 12) bridges platform-specific code. Stable foundation files with zero fan-out include util/serde.rs (211 dependents), net/util.rs (187), collections.rs (132), and xtask/workspace.rs (170) -- these are appropriately stable. workspace.rs, vim.rs, outline_panel.rs, and project_panel.rs all have instability 1.0 (zero dependents, high fan-out), which is expected for application-layer leaf modules. The most actionable improvements are: (1) break the 253-file mega-cycle, likely by extracting shared trait definitions from ui, editor, and project into smaller interface crates that do not depend back on their consumers; (2) reduce editor.rs fan-out by splitting its 54 dependencies into focused sub-modules with narrower dependency sets; (3) resolve the gpui/executor <-> scheduler cycle by moving shared types into a common crate or collapsing them; (4) address the context_server <-> http_client cycle by introducing an HTTP trait abstraction that context_server depends on without pulling in the concrete http_client.

1666
Modules
4819
Dependencies
5.8
Avg Degree
4
Dependency Cycles

Detected Cycles

Cycle (2 files)
crates/context_server/src/transport/http.rscrates/http_client/src/http_client.rscrates/context_server/src/transport/http.rs
Cycle (2 files)
crates/gpui/src/executor.rscrates/scheduler/src/scheduler.rscrates/gpui/src/executor.rs
Cycle (253 files)
crates/ui/src/utils/with_rem_size.rscrates/ui/src/utils/search_input.rscrates/ui/src/utils/color_contrast.rscrates/ui/src/utils.rscrates/ui/src/traits/visible_on_hover.rscrates/ui/src/traits/styled_ext.rscrates/ui/src/traits/clickable.rscrates/ui/src/traits/animation_ext.rscrates/ui/src/traits.rscrates/ui/src/styles/units.rscrates/lsp/src/input_handler.rscrates/lsp/src/lsp.rscrates/language/src/buffer_tests.rscrates/language/src/toolchain.rscrates/task/src/static_source.rscrates/task/src/task.rscrates/language/src/task_context.rscrates/agent/src/outline.rscrates/language/src/language_settings.rscrates/language/src/language_registry.rscrates/language/src/buffer.rscrates/language/src/language.rscrates/rpc/src/proto_client.rscrates/rpc/src/rpc.rscrates/buffer_diff/src/buffer_diff.rscrates/multi_buffer/src/transaction.rscrates/multi_buffer/src/path_key.rscrates/multi_buffer/src/multi_buffer_tests.rscrates/multi_buffer/src/multi_buffer.rscrates/askpass/src/askpass.rscrates/git/src/repository.rscrates/git/src/hosting_provider.rscrates/git/src/git.rscrates/editor/src/git/blame.rs.../t_prediction_types/src/edit_prediction_types.rscrates/editor/src/inlays/inlay_hints.rscrates/editor/src/signature_help.rscrates/editor/src/editor_tests.rscrates/editor/src/edit_prediction_tests.rscrates/editor/src/code_completion_tests.rscrates/editor/src/tasks.rscrates/editor/src/split_editor_view.rscrates/feature_flags/src/feature_flags.rscrates/editor/src/split.rscrates/editor/src/selections_collection.rscrates/editor/src/scroll/autoscroll.rscrates/editor/src/actions.rscrates/editor/src/scroll.rscrates/editor/src/rust_analyzer_ext.rscrates/db/src/db.rscrates/editor/src/persistence.rscrates/editor/src/movement.rscrates/editor/src/mouse_context_menu.rscrates/editor/src/lsp_ext.rscrates/editor/src/lsp_colors.rscrates/editor/src/linked_editing_ranges.rscrates/editor/src/jsx_tag_auto_close.rscrates/editor/src/items.rscrates/editor/src/inlays.rscrates/editor/src/indent_guides.rscrates/editor/src/hover_popover.rscrates/editor/src/hover_links.rscrates/editor/src/highlight_matching_bracket.rscrates/editor/src/editor_settings.rscrates/editor/src/display_map/wrap_map.rscrates/editor/src/display_map/inlay_map.rscrates/editor/src/display_map/fold_map.rscrates/editor/src/display_map/custom_highlights.rscrates/editor/src/display_map/crease_map.rscrates/editor/src/display_map/block_map.rscrates/editor/src/display_map.rscrates/editor/src/code_context_menus.rscrates/editor/src/clangd_ext.rscrates/editor/src/bracket_colorization.rscrates/editor/src/editor.rs.../ant_slash_command/src/slash_command_registry.rs.../nt_slash_command/src/extension_slash_command.rs.../nt_slash_command/src/assistant_slash_command.rscrates/agent_ui/src/slash_command.rscrates/dap/src/transport.rscrates/dap/src/registry.rscrates/dap/src/debugger_settings.rscrates/dap/src/adapters.rscrates/dap/src/dap.rscrates/context_server/src/context_server.rscrates/extension/src/types.rscrates/extension_api/src/settings.rscrates/theme/src/schema.rscrates/theme/src/scale.rscrates/theme/src/font_family_cache.rscrates/theme/src/fallback_themes.rscrates/theme/src/default_colors.rscrates/theme/src/theme.rscrates/ui/src/styles/typography.rscrates/ui/src/styles/spacing.rscrates/repl/src/outputs/image.rs.../s/gpui/src/platform/windows/directx_renderer.rscrates/gpui/src/platform/windows/direct_write.rs.../s/gpui/src/platform/windows/destination_list.rscrates/gpui/src/platform/windows.rscrates/gpui/src/platform/mac.rscrates/gpui/examples/layer_shell.rscrates/gpui/src/platform/linux/wayland.rscrates/edit_prediction_cli/src/headless.rscrates/gpui/src/platform/linux.rscrates/gpui/src/platform.rscrates/ui/src/styles/elevation.rscrates/ui/src/styles/appearance.rscrates/gpui/examples/animation.rscrates/ui/src/styles.rscrates/component/src/component_layout.rscrates/component/src/component.rscrates/ui/src/prelude.rscrates/ui_input/src/input_field.rscrates/ui_input/src/ui_input.rscrates/picker/src/popover_menu.rscrates/picker/src/highlighted_match_with_paths.rscrates/picker/src/head.rscrates/picker/src/picker.rscrates/storybook/src/stories/kitchen_sink.rscrates/storybook/src/stories/focus.rscrates/storybook/src/stories/auto_height_editor.rscrates/storybook/src/stories.rscrates/ui/src/components/tree_view_item.rscrates/ui/src/components/tooltip.rscrates/ui/src/components/toggle.rscrates/ui/src/components/thread_item.rscrates/ui/src/components/tab_bar.rscrates/ui/src/components/tab.rscrates/ui/src/components/sticky_items.rscrates/ui/src/components/stack.rscrates/ui/src/components/scrollbar.rscrates/ui/src/components/right_click_menu.rscrates/ui/src/components/progress/progress_bar.rscrates/ui/src/components/progress.rscrates/gpui/examples/popover.rscrates/ui/src/components/navigable.rscrates/tasks_ui/src/modal.rscrates/gpui/src/elements/list.rscrates/ui/src/components/label/spinner_label.rscrates/ui/src/components/label/loading_label.rscrates/ui/src/components/label/label_like.rs.../es/ui/src/components/label/highlighted_label.rscrates/ui/src/components/label.rscrates/ui/src/components/keybinding_hint.rscrates/ui/src/components/keybinding.rscrates/ui/src/components/icon/icon_decoration.rscrates/ui/src/components/icon/decorated_icon.rscrates/ui/src/components/icon.rscrates/ui/src/components/group.rscrates/ui/src/components/facepile.rscrates/ui/src/components/dropdown_menu.rscrates/ui/src/components/divider.rscrates/ui/src/components/disclosure.rscrates/gpui/examples/data_table.rscrates/ui/src/components/context_menu.rscrates/ui/src/components/content_group.rscrates/call/src/call_settings.rscrates/call/src/call.rscrates/title_bar/src/collab.rscrates/ui/src/components/chip.rscrates/ui/src/components/button/toggle_button.rscrates/ui/src/components/button/split_button.rscrates/ui/src/components/button/icon_button.rscrates/ui/src/components/button/copy_button.rscrates/ui/src/components/button/button_link.rscrates/ui/src/components/button/button_like.rscrates/ui/src/components/button.rscrates/ui/src/components/banner.rscrates/ui/src/components/avatar.rscrates/ui/src/components/ai/configured_api_card.rscrates/ui/src/components/ai.rscrates/ui/src/components.rscrates/ui/src/component_prelude.rscrates/ui/src/ui.rscrates/search/src/search_status_button.rscrates/search/src/search_bar.rscrates/search/src/project_search.rscrates/search/src/buffer_search/registrar.rscrates/search/src/buffer_search.rscrates/search/src/search.rscrates/vim/src/test/vim_test_context.rscrates/vim/src/test/neovim_backed_test_context.rscrates/vim/src/test.rscrates/gpui_macros/src/gpui_macros.rscrates/gpui/src/styled.rscrates/anthropic/src/anthropic.rscrates/language_model/src/fake_provider.rscrates/client/src/telemetry.rscrates/copilot/src/request.rscrates/workspace/src/persistence/model.rscrates/language_model/src/api_key.rscrates/language_model/src/language_model.rscrates/agent_ui/src/context.rscrates/gpui/src/keymap.rscrates/gpui/src/assets.rscrates/gpui/src/app.rscrates/gpui/src/gpui.rscrates/theme/src/settings.rscrates/fs/src/fake_git_repo.rscrates/fs/src/fs.rscrates/worktree/src/worktree_settings.rscrates/worktree/src/worktree.rscrates/project/src/yarn.rscrates/project/src/environment.rscrates/project/src/worktree_store.rscrates/project/src/trusted_worktrees.rscrates/project/src/toolchain_store.rscrates/terminal/src/mappings/mouse.rscrates/terminal/src/terminal_settings.rscrates/terminal/src/terminal_hyperlinks.rscrates/terminal/src/pty_info.rscrates/terminal/src/terminal.rscrates/project/src/terminals.rscrates/project/src/telemetry_snapshot.rscrates/project/src/task_store.rscrates/project/src/task_inventory.rscrates/project/src/project_settings.rscrates/project/src/prettier_store.rscrates/project/src/manifest_tree/server_tree.rscrates/project/src/manifest_tree/manifest_store.rscrates/project/src/manifest_tree.rscrates/project/src/lsp_store/inlay_hint_cache.rs.../roject/src/lsp_store/vue_language_server_ext.rscrates/project/src/lsp_store/lsp_ext_command.rscrates/project/src/lsp_store/log_store.rs.../oject/src/lsp_store/json_language_server_ext.rscrates/project/src/lsp_store.rscrates/project/src/lsp_command.rscrates/project/src/image_store.rscrates/project/src/git_store/pending_op.rscrates/project/src/git_store/git_traversal.rscrates/project/src/git_store/conflict_set.rscrates/project/src/git_store/branch_diff.rscrates/project/src/git_store.rscrates/repl/src/session.rscrates/languages/src/python.rscrates/project/src/debugger/locators/node.rscrates/languages/src/go.rscrates/project/src/debugger/locators/cargo.rscrates/project/src/debugger/locators.rscrates/project/src/debugger/dap_store.rscrates/project/src/debugger/dap_command.rscrates/project/src/debugger/breakpoint_store.rscrates/project/src/debugger.rscrates/project/src/debounced_delay.rscrates/project/src/context_server_store.rscrates/project/src/connection_manager.rscrates/project/src/color_extractor.rscrates/project/src/buffer_store.rscrates/project/src/agent_server_store.rscrates/project/src/agent_registry_store.rscrates/project/src/project.rscrates/ui/src/utils/with_rem_size.rs
Cycle (7 files)
crates/agent_ui/src/acp/thread_view.rscrates/agent_ui/src/acp/message_editor.rscrates/agent_ui/src/acp.rscrates/agent_servers/src/agent_servers.rscrates/agent/src/thread_store.rscrates/agent/src/native_agent_server.rscrates/agent/src/agent.rscrates/agent_ui/src/acp/thread_view.rs
FileLangPageRankBetweennessInOutInstability

Known Issues

Problems the team has documented but not yet fixed (TODO, FIXME, HACK)

824 SATD markers across the codebase (density 0.61 per 1K lines). The bulk is low-severity TODOs (375) and PERF annotations (173), which are largely informational. The 23 critical-severity items are concentrated in security-sensitive code (tool permissions, proxy, shell handling) and are well-documented guardrails rather than unresolved debt. The real risks are: (1) known logic bugs left unresolved in production paths (path_key ordering bug, worktree abs_path bug, GPUI window bounds bug), (2) a cluster of hacks in GPUI platform code that work around upstream or OS-level bugs and could silently break on platform updates, (3) the shell_builder 'broken beyond repair' comment indicating architectural debt in the task infrastructure, and (4) the edit_file_tool being broken under remoting -- a correctness gap in a user-facing agent feature. Most SECURITY-category markers are intentional documentation of security design decisions and are appropriate to keep. The highest-value cleanup targets are the unresolved BUG markers in non-test production code and the demo hack in acp_tools that was never cleaned up.

824
Total Issues
23
Critical
66
High
226
Medium

By Severity

By Category

SeverityCategoryFileLangLineComment

Duplicated Code

Code that appears in multiple places - bugs fixed in one spot may need fixing elsewhere

The codebase has 51,191 duplicated lines across 488,495 total lines (10.5% duplication ratio), organized into 721 clone groups with 6,486 clone pairs. While some duplication is structural (test fixtures, generated code), several clusters represent missing abstractions that carry real bug-fix divergence risk.

Highest-impact duplication clusters:

  1. Language model providers (18 groups, ~1,200 lines): The files under crates/language_models/src/provider/ (vercel.rs, x_ai.rs, open_ai.rs, deepseek.rs, mistral.rs, google.rs, anthropic.rs, open_router.rs, ollama.rs, open_ai_compatible.rs) share heavily duplicated API key state management, authentication flows, settings reading, and model listing boilerplate. Group 661 alone has 8 identical copies of the same code across 8 providers. Group 603 spans all 10 providers. The vercel.rs and x_ai.rs providers are nearly identical (groups 196, 336, 132 totaling ~245 lines). Extraction target: a generic ApiKeyProvider<T> trait or shared ProviderState struct in crates/language_model/ that handles API key storage, authentication checks, and settings observation. This would eliminate approximately 800-1,000 lines.

  2. Git hosting providers (14 groups, ~1,450 lines): All 6 providers (github.rs, gitlab.rs, bitbucket.rs, forgejo.rs, gitea.rs, sourcehut.rs) duplicate URL-building logic, permalink construction, and test structure. Group 4 spans all 6 providers with 309 lines of type-2 clones. Group 118 has 14 instances across the same files. The forgejo/gitea/gitlab trio (group 286) shares 113 lines of exact duplicates. Extraction target: a HostingProviderBase struct or macro that generates the common URL patterns, with per-provider configuration for path formats. Estimated savings: ~900 lines.

  3. Vim test infrastructure (32 groups, ~7,125 lines): The crates/vim/ directory dominates duplication. Group 396 has 54 instances spanning change_list.rs, indent.rs, normal.rs, delete.rs, and more -- 1,602 lines of type-2 clones that appear to be repeated test setup/assertion patterns. Group 9 adds another 809 lines across 51 instances. Group 68 has 807 lines across normal.rs, change.rs, and delete.rs. While test duplication is lower risk, this volume indicates missing test helper functions. Extraction target: shared test utilities for cursor positioning, mode assertion, and text manipulation verification in a vim::test::helpers module.

  4. Theme default colors (1 group, 2,079 lines): crates/theme/src/default_colors.rs has 33 exact copies (group 397) of the same 63-line StaticColorScaleSet struct initialization, differing only in the color values. This is the single largest clone group. Extraction target: a data-driven approach (array of color definitions) with a single function that constructs all scales, or a macro. Estimated savings: ~1,900 lines.

  5. Editor split view (2 groups, ~1,050 lines): crates/editor/src/split.rs contains 7 near-identical blocks (group 221, 773 lines) suggesting repeated logic for left/right split synchronization that could be parameterized.

  6. API client crates (6 groups, ~280 lines cross-crate): The anthropic, open_ai, deepseek, mistral, lmstudio, and x_ai crates duplicate HTTP streaming response handling and error mapping (group 220: 124 lines between anthropic/open_ai). These are separate crates, making this a strong signal for a shared llm_http_client utility crate.

  7. Agent server implementations (7 groups, 250 lines): crates/agent_servers/src/claude.rs and codex.rs share 3 exact-copy groups totaling 106 lines of identical server lifecycle code.

  8. C/C++ language support (1 group, 424 lines): crates/languages/src/c.rs and crates/languages/src/cpp.rs share 212 lines of identical code (group 149), likely test fixtures or shared grammar configuration that belongs in a common module.

  9. Agent tools (group 515, 273 lines): restore_file_from_disk_tool.rs and save_file_tool.rs share 273 lines of duplicated file operation logic -- a clear candidate for a shared file_tool_utils module.

  10. Picker/selector UI pattern (9 cross-file groups): At least 7 separate picker/selector UIs across different crates (command_palette, language_selector, theme_selector, encoding_selector, toolchain_selector, etc.) duplicate the same delegate/list rendering boilerplate (group 324: 7 identical copies). This suggests the picker crate's abstraction could be extended to eliminate more boilerplate.

Cross-package duplication (144 groups): The strongest signals for missing shared libraries are: (a) action_log <-> agent (5+ groups, ~1,500 lines) suggesting shared logging/evaluation infrastructure is needed, (b) agent <-> editor (8+ groups, ~500 lines) suggesting shared text manipulation utilities, and (c) the language model provider ecosystem described above.

Recommended priority: The language model provider and git hosting provider extractions offer the best return -- they affect actively maintained, non-test code where bug-fix divergence is a real risk. When one provider gets a fix for error handling or auth flow, the others are likely to be missed.

10.5%
Duplication Rate
721
Clone Groups
51191
Duplicate Lines
488495
Total Lines

Duplication Level

Technical Debt Gradient

Per-file debt scores - prioritize cleanup where it matters most

The codebase has a sharply bimodal grade distribution: 581 A-grade files (34.9%) versus 586 F-grade files (35.2%), with very few files in between (B through D account for only 10.6% of the 1,666 graded files). The average grade is F and the average score is 58.8, but this average is misleading -- files are either healthy or severely degraded, with almost nothing in the middle. 584 of 586 F-grade files score exactly 0, meaning penalties from complexity, duplication, and coupling completely annihilate their scores.

Debt is heavily concentrated in a few crates. gpui leads with 108 F-grade files out of 174 (62%), followed by project (35F/74, 47%), collab (33F/85, 39%), editor (20F/52, 38%), and vim (17F/39, 44%). git_hosting_providers is the worst by percentage at 82% F-grade. These crates represent the core of the application and are where remediation effort would have the greatest impact.

230 F-grade files score poorly across all 6 dimensions (structural complexity, semantic complexity, duplication, coupling, hotspot activity, and temporal coupling). This indicates systemic, compounding debt rather than isolated issues. The most common penalty source is semantic complexity (deep nesting), applied 1,019 times, followed by duplication (677 times) and structural complexity (416 times).

The most dangerous files are those that are both F-grade and active development hotspots, because debt is accumulating in code that is being changed frequently: crates/project/src/lsp_store.rs (37 defects, hotspot=0.07), crates/editor/src/element.rs (15 defects, hotspot=0.08), crates/workspace/src/workspace.rs (19 defects, hotspot=0.08), crates/multi_buffer/src/multi_buffer.rs (34 defects, hotspot=0.12), and crates/project/src/project.rs (12 defects, hotspot=0.23). These files carry high defect counts and are under active modification, making them the highest-priority targets for refactoring.

Test files dominate the critical defect rankings: crates/editor/src/editor_tests.rs (469 defects), crates/project/tests/integration/project_tests.rs (423), and crates/collab/tests/integration/integration_tests.rs (355). Among non-test production code, crates/editor/src/editor_settings.rs (75 defects), crates/language/src/language_settings.rs (70 defects), and crates/worktree/src/worktree.rs (51 defects) are the worst offenders.

Recommended actions: (1) Prioritize lsp_store.rs, multi_buffer.rs, editor/element.rs, and workspace.rs -- these are active hotspots with compounding multi-dimensional debt. Break down deeply nested logic and extract duplicated patterns. (2) Address the settings files (editor_settings.rs, language_settings.rs, project_settings.rs) which collectively carry 185 critical defects, likely from repetitive configuration boilerplate that could be macro-generated or extracted. (3) In gpui, focus on client.rs (32 defects) and app.rs (24 defects) as the most defect-dense production files. (4) The test files with hundreds of defects likely reflect unsafe patterns (unwrap calls, missing error handling) that propagate bad practices -- consider a targeted cleanup pass.

1666
Files Scored
58.8
Average Score
F
Average Grade
586
Failing Files

Grade Distribution

FileLangScoreGradeStructuralSemanticDuplicationCoupling

Change Activity

How frequently code is being modified

Churn is heavily concentrated: the top 10 files account for 17.6% of all changes across 5,012 files, and the top 100 account for 44.4%. The median file has only 2 commits, while the mean is 9.2, indicating a long tail where a small number of files absorb the vast majority of change activity.

The highest-churn source file is crates/editor/src/editor.rs (778 commits, 359 days active, 28,553 LOC, relative churn 1.51x). Its commit history is a healthy mix of feature additions (syntax node selection, fold persistence, diff review) and bug fixes (clipboard, visual mode, bracket colors), consistent with a core module that naturally accumulates changes rather than one with a design problem.

The agent subsystem stands out as a structural hotspot. crates/agent/src/thread.rs has a relative churn of 5.48x (231 commits, 3,445 LOC) -- meaning roughly 5.5 times the file's current size has been added and removed over the analysis period. crates/agent_ui/src/acp/thread_view.rs shows 2.96x relative churn (343 commits, 11,474 LOC), and crates/agent/src/thread_store.rs shows 12.07x relative churn (64 commits, 301 LOC). Commit messages reveal rapid feature iteration (subagents, message queuing, tool permissions, terminal context) layered with bug fixes and reverts. The combination of high relative churn, sustained activity, and frequent rework suggests the agent module's design is under strain from rapid feature growth and would benefit from stabilization.

The settings_ui crate is another area of concern. crates/settings_ui/src/page_data.rs has 4.31x relative churn (85 commits in only 113 active days, 8,847 LOC), and crates/settings_ui/src/settings_ui.rs has 4.38x relative churn (162 commits, 4,862 LOC). Commits show a steady stream of new settings being added (vim, encoding, font, proxy, edit predictions), plus structural reorganizations like splitting settings content into its own crate. This is mostly feature-driven churn, but the high rate of UI-level bug fixes (scroll breakage, focus loss, panic prevention) suggests the architecture may not be scaling well with the growing number of settings.

crates/git_ui/src/git_panel.rs (3.12x relative churn, 329 commits, 7,346 LOC, 358 days active) shows sustained year-round churn. Commits are a roughly even split between feature work (tree view, commit modal, pull request actions, diff UI) and bug fixes (wrong entry selection, path truncation, checkbox alignment, branch deletion targeting wrong branch). The bug fix density here is notable and may indicate the panel's state management is becoming fragile.

Among deleted or heavily restructured files, crates/agent/src/active_thread.rs (148 commits, now 0 LOC) and crates/assistant_tools/src/edit_file_tool.rs (78 commits, now 0 LOC) confirm significant architectural churn in the agent subsystem -- entire modules being built, iterated on, and then removed or replaced.

Overall, the editor crate's churn is expected for a core text editing component. The concerning patterns are concentrated in the agent, settings_ui, and git_ui subsystems, where high relative churn combined with sustained bug fix commits points to design pressure that may warrant architectural review.

46325
Total Changes
5012
Files Changed
1427453
Lines Added
788318
Lines Deleted
FileLangChangesContributorsChurn Score

Code Ownership

How knowledge is distributed - concentrated knowledge is a risk

Of 1665 analyzed files, 660 (40%) are high risk and 257 have a bus factor of 1 (single contributor). The top 6 contributors (Max Brunsfeld, Marshall Bowers, Conrad Irwin, Antonio Scandurra, Mikayla Maki, Piotr Osiewicz) collectively own the majority of files, with several entire crates owned by a single person. The most critical risks are: (1) large single-owner files in core subsystems like editor, gpui, and agent; (2) entire crates with 100% ownership concentration such as buffer_diff, dev_container, dap_adapters, and action_log; (3) heavily fragmented files like editor.rs (160 contributors, no clear owner at 10.4%) and workspace.rs (105 contributors, top owner at 10.8%) where diffuse responsibility increases defect risk. Max Brunsfeld's concentration across language (90%), multi_buffer (91%), worktree (97%), and lsp (93%) represents the single largest knowledge silo in the project. Immediate knowledge transfer is needed for bus-factor-1 files exceeding 1000 lines in production code paths.

10
Bus Factor
257
Knowledge Silos
1665
Total Files
15.4%
Files at Risk

Top Contributors

Temporal Coupling

Files that frequently change together - reveals hidden dependencies not in the import graph

Temporal coupling analysis of 1,207 file pairs reveals several structural concerns across the Zed codebase.

  1. GPUI Platform Cluster -- Tight but Expected, With a Surprise

The GPUI platform layer forms the densest coupling cluster in the codebase. Files like crates/gpui/src/executor.rs (19 coupling partners), crates/gpui/src/platform/linux/x11/client.rs (15 partners), and crates/gpui/src/platform/linux/wayland/client.rs (15 partners) change together frequently. Most of this is expected: platform trait changes propagate to all implementations. However, crates/repl/src/repl.rs is temporally coupled to nearly every GPUI dispatcher and platform client file (strength 0.40-0.80 across 9 pairs, all with 4 co-changes). REPL has no obvious architectural reason to co-change with low-level platform dispatchers. This likely reflects a batch refactor (e.g., an executor API change that touched REPL), but if it persists, it signals that REPL depends on unstable GPUI internals rather than a stable public API.

  1. Cross-Crate Settings Triad -- Missing Shared Schema

assets/settings/default.json, crates/settings_ui/src/page_data.rs, and crates/settings/src/vscode_import.rs form a triangle of temporal coupling (strength 0.36-0.52, 9-13 co-changes). Every time a setting is added or changed, all three files must be updated in lockstep. This is a classic sign of a missing shared schema or code-generated manifest. The setting definitions are duplicated across the default config file, the UI page data, and the VS Code import mapping. Consider generating page_data.rs and the vscode_import mappings from the canonical default.json, or extracting a shared settings registry that all three consume.

  1. Agent Ecosystem Fragmentation

crates/acp_thread/src/connection.rs is coupled to files in four separate crates: agent_servers (strength 0.50, 6 co-changes), agent (strength 0.43, 6 co-changes), agent_ui (strength 0.40, 4 co-changes), and agent_ui_v2 (strength 0.40, 4 co-changes). This fan-out pattern means a protocol or connection change in acp_thread cascades across the entire agent stack. The coupling between agent_ui and agent_ui_v2 is also notable (e.g., agent_panel.rs coupled with agent_thread_pane.rs and agents_panel.rs at 5 co-changes each), suggesting the v2 migration is progressing in lockstep rather than being independent, which increases coordination cost.

  1. Proto-Collab Coupling -- Expected but Worth Monitoring

crates/proto/proto/zed.proto and crates/proto/src/proto.rs have coupling strength 0.86 (6 co-changes), and crates/collab/src/rpc.rs is coupled to both (strength 0.57-0.67). This is architecturally expected for protobuf changes flowing to RPC handlers. The coupling to crates/remote_server/src/headless_project.rs (strength 0.43) and crates/project/src/project.rs (strength 0.14) is lower, suggesting these consumers are more insulated. No action needed, but watch for the collab/rpc coupling growing.

  1. LLM Provider Coupling Cluster -- Interface Change Amplification

crates/language_models/src/provider/mistral.rs has 18 coupling partners, and crates/language_models/src/provider/anthropic.rs has 17. These providers change together at strength 0.43-0.67. This is a classic N-implementation problem: any change to the provider interface or shared request types (crates/language_model/src/request.rs appears at strength 0.38) forces updates across all providers. The coupling also extends outside the crate to crates/rules_library/src/rules_library.rs (strength 0.38-0.60) and crates/agent/src/edit_agent.rs (strength 0.38-0.60), indicating that provider-level concerns are leaking into consumers. Consider whether a trait default implementation or adapter layer could absorb more of the shared behavior.

  1. Keymap File Triple -- Perfect Coupling

assets/keymaps/default-linux.json, default-macos.json, and default-windows.json have coupling strength 0.96-1.00 with 24-25 co-changes. This is the highest-volume perfect coupling in the dataset. Every keymap change touches all three files. These files likely share most of their content with platform-specific overrides. A layered keymap system (base + platform delta) would eliminate this triple-write pattern.

  1. Edit Prediction Cross-Crate Spread

crates/edit_prediction_ui/src/edit_prediction_button.rs is coupled to crates/language/src/language_settings.rs (strength 0.60, 6 co-changes) and crates/copilot/src/copilot.rs (strength 0.50, 5 co-changes). The coupling to language_settings suggests the edit prediction feature toggles are embedded in language settings rather than having their own configuration surface. The copilot coupling suggests shared UI state for prediction providers. Meanwhile, crates/edit_prediction/src/udiff.rs and crates/edit_prediction_cli/src/load_project.rs have strength 0.50 with 10 co-changes, showing tight coupling between the core prediction format and the CLI tooling.

  1. CI Workflow Coupling

.github/workflows/extension_tests.yml and tooling/xtask/src/tasks/workflows/extension_tests.rs have strength 0.78 (7 co-changes), and similar patterns exist for run_tests.yml and release workflows. This is healthy -- it means CI workflow YAML and the Rust xtask code that generates or validates them stay in sync. However, the coupling between release_nightly.yml and run_tests.rs (strength 0.71) suggests test configuration is entangled with release configuration, which may cause unnecessary CI churn.

Key Recommendations:

  • Extract a shared settings schema to break the default.json / page_data.rs / vscode_import.rs triple coupling.
  • Investigate the REPL-to-GPUI-dispatcher coupling to determine if REPL depends on internal executor APIs that should be stabilized or abstracted.
  • Consider a layered keymap format to eliminate the mandatory triple-edit for platform keymaps.
  • Evaluate whether LLM provider trait defaults or an adapter pattern could reduce the N-provider amplification when the interface changes.
  • Monitor the agent ecosystem coupling as the v2 migration progresses; independent evolution of agent_ui_v2 would reduce coordination cost.
1207
Coupled Pairs
253
Strong Couplings
0.3
Avg Strength
1.0
Max Strength
File AFile BCo-changesStrength

Score Breakdown

How the health score is calculated from individual components

Complexity25%
0
Duplication20%
69
Cohesion15%
77
Debt Gradient15%
59
Known Debt10%
70
Coupling10%
35
Code Smells5%
77

Glossary of Terms

Health Score

A weighted composite metric (0-100) measuring overall code quality. Above 80 is good, 60-80 needs attention, below 60 is concerning.

Hotspot

A file that is both complex AND frequently changed. These are the highest-risk areas because they're hard to change safely but get changed often.

Bus Factor

The minimum number of people who would need to leave before critical knowledge is lost. Higher is better; 1 is a serious risk.

Knowledge Silo

A file that only one person has ever touched. If that person leaves, the knowledge goes with them.

Cyclomatic Complexity

The number of independent paths through code. More paths means more test cases needed and more ways things can go wrong.

Cognitive Complexity

How hard code is to understand. Accounts for nesting, breaks in flow, and things that make humans struggle to follow the logic.

LCOM (Cohesion)

How well a class's methods work together. High LCOM means methods don't share data - the class is probably doing too many unrelated things.

CBO (Coupling)

How many other classes a class depends on. High coupling means changes ripple through the codebase - everything is connected to everything.

Churn Rate

How frequently a file changes. High churn indicates instability - the code may be unclear, have bugs, or be undergoing active development.

Self-Admitted Technical Debt (SATD)

Code issues the team has documented (TODO, FIXME, HACK, XXX). These represent known shortcuts that need eventual attention.

Code Clone / Duplicate

Similar code appearing in multiple places. When a bug is fixed in one spot, it may need fixing elsewhere. Candidates for refactoring into shared functions.

Technical Debt Gradient

Per-file quality score (0-100) combining complexity, duplication, coupling, and other factors. Lower scores mean more accumulated debt.

Temporal Coupling

Files that frequently change together in the same commits. High temporal coupling suggests hidden dependencies not visible in the import graph.

Architectural Smell

A structural pattern that violates design principles: cyclic dependencies, hub-like modules, or stable code depending on unstable code.

Instability

Ratio of outgoing to total dependencies. 0 = maximally stable (many things depend on it), 1 = maximally unstable (depends on many things).

PageRank

Importance of a file in the dependency graph. Files with high PageRank are depended on by many other important files.