File Search Skill Efficient CLI search tools for AI agents. Tool Selection Guide | Task | Use | Instead of | |------|-----|------------| | Search text in code files | (ripgrep) | , | | Find files by name/path | | , | | Structural/syntax-aware code search | (ast-grep) | regex hacks | | Apply rule packs (security/lint, taint) | | regex CI checks | | Search PDFs, Office docs, archives | (ripgrep-all) | manual extraction | | Count lines of code by language | | , | | Code stats with complexity metrics | | , | Decision flow: text → | structural → | rule packs → | filenames → | PDFs/archives → | LOC…

or equivalent structural pattern\",\n \"Command is syntactically valid and handles single-line and multi-line decorators\"\n ],\n \"model_notes\": \"Smaller models may attempt rg '@\\\\w+' which finds decorator lines but misses the associated function. The skill's ast-grep-patterns.md shows the correct multi-line pattern with newline between decorator and def.\"\n },\n {\n \"id\": 29,\n \"eval_name\": \"python-bare-except\",\n \"prompt\": \"Find all bare except blocks in this Python codebase — places where 'except:' is used without specifying an exception type. These catch SystemExit and KeyboardInterrupt which is usually a bug.\",\n \"expected_output\": \"Uses sg (ast-grep) with --lang py and a structural pattern for bare except clauses.\",\n \"files\": [],\n \"assertions\": [\n \"Uses sg (ast-grep) with --lang py, not rg — AST matching distinguishes bare 'except:' from 'except SomeError:' structurally\",\n \"Specifies --lang py for Python language targeting\",\n \"Pattern targets bare except blocks: 'try: $$ except: $

File Search Skill Efficient CLI search tools for AI agents. Tool Selection Guide | Task | Use | Instead of | |------|-----|------------| | Search text in code files | (ripgrep) | , | | Find files by name/path | | , | | Structural/syntax-aware code search | (ast-grep) | regex hacks | | Apply rule packs (security/lint, taint) | | regex CI checks | | Search PDFs, Office docs, archives | (ripgrep-all) | manual extraction | | Count lines of code by language | | , | | Code stats with complexity metrics | | , | Decision flow: text → | structural → | rule packs → | filenames → | PDFs/archives → | LOC…

or equivalent without an exception type\",\n \"Does not use regex that would false-positive on 'except Exception:' or 'except ValueError:'\"\n ],\n \"model_notes\": \"Smaller models often suggest rg 'except:' which also matches 'except Exception:' lines. The skill's ast-grep pattern 'try:\\\\n $$\\\\nexcept:\\\\n $

File Search Skill Efficient CLI search tools for AI agents. Tool Selection Guide | Task | Use | Instead of | |------|-----|------------| | Search text in code files | (ripgrep) | , | | Find files by name/path | | , | | Structural/syntax-aware code search | (ast-grep) | regex hacks | | Apply rule packs (security/lint, taint) | | regex CI checks | | Search PDFs, Office docs, archives | (ripgrep-all) | manual extraction | | Count lines of code by language | | , | | Code stats with complexity metrics | | , | Decision flow: text → | structural → | rule packs → | filenames → | PDFs/archives → | LOC…

