Choose it when syntax describes the change
ast-grep lets you express a code search in the language you are searching. The README says it matches AST nodes rather than text and uses tree-sitter for parsing. Uppercase placeholders such as $MATCH stand for individual nodes.
The README includes the pattern $A && $A() and this rewrite command:
ast-grep -p '$A && $A()' -l ts -r '$A?.()'
This is an upstream example, not a command executed in our recorded run. It illustrates how a pattern and replacement share a placeholder. Before applying a similar rewrite, check both which code it selects and whether the replacement preserves the behavior your project needs. A syntactic match alone does not establish behavioral equivalence.
The README also describes YAML configuration for lint rules and code modifications. That makes ast-grep worth evaluating when a team wants to reuse a syntax-based check instead of repeating a one-off search. Claims about parallel execution come from the README; we did not measure search throughput or rewriting speed.
Check semantic requirements and rule composition
A source-shaped pattern does not establish an identifier's resolved symbol, inferred type, or cross-file relationships. Issue 2413 is a proposal for a pluggable semantic-analysis API. Its author reports that ast-grep has no structured way to attach semantic information to AST nodes and describes using external analyzers. Treat the proposed APIs in that issue as design examples, not available features. The issue does not establish version-specific behavior for 0.45.3.
For a migration, write down what determines whether a call should change. If the answer includes its resolved import or inferred type, obtain that information through suitable analysis and validate the integration before applying the rewrite.
Rule composition has a separate reported limitation. Issue 2927 describes ast-grep 0.45.3 on macOS arm64: a file-based rule referencing a global utility passes the reporter's ast-grep test, while the same rule supplied through scan --inline-rules fails to resolve that utility from utilDirs, including with an explicit configuration. This is the reporter's reproduction, not our test result or proof that every later version behaves the same way. An editor integration that generates inline rules should check this exact workflow in its chosen version.
What our recorded run establishes
In our run on October 16, 2026, the checkout was commit 14934d690a547abce8576baff9a1856a10ae7da8. The recorded environment had 3 CPUs, 8 GB of memory, and image ghcr.io/astral-sh/uv:python3.12-bookworm. The install tail identifies Python 3.12.12. Detection found Python and Rust and selected Python as the primary ecosystem.
| Recorded item | Result | Limit |
|---|---|---|
| Install step | Exit 0; 236,863 ms, rounded to 237 seconds | The tail only identifies the Python environment; installed CLI availability was not checked |
| Build step | Exit 0; 908 ms, rounded to 1 second | Empty output tail; the resulting artifact is not established |
| Dependencies | 36 packages; 88 MB | Not an audited-package count |
| Tests | Skipped; reason: no script |
No test-suite result; does not show that upstream has no tests |
| pip-audit | Recorded advisory total: 0; package field: 0 | Usable audit coverage is unknown |
| Checkout | 325 files; approximately 49,032 lines; 3 MB | Repository inventory, not workload performance |
The detector recorded six CI workflows and did not detect a Dockerfile, Compose configuration, or top-level tests directory. These are discovery results, not a complete inventory of checks or deployment options. Recorded parser summaries were not reconciled against complete logs to establish exhaustive coverage.
No installed-binary check, search workload, rewrite workload, or upstream test execution appears in the supplied record. The successful step statuses therefore support a narrower conclusion than a verified source build or working CLI installation. The zero-advisory summary also cannot support a dependency-safety verdict because audit coverage is unknown.
Installation instructions and the next useful check
The README lists npm, pip, Cargo, cargo-binstall, Homebrew, Scoop, mise, and MacPorts. For a source installation it specifies rustup and cargo install --path ./crates/cli --locked. It also notes that pnpm may require pnpm approve-builds. We did not verify those individual routes.
Choose the route that fits your environment, confirm that the installed ast-grep command runs, and try a representative pattern before committing to a repository-wide migration. Review the matches and diff, then run the application's relevant checks. Those steps resolve the practical questions left open by our harness record.
When to consider Semgrep or Comby
Semgrep's README describes code scanning, bug finding, and coding-standard enforcement. It separately describes an AppSec Platform with result triaging and exploration workflows. Consider that product family when security findings and their handling drive the evaluation. Keep the editions distinct: the README warns that Community Edition can only analyze within a single function or file. We did not compare detection rates, speed, or cost.
Comby's README demonstrates matching nested C-like conditions with if (:[condition]), replacing them with if (1), and using interactive review. Consider it when that template approach fits your change. The supplied evidence does not establish a language-coverage or performance advantage over ast-grep.
How to read the scores
These are editorial assessments of the supplied evidence, not benchmark results. The rubric is: 1 means substantial documented obstacles; 2 means evidence is too limited for a confident recommendation; 3 means a documented route with material checks left open; 4 means detailed supporting evidence with bounded gaps; 5 requires broad, directly verified evidence. Missing evidence is uncertainty, not proof of a product defect. Community and maturity scores do not measure adoption or production reliability.

