Skip to content

Releases: W-Mai/Cha

1.20.0 - 2026-06-05

04 Jun 19:45
8e9963b

Choose a tag to compare

Release Notes

🎉 First minor since v1.0 — and the first release with a proper home on the web. https://cha.to01.icu is now a real product page, not just a README dump. Star the repo, share the link, and tell your linter Cha said hi.

The analyzer itself didn't move — every --version-visible behavior is identical to v1.19.0. What landed is the documentation, presentation, and integration story: somewhere we can actually point new users.

Added

  • Bilingual documentation site at https://cha.to01.icu — landing page (oranda) plus a full mdbook tree at /book/ (English) and /book/zh-CN/ (中文). 60+ pages covering install, quick-start, every CLI subcommand, every output format, LSP integration for VS Code / Helix / Neovim / Zed, configuration reference, JSON Schema, plugin development, six worked recipes (migrate from clippy, monorepo CI, suppress in legacy code, custom plugin in 50 lines, calibrate to your codebase, baseline workflow), three contributor guides (architecture, writing a smell, releasing), and an academic-references page tracing every smell back to its source.
  • Cookbook recipes — six task-oriented walkthroughs: migrate-from-clippy, monorepo-ci, suppress-legacy, custom-plugin-50loc, calibrate, baseline. Each starts with a problem statement and ends with copy-pasteable commands. Authored in English and Chinese (the Chinese versions are written natively, not translated, so the prose style matches the rest of zh-CN).
  • Contributor guidescontributing/architecture.md documents the seven-crate workspace and data flow with mermaid diagrams; writing-a-smell.md walks through MiddleManAnalyzer as the worked example; releasing.md is the runbook for cargo xtask bumprelease.
  • Configuration reference — every .cha.toml key, grouped by plugin, with thresholds and defaults sourced from cha-core/src/plugins/. JSON Schema reference page documenting cha schema output and how to wire it into IDEs.
  • Bilingual landing page (LANDING.md) — hero with logo + tagline + three CTAs, six feature cards (detectors, WASM SDK, LSP, git-aware analysis, output formats, two-level cache), 30-second get-started block, smell-category table, and editor integration links. Replaces the previous "README dumped into the homepage" experience.
  • CJK-aware search via Pagefind 1.4 — replaces mdbook's bundled elasticlunr (which silently dropped non-ASCII tokens, leaving the zh-CN tree un-searchable). Press s or / on any docs page to open a modal that indexes both language trees.
  • Per-page social meta + branded OG card — every page emits og:title / og:image / twitter:card so Slack / iMessage / 微信 link previews show a real card instead of a 32×32 favicon. The 1200×628 card embeds the Cha logo and is regenerable via python3 static/gen_og_card.py.
  • Custom 404 page — site-wide warm-themed 404 with the Cha logo and shortcuts back into the live parts of the site, replacing GitHub Pages' generic gray 404.
  • Language switcher in mdbook header — the toolbar globe icon switches between EN and zh-CN trees and remembers per-page equivalents.
  • xtask docs-check — verifies every page referenced in book/src(-zh-CN)/SUMMARY.md actually exists; runs as part of cargo xtask ci so a broken SUMMARY can't ship.
  • xtask i18n-check — flags zh-CN pages whose git ctime trails their English counterpart, surfacing translation drift.
  • xtask docgen-cli — generates book/src/reference/cli-manual.md from cha help-markdown so the CLI manual page in docs always matches the binary's actual --help. Hidden cha help-markdown subcommand added for this.
  • VS Code extension page — full inventory of what each LSP capability looks like inside VS Code (wavy underlines, lightbulbs, code-lens overlays, inlay hints, hover cards, semantic-token modifier, status-bar workspace scan progress) plus the cha.disabledPlugins setting documentation.

Fixed

  • tree-sitter S-expression query link — the link in docs/plugin-development.md and the zh-CN translation pointed at /syntax-highlighting/queries, which 404s on the current tree-sitter docs site. Updated to /using-parsers/queries/.
  • docs/plugin-development.md FunctionInfo / ClassInfo field tables — were bare struct dumps; now per-field semantic tables (type + what each field actually drives) for both languages.
  • README plugin table — every entry now has an anchor link into docs/plugins.md's detailed description, in both README.md and README.zh-CN.md. The previous UnstableDependency row (which never matched a real detector) was removed and async_callback_leak added.

