treesitter-patterns
Universal patterns for tree-sitter code parsing. Covers AST visitors, query patterns, and language plugin development. Framework-agnostic.
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o treesitter-patterns.zip https://jpskill.com/download/18060.zip && unzip -o treesitter-patterns.zip && rm treesitter-patterns.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/18060.zip -OutFile "$d\treesitter-patterns.zip"; Expand-Archive "$d\treesitter-patterns.zip" -DestinationPath $d -Force; ri "$d\treesitter-patterns.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
treesitter-patterns.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
treesitter-patternsフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
Tree-sitter パターン Skill
あらゆるプロジェクトで tree-sitter を扱うための汎用的なパターンです。AST の解析、クエリパターン、ビジター、言語プラグインの開発を網羅します。
設計原則
この Skill は フレームワークに依存しません。汎用的な tree-sitter パターンを提供します。
- Code-Index-MCP、treesitter-chunker、または特定のプロジェクトに特化したものではありません
- すべての tree-sitter プロジェクトに適用可能な共通パターンを網羅します
- プロジェクト固有のクエリは、プロジェクト固有の Skill に記述します
変数
| 変数 | デフォルト | 説明 |
|---|---|---|
| TREE_SITTER_DIR | tree_sitter | 言語パーサーのディレクトリ |
| QUERY_DIR | queries | .scm クエリファイルのディレクトリ |
| LANGUAGES | auto | 自動検出または言語のリスト |
手順
必須 - 以下のワークフローの手順を順番に実行してください。
- 解析する言語を特定する
- 適切な言語パーサーをインストールする
- 抽出のニーズに合わせてクエリを作成する
- エッジケースとエラーを処理する
危険信号 - 停止して再検討
もしあなたが以下をしようとしているなら:
- エラー処理なしで解析する(構文エラーはよくあります)
- すべてのファイルが正常に解析されると仮定する
- サンプルコードでテストせずにクエリを作成する
- 大きなファイルのパフォーマンスを無視する
停止 -> エラー処理を追加 -> エッジケースでテスト -> その後、続行
クックブック
言語プラグインの開発
- IF: 新しい言語パーサーを作成する場合
- THEN:
./cookbook/language-plugin.mdを読んで実行してください
AST ビジターパターン
- IF: AST をたどって情報を抽出する場合
- THEN:
./cookbook/ast-visitor.mdを読んで実行してください
クエリパターン
- IF: tree-sitter クエリを作成する場合
- THEN:
./cookbook/query-patterns.mdを読んで実行してください
クイックリファレンス
Python のセットアップ
import tree_sitter_python as tspython
from tree_sitter import Language, Parser
# Create parser
parser = Parser(Language(tspython.language()))
# Parse code
source = b"def hello(): pass"
tree = parser.parse(source)
# Access root node
root = tree.root_node
print(root.sexp())
ノードのナビゲーション
# Get children
for child in node.children:
print(child.type, child.text)
# Named children only (skip punctuation)
for child in node.named_children:
print(child.type)
# Find by type
def find_all(node, type_name):
results = []
if node.type == type_name:
results.append(node)
for child in node.children:
results.extend(find_all(child, type_name))
return results
functions = find_all(root, "function_definition")
クエリ言語
; Match function definitions
(function_definition
name: (identifier) @function.name
parameters: (parameters) @function.params
body: (block) @function.body)
; Match class definitions
(class_definition
name: (identifier) @class.name
body: (block) @class.body)
; Match imports
(import_statement
(dotted_name) @import.module)
; Match decorated functions
(decorated_definition
(decorator) @decorator
definition: (function_definition
name: (identifier) @function.name))
クエリの実行
from tree_sitter import Query
query = Query(Language(tspython.language()), """
(function_definition
name: (identifier) @name
body: (block) @body)
""")
captures = query.captures(root)
for node, name in captures:
print(f"{name}: {node.text.decode()}")
一般的なノード型
| 言語 | 関数 | クラス | インポート |
|---|---|---|---|
| Python | function_definition |
class_definition |
import_statement |
| JavaScript | function_declaration |
class_declaration |
import_statement |
| TypeScript | function_declaration |
class_declaration |
import_statement |
| Go | function_declaration |
type_declaration |
import_declaration |
| Rust | function_item |
impl_item |
use_declaration |
エラー処理
def safe_parse(source: bytes) -> tuple[Tree | None, list[str]]:
"""Parse with error collection."""
tree = parser.parse(source)
errors = []
def collect_errors(node):
if node.type == "ERROR" or node.is_missing:
errors.append(f"Error at {node.start_point}: {node.text[:50]}")
for child in node.children:
collect_errors(child)
collect_errors(tree.root_node)
return tree, errors
tree, errors = safe_parse(source)
if errors:
print(f"Parse errors: {errors}")
ビジターパターン
from abc import ABC, abstractmethod
class ASTVisitor(ABC):
"""Base visitor for tree-sitter AST."""
def visit(self, node):
method_name = f"visit_{node.type}"
visitor = getattr(self, method_name, self.generic_visit)
return visitor(node)
def generic_visit(self, node):
for child in node.named_children:
self.visit(child)
@abstractmethod
def visit_function_definition(self, node):
pass
class FunctionExtractor(ASTVisitor):
def __init__(self):
self.functions = []
def visit_function_definition(self, node):
name_node = node.child_by_field_name("name")
if name_node:
self.functions.append(name_node.text.decode())
self.generic_visit(node)
extractor = FunctionExtractor()
extractor.visit(tree.root_node)
print(extractor.functions)
パフォーマンスのヒント
- インクリメンタル解析: 編集の場合、
parser.parse(new_source, old_tree)を使用します - 遅延評価: 特定のノードのみが必要な場合は、ツリー全体をトラバースしないでください
- クエリの最適化: より具体的なクエリを使用して、一致を減らします
- メモリ管理: 大きなファイルは大量のメモリを使用する可能性があります
- バッチ処理: 複数のファイルを並行して処理します
統合
コード解析との統合
def analyze_file(path: Path) -> CodeAnalysis:
source = path.read_bytes()
tree = parser.parse(source)
return CodeAnalysis(
functions=extract_functions(tree),
classes=extract_classes(tree),
imports=extract_imports(tree),
complexity=calculate_complexity(tree)
)
BAML との統合
class Co 📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
Tree-sitter Patterns Skill
Universal patterns for working with tree-sitter in any project. Covers AST parsing, query patterns, visitors, and language plugin development.
Design Principle
This skill is framework-generic. It provides universal tree-sitter patterns:
- NOT tailored to Code-Index-MCP, treesitter-chunker, or any specific project
- Covers common patterns applicable across all tree-sitter projects
- Project-specific queries go in project-specific skills
Variables
| Variable | Default | Description |
|---|---|---|
| TREE_SITTER_DIR | tree_sitter | Directory for language parsers |
| QUERY_DIR | queries | Directory for .scm query files |
| LANGUAGES | auto | Auto-detect or list of languages |
Instructions
MANDATORY - Follow the Workflow steps below in order.
- Identify languages to parse
- Install appropriate language parsers
- Write queries for extraction needs
- Handle edge cases and errors
Red Flags - STOP and Reconsider
If you're about to:
- Parse without error handling (syntax errors are common)
- Assume all files parse successfully
- Write queries without testing on sample code
- Ignore performance for large files
STOP -> Add error handling -> Test on edge cases -> Then proceed
Cookbook
Language Plugin Development
- IF: Creating a new language parser
- THEN: Read and execute
./cookbook/language-plugin.md
AST Visitor Patterns
- IF: Walking the AST to extract information
- THEN: Read and execute
./cookbook/ast-visitor.md
Query Patterns
- IF: Writing tree-sitter queries
- THEN: Read and execute
./cookbook/query-patterns.md
Quick Reference
Python Setup
import tree_sitter_python as tspython
from tree_sitter import Language, Parser
# Create parser
parser = Parser(Language(tspython.language()))
# Parse code
source = b"def hello(): pass"
tree = parser.parse(source)
# Access root node
root = tree.root_node
print(root.sexp())
Node Navigation
# Get children
for child in node.children:
print(child.type, child.text)
# Named children only (skip punctuation)
for child in node.named_children:
print(child.type)
# Find by type
def find_all(node, type_name):
results = []
if node.type == type_name:
results.append(node)
for child in node.children:
results.extend(find_all(child, type_name))
return results
functions = find_all(root, "function_definition")
Query Language
; Match function definitions
(function_definition
name: (identifier) @function.name
parameters: (parameters) @function.params
body: (block) @function.body)
; Match class definitions
(class_definition
name: (identifier) @class.name
body: (block) @class.body)
; Match imports
(import_statement
(dotted_name) @import.module)
; Match decorated functions
(decorated_definition
(decorator) @decorator
definition: (function_definition
name: (identifier) @function.name))
Running Queries
from tree_sitter import Query
query = Query(Language(tspython.language()), """
(function_definition
name: (identifier) @name
body: (block) @body)
""")
captures = query.captures(root)
for node, name in captures:
print(f"{name}: {node.text.decode()}")
Common Node Types
| Language | Functions | Classes | Imports |
|---|---|---|---|
| Python | function_definition |
class_definition |
import_statement |
| JavaScript | function_declaration |
class_declaration |
import_statement |
| TypeScript | function_declaration |
class_declaration |
import_statement |
| Go | function_declaration |
type_declaration |
import_declaration |
| Rust | function_item |
impl_item |
use_declaration |
Error Handling
def safe_parse(source: bytes) -> tuple[Tree | None, list[str]]:
"""Parse with error collection."""
tree = parser.parse(source)
errors = []
def collect_errors(node):
if node.type == "ERROR" or node.is_missing:
errors.append(f"Error at {node.start_point}: {node.text[:50]}")
for child in node.children:
collect_errors(child)
collect_errors(tree.root_node)
return tree, errors
tree, errors = safe_parse(source)
if errors:
print(f"Parse errors: {errors}")
Visitor Pattern
from abc import ABC, abstractmethod
class ASTVisitor(ABC):
"""Base visitor for tree-sitter AST."""
def visit(self, node):
method_name = f"visit_{node.type}"
visitor = getattr(self, method_name, self.generic_visit)
return visitor(node)
def generic_visit(self, node):
for child in node.named_children:
self.visit(child)
@abstractmethod
def visit_function_definition(self, node):
pass
class FunctionExtractor(ASTVisitor):
def __init__(self):
self.functions = []
def visit_function_definition(self, node):
name_node = node.child_by_field_name("name")
if name_node:
self.functions.append(name_node.text.decode())
self.generic_visit(node)
extractor = FunctionExtractor()
extractor.visit(tree.root_node)
print(extractor.functions)
Performance Tips
- Incremental parsing: For edits, use
parser.parse(new_source, old_tree) - Lazy evaluation: Don't traverse entire tree if you only need specific nodes
- Query optimization: Use more specific queries to reduce matches
- Memory management: Large files can use significant memory
- Batch processing: Process multiple files in parallel
Integration
With Code Analysis
def analyze_file(path: Path) -> CodeAnalysis:
source = path.read_bytes()
tree = parser.parse(source)
return CodeAnalysis(
functions=extract_functions(tree),
classes=extract_classes(tree),
imports=extract_imports(tree),
complexity=calculate_complexity(tree)
)
With BAML
class CodeStructure {
functions FunctionInfo[]
classes ClassInfo[]
imports string[]
}
class FunctionInfo {
name string
parameters string[]
return_type string?
line_start int
line_end int
}
Best Practices
- Error tolerance: Always handle parse errors gracefully
- Use queries: Prefer queries over manual traversal
- Test on real code: Test with actual codebases, not just samples
- Document node types: Reference language grammar for node types
- Version parsers: Pin tree-sitter language versions