37 releases (23 stable)
Uses new Rust 2024
| new 1.14.0 | May 14, 2026 |
|---|---|
| 1.13.1 | Apr 30, 2026 |
| 0.7.0 | Apr 17, 2026 |
| 0.6.5 | Apr 15, 2026 |
| 0.1.1 | Apr 10, 2026 |
#121 in Testing
1MB
21K
SLoC
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.
Dependencies
~123MB
~3M SLoC