treesitter-patterns
Universal patterns for tree-sitter code parsing. Covers AST visitors, query patterns, and language plugin development. Framework-agnostic.
What this skill does
# 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.
1. Identify languages to parse
2. Install appropriate language parsers
3. Write queries for extraction needs
4. 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
```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())
```
### Node Navigation
```python
# 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
```scheme
; 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
```python
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
```python
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
```python
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
1. **Incremental parsing**: For edits, use `parser.parse(new_source, old_tree)`
2. **Lazy evaluation**: Don't traverse entire tree if you only need specific nodes
3. **Query optimization**: Use more specific queries to reduce matches
4. **Memory management**: Large files can use significant memory
5. **Batch processing**: Process multiple files in parallel
## Integration
### With Code Analysis
```python
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
```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
1. **Error tolerance**: Always handle parse errors gracefully
2. **Use queries**: Prefer queries over manual traversal
3. **Test on real code**: Test with actual codebases, not just samples
4. **Document node types**: Reference language grammar for node types
5. **Version parsers**: Pin tree-sitter language versions
Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.