ast-grep

AST-aware structural code search and rewrite via ast-grep.

  • ast
  • codemod
  • refactoring
  • structural-search
  • code-search
  • rewrite
  • tree-sitter

Declared platforms: linux · macos · windows

Install
npx skills add 'https://github.com/NousResearch/hermes-agent/tree/main/optional-skills/software-development/ast-grep'
Download bundle ↓
main · 24fd22bScanned 2026-09-15

Contributors

GitHub-linked commit authors for this SKILL.md at the saved revision. Co-authors and history before file renames are not included.

File history ↗
View on GitHub
← Back to SKILL.md
#Requires -Version 5.1# Smoke test for the ast-grep skill on Windows (PowerShell 5.1+).$ErrorActionPreference = 'Stop' $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path$SkillDir  = Split-Path -Parent $ScriptDir$Helper    = Join-Path $SkillDir 'scripts/ast_grep_helper.py'$Python    = if (Get-Command py -ErrorAction SilentlyContinue) { 'py' } else { 'python' } $Output = Join-Path $env:TEMP ("ast-grep-skill-smoke-" + [guid]::NewGuid().ToString('N').Substring(0,8))New-Item -ItemType Directory -Path $Output -Force | Out-Null function Pass([string]$msg) { Write-Host "PASS: $msg" }function Fail([string]$msg) { Write-Host "FAIL: $msg" -ForegroundColor Red; Remove-Item -Recurse -Force $Output -ErrorAction SilentlyContinue; exit 1 } function Run([string[]]$Args) {    $stdoutFile = Join-Path $Output ("out-" + [guid]::NewGuid().ToString('N').Substring(0,8) + ".txt")    $proc = Start-Process -FilePath $Python -ArgumentList (@($Helper) + $Args) -NoNewWindow -PassThru -Wait -RedirectStandardOutput $stdoutFile -RedirectStandardError "$stdoutFile.err"    $stdout = if (Test-Path $stdoutFile) { Get-Content $stdoutFile -Raw } else { '' }    $stderr = if (Test-Path "$stdoutFile.err") { Get-Content "$stdoutFile.err" -Raw } else { '' }    return [pscustomobject]@{        ExitCode = $proc.ExitCode        Stdout = $stdout        Stderr = $stderr        Combined = "$stdout`n$stderr"    }} try {    # 1. --version    $r = Run @('--version')    if ($r.Combined -notmatch 'ast-grep-helper') { Fail '--version output missing' }    Pass '--version'     # 2. langs (must list >=25)    $r = Run @('langs')    $langCount = ($r.Stdout -split "`n" | Where-Object { $_ -match '^  [a-z]' }).Count    if ($langCount -lt 25) { Fail "langs listed only $langCount (expected >=25)" }    Pass 'langs lists at least 25 languages'     # 3. regex misuse: \w+    $r = Run @('validate', '\w+', '--lang', 'ts')    if ($r.ExitCode -ne 2) { Fail "validate '\w+' should exit 2, got $($r.ExitCode)" }    if ($r.Combined -notmatch 'regex') { Fail "validate '\w+' should mention regex" }    Pass 'validate detects \w regex misuse'     # 4. valid pattern    $r = Run @('validate', 'console.log($MSG)', '--lang', 'ts')    if ($r.ExitCode -ne 0) { Fail "validate 'console.log(`$MSG)' should exit 0, got $($r.ExitCode)" }    Pass 'validate accepts plausible pattern'     # 5. Python trailing colon    $r = Run @('validate', 'def $F($$$):', '--lang', 'py')    if ($r.ExitCode -ne 2) { Fail "validate 'def `$F(`$`$`$):' should exit 2, got $($r.ExitCode)" }    if ($r.Combined -notmatch 'colon|trailing') { Fail 'validate should mention trailing colon' }    Pass 'validate detects Python trailing colon'     # 6. Incomplete TS function    $r = Run @('validate', 'function $N', '--lang', 'ts')    if ($r.ExitCode -ne 2) { Fail "validate 'function `$N' should exit 2, got $($r.ExitCode)" }    if ($r.Combined -notmatch 'incomplete|params|body') { Fail 'validate should hint about params/body' }    Pass 'validate detects incomplete TS function'     # 7. Alternation pipe    $r = Run @('validate', 'foo|bar', '--lang', 'ts')    if ($r.ExitCode -ne 2) { Fail "validate 'foo|bar' should exit 2, got $($r.ExitCode)" }    if ($r.Combined -notmatch 'alternation|regex') { Fail 'validate should mention alternation' }    Pass 'validate detects literal | alternation'     # 8. doctor    $r = Run @('doctor')    if ($r.Combined -notmatch 'ast-grep-helper') { Fail 'doctor missing helper version line' }    Pass 'doctor produces output'     # 9. search w/o binary    $r = Run @('-q', 'search', 'foo()', '--lang', 'ts', 'C:/nonexistent-path-xyzzy')    switch ($r.ExitCode) {        { $_ -in 0,1,4 } { Pass "search runs (rc=$($r.ExitCode), ast-grep available)" }        3 {            if ($r.Combined -notmatch 'install') { Fail 'search rc=3 should print install hint' }            Pass 'search without binary prints install hint'        }        default { Fail "search returned unexpected rc=$($r.ExitCode): $($r.Combined)" }    }     # 10. install.ps1 syntax (parse-check via PowerShell tokenizer)    $tokens = $null    $errors = $null    [System.Management.Automation.Language.Parser]::ParseFile(        (Join-Path $SkillDir 'install.ps1'), [ref]$tokens, [ref]$errors) | Out-Null    if ($errors -and $errors.Count -gt 0) { Fail "install.ps1 has parse errors: $($errors -join '; ')" }    Pass 'install.ps1 parses cleanly'     # 11. SKILL.md frontmatter    $skill = Get-Content (Join-Path $SkillDir 'SKILL.md') -Raw    if (-not $skill.StartsWith("---`n") -and -not $skill.StartsWith("---`r`n")) {        Fail 'SKILL.md must start with YAML frontmatter'    }    $endIdx = $skill.IndexOf("`n---`n", 4)    if ($endIdx -lt 0) { $endIdx = $skill.IndexOf("`r`n---`r`n", 4) }    if ($endIdx -lt 0) { Fail 'SKILL.md missing closing ---' }    $fm = $skill.Substring(4, $endIdx - 4)    if ($fm -notmatch '(?m)^name:\s*ast-grep\s*$') { Fail 'frontmatter missing name: ast-grep' }    if ($fm -notmatch '(?m)^description:') { Fail 'frontmatter missing description' }    Pass 'SKILL.md frontmatter shape'     # 12. All required reference files exist    $required = @(        'references/install.md', 'references/patterns.md', 'references/pitfalls.md',        'references/recipes.md', 'references/cli.md', 'references/yaml-rules.md',        'references/sgconfig.md'    )    foreach ($f in $required) {        if (-not (Test-Path (Join-Path $SkillDir $f))) { Fail "missing $f" }    }    Pass 'all references present'     Write-Host ''    Write-Host 'all smoke tests passed'}finally {    Remove-Item -Recurse -Force $Output -ErrorAction SilentlyContinue}