Cha
Install v1.14.0
Cha
察 — Code Health Analyzer
Cha (察, "to examine") is a pluggable code smell detection toolkit. It parses source code at the AST level, runs architectural health checks, and reports findings as terminal output, JSON, LLM context, or SARIF.
⚡ Quick Start
# Analyze current directory (recursive, .gitignore aware) cha analyze # Analyze specific path with JSON output cha analyze src/ --format json --fail-on error # Only analyze changed files (git diff) cha analyze --diff # Analyze changes from piped diff (e.g. PR review) gh pr diff | cha analyze --stdin-diff --fail-on warning # Run specific plugins only cha analyze --plugin complexity,naming # Force full re-analysis (skip cache) cha analyze --no-cache # Generate baseline of current issues cha baseline # Only report new issues (not in baseline) cha analyze --baseline .cha/baseline.json # Generate HTML report cha analyze --format html --output report.html # Parse and inspect file structure cha parse src/ # Generate default config cha init # Print JSON Schema for output format cha schema # Auto-fix naming convention violations cha fix src/ --dry-run # Scaffold a new WASM plugin cha plugin new my-plugin # Build plugin and convert to WASM component cha plugin build # Install plugin cha plugin install my_plugin.wasm # List installed plugins cha plugin list # Remove a plugin cha plugin remove my_plugin # Generate shell completions (fish/bash/zsh/powershell) cha completions fish > ~/.config/fish/completions/cha.fish # Show import dependency graph (DOT/JSON/Mermaid/PlantUML) cha deps --format dot cha deps --format mermaid --depth dir cha deps --format plantuml # Show class hierarchy cha deps --type classes --format dot cha deps --type classes --filter Plugin --format mermaid cha deps --type classes --filter Plugin --detail --format plantuml # Show function call graph (with direction filtering) cha deps --type calls --format dot cha deps --type calls --filter analyze --direction out # what does analyze call? cha deps --type calls --filter analyze --direction in # who calls analyze? # Show refactoring hotspots (change frequency × complexity) cha hotspot cha hotspot -c 200 -t 10 --format json # Infer architectural layers from import dependencies cha layers cha layers --format terminal # colored terminal output with instability bands cha layers --format dsm # dependency structure matrix cha layers --format dot # Graphviz DOT cha layers --depth 2 # override auto-detected directory depth # Auto-suggest thresholds from project statistics cha calibrate # show P90/P95 suggestions cha calibrate --apply # save to .cha/calibration.toml (auto-applied by analyze)
⚡ Performance
Cha uses a two-level cache (L1 in-memory + L2 bincode on disk) with mtime fast-path. Benchmarked on 3,201 C files (NuttX RTOS):
| Command | Cold | Warm Cache | Speedup |
|---|---|---|---|
analyze |
5.7s | 3.3s | 26× |
layers |
— | 0.8s | 16× |
deps |
— | 0.9s | 14× |
calibrate |
— | 0.6s | 22× |
📦 Installation
Shell (macOS / Linux)
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/W-Mai/Cha/releases/latest/download/cha-cli-installer.sh | sh
PowerShell (Windows)
powershell -c "irm https://github.com/W-Mai/Cha/releases/latest/download/cha-cli-installer.ps1 | iex"
Homebrew
brew install W-Mai/cellar/cha-cli
From source
git clone https://github.com/W-Mai/Cha.git cd Cha cargo build --release
Requires Rust (edition 2024).
See cha.to01.icu for all platforms and download options.
🔍 Built-in Plugins
| Plugin | Detects | Category | Severity |
|---|---|---|---|
| LengthAnalyzer | Long methods (>50 lines), large classes, large files | Bloaters | Warning |
| ComplexityAnalyzer | High cyclomatic complexity | Bloaters | Warning/Error |
| CognitiveComplexityAnalyzer | Cognitive complexity — nesting-aware understandability metric (>15) | Bloaters | Warning/Error |
| DuplicateCodeAnalyzer | Structural duplication via AST hash (>10 lines) | Dispensables | Warning |
| CouplingAnalyzer | Excessive imports / dependencies | Couplers | Warning |
| NamingAnalyzer | Too-short names, convention violations | Bloaters | Hint/Warning |
| DeadCodeAnalyzer | Unexported / unreferenced code | Dispensables | Hint |
| ApiSurfaceAnalyzer | Over-exposed public API (>80% exported) | Couplers | Warning |
| LayerViolationAnalyzer | Cross-layer dependency violations | Change Preventers | Error |
| LongParameterListAnalyzer | Functions with >5 parameters | Bloaters | Warning |
| SwitchStatementAnalyzer | Excessive switch/match arms (>8) | OO Abusers | Warning |
| MessageChainAnalyzer | Deep field access chains (a.b.c.d) | Couplers | Warning |
| PrimitiveObsessionAnalyzer | Functions with mostly primitive parameter types | Bloaters | Hint |
| DataClumpsAnalyzer | Repeated parameter type signatures across functions | Bloaters | Hint |
| FeatureEnvyAnalyzer | Methods that reference external objects more than their own | Couplers | Hint |
| MiddleManAnalyzer | Classes where most methods only delegate | Couplers | Hint |
| CommentsAnalyzer | Functions with >30% comment lines | Dispensables | Hint |
| LazyClassAnalyzer | Classes with ≤1 method and very few lines | Dispensables | Hint |
| DataClassAnalyzer | Classes with only fields and accessors, no behavior | Dispensables | Hint |
| TemporaryFieldAnalyzer | Fields used in only a few methods | OO Abusers | Hint |
| SpeculativeGeneralityAnalyzer | Interfaces/traits with ≤1 implementation | Dispensables | Hint |
| RefusedBequestAnalyzer | Subclasses that override most parent methods | OO Abusers | Hint |
| ShotgunSurgeryAnalyzer | Files that always change together (git log) | Change Preventers | Hint |
| DivergentChangeAnalyzer | Files changed for many distinct reasons (git log) | Change Preventers | Hint |
| InappropriateIntimacyAnalyzer | Bidirectional imports between files | Couplers | Warning |
| DesignPatternAdvisor | Suggests Strategy, State, Builder, Null Object, Template Method, Observer | OO Abusers | Hint |
| HardcodedSecretAnalyzer | API keys, tokens, passwords, private keys, JWTs in source code | Security | Warning |
| GodClassAnalyzer | Classes with high coupling (ATFD>5), high complexity (WMC≥47), and low cohesion (TCC<0.33) | Bloaters | Warning |
| BrainMethodAnalyzer | Functions that are long (>65L), complex (≥4), and reference many externals (>7) | Bloaters | Warning |
| HubLikeDependencyAnalyzer | Files with >20 imports, acting as dependency hubs | Couplers | Warning |
| ErrorHandlingAnalyzer | Empty catch/except blocks, excessive unwrap()/expect() calls | Security | Warning |
| TodoTrackerAnalyzer | Leftover TODO/FIXME/HACK/XXX comments in source code | Dispensables | Hint/Warning |
| UnsafeApiAnalyzer | Dangerous function calls: eval, exec, system, unsafe, innerHTML | Security | Warning |
| UnstableDependency | Files depending on less stable modules (Martin's instability metric) | Couplers | Hint |
Supported languages: Python (.py), TypeScript (.ts/.tsx), Rust (.rs), Go (.go), C (.c/.h), C++ (.cpp/.cc/.cxx/.hpp/.hxx).
⚙️ Configuration
Create .cha.toml in your project root:
# Exclude paths from analysis (glob patterns) exclude = ["*/tests/fixtures/*", "vendor/*"] # Strictness: relaxed (2x thresholds), default (1x), strict (0.5x), or custom float strictness = "default" [plugins.length] enabled = true max_function_lines = 30 max_class_lines = 200 [plugins.complexity] warn_threshold = 10 error_threshold = 20 [plugins.coupling] max_imports = 15 [plugins.layer_violation] enabled = true layers = "domain:0,service:1,controller:2" # Per-language overrides (only write differences from global) [languages.c.plugins.naming] enabled = false # C uses snake_case, skip PascalCase check [languages.c.plugins.length] max_function_lines = 80 # C functions tend to be longer # Custom tech debt estimation weights (minutes per severity) [debt_weights] hint = 5 warning = 15 error = 30
All plugins are enabled by default. Set enabled = false to disable.
C language has a builtin profile that disables OOP-specific rules (naming, lazy_class, data_class, design patterns).
Inline Directives
Override analysis per-function directly in source code:
// cha:ignore — suppress all rules for next item // cha:ignore long_method — suppress specific rule // cha:ignore long_method,complexity — suppress multiple rules // cha:set long_method=100 — raise threshold to 100 for next item // cha:set threshold=200 — raise threshold for all rules
Works with //, #, --, and /* */ comment styles.
🧩 WASM Plugins
Extend with custom analyzers via WebAssembly Component Model:
cd examples/wasm-plugin-example cha plugin build cha plugin install example.wasm
Place .wasm files in .cha/plugins/ (project-local) or ~/.cha/plugins/ (global).
Configure plugin options in .cha.toml:
[plugins.hardcoded-strings] SITE_DOMAIN = "example.com" USER_NAME = "octocat"
Writing a plugin
Add to your plugin's Cargo.toml:
[lib] crate-type = ["cdylib"] [dependencies] cha-plugin-sdk = { git = "https://github.com/W-Mai/Cha" } wit-bindgen = "0.55"
Then in src/lib.rs — no WIT file needed, the SDK embeds it:
cha_plugin_sdk::plugin!(MyPlugin); struct MyPlugin; impl Guest for MyPlugin { fn name() -> String { "my-plugin".into() } fn analyze(input: AnalysisInput) -> Vec<Finding> { vec![] } }
See examples/wasm-plugin-example (suspicious names) and examples/wasm-plugin-hardcoded (hardcoded strings) for complete examples.
📖 Full Plugin Development Guide
💡 LSP Integration
cha lsp
Full-featured Language Server Protocol support:
- Diagnostics — real-time code smell detection on open/change/save
- Code Actions — suggested refactorings + Extract Method
- CodeLens — complexity, lines, params displayed above every function/class
- Hover — detailed quality report card (markdown table)
- Inlay Hints — inline
cx:N cog:N NLannotations - Document Symbols — outline view with ⚠ markers for problematic functions
- Semantic Tokens — warning modifier highlights on functions/classes with issues
- Workspace Diagnostics — full project scan without opening files
- Progress — progress notification during workspace scan
Works with any LSP-compatible editor (VS Code, Neovim, Helix, Zed, Sublime).
🔌 Integrations
Pre-commit
# .pre-commit-config.yaml repos: - repo: https://github.com/W-Mai/Cha rev: v1.4.1 hooks: - id: cha-analyze
GitHub Action
# .github/workflows/cha.yml - uses: W-Mai/Cha@v1.4.1 with: fail-on: warning upload-sarif: true
VS Code
Install the Cha extension from the Marketplace. It automatically downloads the cha binary on first launch — no manual setup needed.
Features: all LSP capabilities above + auto-download + auto-update.
🛠️ Development
# Run all CI checks locally cargo xtask ci # Individual steps cargo xtask build # Release build cargo xtask test # Unit + property + fixture tests cargo xtask lint # Clippy + fmt cargo xtask analyze # Self-analysis in all formats cargo xtask lsp-test # LSP smoke test # Release (push → wait CI → tag → wait release workflow → publish to crates.io) cargo xtask release
📁 Project Structure
cha-core/ Core traits, plugin registry, reporters, WASM runtime cha-parser/ Tree-sitter parsing (Python, TypeScript, Rust, Go, C, C++) cha-cli/ CLI binary (analyze, parse) cha-lsp/ LSP server binary xtask/ CI automation (cargo xtask) wit/ WIT interface for WASM plugins examples/ Example WASM plugin static/ Logo and assets
📄 License
MIT License.