Version 0.45.3 matches syntax rather than character sequences
ast-grep parses code with tree-sitter and compares syntax nodes to a pattern written in the target language. A pattern such as $A && $A() uses the uppercase placeholder as a wildcard, so formatting and ordinary identifier changes do not defeat the match. The replacement can reuse captured nodes. This sits in the useful middle between grep, which knows only text, and a compiler API, which makes you write a transformation program.
The approach is easy to try in the online playground before installing anything. On a real repository, ast-grep can search, replace interactively, or apply a rewrite across files. Its compiled Rust implementation uses multiple CPU cores, according to the README. Syntax awareness also cuts false matches in strings and comments, provided the selected tree-sitter grammar parses the code as expected. A malformed file or wrong language selection changes the tree, so previewing the diff remains part of the job.
One YAML configuration turns a pattern into a project rule
Project use starts with sgconfig.yml, rule directories, and YAML files that describe matches, constraints, severity, and fixes. Version 0.45.3 adds a minimum-severity CLI option, which helps CI jobs decide which findings should fail a run. Rules can enforce a house convention or package a migration without compiling a custom linter. Library maintainers can publish the same rule used internally so users can update call sites after an API change.
YAML becomes harder to read once a match depends on several relationships. ast-grep supplies node traversal, utility rules, and constraints, but those concepts still need to be learned. Open issue 2927 documents a current composition gap: in 0.45.3, an inline rule cannot resolve global utilities from utilDirs, even when a project configuration is passed. File-based rules work in the reporter's reproduction. Editor and MCP integrations generating temporary rules may therefore need to inline utility bodies or write rule files.
What happened when we ran it
Our sandbox used commit fc2b153 and installed the Python-packaged route in 271 seconds. It added 36 packages and consumed 85 MB. The checkout was much smaller at 3 MB, with 320 files and about 47,902 lines of source. Installation succeeded, then the build completed in 4 seconds. Six CI workflow files were present, while the scan found no Dockerfile and no top-level tests directory.
The harness found no tests script or target, so it skipped the test step. That is different from a passing suite. ast-grep is a Rust workspace with fixtures and CI configuration, while its pyproject.toml uses maturin to publish the CLI through Python packaging. Our Python-oriented discovery did not select a Cargo test command. A team evaluating the source should identify and run the upstream Rust checks separately instead of treating the 4-second build as enough validation.
Pip-audit reported 0 known vulnerabilities among the 36 installed packages. That clean result applies to the environment created by our run, not every npm, Cargo, Homebrew, or operating-system package path. The repository contains a Cargo lockfile and multiple language bindings, each with its own dependency surface. The useful conclusion is narrow: the measured pip route installed and built successfully with no advisory found by pip-audit, but it offered our harness no default test target.
The README lists eight package managers and one source build
Users can install ast-grep through npm, pip, Cargo, cargo-binstall, Homebrew, Scoop, mise, or MacPorts. The source route is cargo install against the CLI crate after installing rustup. No API token, database, daemon, or cloud account is required. That makes adoption lighter than most static-analysis platforms, especially for a developer who wants one binary in a pre-commit hook or CI image.
Packaging still has edges. The README warns that pnpm may require explicit build approval. Issue 56 tracks the short sg binary name because Unix systems already use /usr/bin/sg to run a command under another group ID; the issue says deprecation of that alias has started. Scripts should call ast-grep explicitly. Teams supporting several operating systems should also pin version 0.45.3 or another chosen release rather than assuming all package managers update together.
Version 0.45.3 does not know types or cross-file symbols
Tree structure answers whether code has a certain shape. It does not by itself prove which function an identifier resolves to, what type flows through an expression, or whether a similarly named import comes from the intended module. Open issue 2413 proposes a pluggable semantic layer precisely because ast-grep currently lacks a shared way to attach symbol, type, import, scope, and reference data to nodes. Issue 334 separately asks for control-flow and data-dependency operators.
That boundary decides which migrations are safe. Renaming a syntactically distinctive call can work well. Changing every open() only when it resolves to one library, or altering an expression only when its inferred type meets a condition, calls for a language-specific compiler or semantic codemod. jscodeshift gives JavaScript migrations procedural control, while Semgrep is a better comparison for security programs with reusable policy sets. Comby suits structural templates when a supported AST grammar is unavailable.
A September 10 push and 53 issues and PRs indicate live maintenance
GitHub showed 15,835 stars, 53 open issues and pull requests, and a last push on September 10, 2026. Release 0.45.3 was published on August 31. Its notes include tree-sitter 0.27, Markdown headings in outline output, a minimum-severity switch, and dependency updates. Current issue discussion includes inline utility resolution and target-platform support, while older design proposals remain open. The combined count is a workload signal, not a count of confirmed defects.
ast-grep earns a place in a developer toolbox because a source-shaped pattern is quicker to author than a compiler extension and safer than blind text replacement. Our 271-second installation was slow for a single CLI, yet the 4-second build and 0 pip-audit findings made the package route uneventful after dependencies arrived. Use dry runs and reviewed diffs for rewrites, keep semantic refactors in language-aware tooling, and wire an explicit upstream test command into source evaluation.