Changed

  • Project homepagehttps://cha.to01.icu is the canonical entry point. README still works on github.com but now points at the docs site for anything beyond the quick-start.
  • CI — the Web workflow builds the EN tree via oranda, re-builds the zh-CN tree via mdbook with MDBOOK_BOOK__SRC=src-zh-CN, indexes both with Pagefind, and restores public/CNAME + drops public/404.html after oranda's clean. Deploys via JamesIves/github-pages-deploy-action@v4.6.4.

Notes for upgraders

Nothing to do. cha analyze produces the same output, .cha.toml accepts the same keys, every CLI flag still works. This is a documentation release: the binary moves from "had a single README" to "had a 60-page bilingual docs site" without changing anything you'd notice from the terminal.

If you want to celebrate by reading something other than --help: https://cha.to01.icu.

Install cha-cli 1.20.0

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/W-Mai/Cha/releases/download/v1.20.0/cha-cli-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/W-Mai/Cha/releases/download/v1.20.0/cha-cli-installer.ps1 | iex"

Install prebuilt binaries via Homebrew

brew install W-Mai/cellar/cha-cli

Download cha-cli 1.20.0

File Platform Checksum
cha-cli-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
cha-cli-x86_64-apple-darwin.tar.xz Intel macOS checksum
cha-cli-x86_64-pc-windows-msvc.zip x64 Windows checksum
cha-cli-x86_64-pc-windows-msvc.msi x64 Windows checksum
cha-cli-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
cha-cli-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum
cha-cli-x86_64-unknown-linux-musl.tar.xz x64 MUSL Linux checksum

1.19.0 - 2026-05-22

22 May 18:34
bb59edc

Choose a tag to compare

Release Notes

Hardcoded thresholds and keyword lists become plugin config; cha fix stops hardcoding smell names; the last two text-scanning detectors switch to AST queries.