is structurally precise and avoids false positives.\"\n },\n {\n \"id\": 30,\n \"eval_name\": \"go-unwrapped-errors\",\n \"prompt\": \"Find all places in this Go codebase where errors are returned without wrapping — 'return err' instead of 'return fmt.Errorf(\\\"...: %w\\\", err)'. These lose context about where the error originated.\",\n \"expected_output\": \"Uses sg (ast-grep) with --lang go and a structural pattern for bare error returns without wrapping.\",\n \"files\": [],\n \"assertions\": [\n \"Uses sg (ast-grep) with --lang go, not rg — structural pattern 'if $ERR != nil { return $ERR }' matches the exact unwrapped-error idiom\",\n \"Specifies --lang go for Go language targeting\",\n \"Pattern targets the unwrapped error return pattern: 'if $ERR != nil { return $ERR }' or similar\",\n \"Does not false-positive on properly wrapped errors using fmt.Errorf with %w\"\n ],\n \"model_notes\": \"Smaller models may suggest rg 'return err' which matches variable names like 'return errorCode' and misses multi-return patterns like 'return nil, err'. The sg pattern is structurally precise.\"\n },\n {\n \"id\": 31,\n \"eval_name\": \"multi-tool-php-import-size\",\n \"prompt\": \"Find all PHP files that import the 'GuzzleHttp\\\\Client' class, then check if any of those files are larger than 10KB. Large files using HTTP clients might need refactoring.\",\n \"expected_output\": \"Combines rg to find import statements with fd -S for size filtering, or uses a pipeline approach.\",\n \"files\": [],\n \"assertions\": [\n \"Uses rg to find 'use GuzzleHttp\\\\Client' or equivalent import pattern in PHP files\",\n \"Uses fd with -S or --size flag to check file sizes against the 10KB threshold\",\n \"Combines the tools in a pipeline or sequential approach (e.g., rg -l | xargs fd -S, or fd -S + rg)\",\n \"Targets PHP files specifically with -t php or -e php\"\n ]\n },\n {\n \"id\": 32,\n \"eval_name\": \"multi-tool-tokei-then-search\",\n \"prompt\": \"Get a language breakdown of this project, then search the dominant language for any functions marked as deprecated (via comments or annotations).\",\n \"expected_output\": \"Uses tokei or scc for language stats first, then rg or sg with appropriate language filter for deprecated markers.\",\n \"files\": [],\n \"assertions\": [\n \"Uses tokei or scc as the first step to determine the dominant language\",\n \"Uses rg or sg as the second step to search for deprecated markers (@deprecated, @Deprecated, #[deprecated], etc.)\",\n \"Applies language-specific file type filter (-t or --lang) based on the tokei/scc output\",\n \"Executes as a deliberate two-step workflow rather than guessing the dominant language\"\n ],\n \"model_notes\": \"Smaller models may skip the tokei step and guess the dominant language, or search all languages. The skill teaches the count-first-then-drill-down pattern explicitly.\"\n }\n ]\n}\n","content_type":"application/json; charset=utf-8","language":"json","size":24226,"content_sha256":"c72a4722d7ff6b06a3391b9ff347155e6a291d3cf388ea3e6a903c45f5b3552d"},{"filename":"references/ast-grep-patterns.md","content":"\u003c!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->\n\u003c!-- SPDX-FileCopyrightText: Netresearch DTT GmbH -->\n\n# ast-grep Pattern Recipes\n\nStructural search patterns for `sg` (ast-grep), organized by language.\n\nast-grep matches code by AST structure, not text. This means patterns are\nimmune to whitespace differences, comment variations, and formatting styles.\n\n---\n\n## Metavariable Reference\n\n| Syntax | Description | Example |\n|--------|-------------|---------|\n| `$VAR` | Single AST node (expression, identifier, literal) | `console.log($MSG)` |\n| `$ file-search — Skillopedia | Zero or more AST nodes (variadic) | `function($$)` |\n| `$_` | Zero or more unnamed nodes (wildcard) | `[$$]` |\n| `$_` | Any single node (unnamed wildcard) | `if ($_) { $$ }` |\n\n**Key rules:**\n- Named metavariables (`$VAR`) capture their match and must match consistently\n within a pattern (same `$VAR` = same value).\n- `$ file-search — Skillopedia is greedy and matches any number of arguments, statements, etc.\n- Use `$_` when you do not care about capturing the value.\n\n---\n\n## JavaScript / TypeScript\n\n### React Patterns\n\n```bash\n# useState hooks\nsg --pattern 'const [$STATE, $SETTER] = useState($$)' --lang tsx\n\n# useEffect with dependency array\nsg --pattern 'useEffect(() => { $$ }, [$$])' --lang tsx\n\n# useEffect without dependencies (runs every render)\nsg --pattern 'useEffect(() => { $$ })' --lang tsx\n\n# Component definitions (function)\nsg --pattern 'function $NAME($$) { $$ return $$ }' --lang tsx\n\n# Arrow function components\nsg --pattern 'const $NAME = ($$) => { $$ }' --lang tsx\n\n# JSX with specific prop\nsg --pattern '\u003c$COMP className={$$} />' --lang tsx\nsg --pattern '\u003c$COMP onClick={$$}>$$\u003c/$COMP>' --lang tsx\n\n# Custom hook calls\nsg --pattern 'const $RESULT = use$HOOK($$)' --lang tsx\n```\n\n### Async/Await Patterns\n\n```bash\n# Async function declarations\nsg --pattern 'async function $NAME($$) { $$ }' --lang js\n\n# Await expressions\nsg --pattern 'await $EXPR' --lang js\n\n# Try/catch around await\nsg --pattern 'try { $$ await $EXPR $$ } catch ($ERR) { $$ }' --lang ts\n\n# Promise.all usage\nsg --pattern 'await Promise.all([$$])' --lang ts\n\n# Unhandled promise (missing await)\nsg --pattern '$VAR.$METHOD($$).then($$)' --lang ts\n```\n\n### Error Handling\n\n```bash\n# Empty catch blocks\nsg --pattern 'try { $$ } catch ($ERR) { }' --lang js\n\n# Console.log in catch (often should be proper logging)\nsg --pattern 'catch ($ERR) { $$ console.log($$) $$ }' --lang js\n\n# Throw new Error\nsg --pattern 'throw new Error($MSG)' --lang ts\n\n# Throw non-Error objects\nsg --pattern 'throw $MSG' --lang ts\n```\n\n### Module Patterns\n\n```bash\n# Default exports\nsg --pattern 'export default $EXPR' --lang ts\n\n# Named exports\nsg --pattern 'export const $NAME = $VALUE' --lang ts\nsg --pattern 'export function $NAME($$) { $$ }' --lang ts\n\n# Dynamic imports\nsg --pattern 'import($PATH)' --lang ts\nsg --pattern 'await import($PATH)' --lang ts\n```\n\n### Common Anti-Patterns\n\n```bash\n# Direct DOM manipulation in React\nsg --pattern 'document.getElementById($$)' --lang tsx\nsg --pattern 'document.querySelector($$)' --lang tsx\n\n# setState in useEffect without cleanup\nsg --pattern 'useEffect(() => { $$ $SETTER($$) $$ })' --lang tsx\n\n# Object mutation\nsg --pattern '$OBJ.$PROP = $VALUE' --lang ts\n```\n\n---\n\n## Python\n\n### Function and Class Patterns\n\n```bash\n# Function definitions\nsg --pattern 'def $NAME($$):\n $

File Search Skill Efficient CLI search tools for AI agents. Tool Selection Guide | Task | Use | Instead of | |------|-----|------------| | Search text in code files | (ripgrep) | , | | Find files by name/path | | , | | Structural/syntax-aware code search | (ast-grep) | regex hacks | | Apply rule packs (security/lint, taint) | | regex CI checks | | Search PDFs, Office docs, archives | (ripgrep-all) | manual extraction | | Count lines of code by language | | , | | Code stats with complexity metrics | | , | Decision flow: text → | structural → | rule packs → | filenames → | PDFs/archives → | LOC…

--lang py\n\n# Async function definitions\nsg --pattern 'async def $NAME($$):\n $

File Search Skill Efficient CLI search tools for AI agents. Tool Selection Guide | Task | Use | Instead of | |------|-----|------------| | Search text in code files | (ripgrep) | , | | Find files by name/path | | , | | Structural/syntax-aware code search | (ast-grep) | regex hacks | | Apply rule packs (security/lint, taint) | | regex CI checks | | Search PDFs, Office docs, archives | (ripgrep-all) | manual extraction | | Count lines of code by language | | , | | Code stats with complexity metrics | | , | Decision flow: text → | structural → | rule packs → | filenames → | PDFs/archives → | LOC…

--lang py\n\n# Class with inheritance\nsg --pattern 'class $NAME($BASE):\n $

File Search Skill Efficient CLI search tools for AI agents. Tool Selection Guide | Task | Use | Instead of | |------|-----|------------| | Search text in code files | (ripgrep) | , | | Find files by name/path | | , | | Structural/syntax-aware code search | (ast-grep) | regex hacks | | Apply rule packs (security/lint, taint) | | regex CI checks | | Search PDFs, Office docs, archives | (ripgrep-all) | manual extraction | | Count lines of code by language | | , | | Code stats with complexity metrics | | , | Decision flow: text → | structural → | rule packs → | filenames → | PDFs/archives → | LOC…

--lang py\n\n# Static methods\nsg --pattern '@staticmethod\ndef $NAME($$):\n $

File Search Skill Efficient CLI search tools for AI agents. Tool Selection Guide | Task | Use | Instead of | |------|-----|------------| | Search text in code files | (ripgrep) | , | | Find files by name/path | | , | | Structural/syntax-aware code search | (ast-grep) | regex hacks | | Apply rule packs (security/lint, taint) | | regex CI checks | | Search PDFs, Office docs, archives | (ripgrep-all) | manual extraction | | Count lines of code by language | | , | | Code stats with complexity metrics | | , | Decision flow: text → | structural → | rule packs → | filenames → | PDFs/archives → | LOC…

--lang py\n\n# Class methods\nsg --pattern '@classmethod\ndef $NAME(cls, $$):\n $

File Search Skill Efficient CLI search tools for AI agents. Tool Selection Guide | Task | Use | Instead of | |------|-----|------------| | Search text in code files | (ripgrep) | , | | Find files by name/path | | , | | Structural/syntax-aware code search | (ast-grep) | regex hacks | | Apply rule packs (security/lint, taint) | | regex CI checks | | Search PDFs, Office docs, archives | (ripgrep-all) | manual extraction | | Count lines of code by language | | , | | Code stats with complexity metrics | | , | Decision flow: text → | structural → | rule packs → | filenames → | PDFs/archives → | LOC…

--lang py\n\n# Property definitions\nsg --pattern '@property\ndef $NAME(self):\n $

File Search Skill Efficient CLI search tools for AI agents. Tool Selection Guide | Task | Use | Instead of | |------|-----|------------| | Search text in code files | (ripgrep) | , | | Find files by name/path | | , | | Structural/syntax-aware code search | (ast-grep) | regex hacks | | Apply rule packs (security/lint, taint) | | regex CI checks | | Search PDFs, Office docs, archives | (ripgrep-all) | manual extraction | | Count lines of code by language | | , | | Code stats with complexity metrics | | , | Decision flow: text → | structural → | rule packs → | filenames → | PDFs/archives → | LOC…

--lang py\n```\n\n### Decorator Patterns\n\n```bash\n# Any decorated function\nsg --pattern '@$DECORATOR\ndef $NAME($$):\n $

File Search Skill Efficient CLI search tools for AI agents. Tool Selection Guide | Task | Use | Instead of | |------|-----|------------| | Search text in code files | (ripgrep) | , | | Find files by name/path | | , | | Structural/syntax-aware code search | (ast-grep) | regex hacks | | Apply rule packs (security/lint, taint) | | regex CI checks | | Search PDFs, Office docs, archives | (ripgrep-all) | manual extraction | | Count lines of code by language | | , | | Code stats with complexity metrics | | , | Decision flow: text → | structural → | rule packs → | filenames → | PDFs/archives → | LOC…

--lang py\n\n# Specific decorator\nsg --pattern '@app.route($$)\ndef $NAME($$):\n $

File Search Skill Efficient CLI search tools for AI agents. Tool Selection Guide | Task | Use | Instead of | |------|-----|------------| | Search text in code files | (ripgrep) | , | | Find files by name/path | | , | | Structural/syntax-aware code search | (ast-grep) | regex hacks | | Apply rule packs (security/lint, taint) | | regex CI checks | | Search PDFs, Office docs, archives | (ripgrep-all) | manual extraction | | Count lines of code by language | | , | | Code stats with complexity metrics | | , | Decision flow: text → | structural → | rule packs → | filenames → | PDFs/archives → | LOC…

--lang py\n\n# Decorator with arguments\nsg --pattern '@$DECORATOR($$)\ndef $NAME($$):\n $

File Search Skill Efficient CLI search tools for AI agents. Tool Selection Guide | Task | Use | Instead of | |------|-----|------------| | Search text in code files | (ripgrep) | , | | Find files by name/path | | , | | Structural/syntax-aware code search | (ast-grep) | regex hacks | | Apply rule packs (security/lint, taint) | | regex CI checks | | Search PDFs, Office docs, archives | (ripgrep-all) | manual extraction | | Count lines of code by language | | , | | Code stats with complexity metrics | | , | Decision flow: text → | structural → | rule packs → | filenames → | PDFs/archives → | LOC…

--lang py\n\n# Pytest fixtures\nsg --pattern '@pytest.fixture($$)\ndef $NAME($$):\n $

File Search Skill Efficient CLI search tools for AI agents. Tool Selection Guide | Task | Use | Instead of | |------|-----|------------| | Search text in code files | (ripgrep) | , | | Find files by name/path | | , | | Structural/syntax-aware code search | (ast-grep) | regex hacks | | Apply rule packs (security/lint, taint) | | regex CI checks | | Search PDFs, Office docs, archives | (ripgrep-all) | manual extraction | | Count lines of code by language | | , | | Code stats with complexity metrics | | , | Decision flow: text → | structural → | rule packs → | filenames → | PDFs/archives → | LOC…

--lang py\n```\n\n### Error Handling\n\n```bash\n# Bare except (catches everything including SystemExit)\nsg --pattern 'try:\n $$\nexcept:\n $

File Search Skill Efficient CLI search tools for AI agents. Tool Selection Guide | Task | Use | Instead of | |------|-----|------------| | Search text in code files | (ripgrep) | , | | Find files by name/path | | , | | Structural/syntax-aware code search | (ast-grep) | regex hacks | | Apply rule packs (security/lint, taint) | | regex CI checks | | Search PDFs, Office docs, archives | (ripgrep-all) | manual extraction | | Count lines of code by language | | , | | Code stats with complexity metrics | | , | Decision flow: text → | structural → | rule packs → | filenames → | PDFs/archives → | LOC…

--lang py\n\n# Except with pass (silenced errors)\nsg --pattern 'except $EXCEPTION:\n pass' --lang py\n\n# Broad exception catching\nsg --pattern 'except Exception as $ERR:\n $

File Search Skill Efficient CLI search tools for AI agents. Tool Selection Guide | Task | Use | Instead of | |------|-----|------------| | Search text in code files | (ripgrep) | , | | Find files by name/path | | , | | Structural/syntax-aware code search | (ast-grep) | regex hacks | | Apply rule packs (security/lint, taint) | | regex CI checks | | Search PDFs, Office docs, archives | (ripgrep-all) | manual extraction | | Count lines of code by language | | , | | Code stats with complexity metrics | | , | Decision flow: text → | structural → | rule packs → | filenames → | PDFs/archives → | LOC…

--lang py\n\n# Context managers\nsg --pattern 'with $EXPR as $VAR:\n $

File Search Skill Efficient CLI search tools for AI agents. Tool Selection Guide | Task | Use | Instead of | |------|-----|------------| | Search text in code files | (ripgrep) | , | | Find files by name/path | | , | | Structural/syntax-aware code search | (ast-grep) | regex hacks | | Apply rule packs (security/lint, taint) | | regex CI checks | | Search PDFs, Office docs, archives | (ripgrep-all) | manual extraction | | Count lines of code by language | | , | | Code stats with complexity metrics | | , | Decision flow: text → | structural → | rule packs → | filenames → | PDFs/archives → | LOC…

--lang py\n```\n\n### Type Annotation Patterns\n\n```bash\n# Typed function signatures\nsg --pattern 'def $NAME($$) -> $RETURN:\n $

File Search Skill Efficient CLI search tools for AI agents. Tool Selection Guide | Task | Use | Instead of | |------|-----|------------| | Search text in code files | (ripgrep) | , | | Find files by name/path | | , | | Structural/syntax-aware code search | (ast-grep) | regex hacks | | Apply rule packs (security/lint, taint) | | regex CI checks | | Search PDFs, Office docs, archives | (ripgrep-all) | manual extraction | | Count lines of code by language | | , | | Code stats with complexity metrics | | , | Decision flow: text → | structural → | rule packs → | filenames → | PDFs/archives → | LOC…

--lang py\n\n# Optional types\nsg --pattern 'Optional[$TYPE]' --lang py\n\n# Union types\nsg --pattern 'Union[$$]' --lang py\n```\n\n---\n\n## PHP\n\n### Class and Method Patterns\n\n```bash\n# Class definitions\nsg --pattern 'class $NAME { $$ }' --lang php\nsg --pattern 'class $NAME extends $BASE { $$ }' --lang php\nsg --pattern 'class $NAME implements $IFACE { $$ }' --lang php\n\n# Method definitions\nsg --pattern 'public function $NAME($$) { $$ }' --lang php\nsg --pattern 'protected function $NAME($$) { $$ }' --lang php\nsg --pattern 'private function $NAME($$) { $$ }' --lang php\n\n# Static methods\nsg --pattern 'public static function $NAME($$) { $$ }' --lang php\n\n# Constructor\nsg --pattern 'public function __construct($$) { $$ }' --lang php\n\n# Constructor property promotion (PHP 8+)\nsg --pattern 'public function __construct(\n $$\n) { $$ }' --lang php\n```\n\n### Common PHP Patterns\n\n```bash\n# Array operations\nsg --pattern 'array_map($CALLBACK, $$)' --lang php\nsg --pattern 'array_filter($ARRAY, $$)' --lang php\n\n# Method chaining\nsg --pattern '$OBJ->$METHOD1($$)->$METHOD2($$)' --lang php\n\n# Type-hinted parameters\nsg --pattern 'function $NAME($TYPE $PARAM) { $$ }' --lang php\n\n# Null coalescing\nsg --pattern '$EXPR ?? $DEFAULT' --lang php\n\n# Match expression (PHP 8+)\nsg --pattern 'match ($EXPR) { $$ }' --lang php\n```\n\n### TYPO3/Symfony/Laravel Patterns\n\n```bash\n# Dependency injection\nsg --pattern 'public function __construct($TYPE $PARAM) { $$ }' --lang php\n\n# Route annotations\nsg --pattern '#[Route($$)]' --lang php\n\n# Doctrine annotations\nsg --pattern '#[ORM\\Column($$)]' --lang php\n```\n\n---\n\n## Go\n\n### Function and Method Patterns\n\n```bash\n# Function definitions\nsg --pattern 'func $NAME($$) $RETURN { $$ }' --lang go\n\n# Methods with receiver\nsg --pattern 'func ($RECV $TYPE) $NAME($$) $RETURN { $$ }' --lang go\n\n# Pointer receiver methods\nsg --pattern 'func ($RECV *$TYPE) $NAME($$) $RETURN { $$ }' --lang go\n\n# Init functions\nsg --pattern 'func init() { $$ }' --lang go\n\n# Main functions\nsg --pattern 'func main() { $$ }' --lang go\n```\n\n### Error Handling\n\n```bash\n# Standard error check\nsg --pattern 'if $ERR != nil { $$ }' --lang go\n\n# Error return without wrapping\nsg --pattern 'if $ERR != nil { return $ERR }' --lang go\n\n# Error wrapping with fmt.Errorf\nsg --pattern 'fmt.Errorf($FMT, $$)' --lang go\n\n# errors.Is / errors.As\nsg --pattern 'errors.Is($ERR, $TARGET)' --lang go\nsg --pattern 'errors.As($ERR, $TARGET)' --lang go\n```\n\n### Concurrency\n\n```bash\n# Goroutine launches\nsg --pattern 'go $FUNC($$)' --lang go\n\n# Channel operations\nsg --pattern '$CH \u003c- $VALUE' --lang go\nsg --pattern '\u003c-$CH' --lang go\n\n# Select statements\nsg --pattern 'select { $$ }' --lang go\n\n# Mutex usage\nsg --pattern '$MU.Lock()' --lang go\nsg --pattern 'defer $MU.Unlock()' --lang go\n\n# WaitGroup\nsg --pattern '$WG.Add($N)' --lang go\nsg --pattern 'defer $WG.Done()' --lang go\n```\n\n### Struct and Interface Patterns\n\n```bash\n# Struct definitions\nsg --pattern 'type $NAME struct { $$ }' --lang go\n\n# Interface definitions\nsg --pattern 'type $NAME interface { $$ }' --lang go\n\n# Struct literal initialization\nsg --pattern '$TYPE{ $$ }' --lang go\n```\n\n### Testing\n\n```bash\n# Test functions\nsg --pattern 'func Test$NAME(t *testing.T) { $$ }' --lang go\n\n# Benchmark functions\nsg --pattern 'func Benchmark$NAME(b *testing.B) { $$ }' --lang go\n\n# Table-driven tests\nsg --pattern 'for $_, $TC := range $CASES { $$ }' --lang go\n\n# t.Run subtests\nsg --pattern 't.Run($NAME, func(t *testing.T) { $$ })' --lang go\n```\n\n---\n\n## Rust\n\n### Function Patterns\n\n```bash\n# Function definitions\nsg --pattern 'fn $NAME($$) -> $RETURN { $$ }' --lang rust\n\n# Async functions\nsg --pattern 'async fn $NAME($$) -> $RETURN { $$ }' --lang rust\n\n# Impl blocks\nsg --pattern 'impl $TYPE { $$ }' --lang rust\n\n# Trait implementations\nsg --pattern 'impl $TRAIT for $TYPE { $$ }' --lang rust\n```\n\n### Error Handling\n\n```bash\n# unwrap calls (potential panics)\nsg --pattern '$EXPR.unwrap()' --lang rust\n\n# expect calls\nsg --pattern '$EXPR.expect($MSG)' --lang rust\n\n# Match on Result\nsg --pattern 'match $EXPR { Ok($VAL) => $$, Err($ERR) => $$ }' --lang rust\n\n# Question mark operator\nsg --pattern '$EXPR?' --lang rust\n```\n\n---\n\n## Tips for Writing ast-grep Patterns\n\n1. **Start simple.** Begin with a small pattern and add complexity. If\n `$FUNC($$)` matches too broadly, add more structure.\n\n2. **Use `--json` output** for programmatic processing. The JSON includes\n file path, line/column ranges, and matched metavariable bindings.\n\n3. **Test patterns interactively** at https://ast-grep.github.io/playground\n to verify they match what you expect.\n\n4. **Language matters.** Always specify `--lang` -- the same text may parse\n differently in different languages.\n\n5. **Metavariable consistency.** Within a single pattern, the same `$NAME`\n must match the same text. Use different names (`$A`, `$B`) for different\n captures.\n\n6. **Whitespace is ignored** in pattern matching. `func ( $ARG )` matches\n `func(arg)`, `func( arg )`, etc.\n\n---\n\n## When to Use ast-grep Over ripgrep\n\n- Matching code **structure** regardless of formatting/whitespace\n- Finding function calls with specific argument patterns\n- Matching patterns that span multiple lines unpredictably\n- Refactoring patterns (find + replace structurally)\n- When regex would be too fragile for the code pattern\n\n---\n\n## Basic Usage\n\n```bash\n# Search with a pattern in a language\nsg --pattern 'console.log($$)' --lang js\n\n# Search in specific directory\nsg --pattern 'fmt.Errorf($$)' --lang go src/\n\n# JSON output for programmatic use\nsg --pattern '$FUNC($$)' --lang py --json\n\n# Find and replace structurally\nsg --pattern 'console.log($$)' --rewrite 'logger.info($$)' --lang js\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":10456,"content_sha256":"de3c392eca1533458ab77b124d206b10232596dde777fd1c11b31b72d2a7ef1f"},{"filename":"references/code-metrics.md","content":"\u003c!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->\n\u003c!-- SPDX-FileCopyrightText: Netresearch DTT GmbH -->\n\n# Code Metrics: tokei and scc\n\nFast codebase analysis tools for counting lines of code, comments, and blanks\nby language.\n\n---\n\n## tokei\n\n```bash\n# Basic usage -- counts all code in current directory\ntokei\n\n# Count specific directory\ntokei src/\n\n# Sort by lines of code\ntokei --sort code\n\n# Specific languages only\ntokei --type=Python,JavaScript\n\n# Output as JSON for processing\ntokei --output json\n\n# Exclude directories\ntokei --exclude='vendor/*' --exclude='node_modules/*'\n```\n\n---\n\n## scc\n\nLike tokei but adds complexity estimation and COCOMO cost modeling.\n\n```bash\n# Basic usage\nscc\n\n# Specific directory\nscc src/\n\n# Sort by lines of code\nscc --sort-by code\n\n# Include complexity and COCOMO\nscc --wide\n\n# Specific languages\nscc --include-ext py,js,ts\n\n# Exclude directories\nscc --exclude-dir vendor,node_modules\n\n# Output as JSON\nscc --format json\n```\n\n---\n\n## When to Use Which\n\n| Need | Tool |\n|------|------|\n| Quick language breakdown | `tokei` |\n| Complexity estimates / cost modeling | `scc` |\n| CI integration / badge generation | `scc` (has badge output) |\n| Fastest possible count | `tokei` |\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1210,"content_sha256":"062f1cdd6b904e0a2f0970a15bf5409b6d51f50613d7643790a70b48154fbd03"},{"filename":"references/enforcement-hook.md","content":"\u003c!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->\n\u003c!-- SPDX-FileCopyrightText: Netresearch DTT GmbH -->\n\n# Enforcement Hook\n\nThis skill's tool table — `rg` instead of `grep`, `fd` instead of `find`, `sg`\nfor structural patterns — is an instruction, and instructions get skipped. The\nreminder that makes it stick **ships with this plugin**: `hooks/hooks.json`\nregisters `scripts/pre_bash_search_nudge.py` as a `PreToolUse` hook on `Bash`.\nInstalling the plugin installs it; there is no per-machine setup and no copy to\nkeep in sync.\n\nThe retro that produced it measured the problem: Bash carried 63% of all tool\ncalls in a session while the dedicated Grep and Glob tools went unused.\n\n## What it says, and how often\n\nThree rules, all **warn-only** — a shell search is never wrong enough to block:\n\n| Command shape | Message |\n|---|---|\n| `find …` | use the Glob tool, or `fd` |\n| `grep -r` / `grep -R` | use the Grep tool or `rg`; `sg` for structural patterns |\n| `grep …` as the first command | prefer the Grep tool or `rg` |\n\nEach rule speaks **once per session**. The value sits in the first firing: it is\nread once and either changes the next command or has a deliberate reason not to\n— several searches batched into one call, or a probe against a scratch file.\nFirings 2..n change nothing and only cost the reader attention while scrolling\n(measured on the source machine: 23 firings of these three rules in one\nsession).\n\n## What it deliberately stays out of\n\n- **A pipe into grep** (`gh pr list | grep open`) filters another command's\n output. That is not a search over the tree, and `rg` would not replace it.\n- **Structured files** (`.json`, `.yaml`, `.toml`, `.csv`, …). The `data-tools`\n plugin ships its own gate for those, which *denies* field extraction. Two\n hooks must not both speak up for one command.\n- **Prose about commands** — a PR body, a commit message, an `echo`. Option\n values carrying text (`--body`, `-m`, `-f body=`) are stripped before the\n scan; `--body-file` names a path and is left alone.\n\n## Verify\n\n```bash\nH=\"$CLAUDE_PLUGIN_ROOT/scripts/pre_bash_search_nudge.py\" # or the plugin cache path\necho '{\"tool_name\":\"Bash\",\"tool_input\":{\"command\":\"find . -name x\"}}' | uv run \"$H\" # warns\necho '{\"tool_name\":\"Bash\",\"tool_input\":{\"command\":\"rg TODO src/\"}}' | uv run \"$H\" # silent\n```\n\nThe full case list runs as `uv run --python 3.11 python scripts/test_pre_bash_search_nudge.py`.\n\nIf nothing happens on a real `find .`, the plugin's hooks have not been picked\nup — open `/hooks` once, or restart the session.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2572,"content_sha256":"830089401c85ce03bdbc3aca243af62bcad0c3eccb35a1e127df425fbe51aca3"},{"filename":"references/fd-guide.md","content":"\u003c!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->\n\u003c!-- SPDX-FileCopyrightText: Netresearch DTT GmbH -->\n\n# fd Guide\n\nFast, user-friendly file finder. Replaces `find` with sane defaults: respects\n`.gitignore`, colorized output, regex by default, smart case.\n\nOn Debian/Ubuntu the apt package installs the binary as `fdfind` — alias or\nsymlink it to `fd`.\n\n---\n\n## Key Flags\n\n```\n-e EXT Filter by extension (-e py, -e rs)\n-t TYPE Filter by type: f (file), d (directory), l (symlink), x (executable)\n-H Include hidden files\n-I Do not respect .gitignore\n-E PATTERN Exclude glob pattern\n-d DEPTH Limit directory depth\n-x CMD Execute command for each result\n-X CMD Execute command with all results at once\n-0 Null-byte separator (for xargs -0)\n-a Show absolute paths\n-L Follow symlinks\n-g GLOB Use glob pattern instead of regex\n-p Match against full path (not just filename)\n--changed-within TIME Files modified within duration (e.g., 1h, 2d, 1w)\n--changed-before TIME Files modified before duration\n-S / --size Filter by size (e.g., +1m for >1MB)\n```\n\n---\n\n## Important: `-e` Matches the Literal Final Extension Only\n\n`fd -e ts` matches `*.ts` — files whose extension is exactly `.ts`. Unlike\n`rg -t ts` (which includes `.tsx`), `fd -e` is a **literal extension match**:\n\n```bash\nfd -e ts # matches *.ts only (NOT *.tsx)\nfd -e js # matches *.js only (NOT *.jsx or *.mjs)\nfd -e ts -e tsx # matches *.ts AND *.tsx\n\n# WRONG: compound suffixes don't work with -e\nfd -e test.ts # matches nothing useful\n\n# RIGHT: use glob patterns for compound suffixes\nfd -g '*.test.ts' # matches foo.test.ts\nfd -g '*.{test,spec}.ts' # matches foo.test.ts and foo.spec.ts\n```\n\n---\n\n## Common Usage\n\n```bash\n# Find Python files\nfd -e py\n\n# Find all test files\nfd 'test_.*\\.py

File Search Skill Efficient CLI search tools for AI agents. Tool Selection Guide | Task | Use | Instead of | |------|-----|------------| | Search text in code files | (ripgrep) | , | | Find files by name/path | | , | | Structural/syntax-aware code search | (ast-grep) | regex hacks | | Apply rule packs (security/lint, taint) | | regex CI checks | | Search PDFs, Office docs, archives | (ripgrep-all) | manual extraction | | Count lines of code by language | | , | | Code stats with complexity metrics | | , | Decision flow: text → | structural → | rule packs → | filenames → | PDFs/archives → | LOC…

\nfd -g '*_test.go'\n\n# Find files modified in the last day\nfd -e js --changed-within 1d\n\n# Find large files\nfd -S +10m\n\n# Find and delete all .pyc files\nfd -e pyc -x rm {}\n\n# Find directories named \"test\" or \"tests\"\nfd -t d '^tests?

File Search Skill Efficient CLI search tools for AI agents. Tool Selection Guide | Task | Use | Instead of | |------|-----|------------| | Search text in code files | (ripgrep) | , | | Find files by name/path | | , | | Structural/syntax-aware code search | (ast-grep) | regex hacks | | Apply rule packs (security/lint, taint) | | regex CI checks | | Search PDFs, Office docs, archives | (ripgrep-all) | manual extraction | | Count lines of code by language | | , | | Code stats with complexity metrics | | , | Decision flow: text → | structural → | rule packs → | filenames → | PDFs/archives → | LOC…

\n\n# Find executable files\nfd -t x\n\n# Find files excluding certain directories\nfd -e ts -E node_modules -E dist\n\n# Find hidden config files\nfd -H '^\\.' -t f\n\n# Find files and pipe to rg for content search\nfd -0 -e py | xargs -0 rg 'import os'\n```\n\n---\n\n## fd + rg Combinations\n\n```bash\n# Find Python files, then search for a pattern\nfd -e py -x rg -l 'async def'\n\n# Find recently changed files and search them\nfd --changed-within 2h -e ts -X rg 'TODO'\n\n# Find config files and search for a key\nfd -g '*.{yml,yaml,toml,json}' -X rg 'database'\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2794,"content_sha256":"e0907dfdc3bdc43c1482efbab9d94e4c28c71ece42c99ec1e987a0a3e952e539"},{"filename":"references/remote-handoff.md","content":"\u003c!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->\n\u003c!-- SPDX-FileCopyrightText: Netresearch DTT GmbH -->\n\n# Beyond Local Files — Remote Handoff Guide\n\nThis skill covers local CLI search tools. When the context you need lives\noutside the repository, hand off to the appropriate tool or skill.\n\n---\n\n## Handoff Table\n\n| Need | Hand off to |\n|------|-------------|\n| Issue/ticket context (Jira, GitHub Issues) | jira-communication skill or `gh issue view` |\n| PR/MR discussion, review comments | git-workflow skill or `gh pr view` |\n| Wiki pages, project documentation sites | WebFetch or documentation skills |\n| Upstream/fork differences | `git log`, `git diff`, `gh repo view` |\n| Live API responses, external services | WebFetch, Playwright |\n\n---\n\n## When to Hand Off\n\n- `rg`/`fd` return no results and the answer likely lives in issues, PRs,\n or external docs\n- Code comments reference issue keys (`#123`, `PROJ-456`, `JIRA-789`)\n- You need the rationale behind a change (check the PR/MR, not just the diff)\n- The user asks about deployment status, CI results, or external service state\n\n---\n\n## Combining Local and Remote Search\n\nA common pattern is local-first, then remote:\n\n1. **Local**: `rg 'PROJ-1234'` — find where the issue is referenced in code\n2. **Local**: `git log --grep='PROJ-1234'` — find commits mentioning it\n3. **Remote**: `gh issue view 1234` or Jira API — get current status\n4. **Decision**: combine local context with remote status to answer the question\n\n---\n\n## Signals That Context Is Remote\n\n- Comments like `// TODO: see #456`, `// Workaround for PROJ-123`\n- Commit messages referencing PRs (`Merge pull request #89`)\n- Configuration referencing external services (URLs, API endpoints)\n- Questions about \"why\" something was done (rationale lives in PRs/issues)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1795,"content_sha256":"d40c01358a588b1da44d0d4afe747fd4a8cd6d5477b1afa6454719e7a331e04d"},{"filename":"references/rga-guide.md","content":"\u003c!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->\n\u003c!-- SPDX-FileCopyrightText: Netresearch DTT GmbH -->\n\n# rga (ripgrep-all) Guide\n\nExtends ripgrep to search inside PDFs, Word/Excel/PowerPoint, SQLite databases,\ncompressed archives, and more.\n\n---\n\n## When to Use rga Instead of rg\n\n- Searching PDF documents for text\n- Searching Word (.docx), Excel (.xlsx), PowerPoint (.pptx) files\n- Searching inside .zip, .tar.gz, .tar.bz2 archives\n- Searching SQLite database contents\n- Searching EPUB ebooks\n\n---\n\n## Supported Formats\n\n| Format | Extension |\n|--------|-----------|\n| PDF | `.pdf` |\n| Word | `.docx`, `.doc` |\n| Excel | `.xlsx`, `.xls` |\n| PowerPoint | `.pptx`, `.ppt` |\n| OpenDocument | `.odt`, `.ods`, `.odp` |\n| Archive | `.zip`, `.tar`, `.tar.gz`, `.tar.bz2`, `.tar.xz` |\n| SQLite | `.db`, `.sqlite`, `.sqlite3` |\n| EPUB | `.epub` |\n\n---\n\n## Usage\n\n```bash\n# Search PDFs for a term\nrga 'quarterly revenue' docs/\n\n# Search all document types\nrga 'confidential' --rga-adapters=+pdfpages,poppler /path/to/docs/\n\n# Search inside archives\nrga 'config' backups/*.tar.gz\n\n# Search with ripgrep flags (most rg flags work)\nrga -i -c 'error' logs/\n\n# List matching files only\nrga -l 'password' /shared/docs/\n```\n\n---\n\n## Dependencies\n\nrga requires adapters to process different file types:\n\n- **PDF**: `poppler` (pdftotext) — usually pre-installed on Linux\n- **Office (.docx, .xlsx, .pptx)**: built-in via `zip` + XML parsing\n- **Legacy Office (.doc, .xls)**: requires `libreoffice` or `catdoc`\n- **Archives**: requires standard tools (`tar`, `unzip`, etc.)\n\nInstall adapters: `sudo apt install poppler-utils` (Debian/Ubuntu) or\n`brew install poppler` (macOS).\n\nWithout poppler and without root, read a single PDF through `pypdf` in a\nthrowaway environment:\n\n```bash\nuv run -q --no-project --with pypdf python3 -c \"import sys, pypdf; print('\\n'.join(p.extract_text() for p in pypdf.PdfReader(sys.argv[1]).pages))\" file.pdf\n```\n\n---\n\n## Cache Behavior\n\nrga caches extracted text for faster subsequent searches. The cache is stored\nin the system cache directory. Use `--rga-no-cache` to disable.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2092,"content_sha256":"08e07c7c973388607f4d2674b795e8ee29dad453cf7ac140c4c39756f8a1b775"},{"filename":"references/ripgrep-patterns.md","content":"\u003c!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->\n\u003c!-- SPDX-FileCopyrightText: Netresearch DTT GmbH -->\n\n# ripgrep Pattern Recipes\n\nPractical `rg` patterns organized by use case. All examples assume you are in\nthe project root directory.\n\n---\n\n## Security Scanning\n\n```bash\n# Hardcoded passwords/secrets\nrg -i '(password|passwd|secret|api_key|apikey|token)\\s*[:=]' -g '!*.lock'\nrg -i '(password|secret|key)\\s*=\\s*[\"\\x27][^\"\\x27]{8,}' -g '!*.lock' -g '!*.md'\n\n# AWS credentials\nrg '(AKIA|ASIA)[A-Z0-9]{16}'\nrg 'aws_secret_access_key\\s*[:=]'\n\n# Private keys\nrg 'BEGIN (RSA |DSA |EC |OPENSSH )?PRIVATE KEY'\n\n# JWT tokens\nrg 'eyJ[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}'\n\n# Dangerous functions\nrg '\\beval\\s*\\(' -t py -t js -t php -t ruby\nrg '\\bexec\\s*\\(' -t py -t php\nrg 'innerHTML\\s*=' -t js -t ts\n\n# SQL injection vectors\nrg '(query|execute)\\s*\\(.*[\"\\x27]\\s*\\+' -t py -t js -t java\nrg '\\$\\w+.*->query\\(\\s*[\"\\x27]' -t php\nrg 'raw\\s*\\(\\s*f[\"\\x27]' -t py # f-string in raw SQL (Python)\n\n# Insecure HTTP\nrg 'http://' -t py -t js -t go -t java -g '!*.lock' -g '!*.md'\nrg 'verify\\s*=\\s*False' -t py # disabled SSL verification\nrg 'rejectUnauthorized.*false' -t js -t ts\n\n# Debug/dev artifacts left in code\nrg '(console\\.log|print\\(|fmt\\.Print)' -t js -t py -t go --count-matches\nrg 'binding\\.pry' -t ruby\nrg 'debugger;' -t js -t ts\nrg 'dd\\(' -t php\n```\n\n---\n\n## Dependency Analysis\n\n```bash\n# Python imports\nrg '^from (\\S+) import' -t py -o -r '$1' --no-filename | sort -u\nrg '^import (\\S+)' -t py -o -r '$1' --no-filename | sort -u\n\n# JavaScript/TypeScript imports\nrg \"^import .+ from ['\\\"]([^'\\\"]+)\" -t js -t ts -o -r '$1' --no-filename | sort -u\nrg \"require\\(['\\\"]([^'\\\"]+)\" -t js -o -r '$1' --no-filename | sort -u\n\n# Go imports\nrg '\"([\\w./]+)\"' -t go -o -r '$1' --no-filename | sort -u\n\n# PHP use statements\nrg '^use\\s+([\\w\\\\\\\\]+)' -t php -o -r '$1' --no-filename | sort -u\n\n# Java imports\nrg '^import\\s+([\\w.]+)' -t java -o -r '$1' --no-filename | sort -u\n\n# Rust use statements\nrg '^use\\s+([\\w:]+)' -t rust -o -r '$1' --no-filename | sort -u\n\n# Find unused imports (files that import X but never reference it again)\n# Step 1: find files importing the module\nrg -l 'import someModule' -t js\n# Step 2: check if the module is used beyond the import line\nrg -c 'someModule' -t js # files with count=1 likely only have the import\n```\n\n---\n\n## Code Quality\n\n```bash\n# TODO/FIXME/HACK/XXX with context\nrg '(TODO|FIXME|HACK|XXX|WARN|DEPRECATED):?\\s' -n --trim\nrg '(TODO|FIXME)\\((\\w+)\\)' -o -r '$1 by $2' --no-filename # extract assignee\n\n# Deprecated usage\nrg '@deprecated' -n -t py -t js -t ts -t java -t php\nrg '@Deprecated' -t java\n\n# Magic numbers (numeric literals in logic, not in declarations)\nrg 'if.*[^=!\u003c>]==[^=].*\\d{2,}' -t py -t js -t go\n\n# Long functions (find function start, count lines until next function)\nrg -n 'def \\w+\\(' -t py # list all function definitions with line numbers\n\n# Empty exception handling\nrg -U 'except.*:\\s*\\n\\s*(pass|\\.\\.\\.)\\s*

File Search Skill Efficient CLI search tools for AI agents. Tool Selection Guide | Task | Use | Instead of | |------|-----|------------| | Search text in code files | (ripgrep) | , | | Find files by name/path | | , | | Structural/syntax-aware code search | (ast-grep) | regex hacks | | Apply rule packs (security/lint, taint) | | regex CI checks | | Search PDFs, Office docs, archives | (ripgrep-all) | manual extraction | | Count lines of code by language | | , | | Code stats with complexity metrics | | , | Decision flow: text → | structural → | rule packs → | filenames → | PDFs/archives → | LOC…

-t py\nrg -U 'catch\\s*\\(.*\\)\\s*\\{\\s*\\}' -t js -t ts -t java\n\n# Commented-out code (heuristic)\nrg '^\\s*//\\s*(if|for|while|return|function|var|let|const)\\b' -t js -t ts\nrg '^\\s*#\\s*(if|for|while|return|def|class|import)\\b' -t py\n\n# Dead code indicators\nrg 'noinspection' -t java -t py\nrg '@ts-ignore' -t ts\nrg '// eslint-disable' -t js -t ts\nrg '# type: ignore' -t py\nrg '# noqa' -t py\nrg '# noinspection' -t py\n```\n\n---\n\n## Refactoring\n\n```bash\n# Find all usages of a function\nrg '\\bfunctionName\\b' -t py -n\n\n# Find function definitions (various languages)\nrg 'def functionName\\(' -t py\nrg 'function functionName\\(' -t js\nrg 'func functionName\\(' -t go\nrg 'fn functionName\\(' -t rust\n\n# Find class definitions\nrg 'class ClassName' -t py -t java -t ts\n\n# Find method calls on a specific type\nrg '\\.methodName\\(' -t go -t java -t ts\n\n# Find variable assignments\nrg '\\bvarName\\s*[:=]' -t py -t js -t ts\n\n# Find all files referencing a module (across languages)\nrg -l '(import|require|use|from).*moduleName'\n\n# Rename preview (show what would change)\nrg 'oldName' -t py -r 'newName' # shows replacements, does not write\n\n# Find interface implementations (Go)\nrg 'func \\(.*\\) MethodName\\(' -t go\n\n# Find all routes/endpoints\nrg '(@app\\.(get|post|put|delete|patch)|router\\.(get|post|put|delete|patch))' -t py\nrg 'app\\.(get|post|put|delete|patch)\\(' -t js -t ts\nrg '(GET|POST|PUT|DELETE|PATCH)\\s+/' -t go\n```\n\n---\n\n## Configuration and Infrastructure\n\n```bash\n# Find all config files\nrg -l '.' -g '*.{yml,yaml,toml,ini,cfg,conf,json,env,env.*}'\n\n# Find Docker-related configs\nrg -l '.' -g 'Dockerfile*' -g 'docker-compose*' -g '.dockerignore'\n\n# Find port bindings\nrg '(port|PORT)\\s*[:=]\\s*\\d+' -g '*.{yml,yaml,toml,json,env,py,js,go}'\nrg ':\\d{4,5}' -g '*.{yml,yaml,toml,env}'\n\n# Find database connection strings\nrg '(postgres|mysql|mongo|redis|sqlite)://' -g '!*.lock' -g '!*.md'\n\n# Find environment variable references\nrg 'os\\.environ\\[' -t py\nrg 'os\\.Getenv\\(' -t go\nrg 'process\\.env\\.' -t js -t ts\nrg '\\$_ENV\\[' -t php\nrg 'getenv\\(' -t php\n\n# Find CI/CD references\nrg -l '.' -g '.github/workflows/*.yml'\nrg -l '.' -g '.gitlab-ci.yml' -g 'Jenkinsfile' -g '.circleci/*'\n```\n\n---\n\n## Advanced Flags and Techniques\n\n```bash\n# Invert match (show lines NOT matching)\nrg -v 'pattern' file.txt\n\n# Show only the matched portion\nrg -o 'pattern' -t py\n\n# Capture groups with replacement (extract data)\nrg 'version:\\s*\"([^\"]+)\"' -o -r '$1' --no-filename\n\n# Search binary files\nrg --binary 'pattern'\n\n# Search compressed files (use rga instead for full support)\nrg -z 'pattern' archive.gz\n\n# Null-byte separated output (for xargs -0)\nrg -l0 'pattern' | xargs -0 wc -l\n\n# Limit number of results\nrg 'pattern' --max-count 5 # max 5 matches per file\nrg 'pattern' -l | head -20 # first 20 matching files\n\n# Search with lookahead/lookbehind (PCRE2)\nrg -P '(?\u003c=import\\s)\\w+' -t py # word after \"import \"\nrg -P 'def \\w+\\((?=.*self)' -t py # methods (have self param)\n\n# Stats about the search\nrg 'pattern' --stats\n\n# Sorted output by file path\nrg 'pattern' --sort path\n\n# Glob patterns for includes\nrg 'pattern' -g '*.{ts,tsx}' -g '!*.test.*' -g '!*.spec.*'\n```\n\n---\n\n## Performance Tips\n\n- **Always specify file types** (`-t`) when possible. This avoids scanning\n irrelevant files entirely.\n- **Limit directory scope** to the relevant subtree.\n- **Use `-l`** (list files) when you only need to know which files match, not\n the matching lines.\n- **Use `--max-count N`** to stop searching a file after N matches.\n- **Exclude large directories** like `vendor/`, `node_modules/`, `dist/`,\n `.git/` with `-g '!dir/'`.\n- **Use `-F`** (fixed string) when your pattern has no regex metacharacters.\n This is faster than regex matching.\n- **Pipe to `head`** when exploring. You do not need all 10,000 results to\n understand the pattern.\n\n---\n\n## Key Flags Reference\n\n```\n-i Case-insensitive search\n-w Match whole words only\n-l List matching file paths only (no content)\n-c Count matching lines per file\n-n Show line numbers (default)\n-t TYPE Restrict to file type (e.g., -t py, -t js, -t go)\n-T TYPE Exclude file type\n-g 'GLOB' Filter by glob pattern (e.g., -g '*.tsx')\n--json Machine-readable JSON output\n-A N / -B N Show N lines after/before match\n-C N Show N lines of context (before + after)\n-U Enable multiline matching\n--hidden Include hidden files (dotfiles)\n--no-ignore Search files ignored by .gitignore\n-F Treat pattern as fixed string (no regex)\n-e PATTERN Specify pattern (useful for multiple patterns or leading dashes)\n--count-matches Count individual matches per file (vs -c which counts matching lines)\n-r REPLACEMENT Replace matches in output (preview, does not modify files)\n```\n\n---\n\n## Progressive Refinement Strategy\n\nStart narrow, widen only if needed:\n\n```bash\n# 1. Count matches first to gauge scope\nrg -c 'pattern' -t py\n\n# 2. If too many, narrow by directory\nrg -c 'pattern' -t py src/core/\n\n# 3. View results with context\nrg -n -C 2 'pattern' -t py src/core/\n\n# 4. If still too many, add word boundaries or refine regex\nrg -nw 'exactFunction' -t py src/core/\n```\n\n---\n\n## Common Patterns\n\n```bash\n# Find function definitions in Python\nrg 'def \\w+\\(' -t py\n\n# Find class definitions in TypeScript\nrg 'class \\w+' -t ts\n\n# Find all imports of a module\nrg \"from ['\\\"](react|vue)\" -t js -t ts\n\n# Find TODO/FIXME comments\nrg '(TODO|FIXME|HACK|XXX):' -n\n\n# Find environment variable usage\nrg '\\$\\{?\\w+\\}?' -t sh\n\n# Find SQL injection risks\nrg 'execute\\(.*\\+.*\\)' -t py\nrg '\\$\\w+.*->query\\(' -t php\n\n# Search with multiple patterns\nrg -e 'pattern1' -e 'pattern2' -t js\n\n# Search for multiline patterns (e.g., function with decorator)\nrg -U '@deprecated\\n.*def \\w+' -t py\n\n# Exclude directories\nrg 'pattern' -g '!vendor/' -g '!node_modules/'\n\n# Fixed string search (no regex interpretation)\nrg -F 'array_map($callback, $items)' -t php\n```\n\n---\n\n## File Type Targeting\n\nripgrep has built-in type definitions. List all with `rg --type-list`.\n\nCommon types: `py`, `js`, `ts`, `go`, `rust`, `java`, `php`, `ruby`, `css`,\n`html`, `json`, `yaml`, `toml`, `md`, `sh`, `sql`, `c`, `cpp`.\n\n**Note:** `-t ts` typically matches `.ts` AND `.tsx`. Run `rg --type-list | grep ts`\nto check your version — some builds include a separate `tsx` type. Similarly,\n`-t js` usually covers `.js`, `.jsx`, `.mjs`. Always verify with `rg --type-list`.\n\n```bash\n# Multiple types\nrg 'pattern' -t js -t ts\n\n# Custom type definition (one-off)\nrg --type-add 'web:*.{html,css,js}' -t web 'pattern'\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":9587,"content_sha256":"bcddbcd696dc6e4bc65c0fda876867b8f62c9e158c2db862d259739d53048206"},{"filename":"references/search-strategies.md","content":"\u003c!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->\n\u003c!-- SPDX-FileCopyrightText: Netresearch DTT GmbH -->\n\n# Search Strategies\n\nUnfocused searches produce overwhelming output. Always scope searches\ndeliberately.\n\n---\n\n## 1. Specify File Types\n\n```bash\n# Good: targeted by type\nrg 'pattern' -t py\nsg --pattern '$FUNC($$)' --lang go\n\n# Bad: search everything\nrg 'pattern'\n```\n\n---\n\n## 2. Limit Directory Scope\n\n```bash\n# Good: specific directory\nrg 'pattern' src/api/\nfd -e ts src/components/\n\n# Bad: search from root\nrg 'pattern' /\n```\n\n---\n\n## 3. Count Before Viewing\n\n```bash\n# First: how many matches?\nrg -c 'pattern' -t py | wc -l # number of files\nrg --count-matches 'pattern' -t py # total matches per file\n\n# Then: view if manageable\nrg -n 'pattern' -t py\n```\n\n---\n\n## 4. Progressive Refinement\n\n```bash\n# Start: broad count\nrg -c 'import' -t py | wc -l\n# => 847 files -- too many\n\n# Narrow: specific module\nrg -c 'from requests import' -t py | wc -l\n# => 23 files -- manageable\n\n# View: with context\nrg -n -C 1 'from requests import' -t py\n```\n\n---\n\n## 5. Exclude Noise\n\n```bash\n# Exclude generated/vendor code\nrg 'pattern' -g '!vendor/' -g '!node_modules/' -g '!*.min.js' -g '!dist/'\nfd -e py -E __pycache__ -E .venv -E '*.pyc'\n```\n\n---\n\n## 6. Batch & Parallelize Independent Queries\n\n`rg` walks the filesystem once per invocation. N sequential calls =\nN walks + N startup costs. Two ways to collapse that:\n\n### 6a. Union patterns in one process (`rg -e ... -e ...`)\n\nWhen you want any of several patterns from the same scope, pass them all\nto one `rg`:\n\n```bash\n# Good: one walk, one process\nrg -t php -e 'RequestHandlerInterface' -e 'MiddlewareInterface' -e 'PSR-15'\n\n# Bad: three walks\nrg -t php 'RequestHandlerInterface'\nrg -t php 'MiddlewareInterface'\nrg -t php 'PSR-15'\n```\n\nUse `-f patterns.txt` for many patterns. Note: ripgrep does not annotate\noutput with which `-e`/`-f` pattern matched — neither plain text nor\n`--json` exposes a stable pattern index. If you need provenance, run\nseparate searches or post-process by re-matching the captured text.\n\n`rg` also accepts multiple `-t` flags and multiple path arguments, so\nprefer batching scope into a single call:\n\n```bash\n# Good: one walk, multiple types\nrg -t php -t js -t ts 'pattern'\n\n# Good: one walk, multiple paths\nrg 'pattern' src/ tests/ docs/\n```\n\n### 6b. Parallel tool calls for distinct intents\n\nUse parallel tool calls when the queries can't collapse into one `rg`\ninvocation — different patterns in different scopes, different tools,\nor different post-processing. Issue them as **parallel tool calls in a\nsingle message**; the agent harness runs them concurrently and total\nwall time ≈ slowest single call.\n\nGood candidates for parallel calls:\n\n- Different patterns in different scopes: `rg 'Error' logs/` + `rg 'TODO' src/`\n- Different tools on same target: `rg X` + `fd -g '*X*'` + `tokei`\n- Different search modes: `rg 'pattern'` + `sg --pattern 'func($$)'`\n\nAnti-pattern: chaining independent greps with `&&` in one Bash call —\nthe shell still runs them sequentially.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3062,"content_sha256":"1097d6e4f08b3d97dee871edac34191e7f030d894180034c8c6be755b4229088"},{"filename":"references/semgrep-patterns.md","content":"\u003c!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->\n\u003c!-- SPDX-FileCopyrightText: Netresearch DTT GmbH -->\n\n# semgrep Pattern Recipes\n\nRule-driven structural code search with semgrep, focused on security and\nlint patterns. Use when `sg` (ast-grep) is the wrong tool: semgrep ships\nwith curated rule packs, supports taint analysis (source → sink dataflow),\nand is the standard for security CI gates.\n\n## semgrep vs ast-grep\n\n| | `sg` (ast-grep) | `semgrep` |\n|--|-----------------|-----------|\n| **Primary use** | Structural search & rewrite | Security/lint rules at scale |\n| **Patterns live in** | CLI flag or YAML | YAML rules (file or registry) |\n| **Rewrite support** | Yes (first-class) | Limited (`autofix:`) |\n| **Taint tracking** | No | Yes (`mode: taint`) |\n| **Rule registry** | No | https://semgrep.dev/r |\n| **Per-language config** | `--lang` flag | `languages:` in rule |\n| **CI integration** | Manual | `semgrep ci` (native) |\n\n**Rule of thumb:** reach for `sg` when you have a structural pattern in\nyour head; reach for `semgrep` when you want to apply a *catalog* of\npatterns (OWASP, CWE, framework-specific lints).\n\n## Quick Examples\n\n```bash\n# Apply the curated security rule pack (no local rules needed)\nsemgrep --config=auto .\n\n# Run a specific rule pack\nsemgrep --config=p/security-audit .\nsemgrep --config=p/owasp-top-ten .\nsemgrep --config=p/r2c-ci .\n\n# Single inline pattern (ad-hoc, no YAML)\nsemgrep -e 'eval(...)' --lang python .\nsemgrep -e 'exec($CMD)' -e 'os.system($CMD)' --lang python .\n\n# JSON output for pipelines\nsemgrep --config=auto --json --quiet .\n\n# Only report severity ERROR (skip WARNING/INFO)\nsemgrep --config=auto --severity=ERROR .\n\n# Limit scope\nsemgrep --config=auto --include='*.py' src/\n```\n\n## Inline Patterns by Language\n\n```bash\n# Python: dangerous deserialization\nsemgrep -e 'pickle.loads($X)' --lang python .\nsemgrep -e 'yaml.load($X)' --lang python . # missing SafeLoader\n\n# Python: SQL string concatenation\nsemgrep -e 'cursor.execute(\"...\" + $X)' --lang python .\n\n# JavaScript/TypeScript: dangerous DOM sinks\nsemgrep -e '$EL.innerHTML = $X' --lang js .\nsemgrep -e 'document.write($X)' --lang js .\n\n# Go: ignored errors (both assignment and short-declaration forms)\nsemgrep -e '_, _ = $F(...)' -e '_, _ := $F(...)' --lang go .\n\n# PHP: unsafe shell\nsemgrep -e 'shell_exec($X)' --lang php .\nsemgrep -e 'eval($X)' --lang php .\n```\n\n## Custom Rule (YAML)\n\nFor anything you want to reuse, write a rule file:\n\n```yaml\n# .semgrep/no-eval.yml\nrules:\n - id: no-eval\n message: \"Avoid eval() — use ast.literal_eval or a parser.\"\n severity: ERROR\n languages: [python]\n pattern: eval(...)\n```\n\nRun it:\n\n```bash\nsemgrep --config=.semgrep/ .\n```\n\n## Taint Mode (Dataflow)\n\nUse when you need to track that *user input* flows into a *dangerous\nsink*. Pattern-only matches miss this; taint mode tracks it across\nassignments and function calls.\n\n```yaml\n# .semgrep/sql-injection.yml\nrules:\n - id: sql-from-request\n mode: taint\n message: \"User input flows into raw SQL.\"\n severity: ERROR\n languages: [python]\n pattern-sources:\n - pattern: request.args.get($X)\n - pattern: request.form.get($X)\n pattern-sinks:\n - pattern: cursor.execute($Q)\n```\n\n## CI Integration\n\n```bash\n# Fail the build on findings of severity ERROR\nsemgrep --config=auto --severity=ERROR --error .\n\n# Diff-aware: only scan changed lines (fast CI mode)\nsemgrep ci --baseline-ref=origin/main\n```\n\n## When NOT to Use semgrep\n\n- **Unstructured text search** → use `rg` instead. semgrep parses code\n (and structured formats like YAML/JSON); it cannot match log lines or\n free-form prose.\n- **One-off structural refactor with a rewrite** → use `sg` instead. Its\n `--rewrite` is first-class; semgrep autofix is more constrained.\n- **Files semgrep cannot parse** → semgrep reports parse errors on\n stderr but produces no findings for those files. If a file is\n unsupported or unparseable, fall back to `rg`/`sg`.\n\n## Further Reading\n\n- semgrep docs: https://semgrep.dev/docs\n- Rule registry: https://semgrep.dev/r\n- Writing rules: https://semgrep.dev/docs/writing-rules/overview\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4133,"content_sha256":"3d48e938584cdb2b026bc7f317932ff5716e7ed0c6afe4e323f24e43cf1e67a4"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"File Search Skill","type":"text"}]},{"type":"paragraph","content":[{"text":"Efficient CLI search tools for AI agents.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Tool Selection Guide","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Task","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Use","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Instead of","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Search text in code files","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"rg","type":"text","marks":[{"type":"code_inline"}]},{"text":" (ripgrep)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"grep","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"grep -r","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Find files by name/path","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"fd","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"find","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"ls -R","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Structural/syntax-aware code search","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"sg","type":"text","marks":[{"type":"code_inline"}]},{"text":" (ast-grep)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"regex hacks","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Apply rule packs (security/lint, taint)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"semgrep","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"regex CI checks","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Search PDFs, Office docs, archives","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"rga","type":"text","marks":[{"type":"code_inline"}]},{"text":" (ripgrep-all)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"manual extraction","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Count lines of code by language","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"tokei","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"cloc","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"wc -l","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Code stats with complexity metrics","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"scc","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"cloc","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"tokei","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"paragraph","content":[{"text":"Decision flow:","type":"text","marks":[{"type":"strong"}]},{"text":" text → ","type":"text"},{"text":"rg","type":"text","marks":[{"type":"code_inline"}]},{"text":" | structural → ","type":"text"},{"text":"sg","type":"text","marks":[{"type":"code_inline"}]},{"text":" | rule packs → ","type":"text"},{"text":"semgrep","type":"text","marks":[{"type":"code_inline"}]},{"text":" | filenames → ","type":"text"},{"text":"fd","type":"text","marks":[{"type":"code_inline"}]},{"text":" | PDFs/archives → ","type":"text"},{"text":"rga","type":"text","marks":[{"type":"code_inline"}]},{"text":" | LOC → ","type":"text"},{"text":"tokei","type":"text","marks":[{"type":"code_inline"}]},{"text":"/","type":"text"},{"text":"scc","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Quick Examples","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"rg 'def \\w+\\(' -t py src/ # rg: text search in Python files\nrg -c 'TODO' -t js | wc -l # rg: count first, then drill down\nsg --pattern 'console.log($$)' --rewrite 'logger.info($$)' --lang js # sg: structural replace\nfd -g '*.test.ts' --changed-within 1d # fd: -g for compound suffixes (NOT -e)\nfd -g '*_test.go' -X rg 'func Test' # fd+rg: find files, verify contents\nrga 'quarterly revenue' docs/ # rga: search inside PDFs/archives\ntokei --sort code # tokei: language stats\nscc --wide # scc: complexity + COCOMO","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Best Practices","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Start narrow.","type":"text","marks":[{"type":"strong"}]},{"text":" Specify types (","type":"text"},{"text":"-t","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"--lang","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"-e","type":"text","marks":[{"type":"code_inline"}]},{"text":"), scope dirs, count first (","type":"text"},{"text":"rg -c","type":"text","marks":[{"type":"code_inline"}]},{"text":").","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Exclude noise","type":"text","marks":[{"type":"strong"}]},{"text":" (","type":"text"},{"text":"-g '!vendor/'","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"fd -E node_modules","type":"text","marks":[{"type":"code_inline"}]},{"text":").","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Batch independent queries.","type":"text","marks":[{"type":"strong"}]},{"text":" Union patterns with ","type":"text"},{"text":"rg -e P1 -e P2 -e P3","type":"text","marks":[{"type":"code_inline"}]},{"text":" (one walk), or issue distinct queries as parallel tool calls in one message — never sequential ","type":"text"},{"text":"&&","type":"text","marks":[{"type":"code_inline"}]},{"text":" chains.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"--json","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" for programmatic processing.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"rg ≠ fd types.","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"rg -t ts","type":"text","marks":[{"type":"code_inline"}]},{"text":" includes ","type":"text"},{"text":".tsx","type":"text","marks":[{"type":"code_inline"}]},{"text":"; ","type":"text"},{"text":"fd -e ts","type":"text","marks":[{"type":"code_inline"}]},{"text":" does NOT. No ","type":"text"},{"text":"-t tsx","type":"text","marks":[{"type":"code_inline"}]},{"text":" in rg.","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"See ","type":"text"},{"text":"references/search-strategies.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/search-strategies.md","title":null}}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Beyond Local Files","type":"text"}]},{"type":"paragraph","content":[{"text":"If local search finds nothing and context lives in issues/PRs/external docs — hand off (","type":"text"},{"text":"gh","type":"text","marks":[{"type":"code_inline"}]},{"text":", Jira, WebFetch). Issue keys in comments signal this.","type":"text"}]},{"type":"paragraph","content":[{"text":"See ","type":"text"},{"text":"references/remote-handoff.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/remote-handoff.md","title":null}}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"References","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Topic","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"File","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"rg flags, patterns, recipes","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/ripgrep-patterns.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/ripgrep-patterns.md","title":null}}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"ast-grep patterns by language","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/ast-grep-patterns.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/ast-grep-patterns.md","title":null}}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"semgrep rules and taint mode","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/semgrep-patterns.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/semgrep-patterns.md","title":null}}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"fd flags, usage, fd+rg combos","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/fd-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/fd-guide.md","title":null}}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"rga formats, usage, caching","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/rga-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/rga-guide.md","title":null}}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"tokei and scc usage","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/code-metrics.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/code-metrics.md","title":null}}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"PreToolUse nudge (ships with plugin)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/enforcement-hook.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/enforcement-hook.md","title":null}}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Search targeting strategies","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/search-strategies.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/search-strategies.md","title":null}}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Remote context handoff guide","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/remote-handoff.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/remote-handoff.md","title":null}}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Modern CLI tools comparison (legacy→modern, all domains)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"cli-tools SKILL.md#preferred-modern-tools","type":"text","marks":[{"type":"link","attrs":{"href":"https://github.com/netresearch/coding_agent_cli_toolset/blob/main/skills/cli-tools/SKILL.md#preferred-modern-tools","title":null}}]}]}]}]}]}]},"metadata":{"date":"2026-11-02","name":"file-search","author":"@skillopedia","source":{"stars":43,"repo_name":"file-search-skill","origin_url":"https://github.com/netresearch/file-search-skill/blob/HEAD/skills/file-search/SKILL.md","repo_owner":"netresearch","body_sha256":"59ff16c1ad966f7d5ef3b9cf28392a0508c1273c73693468ececf06b1e89a769","cluster_key":"2ec6d8b5f97b0d2dff1c761ba27875c2e8ff11f8fb9411e512d2d80f21ea9b85","clean_bundle":{"format":"clean-skill-bundle-v1","source":"netresearch/file-search-skill/skills/file-search/SKILL.md","text_bytes":61927,"source_commit":"d5696239270ffcf9adf9e9c2a37d4f9c132ed20d","skills_sh_rank":18761,"attachment_count":10,"text_attachments":10,"attachment_storage":"skill_attachments","binary_attachments":0},"cluster_size":1,"skill_md_path":"skills/file-search/SKILL.md","import_metadata":{"date":"2026-11-02","author":"@skillopedia","version":"v1","category":"software-engineering","category_label":"Engineering"},"exact_dupes_collapsed_into_this":0},"license":"(MIT AND CC-BY-SA-4.0). See LICENSE-MIT and LICENSE-CC-BY-SA-4.0","version":"v1","category":"software-engineering","metadata":{"author":"Netresearch DTT GmbH","version":"1.8.3","repository":"https://github.com/netresearch/file-search-skill"},"import_tag":"skills-sh-top20k-2026-11","description":"Use when searching codebases (text, structural/AST, files by name, PDFs/archives, code stats) or building context before a task.","allowed-tools":"Bash(rg:*) Bash(fd:*) Bash(sg:*) Bash(rga:*) Bash(tokei:*) Bash(scc:*) Bash(semgrep:*) Read Glob Grep","compatibility":"Requires ripgrep (rg), and uv for the plugin's search-reminder hook (runs it on Python 3.11 or later). Optional: fd, ast-grep, rga, tokei, scc, semgrep."}},"renderedAt":1793666583047}

File Search Skill Efficient CLI search tools for AI agents. Tool Selection Guide | Task | Use | Instead of | |------|-----|------------| | Search text in code files | (ripgrep) | , | | Find files by name/path | | , | | Structural/syntax-aware code search | (ast-grep) | regex hacks | | Apply rule packs (security/lint, taint) | | regex CI checks | | Search PDFs, Office docs, archives | (ripgrep-all) | manual extraction | | Count lines of code by language | | , | | Code stats with complexity metrics | | , | Decision flow: text → | structural → | rule packs → | filenames → | PDFs/archives → | LOC…