Claude Skills Guide

Claude Code for Tree-sitter AST Traversal Workflow

When working with code analysis, refactoring, or automated transformations, understanding how to traverse Tree-sitter’s Abstract Syntax Tree (AST) is essential. Combined with Claude Code’s skill system, you can build powerful workflows that analyze code structure, identify patterns, and perform targeted modifications. This guide walks you through practical AST traversal patterns that integrate smoothly with Claude Code skills.

Understanding the Tree-sitter AST Structure

Tree-sitter represents source code as a hierarchical tree of nodes, where each node corresponds to a syntactic construct in your code—a function call, variable declaration, loop, or expression. Each node has a type (like function_declaration, call_expression, or identifier), children nodes, and positional metadata including start and end positions.

The AST structure follows a consistent pattern: leaf nodes represent tokens (identifiers, literals, operators), while interior nodes represent language constructs (statements, expressions, declarations). Understanding this hierarchy is crucial for effective traversal.

When you parse code with Tree-sitter, you receive a Tree object containing a root Node. From there, you can traverse downward through children, upward through the parent chain, or use cursor-based traversal for efficient iteration.

Basic AST Traversal Patterns

Using TreeCursor for Efficient Traversal

The most performant way to traverse an AST in Tree-sitter is using a TreeCursor. Unlike recursive approaches that create new stack frames for each node, cursors maintain state internally and can iterate through millions of nodes efficiently.

const tree = parser.parse(sourceCode);
const cursor = tree.walk();

while (true) {
  const node = cursor.currentNode();
  console.log(`Node type: ${node.type}, Text: ${node.text}`);
  
  if (cursor.gotoFirstChild()) {
    continue;
  }
  
  if (cursor.gotoNextSibling()) {
    continue;
  }
  
  while (!cursor.gotoParent() && cursor.currentNode()) {
    if (cursor.gotoNextSibling()) {
      break;
    }
  }
  
  if (!cursor.currentNode()) {
    break;
  }
}

This pattern performs a depth-first traversal, visiting every node exactly once. For most Claude Code workflows, you’ll want to filter by node type to focus on relevant constructs.

Finding Specific Node Types

Rather than traversing the entire tree, you can use predicates to find nodes matching specific criteria. This is invaluable for tasks like locating all function definitions or identifying specific patterns:

function findNodesByType(rootNode, targetType) {
  const results = [];
  const cursor = rootNode.walk();
  
  // Use named children for cleaner traversal
  cursor.gotoFirstChild();
  
  do {
    const node = cursor.currentNode();
    if (node.type === targetType) {
      results.push(node);
    }
  } while (cursor.gotoNextSibling());
  
  return results;
}

// Find all function declarations
const functions = findNodesByType(rootNode, 'function_declaration');

For more complex queries, Tree-sitter’s pattern matching using ts_query provides a declarative way to find nodes matching specific tree structures.

Integrating AST Traversal with Claude Code Skills

Claude Code skills excel at orchestrating complex workflows. By combining skill definitions with AST traversal logic, you can create powerful code analysis and transformation tools.

Creating a Code Analysis Skill

A well-structured skill for AST-based analysis separates concerns cleanly—the skill definition provides context and tool access, while the implementation handles the traversal logic:

---
name: analyze-functions
description: "Analyze function definitions in codebase"
---

## Usage

Analyze all functions in a JavaScript file:
- File path: /path/to/file.js
- Output: analysis-results.json

## Implementation Notes

This skill uses tree-sitter-cli for parsing. The analysis extracts:
1. Function names and locations
2. Parameter counts and names
3. Cyclomatic complexity indicators
4. Nested function declarations

The actual implementation would invoke tree-sitter CLI commands or use bindings to parse and analyze the code structure.

Pattern Matching with Tree-sitter Queries

Tree-sitter queries provide a powerful pattern-matching language for finding nodes. Instead of writing manual traversal code, you define patterns that match specific tree structures:

; Find all function calls with their arguments
(call_expression
  function: (identifier) @fn_name
  arguments: (arguments (identifier) @arg))

; Match try-catch blocks
(try_statement
  body: (block) @try_body
  handler: (catch_clause (block) @catch_body))

Captured nodes (@name syntax) are returned as query matches, allowing you to extract exactly the nodes needed for your analysis.

const query = parser.query(`
  (call_expression
    function: (identifier) @fn_name
    arguments: (arguments (identifier) @arg))
`);

const matches = query.captures(rootNode);
for (const match of matches) {
  console.log(`Function: ${match.captures[0].node.text}`);
  console.log(`Argument: ${match.captures[1].node.text}`);
}

Practical Workflow Examples

Automated Refactoring: Renaming Variables Across Scopes

One powerful application combines AST traversal with Claude Code’s file manipulation capabilities. Consider a refactoring task to rename a variable throughout its entire scope:

  1. Parse the source file to identify the variable’s declaration node
  2. Traverse the AST to find all references within the same scope
  3. Collect all file positions where the rename should occur
  4. Use Claude Code’s file editing tools to perform precise replacements

The key advantage is scope awareness—you won’t accidentally rename variables in other scopes that happen to share the same name.

Code Quality Analysis

Build analysis skills that traverse ASTs to detect patterns:

Documentation Generation

Traverse ASTs to extract structured information for documentation:

function extractFunctionDocs(rootNode) {
  const functions = rootNode.descendantsOfType('function_declaration');
  return functions.map(fn => ({
    name: fn.childForField('name').text,
    params: fn.childForField('parameters').text,
    returnType: fn.childForField('return_type')?.text,
    location: fn.startPosition
  }));
}

Best Practices for AST Traversal in Claude Code Workflows

When building Claude Code skills that involve AST traversal, consider these practical guidelines:

Start with Tree-sitter CLI for prototyping before investing in bindings. The CLI provides immediate feedback and works with any language that has tree-sitter-cli available. Once your patterns are solid, you can optimize with language bindings.

Use queries instead of manual traversal whenever possible. Queries are declarative, easier to maintain, and often faster than custom traversal code. Reserve manual traversal for cases where you need complex state management during traversal.

Cache parsed trees when analyzing multiple times. Tree-sitter’s incremental parsing makes this efficient—subsequent parses of modified files reuse significant portions of the previous parse.

Separate concerns between skills and implementations. Keep skill definitions focused on describing what should be analyzed and how results should be presented, while the actual traversal logic lives in scripts or external tools.

Conclusion

Tree-sitter AST traversal unlocks sophisticated code analysis and transformation capabilities within Claude Code workflows. By mastering cursor-based traversal, query patterns, and scope-aware analysis, you can build skills that understand code structure at a semantic level—not just as text, but as organized hierarchies of meaningful constructs.

Start with simple node-finding patterns, then layer in query-based matching for more complex analysis. The investment pays dividends in the reliability and precision of your automated code workflows.

Built by theluckystrike — More at zovo.one