commit fd7783dada4c255f187bf79ff7e0671a5bc43eda Author: Zhongwei Li Date: Sun Nov 30 09:06:54 2025 +0800 Initial commit diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..65da372 --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,12 @@ +{ + "name": "context-efficient-tools", + "description": "CLI tool skills that minimize context usage through targeted extraction instead of reading entire files", + "version": "0.1.2", + "author": { + "name": "David Golden", + "email": "xdg@xdg.me" + }, + "skills": [ + "./skills" + ] +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..3a23cea --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# context-efficient-tools + +CLI tool skills that minimize context usage through targeted extraction instead of reading entire files diff --git a/plugin.lock.json b/plugin.lock.json new file mode 100644 index 0000000..4913fec --- /dev/null +++ b/plugin.lock.json @@ -0,0 +1,81 @@ +{ + "$schema": "internal://schemas/plugin.lock.v1.json", + "pluginId": "gh:xdg/xdg-claude:context-efficient-tools", + "normalized": { + "repo": null, + "ref": "refs/tags/v20251128.0", + "commit": "805179ada0b65e12df3c987c958597d9250506c2", + "treeHash": "8508708e211de161928269ca9175632994e397a7552e5a4b555a41cc985d0c81", + "generatedAt": "2025-11-28T10:29:05.562286Z", + "toolVersion": "publish_plugins.py@0.2.0" + }, + "origin": { + "remote": "git@github.com:zhongweili/42plugin-data.git", + "branch": "master", + "commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390", + "repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data" + }, + "manifest": { + "name": "context-efficient-tools", + "description": "CLI tool skills that minimize context usage through targeted extraction instead of reading entire files", + "version": "0.1.2" + }, + "content": { + "files": [ + { + "path": "README.md", + "sha256": "7fdcf537e96ad3eb801290deb0e323d38b3dce04bc042fc9d93014889f2b2845" + }, + { + "path": ".claude-plugin/plugin.json", + "sha256": "09aaee3c496fd5540296cb0914aa6e0a0187466f1740061deb398ade7bf2b366" + }, + { + "path": "skills/yq/SKILL.md", + "sha256": "357eb1ebca0ff35b6be2e756dfdcad736af2102389d16fc5c8a9af13841b5e9d" + }, + { + "path": "skills/yq/reference/yq-guide.md", + "sha256": "1d1e53fcadc5c2317d6d941ccdc18f8994a19b5c719507fe4ab94f7291dd74fb" + }, + { + "path": "skills/ast-grep/SKILL.md", + "sha256": "7b014e400aa787d5746016d857d6339b2f8b3a2e6ab611f592eb321399931e16" + }, + { + "path": "skills/ast-grep/reference/ast-grep-guide.md", + "sha256": "62f6d7d967597ab1c93229e273c5f2c2eba0ed135eca8467766bea8366935359" + }, + { + "path": "skills/code-structure/SKILL.md", + "sha256": "c4bd0895b58b5a287f0bd6d502d8f2ccd624ad59708436710cc44b294a6c8113" + }, + { + "path": "skills/code-structure/reference/code-structure-guide.md", + "sha256": "6feb3ce87d75aefdbe2f51bc79d8c99fa56fff234628e1e0b13682387ef070e7" + }, + { + "path": "skills/jq/SKILL.md", + "sha256": "364b196f79637d1bf700024eb49629d2d261a3939351625020fa252d4945d168" + }, + { + "path": "skills/jq/reference/jq-guide.md", + "sha256": "188a56334f65604c65ac68d7064b15552221f9428fd6a87bfc9f0cb8a0f15d75" + }, + { + "path": "skills/ripgrep/SKILL.md", + "sha256": "2741e6e345ea825a55a7213737e3a94fa1669ef30ea72917e66c58e5460c15ac" + }, + { + "path": "skills/ripgrep/reference/ripgrep-guide.md", + "sha256": "2539363819a9064bfc7e3ca9477f1bacd7301774cdea251113b4af58c6e6c864" + } + ], + "dirSha256": "8508708e211de161928269ca9175632994e397a7552e5a4b555a41cc985d0c81" + }, + "security": { + "scannedAt": null, + "scannerVersion": null, + "flags": [] + } +} \ No newline at end of file diff --git a/skills/ast-grep/SKILL.md b/skills/ast-grep/SKILL.md new file mode 100644 index 0000000..88de7fe --- /dev/null +++ b/skills/ast-grep/SKILL.md @@ -0,0 +1,41 @@ +--- +name: ast-grep +description: Use ast-grep for structural code search and refactoring when editing code structure with ambiguity in text matching, handling "old_string not unique" problems, or performing formatting-independent pattern matching across function signatures, method calls, and class structures +--- + +# ast-grep: Structural Code Search and Editing + +Use ast-grep to solve the "old_string not unique" problem by matching code structure instead of exact text. This enables refactoring across formatting variations and structural patterns. + +## When to Use ast-grep vs Text Tools + +### Use ast-grep when: +- **Structural code changes** - Refactoring function signatures, method calls, class structures +- **Formatting-independent matching** - Need to find code regardless of whitespace/line breaks +- **Pattern variations** - Matching similar structures with different variable names/arguments +- **"old_string not unique" problem** - Edit tool fails because text appears in multiple contexts +- **Complex queries** - Finding nested structures, specific AST patterns + +### Use text tools (Edit/Grep) when: +- **Simple, unique string replacement** - The exact text appears once or in consistent format +- **Non-code files** - Markdown, configs, data files +- **Comment/documentation edits** - Content that isn't code structure +- **Very small changes** - Single line, obvious context, no ambiguity + +## Key Decision Rule + +**If editing code structure and there's any ambiguity in text matching → use ast-grep.** + +ast-grep's primary value: **Solves the "old_string not unique" problem by matching structure instead of exact text.** + +## Detailed Reference + +For comprehensive patterns, syntax, metavariables, common use cases, language-specific tips, and best practices, load [ast-grep guide](./reference/ast-grep-guide.md). + +The reference includes: +- Pattern syntax and metavariables (`$VAR`, `$$$ARGS`, `$$STMT`) +- Recommended workflow (search, verify, apply, validate) +- Common use cases with examples (function calls, imports, method renames) +- Language-specific tips (JavaScript/TypeScript, Python, Go, Rust) +- Best practices and pitfalls to avoid +- Integration strategies with Edit tool diff --git a/skills/ast-grep/reference/ast-grep-guide.md b/skills/ast-grep/reference/ast-grep-guide.md new file mode 100644 index 0000000..787807f --- /dev/null +++ b/skills/ast-grep/reference/ast-grep-guide.md @@ -0,0 +1,263 @@ +# ast-grep Comprehensive Reference Guide + +This guide provides comprehensive ast-grep knowledge for structural code search and transformation. + +# Core ast-grep Concepts + +## Pattern Syntax +- Use **actual code syntax** for the target language +- Use **metavariables** to capture patterns: + - `$VAR` - matches any single AST node (expression, identifier, etc.) + - `$$$ARGS` - matches multiple nodes (zero or more) + - `$$STMT` - matches multiple statements + +## Basic Commands +```bash +# Search for pattern +ast-grep -p 'PATTERN' + +# Specify language (always prefer explicit language) +ast-grep -l typescript -p 'PATTERN' + +# Search and replace (preview) +ast-grep -p 'OLD_PATTERN' -r 'NEW_PATTERN' + +# Apply changes (after verification) +ast-grep -p 'OLD_PATTERN' -r 'NEW_PATTERN' --update-all + +# JSON output (for parsing) +ast-grep -p 'PATTERN' --json +``` + +**CRITICAL CONSTRAINT**: You cannot use interactive mode (`-i`) - you cannot respond to interactive prompts. + +--- + +# Recommended Workflow + +## 1. Search Phase (Discovery) +```bash +# First, find matches to understand scope +ast-grep -l LANG -p 'PATTERN' [file_or_dir] + +# Count matches to verify expectations +ast-grep -p 'PATTERN' | wc -l +``` + +## 2. Verification Phase (Before Changes) +- **Always** run search first to see what will match +- Review matches to ensure pattern is correct +- Verify no false positives + +## 3. Application Phase (Making Changes) +Two viable strategies: + +**Strategy A: Direct Application** (for high confidence scenarios) +```bash +ast-grep -p 'OLD' -r 'NEW' # Preview first +ast-grep -p 'OLD' -r 'NEW' --update-all # Apply after thorough review +``` + +**Strategy B: Hybrid Approach** (RECOMMENDED for maximum control) +1. Use ast-grep to find matches: `ast-grep -l LANG -p 'PATTERN'` +2. Read the files to see actual context +3. Use Edit tool to apply changes with precise control + +This combines ast-grep's structural search with Edit's precision. + +## 4. Validation Phase +```bash +# After changes, verify the new pattern exists +ast-grep -p 'NEW_PATTERN' [file_or_dir] +``` + +--- + +# Common Use Cases with Examples + +## 1. Function Call Refactoring +```bash +# Find all calls to a function +ast-grep -l typescript -p 'oldFunction($$$ARGS)' + +# Replace with new function +ast-grep -l typescript -p 'oldFunction($$$ARGS)' -r 'newFunction($$$ARGS)' +``` + +## 2. Method Rename +```bash +# Find method calls on any object +ast-grep -l javascript -p '$OBJ.oldMethod($$$ARGS)' -r '$OBJ.newMethod($$$ARGS)' +``` + +## 3. Import Statement Changes +```bash +# TypeScript/JavaScript: change import source +ast-grep -l typescript -p 'import $WHAT from "old-package"' -r 'import $WHAT from "new-package"' +``` + +## 4. Adding Parameters to Function Calls +```bash +# Add a new parameter to all calls +ast-grep -l javascript -p 'doThing($ARG1, $ARG2)' -r 'doThing($ARG1, $ARG2, { new: true })' +``` + +## 5. Find Complex Patterns +```bash +# Find try-catch blocks with specific pattern +ast-grep -l javascript -p 'try { $$$BODY } catch ($ERR) { console.error($$$) }' + +# Find async functions +ast-grep -l typescript -p 'async function $NAME($$$ARGS) { $$$BODY }' +``` + +## 6. Class Method Changes +```bash +# Find all methods in classes +ast-grep -l typescript -p 'class $CLASS { $$$A $METHOD($$$PARAMS) { $$$BODY } $$$B }' +``` + +--- + +# Language-Specific Tips + +## JavaScript/TypeScript (`-l typescript` or `-l javascript`) +- Works for: .js, .jsx, .ts, .tsx +- Patterns use JS/TS syntax exactly as written +- Arrow functions: `($$$ARGS) => $BODY` +- Always use `-l typescript` for TypeScript files + +## Python (`-l python`) +- Indentation in pattern matters less than structure +- Use Python syntax: `def $NAME($$$ARGS):` + +## Go (`-l go`) +- Use Go syntax: `func $NAME($$$ARGS) $RET { $$$ }` +- Package/import matching: `import "$PKG"` + +## Rust (`-l rust`) +- Use Rust syntax: `fn $NAME($$$ARGS) -> $RET { $$$ }` +- Match macros: `println!($$$ARGS)` + +--- + +# Best Practices + +## 1. Always Verify Before Applying +```bash +# NEVER apply changes without seeing matches first +# BAD: ast-grep -p 'pattern' -r 'replacement' --update-all +# GOOD: +ast-grep -p 'pattern' # Review matches +ast-grep -p 'pattern' -r 'replacement' # Preview changes +ast-grep -p 'pattern' -r 'replacement' --update-all # Apply only after review +``` + +## 2. Always Use Explicit Language Flag +```bash +# BAD: ast-grep -p 'pattern' # May auto-detect incorrectly +# GOOD: ast-grep -l typescript -p 'pattern' # Explicit and reliable +``` + +## 3. Start Specific, Broaden if Needed +- Begin with very specific patterns +- If no matches, gradually make pattern more general +- Use metavariables for parts that vary, keep fixed parts specific + +## 4. Use Metavariables Appropriately +- `$VAR` - single expression (e.g., `$X + $Y`) +- `$$$ARGS` - multiple items in lists (e.g., function arguments) +- `$$STMT` - multiple statements (e.g., function body) + +## 5. Combine with Other Tools +```bash +# Use ast-grep to find, pipe to other tools +ast-grep -p 'pattern' | rg -e 'additional-filter' + +# Use ast-grep to find locations, then Edit to apply +ast-grep -l typescript -p 'pattern' # Find matches +# Then use Edit tool with precise context +``` + +--- + +# Common Pitfalls to Avoid + +## 1. Overly Broad Patterns +❌ `ast-grep -p '$X'` - matches everything +✓ `ast-grep -l typescript -p 'specificFunction($X)'` - targeted + +## 2. Forgetting Language Flag +❌ `ast-grep -p 'pattern'` - may misdetect language +✓ `ast-grep -l typescript -p 'pattern'` - explicit + +## 3. Not Verifying Before --update-all +❌ `ast-grep -p 'old' -r 'new' --update-all` - blind changes +✓ Preview first, verify matches, then apply + +## 4. Expecting Exact Text Matching +ast-grep matches **structure**, not text: +- `foo( x )` and `foo(x)` are the same structurally +- Line breaks don't matter in most cases +- Comments are typically ignored + +## 5. Using for Non-Code Files +ast-grep won't help with: +- Markdown content +- JSON/YAML values (not code structure) +- Plain text files +- Comments (usually) + +--- + +# Error Handling + +## If ast-grep fails or is unavailable: +1. Fall back to text-based tools immediately +2. Don't apologize excessively - just use the alternative approach + +## If pattern doesn't match: +1. Verify language detection: ensure `-l LANG` is used +2. Simplify pattern - start with minimal matching case +3. Check syntax - ensure pattern is valid code for target language +4. Fall back to Grep for discovery, then use Edit + +## If too many matches: +1. Make pattern more specific +2. Add context to pattern (surrounding code) +3. Use directory/file path to narrow scope +4. Consider using ast-grep for finding, Edit for selective changes + +--- + +# Integration with Edit Tool + +## Hybrid Strategy (Recommended for Precision) + +When maximum control is needed: + +1. **Use ast-grep to identify locations:** +```bash +ast-grep -l typescript -p 'pattern' +``` + +2. **Read the matched files** to see actual context + +3. **Use Edit tool** with precise old_string/new_string based on actual file content + +This combines ast-grep's structural search with Edit's precise control. This is often the best approach because: +- ast-grep finds the right locations structurally +- Edit gives precise control over the exact changes +- Each match can be handled differently if needed +- Lower risk of unintended changes + +--- + +# Summary: Key Principles + +1. **ast-grep solves the "not unique" problem** by matching code structure instead of text +2. **Always verify before applying** - search first, review matches, then apply +3. **Always use explicit language flag** (`-l typescript`, `-l python`, etc.) +4. **Use metavariables correctly** - `$VAR` for single nodes, `$$$ARGS` for multiple +5. **Consider hybrid approach** - ast-grep for finding, Edit for applying +6. **Fall back gracefully** - if ast-grep doesn't work, use text tools without hesitation diff --git a/skills/code-structure/SKILL.md b/skills/code-structure/SKILL.md new file mode 100644 index 0000000..be44628 --- /dev/null +++ b/skills/code-structure/SKILL.md @@ -0,0 +1,82 @@ +--- +name: code-structure +description: Extract file structure (functions, classes, exports) efficiently without reading entire files, using ast-grep, go doc, ctags, or other language-specific tools to get outlines and signatures +--- + +# Code Structure Exploration Tools + +## Recognizing Structure Questions + +**These keywords mean use structure tools, NOT grep/search:** +- "all the methods/functions/classes in..." +- "list of function signatures" +- "what functions/exports/API..." +- "package API" or "module exports" +- "method signatures with receivers" (Go) +- "what's available in..." + +**These keywords mean use search (Grep tool or ast-grep):** +- "where is X defined" +- "find calls to X" +- "search for pattern Y" + +## Before You Choose a Tool + +Ask yourself: +1. Am I listing/exploring what exists? → Structure tools +2. Am I finding WHERE something is? → Search tools (Grep or ast-grep) +3. Am I understanding HOW something works? → Read + +## When to Get File Outline vs Read + +**Get outline/index when:** +- File is large (>500 lines) +- Need to see what's available (functions, classes, exports) +- Exploring unfamiliar code +- Want to decide what to read in detail +- **Saves 90%+ context** vs reading entire file + +**Just use Read when:** +- File is small (<500 lines) +- Already know what you're looking for +- Need to understand implementation details +- ast-grep pattern already targets what you need + +## Anti-Patterns + +**DON'T use grep/rg/Grep tool for:** +- Extracting function/method lists +- Getting API overviews +- Finding all exports/public members +- Getting signatures/interfaces + +These are STRUCTURE queries, not SEARCH queries. + +## Exploration Strategy + +**Tiered approach (try in order):** + +1. **ast-grep with known patterns** - Fast, targeted + - Extract exports, functions, classes with specific patterns + - See [code structure guide](./reference/code-structure-guide.md) for patterns + +2. **Toolchain-specific approaches** - When available + - **Go:** `go doc -all ` for all methods/functions with signatures + - Example: "list all methods" → `go doc -all ./internal/pkg` + - Example: "method signatures" → `go doc -all ./internal/pkg` + - **Python:** Language-specific indexers + - **ctags/universal-ctags:** Symbol index across languages + - See [code structure guide](./reference/code-structure-guide.md) for examples + +3. **Read file** - Last resort for exploration + - Sometimes necessary to understand structure + +## Key Principle + +**Use structure tools to decide what to read, then read selectively.** + +Don't read 1000-line files blind. Get an outline first, then read the 50 lines you actually need. + +## Detailed Patterns + +For language-specific extraction patterns, ast-grep examples, ctags usage, and integration strategies, load [code structure guide](./reference/code-structure-guide.md). diff --git a/skills/code-structure/reference/code-structure-guide.md b/skills/code-structure/reference/code-structure-guide.md new file mode 100644 index 0000000..db288a0 --- /dev/null +++ b/skills/code-structure/reference/code-structure-guide.md @@ -0,0 +1,400 @@ +# Code Structure Exploration + +**Goal: Get outline/index of large files without reading entire file.** + +## Strategy: Tiered Approach + +Try tools in this order (stop when you get what you need): +1. **ast-grep** - Targeted pattern extraction (fastest when pattern known) +2. **Language-specific tools** - Best quality, language-aware +3. **ctags** - Universal fallback, simple +4. **Read file** - Last resort (but now you know it's worth it) + +--- + +# Method 1: ast-grep (Targeted Extraction) + +**Best when:** You know what patterns to look for + +## JavaScript/TypeScript + +### List all exported functions +```bash +ast-grep -l typescript -p 'export function $NAME($$$)' file.ts +``` + +### List all class definitions +```bash +ast-grep -l typescript -p 'export class $NAME { $$$ }' file.ts +``` + +### List all interface definitions +```bash +ast-grep -l typescript -p 'interface $NAME { $$$ }' file.ts +``` + +### List all type definitions +```bash +ast-grep -l typescript -p 'type $NAME = $$$' file.ts +``` + +### Find all imports +```bash +ast-grep -l typescript -p 'import $WHAT from $WHERE' file.ts +``` + +### Combine patterns for full outline +```bash +# Get exports, classes, interfaces, types in one go +ast-grep -l typescript -p 'export function $NAME($$$)' file.ts +ast-grep -l typescript -p 'export class $NAME' file.ts +ast-grep -l typescript -p 'interface $NAME' file.ts +ast-grep -l typescript -p 'type $NAME' file.ts +``` + +## Python + +### List all function definitions +```bash +ast-grep -l python -p 'def $NAME($$$):' file.py +``` + +### List all class definitions +```bash +ast-grep -l python -p 'class $NAME:' file.py +ast-grep -l python -p 'class $NAME($$$):' file.py # With inheritance +``` + +### List all imports +```bash +ast-grep -l python -p 'import $NAME' file.py +ast-grep -l python -p 'from $MODULE import $$$' file.py +``` + +## Go + +### List all function definitions +```bash +ast-grep -l go -p 'func $NAME($$$) $$$ { $$$ }' file.go +``` + +### List all type definitions +```bash +ast-grep -l go -p 'type $NAME struct { $$$ }' file.go +ast-grep -l go -p 'type $NAME interface { $$$ }' file.go +``` + +### List all exported functions (capitalized) +```bash +ast-grep -l go -p 'func $NAME($$$)' file.go | rg -e '^[A-Z]' +``` + +## Rust + +### List all function definitions +```bash +ast-grep -l rust -p 'fn $NAME($$$) { $$$ }' file.rs +ast-grep -l rust -p 'pub fn $NAME($$$) { $$$ }' file.rs # Public only +``` + +### List all struct definitions +```bash +ast-grep -l rust -p 'struct $NAME { $$$ }' file.rs +``` + +### List all trait definitions +```bash +ast-grep -l rust -p 'trait $NAME { $$$ }' file.rs +``` + +--- + +# Method 2: Language-Specific Tools + +**Best when:** Available and well-supported for the language + +## Go: go doc + +### List package contents +```bash +go doc ./path/to/package +``` + +### List specific file symbols +```bash +go doc -all ./path/to/package | rg -e '^func|^type' +``` + +This is ideal for Go - uses actual compiler, understands exports, very reliable. + +## Python: Language-specific options + +### Using Python's inspect module (if interactive) +```bash +python3 -c "import ast; import sys; tree = ast.parse(open('file.py').read()); print([node.name for node in ast.walk(tree) if isinstance(node, (ast.FunctionDef, ast.ClassDef))])" +``` + +More complex but accurate. + +## JavaScript/TypeScript: Language Server (if available) + +Some projects have LSP tooling that can extract symbols. Variable availability. + +--- + +# Method 3: ctags/universal-ctags (Universal Fallback) + +**Best when:** Need quick universal solution across languages + +## Basic Usage + +### Generate tags for single file +```bash +ctags -f - file.js +``` +Output format: `symbolfilelinetype` + +### Common output (shows functions, classes, etc.) +```bash +ctags -f - file.ts | grep -v '^!' | cut -f1,4 +``` +Shows symbol names and types. + +### Filter by type +```bash +# Functions only +ctags -f - file.py --kinds-Python=f + +# Classes only +ctags -f - file.py --kinds-Python=c + +# Functions and classes +ctags -f - file.py --kinds-Python=fc +``` + +### Language-specific kinds + +Common types: +- `f` - functions +- `c` - classes +- `m` - methods +- `v` - variables +- `i` - interfaces (TypeScript) +- `t` - types (TypeScript/Go) + +### Pretty output +```bash +ctags -f - --fields=+n file.ts | grep -v '^!' | awk '{print $4 " " $1 " (line " $3 ")"}' +``` +Shows: type, name, line number + +## Limitations + +- May miss some language-specific constructs +- Doesn't understand semantic context +- But works across many languages with simple interface + +--- + +# Integration Strategy + +## Use Case: Explore Large Unknown File + +**Step 1: Get quick outline** +```bash +# Try ast-grep with common patterns first +ast-grep -l typescript -p 'export function $NAME' file.ts +ast-grep -l typescript -p 'export class $NAME' file.ts + +# Or use ctags for quick overview +ctags -f - file.ts | grep -v '^!' | cut -f1,4 | sort -u +``` + +**Step 2: Decide what to investigate** +Based on names, pick interesting functions/classes. + +**Step 3: Use ast-grep for targeted search** +```bash +# Found "processData" function, now see how it's called +ast-grep -l typescript -p 'processData($$$)' . +``` + +**Step 4: Read selectively** +Now read just the relevant sections, not the entire file. + +## Use Case: "What does this file export?" + +```bash +# JavaScript/TypeScript +ast-grep -l typescript -p 'export $WHAT' file.ts + +# Python +ast-grep -l python -p 'def $NAME($$$):' file.py | rg -e '^[^_]' # Non-private + +# Go (exported = capitalized) +go doc ./path/to/package +``` + +## Use Case: "What classes/interfaces are available?" + +```bash +# TypeScript +ast-grep -l typescript -p 'interface $NAME { $$$ }' file.ts +ast-grep -l typescript -p 'class $NAME { $$$ }' file.ts + +# Python +ast-grep -l python -p 'class $NAME' file.py + +# Go +ast-grep -l go -p 'type $NAME struct { $$$ }' file.go +``` + +--- + +# Decision Flow + +``` +Need to understand large file? +│ +├─ Know what patterns to look for? (exports, classes, etc.) +│ → Use ast-grep with specific patterns +│ → Fast, targeted, precise +│ +├─ Go language file? +│ → Use `go doc` for package/file +│ → Best quality, compiler-aware +│ +├─ Need universal quick outline? +│ → Use ctags +│ → Simple, works across languages +│ +├─ Need detailed understanding? +│ → Read file (selectively based on outline) +│ → Use outline to guide what sections to read +│ +└─ Exploring multiple files? + → Combine: get outline of each, identify relevant ones, read those +``` + +--- + +# Best Practices + +## 1. Start with Cheapest Tool +```bash +# Fast: ast-grep with known pattern +ast-grep -l typescript -p 'export function $NAME' file.ts + +# Medium: ctags for overview +ctags -f - file.ts | cut -f1 + +# Expensive: Read entire file +# Only after outline shows it's relevant +``` + +## 2. Combine with grep for Filtering +```bash +# Get all functions, filter to exported (capitalized in Go) +ast-grep -l go -p 'func $NAME($$$)' file.go | rg -e '^func [A-Z]' + +# Get ctags output, filter to public methods +ctags -f - file.py | rg -e '\tm\t' | rg -e '^[^_]' +``` + +## 3. Use Outline to Guide Detailed Reading +Don't read blindly. Get outline, identify relevant sections, then read those. + +## 4. Cache Results for Large Explorations +If exploring many files: +```bash +# Generate tags for entire directory +ctags -R -f .tags . + +# Query as needed +grep 'functionName' .tags +``` + +## 5. Verify with Read When Needed +Outlines give structure but not implementation. When you need details, read the specific section. + +--- + +# Common Workflows + +## "What's in this 2000-line file?" +```bash +# Quick outline +ast-grep -l typescript -p 'export function $NAME' large-file.ts +ast-grep -l typescript -p 'export class $NAME' large-file.ts + +# Or ctags +ctags -f - large-file.ts | grep -v '^!' | cut -f1,4 | sort +``` + +## "Find all API endpoints in this file" +```bash +# Express.js +ast-grep -l javascript -p 'router.$METHOD($$$)' routes.js + +# Or search for specific pattern +ast-grep -l javascript -p 'app.get($$$)' app.js +``` + +## "What classes are in this Python module?" +```bash +ast-grep -l python -p 'class $NAME:' module.py +``` + +## "What does this Go package export?" +```bash +go doc ./path/to/package +``` + +--- + +# Limitations and Fallbacks + +## When Tools Fail + +**ast-grep**: Requires knowing patterns +- Fallback: Try ctags or Read + +**ctags**: May miss complex constructs +- Fallback: Use ast-grep with specific patterns or Read + +**Language tools**: May not be available +- Fallback: Try ctags or ast-grep + +## When to Just Read + +Sometimes reading is the right answer: +- File is <500 lines +- Outline doesn't give enough context +- Need to understand implementation +- Tools don't support the language/construct + +**The outline told you it's worth reading** - that's still a win. + +--- + +# Summary + +**Primary strategy: ast-grep for targeted extraction** +```bash +ast-grep -l LANG -p 'export function $NAME' file +``` + +**Universal fallback: ctags** +```bash +ctags -f - file | grep -v '^!' | cut -f1,4 +``` + +**Go-specific: go doc** +```bash +go doc ./path/to/package +``` + +**Key principle:** +**Get outline → Decide what's relevant → Read selectively** + +**Don't read 1000-line files blind. Use structure tools to guide your reading.** diff --git a/skills/jq/SKILL.md b/skills/jq/SKILL.md new file mode 100644 index 0000000..5b81ac4 --- /dev/null +++ b/skills/jq/SKILL.md @@ -0,0 +1,57 @@ +--- +name: jq +description: Extract specific fields from JSON files efficiently using jq instead of reading entire files, saving 80-95% context. +--- + +# jq: JSON Data Extraction Tool + +Use jq to extract specific fields from JSON files without loading entire file contents into context. + +## When to Use jq vs Read + +**Use jq when:** +- Need specific field(s) from structured data file +- File is large (>50 lines) and only need subset +- Querying nested structures +- Filtering/transforming data +- **Saves 80-95% context** vs reading entire file + +**Just use Read when:** +- File is small (<50 lines) +- Need to understand overall structure +- Making edits (need full context anyway) + +## Common File Types + +JSON files where jq excels: +- package.json, tsconfig.json +- Lock files (package-lock.json, yarn.lock in JSON format) +- API responses +- Configuration files + +## Quick Examples + +```bash +# Get version from package.json +jq -r .version package.json + +# Get nested dependency version +jq -r '.dependencies.react' package.json + +# List all dependencies +jq -r '.dependencies | keys[]' package.json +``` + +## Core Principle + +Extract exactly what is needed in one command - massive context savings compared to reading entire files. + +## Detailed Reference + +For comprehensive jq patterns, syntax, and examples, load [jq guide](./reference/jq-guide.md): +- Core patterns (80% of use cases) +- Real-world workflows +- Advanced patterns +- Pipe composition +- Error handling +- Integration with other tools diff --git a/skills/jq/reference/jq-guide.md b/skills/jq/reference/jq-guide.md new file mode 100644 index 0000000..3fc6920 --- /dev/null +++ b/skills/jq/reference/jq-guide.md @@ -0,0 +1,361 @@ +# jq: JSON Query and Extraction Reference + +**Goal: Extract specific data from JSON without reading entire file.** + +## The Essential Pattern + +```bash +jq '.field' file.json +``` + +Use `-r` flag for raw output (removes quotes from strings): +```bash +jq -r '.field' file.json +``` + +**Use `-r` by default for string values** - cleaner output. + +--- + +# Core Patterns (80% of Use Cases) + +## 1. Extract Top-Level Field +```bash +jq -r '.version' package.json +jq -r '.name' package.json +``` + +## 2. Extract Nested Field +```bash +jq -r '.dependencies.react' package.json +jq -r '.scripts.build' package.json +jq -r '.config.database.host' config.json +``` + +## 3. Extract Multiple Fields +```bash +jq '{name, version, description}' package.json +``` +Creates object with just those fields. + +Or as separate lines: +```bash +jq -r '.name, .version' package.json +``` + +## 4. Extract from Array by Index +```bash +jq '.[0]' array.json # First element +jq '.items[2]' data.json # Third element +``` + +## 5. Extract All Array Elements +```bash +jq '.[]' array.json # All elements +jq '.items[]' data.json # All items +``` + +## 6. Extract Field from Each Array Element +```bash +jq -r '.dependencies | keys[]' package.json # All dependency names +jq -r '.items[].name' data.json # Name from each item +``` + +## 7. Filter Array by Condition +```bash +jq '.items[] | select(.active == true)' data.json +jq '.items[] | select(.price > 100)' data.json +``` + +## 8. Get Object Keys +```bash +jq -r 'keys[]' object.json +jq -r '.dependencies | keys[]' package.json +``` + +## 9. Check if Field Exists +```bash +jq 'has("field")' file.json +``` + +## 10. Handle Missing Fields (Use // for Default) +```bash +jq -r '.field // "default"' file.json +``` + +--- + +# Common Real-World Workflows + +## "What version is this package?" +```bash +jq -r '.version' package.json +``` + +## "What's the main entry point?" +```bash +jq -r '.main' package.json +``` + +## "List all dependencies" +```bash +jq -r '.dependencies | keys[]' package.json +``` + +## "What version of React?" +```bash +jq -r '.dependencies.react' package.json +``` + +## "List all scripts" +```bash +jq -r '.scripts | keys[]' package.json +``` + +## "Get specific script command" +```bash +jq -r '.scripts.build' package.json +``` + +## "Check TypeScript compiler options" +```bash +jq '.compilerOptions' tsconfig.json +``` + +## "Get target from tsconfig" +```bash +jq -r '.compilerOptions.target' tsconfig.json +``` + +## "List all services from docker-compose JSON" +```bash +jq -r '.services | keys[]' docker-compose.json +``` + +## "Get environment variables for a service" +```bash +jq '.services.api.environment' docker-compose.json +``` + +--- + +# Advanced Patterns (20% Use Cases) + +## Combine Multiple Queries +```bash +jq '{version, deps: (.dependencies | keys)}' package.json +``` + +## Map Array Elements +```bash +jq '[.items[] | .name]' data.json # Array of names +``` + +## Count Array Length +```bash +jq '.items | length' data.json +jq '.dependencies | length' package.json +``` + +## Sort Array +```bash +jq '.items | sort_by(.name)' data.json +``` + +## Group and Transform +```bash +jq 'group_by(.category)' data.json +``` + +## Complex Filter +```bash +jq '.items[] | select(.active and .price > 100) | .name' data.json +``` + +--- + +# Pipe Composition + +jq uses `|` for piping within queries: +```bash +jq '.items | map(.name) | sort' data.json +``` + +Can also pipe to shell commands: +```bash +jq -r '.dependencies | keys[]' package.json | wc -l # Count dependencies +jq -r '.dependencies | keys[]' package.json | sort # Sorted dependency list +``` + +--- + +# Common Flags + +- `-r` - Raw output (no quotes) - **USE THIS FOR STRINGS** +- `-c` - Compact output (single line) +- `-e` - Exit with error if output is false/null +- `-S` - Sort object keys +- `-M` - Monochrome (no colors) + +**Default to `-r` for string extraction.** + +--- + +# Handling Edge Cases + +## If Field Might Not Exist +```bash +jq -r '.field // "not found"' file.json +``` + +## If Result Might Be Null +```bash +jq -r '.field // empty' file.json # Output nothing if null +``` + +## If Array Might Be Empty +```bash +jq -r '.items[]? // empty' file.json # ? suppresses errors +``` + +## Multiple Possible Paths +```bash +jq -r '.field1 // .field2 // "default"' file.json +``` + +--- + +# Error Handling + +If field doesn't exist: +```bash +# BAD: jq '.nonexistent' file.json +# → null (but no error) + +# GOOD: Check existence first +jq -e 'has("field")' file.json && jq '.field' file.json +``` + +Or use default: +```bash +jq -r '.field // "not found"' file.json +``` + +--- + +# Integration with Other Tools + +## With ast-grep +```bash +# Get dependencies, then search code for usage +jq -r '.dependencies | keys[]' package.json | while read dep; do + rg -l "from ['\"]$dep['\"]" +done +``` + +## With Edit Tool +Common workflow: +1. Use jq to extract current value +2. Modify value +3. Use Edit tool to update JSON (or jq for complex updates) + +## Reading STDIN +```bash +echo '{"key":"value"}' | jq -r '.key' +``` + +--- + +# Best Practices + +## 1. Always Use -r for String Fields +```bash +# BAD: jq '.version' package.json → "1.0.0" (with quotes) +# GOOD: jq -r '.version' package.json → 1.0.0 (raw) +``` + +## 2. Test Queries on Small Examples First +```bash +echo '{"test":"value"}' | jq -r '.test' +``` + +## 3. Use // for Defaults +```bash +jq -r '.field // "default"' file.json +``` + +## 4. Use keys[] for Object Properties +```bash +jq -r 'keys[]' object.json +``` + +## 5. Combine with Shell Pipes +```bash +jq -r '.dependencies | keys[]' package.json | grep react +``` + +--- + +# Quick Reference + +## Most Common Commands + +```bash +# Single field +jq -r '.field' file.json + +# Nested field +jq -r '.parent.child' file.json + +# Array element +jq '.array[0]' file.json + +# All array elements +jq '.array[]' file.json + +# Object keys +jq -r 'keys[]' file.json + +# Filter array +jq '.array[] | select(.field == "value")' file.json + +# Multiple fields +jq '{field1, field2}' file.json + +# With default +jq -r '.field // "default"' file.json +``` + +--- + +# When to Use Read Instead + +Use Read tool when: +- File is < 50 lines +- Need to see overall structure +- Making edits (need full context) +- Exploring unknown JSON structure + +Use jq when: +- File is large +- Know exactly what field(s) are needed +- Want to save context tokens + +--- + +# Summary + +**Default pattern:** +```bash +jq -r '.field' file.json +``` + +**Key principles:** +1. Use `-r` for string output (raw, no quotes) +2. Use `.` notation for nested fields +3. Use `[]` for array access +4. Use `//` for defaults +5. Use `keys[]` for object properties +6. Pipe with `|` inside jq, pipe to shell after + +**Massive context savings: Extract only what is needed instead of reading entire JSON files.** diff --git a/skills/ripgrep/SKILL.md b/skills/ripgrep/SKILL.md new file mode 100644 index 0000000..81b919f --- /dev/null +++ b/skills/ripgrep/SKILL.md @@ -0,0 +1,45 @@ +--- +name: ripgrep +description: Efficient text search using ripgrep (rg) with one-shot patterns that minimize iterations by getting files, line numbers, and context in a single call +--- + +# ripgrep: Powerful, one-shot text search + +## Default Strategy + +**For content search: use Bash(rg) with `-e 'pattern' -n -C 2` for one-shot results.** + +This gives files, line numbers, and context in a single call - minimizes iterations and context usage. + +Always prefer getting line numbers and surrounding context over multiple search attempts. + +## Tool Selection + +**Grep tool** (built on ripgrep) - Use for structured searches: +- Basic pattern matching with structured output +- File type filtering with `type` parameter +- When special flags like `-F`, `-v`, `-w`, or pipe composition are not needed +- Handles 95% of search needs + +**Bash(rg)** - Use for one-shot searches needing special flags or composition: +- Fixed string search (`-F`) +- Invert match (`-v`) +- Word boundaries (`-w`) +- Context lines with patterns (`-n -C 2`) +- Pipe composition (`| head`, `| wc -l`, `| sort`) +- Default choice for efficient one-shot results + +**Glob tool** - Use for file name/path matching only (not content search) + +## When to Load Detailed Reference + +Load [ripgrep guide](./reference/ripgrep-guide.md) when needing: +- One-shot search pattern templates +- Effective flag combinations for complex searches +- Pipe composition patterns +- File type filters reference (`-t` flags) +- Pattern syntax examples +- Translation between Grep tool and rg commands +- Performance optimization for large result sets + +The guide focuses on practical patterns for getting targeted results in minimal calls. diff --git a/skills/ripgrep/reference/ripgrep-guide.md b/skills/ripgrep/reference/ripgrep-guide.md new file mode 100644 index 0000000..24ba737 --- /dev/null +++ b/skills/ripgrep/reference/ripgrep-guide.md @@ -0,0 +1,326 @@ +# ripgrep Search Patterns Reference + +Practical search patterns for efficient one-shot searches with ripgrep. + +# One-Shot Search Strategy + +**Goal: Get files + line numbers + context in ONE call.** + +## The Primary Pattern + +```bash +rg -n -C 2 -t TYPE -e 'pattern' +``` + +**What this gives:** +- `-n` - Line numbers +- `-C 2` - 2 lines context before/after +- `-t TYPE` - File type filter +- `-e 'pattern'` - The search pattern + +**Use this as the default.** Adjust only when needed. + +--- + +# Essential Flag Combinations + +## 1. Standard Search with Context +```bash +rg -n -C 2 -t js -e 'functionName' +``` +Most common pattern - gives everything needed. + +## 2. Fixed String (Literal) Search +```bash +rg -F -n -C 2 -t js -e 'exact.string.with.dots' +``` +Use `-F` when pattern has regex special chars (`.` `*` `(` `)` etc.) +**Avoids regex escaping hell.** + +## 3. Word Boundary (Precise) Search +```bash +rg -w -n -C 2 -t js -e 'variable' +``` +`-w` matches whole words only. Finds "variable" but not "variableName". + +## 4. Case-Insensitive Search +```bash +rg -i -n -C 2 -t js -e 'pattern' +``` +`-i` for case-insensitive matching. + +## 5. List Files Only (Quick Overview) +```bash +rg -l -t js -e 'pattern' | head -20 +``` +`-l` lists filenames only. Pipe to `head` to limit. + +## 6. Count Matches +```bash +rg -c -t js -e 'pattern' +``` +`-c` shows count per file. + +## 7. Invert Match (Find Files WITHOUT Pattern) +```bash +rg -l -t js -e 'import React' | rg -v -F -e 'import { useState }' +``` +First find files with React, then filter out files with useState. + +Or simpler: +```bash +rg -L -t js -e 'pattern' +``` +`-L` lists files that do NOT match. + +## 8. Multiple Patterns (OR Logic) +```bash +rg -n -C 2 -t js -e 'pattern1' -e 'pattern2' +``` +Matches either pattern. + +## 9. Specific Directory +```bash +rg -n -C 2 -t js -e 'pattern' src/components +``` +Add directory path at end to narrow scope. + +--- + +# Pipe Composition Patterns + +## Limit Results +```bash +rg -n -t js -e 'pattern' | head -30 +``` +Get first 30 result lines. + +## Count Total Matches +```bash +rg -n -t js -e 'pattern' | wc -l +``` + +## Sort and Deduplicate +```bash +rg -o -t js -e 'import.*from.*' | sort | uniq +``` +`-o` shows only matching part. Useful for extracting patterns. + +## Filter Results Further +```bash +rg -n -t js -e 'function' | rg -e 'export' +``` +Find functions, then filter to only exported ones. + +--- + +# File Type Filters (-t) + +**Common types:** +- `-t js` - JavaScript (.js, .jsx, .mjs, .cjs, .vue) +- `-t ts` - TypeScript (.ts, .tsx, .cts, .mts) +- `-t py` - Python (.py, .pyi) +- `-t go` - Go (.go) +- `-t rust` - Rust (.rs) +- `-t java` - Java (.java, .jsp, .properties) +- `-t ruby` - Ruby (.rb, .gemspec, Gemfile, Rakefile) +- `-t c` - C (.c, .h) +- `-t cpp` - C++ (.cpp, .hpp, .cc, .hh) +- `-t sh` - Shell (.sh, .bash, .zsh, .bashrc) +- `-t html` - HTML (.html, .htm, .ejs) +- `-t css` - CSS (.css, .scss) +- `-t md` - Markdown (.md, .markdown, .mdx) +- `-t json` - JSON (.json) +- `-t yaml` - YAML (.yaml, .yml) + +**Multiple types:** +```bash +rg -t js -t ts -e 'pattern' +``` + +**Glob patterns (more flexible):** +```bash +rg -g '*.test.js' -e 'pattern' # Test files only +rg -g '!*.test.js' -e 'pattern' # Exclude test files +rg -g 'src/**/*.js' -e 'pattern' # Specific directory pattern +``` + +--- + +# Pattern Syntax Quick Reference + +## Literal Search (Use -F) +```bash +rg -F -e 'exact.string' +``` +When pattern has special chars, use `-F` instead of escaping. + +## Regex Patterns +```bash +rg -e 'function\s+\w+' # Function declarations +rg -e 'import.*from\s+["\']' # Import statements +rg -e 'class\s+\w+.*\{' # Class definitions +rg -e '^\s*#' # Lines starting with # +rg -e 'TODO:|FIXME:|XXX:' # Multiple comment markers +``` + +## Common Regex Elements +- `\s` - whitespace +- `\w` - word character +- `\d` - digit +- `.` - any character +- `.*` - zero or more any character +- `\b` - word boundary (or use `-w` flag) +- `^` - start of line +- `$` - end of line +- `[abc]` - character class +- `(foo|bar)` - alternation + +--- + +# Decision Flow + +``` +Need to search code? +│ +├─ Simple pattern, no special needs? +│ → Use Grep tool (structured output) +│ +├─ Need one-shot with context? +│ → rg -n -C 2 -t TYPE -e 'pattern' +│ +├─ Pattern has dots, parens, special chars? +│ → rg -F -n -C 2 -t TYPE -e 'exact.string' +│ +├─ Need precise word matching? +│ → rg -w -n -C 2 -t TYPE -e 'word' +│ +├─ Need to find files WITHOUT something? +│ → rg -L -t TYPE -e 'pattern' +│ +└─ Need to compose with other commands? + → rg -n -t TYPE -e 'pattern' | head/wc/sort/etc +``` + +--- + +# Common Workflows + +## "Find all uses of this function" +```bash +rg -n -C 2 -t js -e 'functionName\(' +``` +Use `\(` to find actual calls (not definitions). + +## "Which files import this package?" +```bash +rg -l -t js -e 'from ["\']package-name["\']' +``` + +## "How is this class used?" +```bash +rg -n -C 3 -t py -e 'ClassName' +``` +More context (C 3) to see usage patterns. + +## "Find TODOs in specific directory" +```bash +rg -n -e 'TODO:' src/ +``` + +## "Find files that import X but not Y" +```bash +rg -l -t js -e 'import.*from.*package-x' | rg -v -F -e 'package-y' +``` + +## "Count occurrences across codebase" +```bash +rg -c -t js -e 'pattern' | rg -e ':' | wc -l +``` +Count files with matches. + +--- + +# Best Practices + +## 1. Start with Standard Pattern +```bash +rg -n -C 2 -t TYPE -e 'pattern' +``` +Adjust only if needed. + +## 2. Use -F for Literal Strings +Don't escape regex chars - use `-F`: +```bash +# BAD: rg -e 'function\(\)' +# GOOD: rg -F -e 'function()' +``` + +## 3. Always Use Single Quotes +```bash +# GOOD: rg -e 'pattern' +# BAD: rg -e "pattern" # Shell may interpret special chars +``` + +## 4. Use Type Filters +```bash +# GOOD: rg -t js -e 'pattern' +# LESS GOOD: rg -e 'pattern' # Searches everything +``` + +## 5. Limit Large Results +```bash +rg -n -t js -e 'common_word' | head -50 +``` + +## 6. Use -w for Precision +```bash +# Finds "test" in "testing", "latest", etc: +rg -e 'test' + +# Finds only "test" as whole word: +rg -w -e 'test' +``` + +--- + +# When to Use Grep Tool Instead + +Use Grep tool when: +- Simple pattern with no special flags needed +- Want structured output modes (files/content/count) +- Don't need to pipe results +- Pattern doesn't need -F, -v, or -w + +Use Bash(rg) when: +- Need one-shot results with context +- Need -F (literal), -v (invert), -w (word boundary) +- Want to pipe/compose with other commands +- Need maximum control and efficiency + +**Default to Bash(rg) for most searches** - it's more efficient for one-shot results. + +--- + +# Summary + +**Default search command:** +```bash +rg -n -C 2 -t TYPE -e 'pattern' +``` + +**Key flags to remember:** +- `-F` - Literal search (avoid escaping) +- `-w` - Word boundaries (precise) +- `-v` - Invert match (find files WITHOUT) +- `-l` - List files only +- `-L` - List files that DON'T match + +**Compose with pipes:** +```bash +rg ... | head -N # Limit results +rg ... | wc -l # Count +rg ... | rg ... # Filter further +``` + +This reference provides practical patterns for efficient one-shot searches. diff --git a/skills/yq/SKILL.md b/skills/yq/SKILL.md new file mode 100644 index 0000000..94952e3 --- /dev/null +++ b/skills/yq/SKILL.md @@ -0,0 +1,51 @@ +--- +name: yq +description: Extract specific fields from YAML files efficiently using qq instead of reading entire files, saving 80-95% context. +--- + +# yq: YAML Query and Extraction Tool + +Use yq to extract specific fields from YAML files without reading entire file contents, saving 80-95% context usage. + +## When to Use yq + +**Use yq when:** +- Need specific field(s) from structured YAML file +- File is large (>50 lines) and only need subset of data +- Querying nested structures in YAML +- Filtering/transforming YAML data +- Working with docker-compose.yml, GitHub Actions workflows, K8s configs + +**Just use Read when:** +- File is small (<50 lines) +- Need to understand overall structure +- Making edits (need full context anyway) + +## Tool Selection + +**JSON files** → Use `jq` +- Common: package.json, tsconfig.json, lock files, API responses + +**YAML files** → Use `yq` +- Common: docker-compose.yml, GitHub Actions, CI/CD configs + +Both tools extract exactly what you need in one command - massive context savings. + +## Quick Examples + +```bash +# Get version from package.json +jq -r .version package.json + +# Get service ports from docker-compose +yq '.services.*.ports' docker-compose.yml +``` + +## Detailed Reference + +For comprehensive yq patterns, syntax, and examples, load [yq guide](./reference/yq-guide.md): +- Core patterns (80% of use cases) +- Real-world workflows (Docker Compose, GitHub Actions, Kubernetes) +- Advanced patterns and edge case handling +- Output formats and pipe composition +- Best practices and integration with other tools diff --git a/skills/yq/reference/yq-guide.md b/skills/yq/reference/yq-guide.md new file mode 100644 index 0000000..0d7056c --- /dev/null +++ b/skills/yq/reference/yq-guide.md @@ -0,0 +1,432 @@ +# yq: YAML Query and Extraction + +**Goal: Extract specific data from YAML without reading entire file.** + +**Note:** This guide assumes `mikefarah/yq` (the most common version). Syntax is similar to jq. + +## The Essential Pattern + +```bash +yq '.field' file.yml +``` + +yq defaults to YAML output. Use `-r` for raw output or `-o json` for JSON: +```bash +yq -r '.field' file.yml # Raw string output +yq -o json file.yml # Convert to JSON +``` + +--- + +# Core Patterns (80% of Use Cases) + +## 1. Extract Top-Level Field +```bash +yq '.version' config.yml +yq '.name' config.yml +``` + +## 2. Extract Nested Field +```bash +yq '.services.web.image' docker-compose.yml +yq '.jobs.build.steps' .github/workflows/ci.yml +``` + +## 3. Extract from Array by Index +```bash +yq '.items[0]' file.yml # First element +yq '.jobs.build.steps[2]' ci.yml # Third step +``` + +## 4. Extract All Array Elements +```bash +yq '.items[]' file.yml # All elements +yq '.services.*.ports' docker-compose.yml # All ports from all services +``` + +## 5. Extract Field from Each Array Element +```bash +yq '.services.*.image' docker-compose.yml # All service images +yq '.jobs.*.runs-on' .github/workflows/ci.yml # All job runners +``` + +## 6. Get Object Keys +```bash +yq 'keys' object.yml +yq '.services | keys' docker-compose.yml +``` + +## 7. Filter Array by Condition +```bash +yq '.items[] | select(.active == true)' file.yml +yq '.services.* | select(.ports)' docker-compose.yml +``` + +## 8. Extract Specific Array Elements +```bash +yq '.services.web' docker-compose.yml +yq '.jobs.build' .github/workflows/ci.yml +``` + +## 9. Handle Missing Fields +```bash +yq '.field // "default"' file.yml +``` + +## 10. Convert YAML to JSON +```bash +yq -o json file.yml +``` + +--- + +# Common Real-World Workflows + +## Docker Compose + +### "List all services" +```bash +yq '.services | keys' docker-compose.yml +``` + +### "Get image for service" +```bash +yq '.services.web.image' docker-compose.yml +``` + +### "Get all ports" +```bash +yq '.services.*.ports' docker-compose.yml +``` + +### "Get environment variables for service" +```bash +yq '.services.api.environment' docker-compose.yml +``` + +### "Get depends_on for service" +```bash +yq '.services.web.depends_on' docker-compose.yml +``` + +## GitHub Actions + +### "List all jobs" +```bash +yq '.jobs | keys' .github/workflows/ci.yml +``` + +### "Get build steps" +```bash +yq '.jobs.build.steps' .github/workflows/ci.yml +``` + +### "Get trigger events" +```bash +yq '.on' .github/workflows/ci.yml +``` + +### "Get runner for job" +```bash +yq '.jobs.build.runs-on' .github/workflows/ci.yml +``` + +## Kubernetes + +### "Get container image" +```bash +yq '.spec.template.spec.containers[0].image' deployment.yml +``` + +### "Get replicas" +```bash +yq '.spec.replicas' deployment.yml +``` + +### "List all container names" +```bash +yq '.spec.template.spec.containers[].name' deployment.yml +``` + +## Configuration Files + +### "Get database host" +```bash +yq '.database.host' config.yml +``` + +### "Get API key" +```bash +yq '.api.key' config.yml +``` + +--- + +# Advanced Patterns (20% Use Cases) + +## Combine Multiple Queries +```bash +yq '{version: .version, services: (.services | keys)}' docker-compose.yml +``` + +## Count Array Length +```bash +yq '.items | length' file.yml +yq '.services | length' docker-compose.yml +``` + +## Filter and Extract +```bash +yq '.services.* | select(.ports) | .image' docker-compose.yml +``` + +## Map Array +```bash +yq '[.items[].name]' file.yml +``` + +## Multi-Document YAML (Multiple --- separated docs) +```bash +yq 'select(document_index == 0)' multi.yml # First document +yq 'select(document_index == 1)' multi.yml # Second document +``` + +--- + +# Output Formats + +```bash +yq file.yml # YAML output (default) +yq -o json file.yml # JSON output +yq -o yaml file.yml # Explicit YAML output +yq -r '.field' file.yml # Raw output (strings without quotes) +``` + +**For string fields, use `-r` for raw output (like jq).** + +--- + +# Pipe Composition + +yq uses `|` for piping within queries (like jq): +```bash +yq '.services | keys | .[]' docker-compose.yml +``` + +Can also pipe to shell commands: +```bash +yq '.services | keys' docker-compose.yml | wc -l # Count services +yq '.services.*.image' docker-compose.yml | sort | uniq # Unique images +``` + +--- + +# Common Flags + +- `-r` - Raw output (strings without quotes) +- `-o FORMAT` - Output format (yaml, json, props, xml, etc.) +- `-i` - In-place edit (DANGEROUS - use carefully) +- `-P` - Pretty print +- `-I INDENT` - Indentation level + +**Default to `-r` for string extraction, `-o json` for JSON output.** + +--- + +# YAML-Specific Features + +## Anchors and Aliases +YAML supports anchors (&) and aliases (*): +```yaml +default: &default + timeout: 30 + +production: + <<: *default + host: prod.example.com +``` + +yq resolves these automatically: +```bash +yq '.production.timeout' file.yml # Returns 30 (from anchor) +``` + +## Multi-Document YAML +Many YAML files contain multiple documents separated by `---`: +```bash +yq 'select(document_index == 0)' file.yml # First document +yq 'select(document_index == 1)' file.yml # Second document +``` + +--- + +# Handling Edge Cases + +## If Field Might Not Exist +```bash +yq '.field // "not found"' file.yml +``` + +## If Array Might Be Empty +```bash +yq '.items[]? // empty' file.yml +``` + +## Multiple Possible Paths +```bash +yq '.field1 // .field2 // "default"' file.yml +``` + +--- + +# Comparison with jq + +**Similarities:** +- Similar query syntax (`.field`, `.nested.field`, `.array[]`) +- Pipe operator `|` +- Filter with `select()` +- Default values with `//` + +**Differences:** +- yq handles YAML (jq handles JSON) +- yq can output multiple formats (`-o json`, `-o yaml`) +- yq handles YAML features (anchors, multi-doc) +- Slightly different handling of wildcards (`.*` in yq, similar in jq) + +**Converting between formats:** +```bash +yq -o json file.yml | jq '.field' # YAML → JSON → query with jq +jq '.' file.json | yq -P # JSON → pretty YAML +``` + +--- + +# Integration with Other Tools + +## With ast-grep +```bash +# Get dependencies from YAML, search code for usage +yq '.dependencies | keys' config.yml | while read dep; do + rg -l "$dep" +done +``` + +## With jq (via JSON conversion) +```bash +yq -o json file.yml | jq '.complex.query' +``` +If yq syntax doesn't work, convert to JSON and use jq. + +## With Docker Compose +```bash +# Get all service images, then pull them +yq '.services.*.image' docker-compose.yml | xargs -n1 docker pull +``` + +--- + +# Best Practices + +## 1. Use -r for String Fields +```bash +# BAD: yq '.version' file.yml → may include YAML formatting +# GOOD: yq -r '.version' file.yml → raw string +``` + +## 2. Use -o json for Complex Queries +If yq query is complex, convert to JSON and use jq: +```bash +yq -o json file.yml | jq '.complex.query' +``` + +## 3. Test Queries on Small Examples +```bash +echo 'key: value' | yq '.key' +``` + +## 4. Use // for Defaults +```bash +yq -r '.field // "default"' file.yml +``` + +## 5. Be Aware of Multi-Document Files +Check if file has multiple documents (look for `---`). + +--- + +# Quick Reference + +## Most Common Commands + +```bash +# Single field +yq '.field' file.yml + +# Nested field +yq '.parent.child' file.yml + +# Array element +yq '.array[0]' file.yml + +# All array elements +yq '.array[]' file.yml + +# Object keys +yq 'keys' file.yml + +# Filter array +yq '.array[] | select(.field == "value")' file.yml + +# All services (docker-compose) +yq '.services | keys' docker-compose.yml + +# Convert to JSON +yq -o json file.yml + +# Raw string output +yq -r '.field' file.yml +``` + +--- + +# When to Use Read Instead + +Use Read tool when: +- File is < 50 lines +- Need to see overall structure +- Making edits (need full context) +- Exploring unknown YAML structure + +Use yq when: +- File is large (docker-compose, k8s configs often are) +- You know exactly what field(s) you need +- Want to save context tokens + +--- + +# Summary + +**Your default pattern:** +```bash +yq '.field' file.yml +``` + +**For strings:** +```bash +yq -r '.field' file.yml +``` + +**For JSON output:** +```bash +yq -o json file.yml +``` + +**Key principles:** +1. Use `-r` for raw string output +2. Use `.` notation for nested fields +3. Use `[]` for arrays, `[n]` for specific index +4. Use `| keys` for object keys +5. Use `//` for defaults +6. Use `-o json` to convert to JSON if needed + +**Massive context savings: Extract only what you need instead of reading entire YAML files.**