# pi-ast-grep

pi-ast-grep is a Pi extension. It gives Pi six tools for structural code
work with [ast-grep](https://astgrep.com).

ast-grep matches code by its syntax tree, not by raw text. A query can
find calls, declarations, or members by structure. The extension runs the
ast-grep command-line tool and returns bounded, structured results to the
model.

The extension is standalone. It depends on Pi's bundled core packages
(`pi-coding-agent`, `pi-ai`, `pi-agent-core`, `pi-tui`, `typebox`) and on
the ast-grep binary. It does not need another Pi extension.

## Requirements

The extension needs:

- Pi 0.83.0 or newer. The bundled Pi packages are peer dependencies. The
  package manager does not enforce the version floor.
- Node.js 22 or newer.
- The ast-grep command-line tool, version 0.44.0 or newer. Put the binary
  on PATH, or set `AST_GREP_BIN` to the path of the binary.
  `ast_grep_outline` requires version 0.44.0 or newer. With an older
  binary, the other tools still work, but the footer and `/ast-grep-check`
  show a version warning.

Install ast-grep:

```bash
# macOS
brew install ast-grep
# Other platforms: https://astgrep.com
ast-grep --version   # the version must be 0.44.0 or newer
```

## Install

Install the extension from a checkout of this repository:

```bash
npm install
pi -e ./src/index.ts
```

Install the extension from npm (once the package is published):

```bash
pi install npm:@juvio15/pi-ast-grep
```

`AST_GREP_BIN` overrides binary resolution. Set it to the absolute path of
an ast-grep executable to use a specific binary. This is useful for a
mise or brew install that is not on PATH.

## Tools

The extension registers six tools.

| Tool | Purpose | Notable parameters |
|---|---|---|
| `ast_grep_run` | Search by AST pattern with meta variables, for example `console.log($ARG)`. | `pattern` or `kind` (exactly one), `code` (snippet mode, needs `lang`), `context`, `globs`, `max_results`, `threads`, `follow`, `no_ignore` |
| `ast_grep_scan` | Scan with full YAML rules (relational, composite, severity). | `rule_yaml` or `rule_file`, or project config via `sgconfig.yml`; `config`, `filter`, `globs`, `max_results`, `threads`, `follow`, `no_ignore` |
| `ast_grep_rewrite` | Preview and apply structural rewrites (pattern or YAML `fix`). | `mode` (`pattern` or `rule`), `pattern`, `rewrite`, `rule_yaml`, `apply` (default false), `context`, `globs`, `max_results`, `threads`, `follow`, `no_ignore` |
| `ast_grep_outline` | Make a compact structural map of files or directories: top-level items and direct members with signatures and line numbers. | `items`, `view`, `match`, `type`, `pub_members`, `outline_rules`, `no_default_outline_rules`, `threads`, `follow`, `no_ignore` |
| `ast_grep_debug_query` | Show the tree-sitter CST or AST of a pattern to find node kinds. | `pattern`, `lang`, `format` (`cst`, `ast`, `pattern`, `sexp`) |
| `ast_grep_languages` | List the supported languages, aliases, and file extensions. | — |

The extension registers two commands:

- `/ast-grep-check` — verify the binary, its minimum version, and the
  extension tools. On success, it sets the session name to
  `ast-grep-ok`. Scripts can poll this name. Tools filtered out of the
  session (`--tools`, `--exclude-tools`) are reported, not treated as
  an error.
- `/ast-grep-rules` — manage a saved-rules library: `save <name> <yaml>`,
  `list`, `get <name>`, `delete <name>`, `validate <name>`. Entries are
  stored with `appendEntry` and restored per session branch.

## Runtime promotion

When at least one ast-grep tool is active, the extension adds a bounded
guidance block to the system prompt (with `before_agent_start`). The block
points to the most useful actions: outline a file or directory before you
read it, use structural search before text search, scan for relational
rules, debug a pattern that does not match, and preview rewrites before
you apply them.

Promotion is on by default. You can disable it per project in
`.pi/ast-grep.json`:

```json
{
  "promotion": { "enabled": false }
}
```

The extension adds the block only when an ast-grep tool is active in the
session. It skips the block when the ast-grep binary is missing (the
footer warning covers that case). The binary check costs one
`ast-grep --version` run per agent start while an ast-grep tool is active.

## Examples

Find every `console.log` call and its arguments in the current project:

```
ast_grep_run pattern="console.log($ARG)" lang="ts" path="."
```

Query a code snippet without a file (the snippet is searched as one file):

```
ast_grep_run code="console.log('hi')" lang="ts"
```

Find function declarations, or add context lines around matches:

```
ast_grep_run kind="function_declaration" lang="ts" path="src"
ast_grep_run pattern="console.log($ARG)" lang="ts" path="src" context=1
```

Find async functions that `await` (relational rule with `stopBy: end`):

```
ast_grep_scan rule_yaml="id: async-await
language: TypeScript
severity: warning
rule:
  kind: function_declaration
  has:
    pattern: await $EXPR
    stopBy: end"
```

Scan with a project's `sgconfig.yml` rules (omit `rule_yaml` and
`rule_file`; ast-grep finds the config from the target path upward), or
run a rule file:

