원클릭으로
write-ast-grep-rule
Use when writing a new pi-lens ast-grep rule YAML file — covers schema, drop path, gotchas, and NAPI runner constraints
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Use when writing a new pi-lens ast-grep rule YAML file — covers schema, drop path, gotchas, and NAPI runner constraints
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Use when searching or replacing code patterns - use ast-grep instead of text search for semantic accuracy
Navigate code with IDE features and run proactive LSP diagnostics on files/folders/batches. Use as PRIMARY for code intelligence and type/error checks.
Use when writing a new pi-lens tree-sitter query rule YAML file — covers schema, S-expression syntax, capture names, predicates, and gotchas
Anthropic Claude Pro/Max OAuth compatibility workflow for this repo. Use when debugging Anthropic OAuth failures, misleading extra-usage errors, Pi request shaping, prompt fingerprinting, or deciding between hook-based fixes and deeper provider overrides.
Aggressive design-polish skill for making websites feel authored, editorial, image-led, and typographically intentional. Use when a page looks too generic, safe, same-font, SaaS-like, cluttered, or visually under-authored.
TypeScript conventions, code design principles (SOLID, self-documenting code, file organization), structural design heuristics (dependency width, LoD, output arguments), pnpm rules, ES2024 target, and Pi SDK patterns. Load during implementation, refactoring, or code review.
| name | write-ast-grep-rule |
| description | Use when writing a new pi-lens ast-grep rule YAML file — covers schema, drop path, gotchas, and NAPI runner constraints |
Drop path: rules/ast-grep-rules/rules/<id>.yml
Same id as a built-in overrides it. Multiple rules per file: separate with ---.
id: no-foo-bar
language: TypeScript # PascalCase — see languages below
severity: warning # error | warning | info
message: "Avoid foo.bar() — use baz() instead"
note: |
Longer explanation / fix guidance here.
rule:
pattern: foo.bar($ARG)
TypeScript JavaScript Python Go Rust Java C Cpp CSharp Kotlin Ruby Php
rule:
pattern: foo($X) # ast-grep pattern — $X single, $$$ARGS multi
kind: call_expression # AST node kind (alternative to pattern)
regex: "secret|token" # regex on node text
has: # descendant must match
pattern: await $$$
not:
kind: comment
any:
- pattern: foo($X)
- pattern: bar($X)
all:
- pattern: $OBJ.send($$$)
- not: { kind: await_expression }
inside follows precedes stopBy field nthChild constraints
Use tree-sitter rules instead when you need relational context (inside function, follows import).
❌ Overly broad patterns — filtered out automatically
$VAR $NAME $_ $X $EXPR (single bare metavar)
❌ PascalCase language is required
language: typescript → language: TypeScript
❌ $VAR inside strings — matches literal "$VAR", not a metavar
"from $PATH" → use tree-sitter or grep instead
✅ Test in playground: https://ast-grep.github.io/playground.html
✅ Schema + autocomplete: rules/ast-grep-rules/rule-schema.json
✅ Docs: docs/custom-rules.md
⚠ The NAPI runner's `has`/`not` semantics DIFFER from the `ast-grep` CLI:
- NAPI runner (production): `has` searches ALL descendants (recursive).
- CLI (`ast-grep scan`): `has` is IMMEDIATE children only, unless `stopBy: end`.
So `kind: switch_statement` + `not: {has: {kind: switch_default}}` works in the
runner but UNDER-reports via the CLI. To reproduce in the CLI add `stopBy: end`
— but NEVER ship `stopBy` (the runner SKIPS rules that use it; see limits above).
✅ Prefer `regex` on the matched node's OWN text over `has` when you only need to
inspect the node — avoids recursive-descendant false positives:
kind: export_statement
regex: '^export\s+(let|var)\b' # precise; no has-recursion FP
(NAPI evaluates `regex` with JS RegExp on node.text() — keep it LINEAR so the
detector can't itself ReDoS.)
✅ One `language: TypeScript` rule runs on .ts/.tsx/.js/.jsx in the NAPI runner
(no per-file language gate). A `-js` twin DOUBLE-FIRES (the dedup key includes
the rule id). Add a `-js` variant ONLY if you need the CLI/.sgconfig path, which
DOES gate strictly by language.
✅ Node-kind facts:
- let / const → `lexical_declaration` (var is NOT here)
- var → `variable_declaration`
- a regex literal's pattern text → `regex_pattern`
✅ Test through the REAL runner from the repo root — it loads the actual shipped
rules from rules/ast-grep-rules/rules. Assert on diagnostic `rule` ids:
const res = await runner.run(ctx); // ctx.filePath = temp .ts, cwd = repo
For pattern/kind/regex-only rules (CLI-identical semantics) `ast-grep scan` is fine.
✅ Before shipping any text/regex detector, FP-scan the codebase:
ast-grep scan -r <rule>.yml clients tools
Real safe variants bite (e.g. ReDoS: (ba+)+ is safe — a mandatory prefix makes
the partition unique; flag only a single quantified atom inside the group).