Generate Release Notes
teambit/bit
Generate comprehensive release notes for Bit from git commits and pull requests.
Reference for writing and debugging TypeScript and JavaScript codemods with @ast-grep/napi: parsing, node queries, meta-variables, rule objects and editing.
$ npx skills add warp-drive-data/warp-drive --skill ast-grep-codemods -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install warp-drive-data/warp-drive ast-grep-codemods --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/warp-drive-data/warp-drive.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/ast-grep-codemods .claude/skills/ast-grep-codemods && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "ast-grep-codemods" agent skill from https://github.com/warp-drive-data/warp-drive/tree/main/.claude/skills/ast-grep-codemods into .claude/skills/ast-grep-codemods/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ast-grep-codemods", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/warp-drive-data/warp-drive/tree/main/.claude/skills/ast-grep-codemodsType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add warp-drive-data/warp-drive --skill ast-grep-codemods -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install warp-drive-data/warp-drive ast-grep-codemods --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/warp-drive-data/warp-drive.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.claude/skills/ast-grep-codemods .agents/skills/ast-grep-codemods && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "ast-grep-codemods" agent skill from https://github.com/warp-drive-data/warp-drive/tree/main/.claude/skills/ast-grep-codemods into .agents/skills/ast-grep-codemods/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ast-grep-codemods", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add warp-drive-data/warp-drive --skill ast-grep-codemods -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install warp-drive-data/warp-drive ast-grep-codemods --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/warp-drive-data/warp-drive.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.claude/skills/ast-grep-codemods .cursor/skills/ast-grep-codemods && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "ast-grep-codemods" agent skill from https://github.com/warp-drive-data/warp-drive/tree/main/.claude/skills/ast-grep-codemods into .cursor/skills/ast-grep-codemods/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ast-grep-codemods", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/warp-drive-data/warp-drive.git --path .claude/skills/ast-grep-codemods--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add warp-drive-data/warp-drive --skill ast-grep-codemods -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install warp-drive-data/warp-drive ast-grep-codemods --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/warp-drive-data/warp-drive.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.claude/skills/ast-grep-codemods .gemini/skills/ast-grep-codemods && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "ast-grep-codemods" agent skill from https://github.com/warp-drive-data/warp-drive/tree/main/.claude/skills/ast-grep-codemods into .gemini/skills/ast-grep-codemods/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ast-grep-codemods", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install warp-drive-data/warp-drive ast-grep-codemodsInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add warp-drive-data/warp-drive --skill ast-grep-codemods -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/warp-drive-data/warp-drive.git skills-src && mkdir -p .github/skills && cp -r skills-src/.claude/skills/ast-grep-codemods .github/skills/ast-grep-codemods && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "ast-grep-codemods" agent skill from https://github.com/warp-drive-data/warp-drive/tree/main/.claude/skills/ast-grep-codemods into .github/skills/ast-grep-codemods/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ast-grep-codemods", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add warp-drive-data/warp-drive --skill ast-grep-codemods -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install warp-drive-data/warp-drive ast-grep-codemods --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/warp-drive-data/warp-drive.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.claude/skills/ast-grep-codemods .opencode/skills/ast-grep-codemods && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "ast-grep-codemods" agent skill from https://github.com/warp-drive-data/warp-drive/tree/main/.claude/skills/ast-grep-codemods into .opencode/skills/ast-grep-codemods/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ast-grep-codemods", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
ast-grep-codemodsReference for writing and debugging TypeScript and JavaScript codemods with @ast-grep/napi: parsing, node queries, meta-variables, rule objects and editing.
The ast-grep rule system used by the schema-migration codemods in the repository's `packages/codemods` project is documented, built on the Node.js binding `@ast-grep/napi`. It shows how to parse source with `parse` and a language, then use `SgNode` methods to search (`find`, `findAll`), traverse (`children`, `parent`, `child`), inspect (`kind`, `text`, `isLeaf`) and extract meta-variable matches.
Edits are made with `replace` and applied in a batch through `commitEdits`. Complex queries use a `NapiConfig` rule object with the atomic rules `kind`, `pattern` and `regex`. In patterns, `$NAME` matches one node, `$$NAME` matches zero or more non-greedily and `$$$NAME` greedily. One gotcha: tree-sitter kind names differ between grammars (`field_definition` for TypeScript, `public_field_definition` or `class_field` elsewhere), so kind lookups should be wrapped in try/catch when trying several.
3 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 34ad57e. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are typescript).
From the folder's file list and the shell code blocks in SKILL.md.
Links to these hosts (documentation or services it may open):
ast-grep.github.ioFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
ast-grep Codemod Reference loads about 2.6k tokens when it runs. Until then it costs about 62 tokens; SKILL.md has 400 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from warp-drive-data/warp-drive at commit 34ad57e, republished under its MIT licence (© warp-drive-data). 400 words, ~2,566 tokens.
.claude/skills/ast-grep-codemods/SKILL.md (or your agent's skills folder).This skill provides the ast-grep rule system reference used by packages/codemods/src/schema-migration/.
The codemods use @ast-grep/napi (the Node.js binding) to parse and transform TypeScript/JavaScript ASTs.
import { parse, Lang, type SgNode } from '@ast-grep/napi';
const ast = parse(Lang.TypeScript, sourceCode);
const root: SgNode = ast.root();// Find first match (returns null if not found)
node.find(matcher: string | number | NapiConfig): SgNode | null
// Find all matches
node.findAll(matcher: string | number | NapiConfig): SgNode[]
// Boolean checks
node.matches(pattern: string): boolean
node.inside(pattern: string): boolean
node.has(pattern: string): booleannode.children(): SgNode[] // Direct children
node.parent(): SgNode | null // Parent node
node.child(nth: number): SgNode | null
node.field(name: string): SgNode | null // Named field (e.g., 'name', 'body', 'source')
node.ancestors(): SgNode[]
node.next(): SgNode | null // Next sibling
node.nextAll(): SgNode[]
node.prev(): SgNode | null // Previous sibling
node.prevAll(): SgNode[]node.kind(): string // Tree-sitter node type (e.g., 'field_definition', 'class_body')
node.text(): string // Full source text
node.isLeaf(): boolean
node.isNamed(): boolean
node.range(): Range // { start: Pos, end: Pos } (0-indexed)// After finding with a pattern containing $VAR or $$$VARS:
node.getMatch('VAR'): SgNode | null
node.getMultipleMatches('VARS'): SgNode[]const edit = node.replace('newCode'); // Returns Edit object
const newSource = root.commitEdits([edit1, edit2]); // Apply batch editsThe find and findAll methods accept a NapiConfig object for complex queries:
node.findAll({
rule: { /* rule object */ },
constraints?: { /* meta-variable constraints */ },
})Match individual nodes by their properties.
kind - Match by tree-sitter node type// Find all class declarations
root.findAll({ rule: { kind: 'class_declaration' } })
// Common TypeScript/JavaScript kinds:
// class_declaration, class_body, field_definition, method_definition,
// import_statement, identifier, property_identifier, decorator,
// call_expression, member_expression, string, template_stringGotcha: Not all kind names are valid in all grammars. TypeScript uses field_definition,
some JavaScript grammars use public_field_definition or class_field. Wrap in try/catch
when iterating over multiple possible kinds.
pattern - Match by code pattern with meta-variables// Simple pattern
root.findAll({ rule: { pattern: 'console.log($ARG)' } })
// Pattern with context (for ambiguous syntax like class members)
root.findAll({
rule: {
pattern: {
context: 'class A { $FIELD = $INIT }',
selector: 'field_definition',
}
}
})Meta-variables:
$NAME - matches a single AST node$$NAME - matches zero or more nodes (non-greedy)$$$NAME - matches zero or more nodes (greedy)regex - Match node text against regex// Match identifiers starting with underscore
root.findAll({ rule: { kind: 'identifier', regex: '^_' } })Combine rules with boolean logic.
all - Every rule must match (AND)root.findAll({
rule: {
all: [
{ kind: 'call_expression' },
{ pattern: '$OBJ.$METHOD($$$ARGS)' },
]
}
})any - At least one rule must match (OR)root.findAll({
rule: {
any: [
{ kind: 'field_definition' },
{ kind: 'public_field_definition' },
{ kind: 'class_field' },
]
}
})not - Negate a rule// Find all identifiers that aren't 'constructor'
root.findAll({
rule: {
kind: 'identifier',
not: { regex: '^constructor$' },
}
})matches - Reference a utility rule by IDroot.findAll({
rule: { matches: 'is-ember-decorator' },
utils: {
'is-ember-decorator': {
kind: 'decorator',
has: { pattern: '@$NAME', inside: { kind: 'class_body' } },
}
}
})Filter nodes by their position relative to other nodes in the AST.
inside - Node is contained within a matching ancestor// Find field_definition nodes that are DIRECT children of class_body
root.findAll({
rule: {
kind: 'field_definition',
inside: {
kind: 'class_body',
stopBy: 'neighbor', // Only check immediate parent
}
}
})has - Node contains a matching descendant// Find class declarations that have a decorator
root.findAll({
rule: {
kind: 'class_declaration',
has: {
kind: 'decorator',
stopBy: 'neighbor', // Only check direct children
}
}
})follows - Node appears after a matching sibling// Find nodes that follow a decorator
root.findAll({
rule: {
kind: 'field_definition',
follows: { kind: 'decorator' },
}
})precedes - Node appears before a matching siblingroot.findAll({
rule: {
kind: 'decorator',
precedes: { kind: 'method_definition' },
}
})stopBy Parameter (Critical)Controls how far relational rules search. This is the most important parameter for correct queries.
| Value | Behavior |
|---|---|
'neighbor' | (Default) Only checks one level (immediate parent for inside, direct children for has) |
'end' | Searches all the way (all ancestors for inside, all descendants for has) |
{ rule } | Stops when a node matching the rule is found (inclusive) |
Common pattern: matching only direct class members
// WRONG: findAll with just kind searches ALL descendants recursively
classBody.findAll({ rule: { kind: 'field_definition' } })
// ^ This picks up nested properties inside object literals!
// RIGHT: Use inside rule with stopBy: 'neighbor' to match direct children only
classBody.findAll({
rule: {
kind: 'field_definition',
inside: { kind: 'class_body', stopBy: 'neighbor' },
}
})field ParameterRestricts matches to a specific named field position in the parent node.
// Match only the KEY in a key-value pair, not values that happen to match
root.findAll({
rule: {
kind: 'pair',
has: {
field: 'key', // Only match the 'key' field position
regex: 'prototype',
}
}
})Common tree-sitter fields: name, body, source, key, value, left, right,
arguments, decorator, type_annotation.
import { NODE_KIND_CLASS_BODY, NODE_KIND_FIELD_DEFINITION, NODE_KIND_METHOD_DEFINITION } from './code-processing.js';
const DIRECT_CLASS_MEMBER = { inside: { kind: NODE_KIND_CLASS_BODY, stopBy: 'neighbor' } } as const;
// Properties - try multiple kinds since grammar varies
function findPropertyDefinitions(classBody: SgNode): SgNode[] {
for (const nodeType of ['field_definition', 'public_field_definition', 'class_field']) {
try {
const props = classBody.findAll({ rule: { kind: nodeType, ...DIRECT_CLASS_MEMBER } });
if (props.length > 0) return props;
} catch {
// Kind not valid in this grammar
}
}
return [];
}
// Methods
function findMethodDefinitions(classBody: SgNode): SgNode[] {
return classBody.findAll({ rule: { kind: NODE_KIND_METHOD_DEFINITION, ...DIRECT_CLASS_MEMBER } });
}const imports = root.findAll({ rule: { kind: 'import_statement' } });
for (const imp of imports) {
const source = imp.field('source'); // The string literal after 'from'
const clause = imp.field('import'); // The import clause (specifiers)
const sourcePath = source?.text(); // e.g., "'@ember-data/model'"
}// Walk backwards through siblings collecting decorator nodes
function collectPrecedingDecorators(node: SgNode): string[] {
const decorators: string[] = [];
const siblings = node.parent()?.children() ?? [];
const idx = siblings.indexOf(node);
for (let i = idx - 1; i >= 0; i--) {
const sib = siblings[i];
if (!sib) continue;
if (sib.kind() === 'decorator') decorators.unshift(sib.text());
else if (sib.text().trim() !== '') break;
}
return decorators;
}// Find class with heritage clause
const classDecl = root.find({ rule: { kind: 'class_declaration' } });
const heritage = classDecl?.find({ rule: { kind: 'class_heritage' } });
const identifiers = heritage?.findAll({ rule: { kind: 'identifier' } }) ?? [];
const baseClasses = identifiers.map((id) => id.text());// Match decorated class fields like: @attr('string') name;
root.findAll({
rule: {
pattern: {
context: 'class A { @$DECORATOR $FIELD = $VALUE }',
selector: 'field_definition',
}
}
})node.kind() liberally - When a rule isn't matching, log the actual kinds: classBody.children().map(c => c.kind())findAll with rules - Invalid kind names throw at runtime, not compile timestopBy behavior - The default 'neighbor' only searches one level. Use 'end' for recursive search.© warp-drive-data, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .claude/skills/ast-grep-codemods of warp-drive-data/warp-drive.
Open the folder on GitHubat commit 34ad57e
ast-grep Codemod Reference next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| ast-grep Codemod Reference this skillwarp-drive-data/warp-drive | 3.2k | — | ~2.6k | Automated safety check: Pass | MIT | |
| Generate Release Notesteambit/bit | 18k | — | ~2.2k | Automated safety check: Pass | Custom licence | |
| Convert Internal Package to TypeScriptTryGhost/Ghost | 56k | — | ~1.2k | Automated safety check: Pass | MIT | |
| jscpd Code Migration Trackerkucherenko/jscpd | 6.4k | — | ~5k | Automated safety check: Pass | MIT | |
| Dinero Best Practicesdinerojs/dinero.js | 6.8k | — | ~756 | Automated safety check: Pass | MIT | |
| Coding Standardskurealnum/dotfiles | 290 | 17 repos | ~2.9k | Automated safety check: Pass | None |
teambit/bit
Generate comprehensive release notes for Bit from git commits and pull requests.
TryGhost/Ghost
Moves a legacy internal Ghost package from JavaScript and CommonJS to TypeScript and ESM in three focused commits that keep git file history intact.
kucherenko/jscpd
Measures a code port between languages or frameworks with jscpd's function-level comparison, porting tests before code and tracking what is left unmatched.
dinerojs/dinero.js
Core best practices for the Dinero.js money library. An agent skill from dinerojs/dinero.js.
kurealnum/dotfiles
Universal coding standards, best practices, and patterns for TypeScript, JavaScript, React, and Node.js development.
kucherenko/jscpd
Removes copy-paste duplication found by jscpd, starting with exact clones and hotspots, then renamed and near-miss copies, using proven refactoring strategies.
warp-drive-data/warp-drive
Turns natural-language code queries into ast-grep rules for structural search, testing each rule against an example file before running it on a codebase.
warp-drive-data/warp-drive
Ensures `.mock-cache` fixture directories under `tests/*` are staged and committed whenever a change adds or modifies a test that uses…
Works with
Categories
Reference for writing and debugging TypeScript and JavaScript codemods with @ast-grep/napi: parsing, node queries, meta-variables, rule objects and editing. js binding `@ast-grep/napi`. It shows how to parse source with `parse` and a language, then use `SgNode` methods to search (`find`, `findAll`), traverse (`children`, `parent`, `child`), inspect (`kind`, `text`, `isLeaf`) and extract meta-variable matches.
ast-grep Codemod Reference fits situations like: writing a codemod that rewrites TypeScript or JavaScript with ast-grep; debugging a tree-sitter node kind that does not match; working in the packages/codemods directory.
Run `npx skills add warp-drive-data/warp-drive --skill ast-grep-codemods -a claude-code`. Or copy the skill folder (.claude/skills/ast-grep-codemods in warp-drive-data/warp-drive) into .claude/skills/ast-grep-codemods in your project. Claude Code loads it when a task matches its description.
Run `npx skills add warp-drive-data/warp-drive --skill ast-grep-codemods -a codex`. Or copy the skill folder (.claude/skills/ast-grep-codemods in warp-drive-data/warp-drive) into .agents/skills/ast-grep-codemods in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add warp-drive-data/warp-drive --skill ast-grep-codemods -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/ast-grep-codemods, .gemini/skills/ast-grep-codemods, .github/skills/ast-grep-codemods and .opencode/skills/ast-grep-codemods in your project.
SKILL.md names no scripts, command-line tools or credentials: ast-grep Codemod Reference is instructions for the agent only. Our summary lists: Node.js with the `@ast-grep/napi` package.
SKILL.md names 1 domain. As links in the text: ast-grep.github.io. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
ast-grep Codemod Reference is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 2.6k tokens (SKILL.md is roughly 10k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with ast-grep Codemod Reference: Generate Release Notes (teambit/bit, 18k stars), Convert Internal Package to TypeScript (TryGhost/Ghost, 56k stars), jscpd Code Migration Tracker (kucherenko/jscpd, 6.4k stars) and Dinero Best Practices (dinerojs/dinero.js, 6.8k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
warp-drive-data (a GitHub organization) maintains it in warp-drive-data/warp-drive, which has 3,158 GitHub stars. The repository holds 3 skills in this directory. The repository was last updated on October 9, 2026.
Source: warp-drive-data/warp-drive on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.