```
ast_grep_scan path="src"
ast_grep_scan rule_file="rules/no-console.yml" path="src"
ast_grep_scan config="/abs/path/sgconfig.yml" path="src"
```

Preview renaming `foo(...)` to `bar(...)`, then apply it:

```
ast_grep_rewrite mode="pattern" pattern="foo($X)" rewrite="bar($X)" lang="ts" path="src" apply=false
ast_grep_rewrite mode="pattern" pattern="foo($X)" rewrite="bar($X)" lang="ts" path="src" apply=true
```

Map a file before you read it. Outline is the fastest way to understand
an unfamiliar file or directory: a structural table of contents with
line numbers. The default view shows member signatures with line
numbers:

```
ast_grep_outline path="src/parser.ts"
ast_grep_outline path="src" items="exports" view="names"
ast_grep_outline path="src/parser.ts" items="imports" view="names"
ast_grep_outline path="src" match="parser" type="function" view="signatures"
```

Show the source of one symbol. Search by node kind with ast_grep_run.
The match text is the full node source, the body included. For an
exported symbol, the export keyword is not part of the node text.
Select the symbol you need from the results:

```
ast_grep_run kind="function_declaration" lang="ts" path="src/parser.ts"
ast_grep_run kind="class_declaration" lang="ts" path="src/parser.ts"
```

## Skill

The package ships a Pi skill at `skills/pi-ast-grep/SKILL.md`. The `pi`
manifest registers it and the published package includes it. The skill is
a model-facing quick reference for the six tools: invocation by exact
identifier, shared parameters, and the safety rules (preview rewrites
before you apply them; the extension blocks rewrites in untrusted
projects).

## Behavior notes

The details are in [docs/design.md](docs/design.md). Quick pointers:

- Output limits, truncation, and JSON safety: design.md "Output limits
  and JSON safety".
- Exit codes and error handling: design.md "Error handling".
- Rewrite safety and the preview-then-apply gate: design.md "Rewrite
  safety".
- Paths and binary resolution: design.md "Version management".
- Runtime promotion: design.md "Runtime promotion".
- Language catalog: `src/languages.ts` is generated by
  `scripts/gen-languages.mjs` against the installed binary and stamped
  with the ast-grep version it was built against (28 languages for
  0.45.0).

## Check the package

Run these commands to check the package:

```bash
npm run check          # ultracite format and lint check
npm run typecheck      # tsc --noEmit
npm run test:all       # unit, contract, and integration tests
npm run package:check  # npm pack --dry-run
npm run smoke          # live Pi RPC check (no API key needed)
node scripts/live-smoke.mjs --model   # also drive tools with DeepSeek (needs key)
```

The integration tests run the real `ast-grep` binary on fixture files
(including a `test/fixtures/sgconfig/` project for config-mode tests).
They skip automatically when the binary is missing.

## Documentation

- [Design notes](docs/design.md) — architecture decisions and API surface
- [Ast-grep guides](https://astgrep.com/guide/rule-config) — rule syntax,
  rewrite semantics, project scanning, and outline usage