Added

  • Plugin::try_fix(finding, ctx) -> Option<Patch> — every plugin can now contribute auto-fixes. cha fix walks all enabled plugins and asks each one. Adding fix support for a new smell is one trait override, not a host-side if smell_name == ... patch.
  • cha_core::Patch / cha_core::TextEdit — public byte-range edit types for plugin authors. Edits within a single finding are applied in reverse byte-offset order.
  • DesignPatternAdvisor config — 8 magic-number thresholds (strategy_min_arms, state_min_arms, builder_min_params, builder_alt_min_params, builder_alt_min_optional, null_object_min_count, template_min_self_calls, template_min_methods) and 2 keyword lists (type_field_keywords, state_field_keywords) are now overridable via [plugins.design_pattern].
  • GodClassAnalyzer::min_tcc — Tight Class Cohesion threshold (Lanza-Marinescu's 1/3) is configurable.
  • cache.rs walker skip-dirs — extended from {target, node_modules, dist} to also skip build, out, __pycache__, venv, .venv, vendor. Reduces unnecessary .cha.toml discovery work in polyglot repos.

Fixed

  • switch_statement / message_chain: replaced bespoke text scanners (find_switch_keyword, walk_chain and ~140 lines of hand-rolled tokenization) with tree-sitter queries against switch_statement / match_expression / field_expression / member_expression / selector_expression. Smell counts unchanged, but keyword positions are now sourced from the AST. No more false positives on keywords inside strings.
  • inappropriate_intimacy import resolution: extension probe expanded from {.ts, .tsx, .rs} to also include .py, .go, .cpp, .cc, .cxx, .c, .h, .hpp, .hxx, .js, .jsx, .mts, .cts. Sibling-file lookups in non-JS/Rust projects no longer silently fail.
  • calibrate.rs table rendering: 3 metric labels were hardcoded across 3 separate println blocks. Adding a calibration metric now means one entry in a (label, samples) array.

Changed

  • cha fix delegates to Plugin::try_fix for every finding — no more filter(|f| f.smell_name == "naming_convention") on the host. Existing behavior preserved (NamingAnalyzer fixes naming_convention PascalCase violations); other plugins return None until they opt in.

Install cha-cli 1.19.0

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/W-Mai/Cha/releases/download/v1.19.0/cha-cli-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/W-Mai/Cha/releases/download/v1.19.0/cha-cli-installer.ps1 | iex"

Install prebuilt binaries via Homebrew

brew install W-Mai/cellar/cha-cli

Download cha-cli 1.19.0

File Platform Checksum
cha-cli-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
cha-cli-x86_64-apple-darwin.tar.xz Intel macOS checksum
cha-cli-x86_64-pc-windows-msvc.zip x64 Windows checksum
cha-cli-x86_64-pc-windows-msvc.msi x64 Windows checksum
cha-cli-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
cha-cli-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum
cha-cli-x86_64-unknown-linux-musl.tar.xz x64 MUSL Linux checksum

1.18.0 - 2026-05-22

22 May 11:51
c175a5c

Choose a tag to compare

Release Notes

Built-in detectors now use AST queries instead of text scanning. Several core plugins previously did substring matches that misfired on strings, comments, and unrelated identifiers.

Added

  • cha_core::query — host-side tree-sitter query helper (run_query / run_queries / node_to_match). Both built-in plugins and the WASM tree_query host import now go through this single API.
  • DeadCodeAnalyzer::entry_points — entry-point names are now configurable via [plugins.dead_code] entry_points = [...]. Default list expanded from Rust-only (5 names) to multi-language (Rust + Python __init__ etc + Go init + C _start + tokio).
  • LengthAnalyzer::complexity_factor_threshold — was hardcoded 10.0, now configurable via [plugins.length].

Fixed

  • unsafe_api: rewritten from line-based line.contains + odd-quote-count heuristic to per-language tree-sitter queries. Picks up real sprintf/strcpy/strcat/system call sites that the line-based heuristic missed. Comments and string literals containing keywords like unsafe no longer false-positive.
  • dead_code: substring is_in_file_referenced replaced with AST identifier scan. Token-concat macro detection rewritten — instead of nuking the entire file when any #define ... ## exists, parse define bodies for prefix##X##suffix slots, scan call sites for invocation arguments, synthesize plausible expansion names, and add them to the reference set. X-macro dispatch tables (e.g. STYLE_DEF) no longer hide every dispatch function. IdentifierPositions lookup is now O(1) per symbol via HashMap<name, Vec<line>>.
  • error_handling: unwrap_abuse uses tree-sitter ((call_expression field_expression unwrap|expect)); empty-catch detection is per-language (Rust skipped, TS catch_clause, Python except_clause). String literals and comments containing the substring unwrap or catch no longer trigger.
  • hardcoded_secret: regex matches now run against string_literal node text only, not full source lines. Comments and identifier names with secret-like substrings no longer false-positive.
  • cha fix: String::replace whole-content substitution replaced with tree-sitter identifier-node range collection + byte-offset reverse substitution. The previous implementation could rewrite identifier names inside string literals and comments, corrupting source files.
  • git_metrics::check_test_ratio: f.contains("test") || f.contains("spec") replaced with cha_core::is_test_path. The substring check wrongly counted request.rs / spectrum.rs etc. as test files, polluting the test-to-production ratio that drives low_test_ratio.
  • wasm.rs::infer_file_role: replaced duplicate test-path heuristics with cha_core::is_test_path. WASM plugins' FileRole::Test classification now matches the canonical convention used elsewhere (__tests__/, __mocks__/, .test.ts, .spec.ts).
  • find_macro_invocation_args: word-boundary check added — STYLE_DEF no longer matches STYLE_DEFINE invocations.

Removed

  • unsafe_api is_in_string heuristic — superseded by tree-sitter queries that distinguish string literals at the AST level.
  • error_handling line-based detect_empty_catch — replaced with grammar-aware queries.
  • HostState::query_cache — query compilation now lives in cha_core::query (compile-on-demand; LRU caching to be added if measurement warrants).

Install cha-cli 1.18.0

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/W-Mai/Cha/releases/download/v1.18.0/cha-cli-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/W-Mai/Cha/releases/download/v1.18.0/cha-cli-installer.ps1 | iex"

Install prebuilt binaries via Homebrew

brew install W-Mai/cellar/cha-cli

Download cha-cli 1.18.0

File Platform Checksum
cha-cli-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
cha-cli-x86_64-apple-darwin.tar.xz Intel macOS checksum
cha-cli-x86_64-pc-windows-msvc.zip x64 Windows checksum
cha-cli-x86_64-pc-windows-msvc.msi x64 Windows checksum
cha-cli-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
cha-cli-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum
cha-cli-x86_64-unknown-linux-musl.tar.xz x64 MUSL Linux checksum

1.17.0 - 2026-05-21

21 May 17:46
ff6d2ae

Choose a tag to compare

Release Notes

Added

  • project_query::function_at(path, line, col) — new host import returning the FunctionInfo whose body contains the given position. Useful for tree-query–driven detectors that need to disambiguate which declared function a queried position belongs to.
  • WasmPluginTest::option_list / option_bool / option_int / option_float — list and typed option setters in the test harness, replacing the previous string-only option().

Changed (breaking for WASM plugins)

  • tree_query::QueryMatch.start_line / end_line are now 1-based (was 0-based). Aligns with FunctionInfo / ClassInfo / CommentInfo line numbering — no more per-plugin off-by-one conversion. Inputs to node_at(line, col) and nodes_in_range(start, end) are likewise 1-based now.
  • Existing plugins compiled against the pre-1.17 WIT will need to be rebuilt against the new SDK; instantiation will fail loudly otherwise.

Fixed

  • react-hooks example plugin — false positives on hook_after_early_return (in sibling components and inside return expressions like return useState()) eliminated by switching to project_query::function_at for host-function disambiguation. Now reports 5 true positives / 0 false positives on the 6-component .tsx fixture (was 5 / 2).

Documentation

  • docs/plugin-development.md: added Line/Column convention note, Project Query API section, WASM Compatibility Cheatsheet (regex panics, no clock, no FS), cha plugin build vs cargo build distinction, and new option helpers in Testing.

Install cha-cli 1.17.0

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/W-Mai/Cha/releases/download/v1.17.0/cha-cli-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/W-Mai/Cha/releases/download/v1.17.0/cha-cli-installer.ps1 | iex"

Install prebuilt binaries via Homebrew

brew install W-Mai/cellar/cha-cli

Download cha-cli 1.17.0

File Platform Checksum
cha-cli-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
cha-cli-x86_64-apple-darwin.tar.xz Intel macOS checksum
cha-cli-x86_64-pc-windows-msvc.zip x64 Windows checksum
cha-cli-x86_64-pc-windows-msvc.msi x64 Windows checksum
cha-cli-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
cha-cli-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum
cha-cli-x86_64-unknown-linux-musl.tar.xz x64 MUSL Linux checksum

1.16.0 - 2026-05-21

21 May 11:35
12039a6

Choose a tag to compare

Release Notes

Added

  • TsxParser in cha-parser.tsx files now route to a parser using tree_sitter_typescript::LANGUAGE_TSX, so JSX nodes (jsx_element, jsx_attribute, jsx_self_closing_element) are first-class AST citizens. WASM plugins can now match them via tree_query::run_query.
  • examples/wasm-plugin-react-hooks — example WASM plugin demonstrating tree_query integration. Detects 5 React Rules of Hooks violations: hooks called from non-component functions, hooks in conditionals, hooks in loops, hooks after early return, and hooks in nested callbacks.
  • examples/wasm-plugin-todo-tracker — example WASM plugin demonstrating extended TODO comment tracking beyond the builtin todo_tracker. Adds 5 new smells: extended tag set (BUG/WIP/OPTIMIZE/PERF/DEPRECATED + user-configurable extras), (by:YYYY-MM-DD) expiration, priority escalation (!/!!/!!!), per-file TODO hotspot detection, and required-attribution policy.

Notes

  • WIT unchanged at cha:plugin@0.3.0 (no breaking change).
  • Routing for .ts / .mts / .cts continues to use LANGUAGE_TYPESCRIPT. Only .tsx switched.

Install cha-cli 1.16.0

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/W-Mai/Cha/releases/download/v1.16.0/cha-cli-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/W-Mai/Cha/releases/download/v1.16.0/cha-cli-installer.ps1 | iex"

Install prebuilt binaries via Homebrew

brew install W-Mai/cellar/cha-cli

Download cha-cli 1.16.0

File Platform Checksum
cha-cli-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
cha-cli-x86_64-apple-darwin.tar.xz Intel macOS checksum
cha-cli-x86_64-pc-windows-msvc.zip x64 Windows checksum
cha-cli-x86_64-pc-windows-msvc.msi x64 Windows checksum
cha-cli-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
cha-cli-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum
cha-cli-x86_64-unknown-linux-musl.tar.xz x64 MUSL Linux checksum

1.15.0 - 2026-05-14

21 May 07:43
53c7a7b

Choose a tag to compare

Release Notes

Added

  • ProjectQuery trait in cha-core — plugins now access cross-file data through a typed interface on AnalysisContext.project instead of host-side post-hoc string-matched filtering. 12 methods cover the project-level queries existing post-analysis passes need: is_called_externally, callers_of, function_home/function_by_name/class_home, is_third_party, workspace_crate_names, is_test_path, etc. WASM plugins also gain access via the project-query host import.
  • ProjectQueryBulk trait extends ProjectQuery for in-process iteration (iter_models); not exposed to WASM.
  • cha_core::is_test_path — public utility consolidating two duplicated implementations.
  • example-wasm unused_helper smell — demonstrates project_query::callers_of callback.

Changed

  • WIT bumped to cha:plugin@0.3.0 (breaking) — adds project-query host import. External plugins compiled against 0.2.0 must rebuild.
  • large_api_surface C/C++ heuristics.h/.hpp headers are now skipped (their 100% public surface is by design); .c/.cpp implementation files use a higher count threshold (30, configurable as c_max_exported_count) and the ratio gate is effectively off (configurable as c_max_exported_ratio). lvgl baseline: 393 → 34 findings (-91%).
  • dead_code is now project-aware — uses ProjectQuery::is_called_externally to confirm cross-file usage; the per-file text search is just an early shortcut. The token-concat macro heuristic (#define ... ##) remains because parsers don't macro-expand. lvgl baseline: 67 → 6 findings (-91%).

Removed

  • Plugin::cross_file_aware_smells trait method — replaced by typed query through AnalysisContext.project.
  • cha-cli::cross_file_filter module — the post-hoc string-matched filter is gone; plugins produce final findings using the typed trait.
  • 3 duplicated workspace_crate_names impls + 3 duplicated is_third_party/is_external_leak impls + 2 duplicated is_test_path impls — all consolidated.

Added

  • New .cha.toml config keys for api_surface: max_exported_ratio, c_max_exported_count, c_max_exported_ratio, skip_c_headers. All language-aware defaults preserved.

Install cha-cli 1.15.0

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/W-Mai/Cha/releases/download/v1.15.0/cha-cli-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/W-Mai/Cha/releases/download/v1.15.0/cha-cli-installer.ps1 | iex"

Install prebuilt binaries via Homebrew

brew install W-Mai/cellar/cha-cli

Download cha-cli 1.15.0

File Platform Checksum
cha-cli-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
cha-cli-x86_64-apple-darwin.tar.xz Intel macOS checksum
cha-cli-x86_64-pc-windows-msvc.zip x64 Windows checksum
cha-cli-x86_64-pc-windows-msvc.msi x64 Windows checksum
cha-cli-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
cha-cli-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum
cha-cli-x86_64-unknown-linux-musl.tar.xz x64 MUSL Linux checksum

1.14.0 - 2026-05-14

14 May 07:28

Choose a tag to compare

Release Notes

Added

  • Plugin AST Query API — WASM plugins can now execute tree-sitter queries against the current file's AST via the tree-query host import interface (run-query, run-queries, node-at, nodes-in-range). Enables plugins to do custom structural pattern matching without reimplementing parsing.
  • file-role enum in analysis-input — host infers whether a file is source, test, doc, config, or generated from its path, allowing plugins to apply differential detection strategies.
  • SourceModel enrichmentanalysis-input now includes comments, type-aliases, parameter-names, switch-arm-values, and is-module-decl fields previously only available to internal plugins.
  • parse_file_full() in cha-parser — returns ParseResult carrying model + tree-sitter Tree + Language for downstream use by WASM host callbacks.

Changed

  • WIT bumped to cha:plugin@0.2.0 — breaking change: plugins compiled against 0.1.0 must be recompiled. No behavioral change for existing internal plugins.

Install cha-cli 1.14.0

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/W-Mai/Cha/releases/download/v1.14.0/cha-cli-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/W-Mai/Cha/releases/download/v1.14.0/cha-cli-installer.ps1 | iex"

Install prebuilt binaries via Homebrew

brew install W-Mai/cellar/cha-cli

Download cha-cli 1.14.0

File Platform Checksum
cha-cli-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
cha-cli-x86_64-apple-darwin.tar.xz Intel macOS checksum
cha-cli-x86_64-pc-windows-msvc.zip x64 Windows checksum
cha-cli-x86_64-pc-windows-msvc.msi x64 Windows checksum
cha-cli-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
cha-cli-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum
cha-cli-x86_64-unknown-linux-musl.tar.xz x64 MUSL Linux checksum

1.13.1 - 2026-04-30

30 Apr 09:48
2e79439

Choose a tag to compare

Release Notes

Added

  • abstraction_leak_surgery detector — files that co-change in git history and share a third-party type in their function signatures. Upgrade of the classic shotgun_surgery: instead of "these files always change together" (agnostic of why), this pinpoints "these files always change together because they all depend on the same external type" — the shared external type is the concrete abstraction leak driving the co-change cascade. Severity Hint.
    • Inputs: git co-change counts (git log --name-only -N, threshold ≥ 5 commits in last 100) × per-file TypeOrigin::External sets derived from parameter / return types. Workspace-sibling crates auto-whitelisted (same mechanism cross_boundary_chain / leaky_public_signature use), so cha_core-internal dependencies between cha-parser / cha-cli don't fire.
    • Cha self-baseline: 10 genuine findings, all pointing at the 5 language parsers sharing tree_sitter::Node — exactly the abstraction leak the detector is designed to find (tree-sitter upgrades ripple across every parser file). lvgl src/: 0 (C project, no External origins).

Install cha-cli 1.13.1

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/W-Mai/Cha/releases/download/v1.13.1/cha-cli-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/W-Mai/Cha/releases/download/v1.13.1/cha-cli-installer.ps1 | iex"

Install prebuilt binaries via Homebrew

brew install W-Mai/cellar/cha-cli

Download cha-cli 1.13.1

File Platform Checksum
cha-cli-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
cha-cli-x86_64-apple-darwin.tar.xz Intel macOS checksum
cha-cli-x86_64-pc-windows-msvc.zip x64 Windows checksum
cha-cli-x86_64-pc-windows-msvc.msi x64 Windows checksum
cha-cli-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
cha-cli-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum
cha-cli-x86_64-unknown-linux-musl.tar.xz x64 MUSL Linux checksum

1.13.0 - 2026-04-30

30 Apr 09:05
daa30e8

Choose a tag to compare

Release Notes

Added

  • primitive_representation detector (roadmap S8.2). Flags function parameters whose name carries a domain concept (user_id, email, status_code, api_url, password, language, …) but whose type is a raw scalar primitive (String, i32, bool, char, …). Signals an opportunity to introduce a newtype / value object to preserve the invariant. Per-parameter detection groups all offending params of one function into a single hint. Complements the existing primitive_obsession (which looks at per-function ratio): this fires on even a single param when it's clearly a business concept.
    • Business-token and noise-token vocabularies are deliberately narrow to keep signal-to-noise high. Substring matches are ruled out (tokens must be standalone words — widget_identifier does not trigger on id).
    • Parameters already typed with project-local newtypes (e.g. id: UserId where UserId is TypeOrigin::Local) are skipped — the author already did the right thing.
    • Container types (Path, PathBuf, Vec, Arc, Box, HashMap, …) are treated as domain-carrying and excluded; wrapping path: &Path in a newtype would destroy the abstraction.
    • Only runs on is_exported functions — private helpers are noise for a design signal aimed at public API hygiene.
    • Cha self-analyze: 14 findings (all genuine — rel_path/env_hash/language/key/hash as raw types). lvgl src/ baseline: 53 findings (TTF platformID/encodingID/languageID/nameID: int, file-explorer path/dir: char pointers, …).
  • stringly_typed_dispatch detector (roadmap S8.8). Flags functions whose switch/match body dispatches on ≥ 3 string or ≥ 3 integer literal arms — classic "the arm values should have been an enum" smell. Char-literal arms (C tokenisers) skipped. Enum-variant / structural-pattern arms classify as Other and never contribute to the threshold, so match event { Event::Click => …, Event::Scroll => …, _ => … } stays quiet while match s { "click" => …, "scroll" => …, "submit" => … } fires. Severity Hint. Complements S8.2 primitive_representation (signature side) with the body-side dispatch signal.
    • New cha_core::ArmValue enum (Str / Int / Char / Other) + FunctionInfo.switch_arm_values + FunctionSymbol.switch_arm_values. Populated by every parser via a new shared cha-parser/src/switch_arms.rs helper — language-specific arm-node kinds funnel through one classifier.
    • Cha self-baseline: 20 findings (all node-kind dispatchers in the 6 language parsers — valid detections, users can add // cha:ignore stringly_typed_dispatch if the dispatch shape is forced by tree-sitter). lvgl src/ baseline: 23 findings (PNG/JPEG/QR error-code dispatchers, color-format size tables, TTF bytecode interpreter).
  • cross_boundary_chain detector (roadmap S8.U4). Flags functions where chain_depth ≥ 3 and the chain's root parameter is externally-typed (TypeOrigin::External(crate)) — the function is reaching into a third-party library's internal field layout, not just over-chaining local data. Companion to the existing message_chain (which fires on depth regardless of source): cross_boundary_chain is narrower but a stronger abstraction-leak signal. Severity Hint.
    • Workspace crates are auto-whitelisted (same mechanism leaky_public_signature uses), so sibling cha_core::Finding traversals inside this repo don't fire. Cha self-baseline: 4 findings, all genuine tree_sitter::Node traversals in cha-parser. lvgl src/ baseline: 0 (C project, few External origins by design).
    • Zero parser changes — reuses chain_depth, parameter_types (with origin), parameter_names, external_refs. Pure post-pass on ProjectIndex.
  • FunctionInfo.parameter_names + FunctionSymbol.parameter_names (cha-core). Parallel to parameter_types: identifier names in declaration order. All six parsers (Rust / TS / Python / Go / C / C++) extract these; self / C++ this positions skipped to stay length-aligned with parameter_types. Enables name-semantic analyses like primitive_representation, future LSP hover with full signatures, future cha summary.
  • New helpers cha_parser::rust_imports::rust_param_names and cha_parser::cpp::c_param_name extract identifier names from their language's declarator chains; reused across all C/C++ function-definition sites.

Install cha-cli 1.13.0

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/W-Mai/Cha/releases/download/v1.13.0/cha-cli-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/W-Mai/Cha/releases/download/v1.13.0/cha-cli-installer.ps1 | iex"

Install prebuilt binaries via Homebrew

brew install W-Mai/cellar/cha-cli

Download cha-cli 1.13.0

File Platform Checksum
cha-cli-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
cha-cli-x86_64-apple-darwin.tar.xz Intel macOS checksum
cha-cli-x86_64-pc-windows-msvc.zip x64 Windows checksum
cha-cli-x86_64-pc-windows-msvc.msi x64 Windows checksum
cha-cli-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
cha-cli-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum
cha-cli-x86_64-unknown-linux-musl.tar.xz x64 MUSL Linux checksum

1.12.0 - 2026-04-28

28 Apr 13:57
fcd20b9

Choose a tag to compare

Release Notes

Added

  • SymbolIndex — structural view of a file, cached separately from SourceModel. New type in cha-core::model carrying the fields consumers like cha deps, LSP workspace-symbols, and future cha summary all share — class/function names + signatures + positions + type_aliases — without per-function-body data (complexity, body hash, TypeRef origin, cognitive, chain depth etc. stay in SourceModel).
    • ProjectCache::{get,put}_symbols store to symbols/{chash}.bin, mirrored independently of parse/{chash}.bin. Same env_hash mechanism invalidates both on parser code changes.
    • cached_symbols(path) is a new warm fast path that skips SourceModel deserialisation entirely — symbols/{chash}.bin is roughly 10% the size of parse/{chash}.bin.
    • cached_parse now populates both caches on every fresh parse, so the two views are always in lockstep.
    • lvgl src/ warm benchmarks (379 files): deps --type imports 1.28s → 38ms (34×), --type classes 1.30s → 56ms (23×), --type calls 1.30s → 48ms (27×). Edge counts unchanged vs. pre-migration (1351/142/8109).
    • cha-cli/src/c_oop_enrich grows a enrich_c_oop_symbols / attribute_methods_by_name_from_symbols pair alongside the existing SourceModel functions. Shared attribute_one_raw keeps attribution rules single-sourced; build-index / write-back are deliberate parallel code paths because the two storage types have to stay independent.
    • cha-cli/src/parse_cache.rs (new module) hosts both cached_parse and cached_symbols.
  • C++ parser now handles ClassName::method() out-of-class definitions, namespaces, and templates. Three gaps in the previous CppParser have been closed:
    • void Foo::bar() {...} (and ::global(), A::B::c(), destructors Foo::~Foo(), operators Foo::operator+()) was silently dropped — find_func_name_node only accepted bare identifier declarators. It now also unwraps qualified_identifier, destructor_name, and operator_name.
    • Out-of-class method definitions now attribute to their owning same-file class: void Foo::bar() bumps ClassInfo::method_count on Foo and flips has_behavior. Cross-file attribution still runs through cha-cli::c_oop_enrich.
    • namespace_definition, linkage_specification (extern "C" { ... }), and template_declaration are now explicitly matched in the top-level dispatch (previously fell through to the generic recursion arm) — same observable behaviour, but the nesting constructs are now a stable hook rather than an accidental default-case artefact.
    • C++-specific declarator helpers moved to a new cha-parser/src/cpp.rs so c_lang.rs stays below the large_file gate.
  • SourceModel.type_aliases now populated for Rust, TypeScript, Python, and Go (previously all four returned empty vec![] with parser-side TODOs). Each parser recognises its language's alias form and records (alias, rhs) pairs: Rust type X = Y; / pub type X<T> = Y;, TypeScript type X = Y; / export type X<T> = Y;, Python 3.12+ type X = Y and pre-3.12 X: TypeAlias = Y, Go type X = Y (only the true alias form — type X Y defined types are excluded). Plain Python X = Y assignments remain unclassified (too ambiguous). Shared extraction lives in a new cha-parser/src/type_aliases.rs module so per-language files stay below the large_file gate.

Changed

  • boundary_leak detector migrated to ProjectIndex. The three smells it emits (abstraction_boundary_leak, return_type_leak, test_only_type_in_production) previously parsed the whole project a second time — the codebase noted a "cached model occasionally drops typedef aliases" concern with root cause TBD. v1.11.0's binary-mtime cache keying removed the suspected root cause, and a new cache::tests::cache_roundtrip_preserves_type_aliases unit test makes the invariant a testable one. boundary_leak::detect now takes &ProjectIndex and shares the same parse pass as anemic_domain_model, typed_intimacy, module_envy, and friends. Verified against lvgl's src/ tree: 155 findings before = 155 findings after (abstraction_boundary_leak: 154, return_type_leak: 1). Completes roadmap S8.infra.4.

Fixed

  • C++: template specialisation methods attribute to the right class. template<> void Foo<int>::bar() used to drop on the floor because the qualifier Foo<int> (a template_type node) didn't match the stored class name Foo. attach_to_class now strips trailing <...> template arguments before matching, so out-of-class specialisations attribute correctly. Same stripping applies to any declaration whose declarator surfaces Foo<...> as the owning scope.
  • C++: real inheritance (class Derived : public Base) now recognised. extract_class consults the base_class_clause child and pulls the first type_identifier (or template_type's underlying name) as parent_name. Falls back to the first-field heuristic only when no base clause is present, so legacy C struct-embedding cases still work. Also fixes the class-name extraction for templated classes so template<typename T> class Foo {...} stores "Foo" instead of "Foo<T>".
  • C++: reference-return methods no longer vanish. const int& Foo::get() and similar reference_declarator-wrapped definitions used to be silently dropped because tree-sitter-cpp's reference_declarator has no declarator field — the declarator walker returned None. Both find_func_name_node (c_lang) and descend_to_qualified_identifier (cpp) now fall back to the first named child when the field is absent. Same fix path covers reference-return + qualified (const T& Foo::bar()) so class attribution still works. 6 additional regression tests (reference/pointer return types, multi-method attribution, constructor, extern "C", const member) added in cha-parser/tests/cpp_enhancements.rs (14 total).

Install cha-cli 1.12.0

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/W-Mai/Cha/releases/download/v1.12.0/cha-cli-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/W-Mai/Cha/releases/download/v1.12.0/cha-cli-installer.ps1 | iex"

Install prebuilt binaries via Homebrew

brew install W-Mai/cellar/cha-cli

Download cha-cli 1.12.0

File Platform Checksum
cha-cli-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
cha-cli-x86_64-apple-darwin.tar.xz Intel macOS checksum
cha-cli-x86_64-pc-windows-msvc.zip x64 Windows checksum
cha-cli-x86_64-pc-windows-msvc.msi x64 Windows checksum
cha-cli-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
cha-cli-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum
cha-cli-x86_64-unknown-linux-musl.tar.xz x64 MUSL Linux checksum