Commands, package names, and image names on this page come from the open-source project that Mibyan Desktop is built on, and can differ from the Mibyan Desktop installer. For the supported Mibyan install and update path, see Install and update.
Skill metadata
Reference: full SKILL.md
The following is the complete skill definition that Mibyan loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
ast-grep
ast-grep (binary also named sg) is an AST-aware search and rewrite tool across 25 languages. It treats your pattern as code, parses it the same way it parses your project, and matches structurally. It is the right tool whenever your question depends on code shape rather than text bytes.
This skill ships a Python wrapper at scripts/ast_grep_helper.py and platform install scripts at install.sh (POSIX) and install.ps1 (Windows). The helper adds offline pattern validation, the two-pass write trick, and binary auto-resolution. Use it as your default entry point.
Upstream source: vendored from code-yeongyu/ast-grep-skill (MIT), as shipped in oh-my-openagent’s shared-skills bundle.
When to use this skill
Use it whenever the question is about code structure, not bytes:- “Find every function that takes a
Requestparameter.” - “Rewrite every
console.log(x)tologger.info(x).” - “Strip every
as anycast.” - “Replace
require(...)withimportacross the repo.” - “Find empty catch blocks.”
- “Migrate
Optional[X]toX | None.” - “Apply this codemod across these 200 files.”
- “Run our YAML lint rules and surface violations.”
search_files (or plain rg) when the question is text-shaped (string literal contents, comments, license headers, file names, cross-language regex). When in doubt, ask: “does the answer depend on the language’s syntax tree, or just on the file’s bytes?” If the former, ast-grep. If the latter, search_files.
Mibyan integration notes:
- Run the helper and
sgthrough theterminaltool. Single-quote every pattern so the shell never expands$VAR. - For find→read chains around matches, use
--json-outand process withexecute_coderather than piping through interpreters. - This complements (does not replace) Mibyan’s
patchtool:patchis for targeted edits you author; ast-grep is for pattern-driven bulk rewrites across many sites.
Three things the agent must internalize
1. ast-grep is NOT regex
The wildcards are$VAR (one AST node) and $$$ (zero or more nodes). Regex syntax fails silently:
The full anti-pattern table is in
references/pitfalls.md §1. The helper’s validate subcommand catches these mechanically — call it before debugging “no matches” by hand.
2. Patterns must be valid code
The pattern itself must parse.def $FN($$$): fails because the trailing : makes it incomplete; use def $FN($$$). function $NAME without params/body fails; use function $NAME($$$) { $$$ }. Full table per language in references/pitfalls.md §2.
3. --update-all and --json are mutually exclusive (silently)
This is the single biggest gotcha when scripting. sg run -p P -r R --json --update-all returns the JSON but does not mutate files. To both preview AND apply, run two passes:
replace --apply. Read references/pitfalls.md §9.
The helper script — scripts/ast_grep_helper.py
A single-file Python 3 stdlib wrapper. Same on every OS. The agent’s default entry point.
search — find all matches of a pattern
\w, .*, |, etc.) the helper exits with a hint and never calls sg — saves a round-trip. Pass --force to skip validation.
Flags:
--lang ts(or any of the 25 languages; aliases likejs,py,rs,ktaccepted)--globs '!**/*.test.ts'(repeatable; prefix!to exclude)-C 3(context lines)--json-out(raw JSON instead of human format)
replace — rewrite by pattern, dry-run by default
- Validates both
patternandrewritefor hint-detectable mistakes. - Runs pass 1 with
--json=compactto collect matches and show a preview. - If
--applyis set, runs pass 2 with--update-allto mutate files.
scan — run YAML rules
validate — offline pattern check (no sg call)
Useful for CI lints, pre-commit hooks, and quick sanity checks:
langs / doctor / install
new and test subcommands proxy directly to sg new and sg test.
Direct sg use (when the helper isn’t enough)
The helper is opinionated. For full control, drop to sg. The skill ships a CLI cheat sheet in references/cli.md. The minimal idioms:
sg directly in a shell, always single-quote patterns so $VAR is not expanded by the shell.
Decision tree — what to use, when
Always run dry-run first when rewriting
A bad pattern silently rewrites the wrong thing. The helper’sreplace defaults to dry-run for this reason. The flow is:
- Search to confirm matches:
helper search '<pattern>' --lang X . - Dry-run rewrite:
helper replace '<pattern>' '<rewrite>' --lang X .(no--apply) - Inspect the dry-run summary: number of matches, files affected, the per-location preview.
- If wrong: refine pattern, go back to step 1.
- If right:
helper replace '<pattern>' '<rewrite>' --lang X . --apply.
--apply in a git repo, review with git diff --stat before committing.
When sg returns 0 matches but you know the code is there
In priority order:
- Run
helper validate '<pattern>' --lang <lang>— catches regex misuse, missing function bodies, Python trailing colons. - Check
--lang—sginfers from extension; if you pass a.tsxfile with--lang ts(nottsx), JSX won’t parse. - Inspect the parsed pattern:
sg run -p '<pattern>' --lang <lang> --debug-query=ast --stdin <<< '<sample>'. If it showsERRORnodes, the pattern is malformed. - Check the AST of the target file:
sg run -p '$_' --lang <lang> --debug-query=cst path/to/file | head -40— find thekindyou’re trying to match. - Try the playground: <https://ast-grep.github.io/playground.html> — paste code + pattern, see what’s happening.
When to use YAML rules vs inline -p patterns
Use inline -p when:
- One-off ad-hoc query.
- The pattern is simple (no constraints, no fix template).
- You’re exploring.
rules/, run via sg scan) when:
- The pattern is reused (lint rule, codemod that runs in CI).
- You need
constraints,transform, complexinside/has, or composite logic. - You want auto-fix (
fix:field). - You want to test the rule (snapshot tests via
sg test).
references/yaml-rules.md. Project setup (sgconfig.yml, ruleDirs, utilDirs) is in references/sgconfig.md.
Output discipline
sg run --json=compactproduces an array of match objects:{ file, range: {start, end}, text, replacement?, lines, language, ... }.- Without
--json,sgproduces human-readable colored output suitable for terminals. - The helper’s default output is human-readable (file:line:column + match preview). Pass
--json-outfor raw JSON. - The helper’s
replacealways summarizes: number of matches, number of files, per-location preview.
Required reading (in order of priority)
references/patterns.md— meta-variables, naming rules, strictness levels. Read when you’re unsure why a pattern doesn’t match.references/pitfalls.md— the failure-mode field guide. Read when 0 matches surprises you.references/recipes.md— copy-paste patterns by language. Read first when you start a new task.references/cli.md—sg run,sg scan,sg test,sg new,sg lsp. Read when the helper isn’t enough.references/yaml-rules.md— YAML rule schema. Read when you outgrow inline patterns.references/sgconfig.md— project-level configuration. Read when you set upsg scanfor a real project.references/install.md— per-OS install methods. Read only ifinstall.sh/install.ps1fail.
Invariants (do not break)
- Validate before searching. When emitting a pattern programmatically, call
helper validatefirst. It catches the regex-misuse class of mistakes that account for ~70% of “0 matches” debug sessions. - Dry-run before applying. Never run
sg run -r ... --update-allwithout first inspecting the matches. The helper’sreplaceenforces this by default. - Two-pass writes. When using
sgdirectly to both preview and apply, run two invocations —--jsonignores--update-all. - Single-quote patterns in shell.
'$VAR'not"$VAR". The shell expands$VARto the empty string in double quotes, breaking the pattern. - Pattern is code, not regex. When the pattern would need
|,.*,\w, or[a-z], switch to search_files instead. Don’t try to force ast-grep into a regex shape. --langis required for stdin. When piping with--stdin, set--langexplicitly;sgcannot infer from extension.- Linux: prefer
ast-grepoversgbecausesgcollides withsetgroupsfromutil-linux. The helper handles this; if you callsgdirectly, alias it:alias sg=ast-grep.

