#linter #ast #code-quality #wasm

app cha-cli

Cha — pluggable code smell detection CLI (察)

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

MIT license

1MB
21K SLoC

Cha

cha logo

察 — Code Health Analyzer

CI License Stars Release

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 NL annotations
  • 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