Initial commit
This commit is contained in:
12
.claude-plugin/plugin.json
Normal file
12
.claude-plugin/plugin.json
Normal file
@@ -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"
|
||||
]
|
||||
}
|
||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# context-efficient-tools
|
||||
|
||||
CLI tool skills that minimize context usage through targeted extraction instead of reading entire files
|
||||
81
plugin.lock.json
Normal file
81
plugin.lock.json
Normal file
@@ -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": []
|
||||
}
|
||||
}
|
||||
41
skills/ast-grep/SKILL.md
Normal file
41
skills/ast-grep/SKILL.md
Normal file
@@ -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
|
||||
263
skills/ast-grep/reference/ast-grep-guide.md
Normal file
263
skills/ast-grep/reference/ast-grep-guide.md
Normal file
@@ -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
|
||||
82
skills/code-structure/SKILL.md
Normal file
82
skills/code-structure/SKILL.md
Normal file
@@ -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 <package>` 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).
|
||||
400
skills/code-structure/reference/code-structure-guide.md
Normal file
400
skills/code-structure/reference/code-structure-guide.md
Normal file
@@ -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: `symbol<tab>file<tab>line<tab>type`
|
||||
|
||||
### 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.**
|
||||
57
skills/jq/SKILL.md
Normal file
57
skills/jq/SKILL.md
Normal file
@@ -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
|
||||
361
skills/jq/reference/jq-guide.md
Normal file
361
skills/jq/reference/jq-guide.md
Normal file
@@ -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.**
|
||||
45
skills/ripgrep/SKILL.md
Normal file
45
skills/ripgrep/SKILL.md
Normal file
@@ -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.
|
||||
326
skills/ripgrep/reference/ripgrep-guide.md
Normal file
326
skills/ripgrep/reference/ripgrep-guide.md
Normal file
@@ -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.
|
||||
51
skills/yq/SKILL.md
Normal file
51
skills/yq/SKILL.md
Normal file
@@ -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
|
||||
432
skills/yq/reference/yq-guide.md
Normal file
432
skills/yq/reference/yq-guide.md
Normal file
@@ -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.**
|
||||
Reference in New Issue
Block a user