From cheese-flow
AST-aware code search using tilth MCP. Finds definitions first, then usages. Use tree-sitter structural matching instead of blind text grep. Understand dependencies and call graphs. Use when: finding where symbols are defined, tracing call chains, understanding code structure, finding all callers of a function. Do NOT use for reading files — use cheez-read. Do NOT use for editing — use cheez-write. Examples: "find where handleAuth is defined", "what calls validateToken?", "trace the ServeHTTP, HandlersChain, Next functions", "find all implementations of the UserService interface".
How this skill is triggered — by the user, by Claude, or both
Slash command
/cheese-flow:cheez-searchThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
> **Hard dependency**: If `mcp__tilth__tilth_search` is unavailable, stop immediately and report
Hard dependency: If
mcp__tilth__tilth_searchis unavailable, stop immediately and report "tilth MCP server is not loaded — cannot proceed." Do NOT fall back toGrep,Glob, or any host tool.
AST-aware code search via tilth MCP (tilth_search, tilth_deps).
Tree-sitter finds where symbols are defined — not just where strings appear.
Understand dependencies instead of blindly grepping.
Traditional grep finds text matches. tilth_search finds semantic matches:
Each match includes its surrounding file structure, so you know what you're looking at without a second read.
Why this matters:
All six rows below are first-class — picking the right one is the difference between one call and a long grep walk.
| Goal | Tool | Example |
|---|---|---|
| Find where a symbol is defined / used | tilth_search (default kind: "symbol") | tilth_search(query: "handleAuth", scope: "src/") |
| Find every call site of a function | tilth_search(kind: "callers") | tilth_search(query: "validateToken", kind: "callers") |
| Find literal strings, TODOs, error messages | tilth_search(kind: "content") | tilth_search(query: "TODO: fix", kind: "content") |
| Find lines matching a regex | tilth_search(kind: "regex") | tilth_search(query: "rate.?limit", kind: "regex") |
| Match an AST shape (template with metavars) | sg (ast-grep, via Bash) | sg --lang typescript -p 'JSON.parse(JSON.stringify($X))' --json src/ |
| Module import / blast-radius graph | tilth_deps | tilth_deps(path: "src/auth.ts") |
Rule of thumb: stay in tilth for anything name-shaped or text-shaped.
Drop to sg only when the pattern needs structural metavariables ($X,
$$$BODY) that tilth can't express.
Basic symbol search:
tilth_search(query: "handleAuth", scope: "src/")
Output:
# Search: "handleAuth" in src/ — 6 matches (2 definitions, 4 usages)
## src/auth.ts:44-89 [definition]
[24-42] fn validateToken(token: string)
→ [44-89] export fn handleAuth(req, res, next)
[91-120] fn refreshSession(req, res)
44 │ export function handleAuth(req, res, next) {
45 │ const token = req.headers.authorization?.split(' ')[1];
...
88 │ next();
89 │ }
── calls ──
validateToken src/auth.ts:24-42 fn validateToken(token: string): Claims | null
refreshSession src/auth.ts:91-120 fn refreshSession(req, res)
## src/routes/api.ts:34 [usage]
→ [34] router.use('/api/protected/*', handleAuth);
Key features:
[definition] vs [usage] — know what you're looking at── calls ── footer shows what the function calls (one-hop callees)Trace across files in one call:
tilth_search(query: "ServeHTTP, HandlersChain, Next", scope: ".")
Each symbol gets its own result block. The expand budget is shared — at least one expansion per symbol, deduplicated across files.
Use cases:
Find all places that call a specific function using structural tree-sitter matching (not text search):
tilth_search(query: "isTrustedProxy", kind: "callers", scope: ".")
Output:
# Callers of "isTrustedProxy" — 5 call sites
## context.go:1011 [caller: ClientIP]
→ trusted = c.engine.isTrustedProxy(remoteIP)
## context.go:1045 [caller: RemoteIP]
→ if c.engine.isTrustedProxy(ip) {
## context_test.go:234 [caller: TestClientIP]
→ assert.True(t, engine.isTrustedProxy(testIP))
Why this beats grep:
Search for text that isn't a code symbol:
tilth_search(query: "TODO: fix", kind: "content", scope: ".")
Use content search for:
kind: "regex"For patterns that aren't a single literal, switch kinds rather than embedding slashes in a content query:
tilth_search(query: "rate.?limit", kind: "regex", scope: ".")
tilth_search(query: "FIXME\\(.*?\\):", kind: "regex", scope: "src/")
glob to bound the file set; regex is the most expensive kind./.../ delimiters — pass the bare regex.tilth covers names and text. For shapes with metavariables — “any call to
JSON.parse(JSON.stringify(…))”, “any for loop with time.Sleep in its
body” — use sg (ast-grep) via Bash. The agent template's tools: frontmatter
must list bash for these calls to land.
# AST template: $X is a metavar that matches any single node.
sg --lang typescript -p 'JSON.parse(JSON.stringify($X))' --json src/
# $$$BODY matches a sequence of statements.
sg --lang rust -p 'impl std::fmt::Display for $TYPE { $$$BODY }' --json src/
# Bound the scan; never splice unvalidated user input as the path.
SCOPE=$(realpath "$SCOPE_INPUT")
sg --lang python -p 're.match($PATTERN, $INPUT)' --json "$SCOPE"
When sg is the right pick:
$X, $$$BODY) or specific node kinds.When to stay in tilth:
kind: "symbol".kind: "content".kind: "callers".── calls ── footer → tilth.Hard rules for sg invocations:
$ARGUMENTS before splicing
it into the command line. Reject ;, &, |, backtick, $(, >, <,
newline. Resolve to an absolute path with realpath (or tilth_files) and
confirm it sits under the repo root.--json and parse defensively — the JSON shape varies between
ast-grep versions.--globs or by post-filtering the
JSON output.See agents/nih-scanner.md.eta for the canonical multi-language sg recipe.
Focus search on specific file types:
# Only Rust files
tilth_search(query: "handleAuth", scope: ".", glob: "*.rs")
# Exclude test files
tilth_search(query: "handleAuth", scope: ".", glob: "!*.test.ts")
# Multiple extensions
tilth_search(query: "handleAuth", scope: ".", glob: "*.{go,rs}")
When editing a file, pass it as context to boost related results:
tilth_search(query: "validateToken", scope: ".", context: "src/auth.ts")
Results from the same file or nearby directories rank higher.
The expand parameter controls how many matches show full source:
# Default: 2 expansions
tilth_search(query: "handleAuth", scope: ".")
# More detail
tilth_search(query: "handleAuth", scope: ".", expand: 5)
# Compact (outlines only)
tilth_search(query: "handleAuth", scope: ".", expand: 0)
For understanding module relationships (not searching):
tilth_deps(path: "src/auth.ts")
Output:
# Dependencies for src/auth.ts
── imports ──
express external
jsonwebtoken external
@/config src/config/index.ts
── imported by ──
src/routes/api.ts:5
src/routes/admin.ts:8
src/middleware/auth.ts:3
Use for:
tilth tracks what you've already seen:
[shown earlier]Search for the symbol:
tilth_search(query: "UserService", scope: ".")
Look for [definition] results — these are the declarations
Check ── calls ── to understand what it depends on
Start with the entry point:
tilth_search(query: "handleRequest", scope: ".")
Follow the calls footer to see what it calls
Search for callees if needed:
tilth_search(query: "validateInput, processData, saveResult", scope: ".")
Use callers kind:
tilth_search(query: "deprecated_function", kind: "callers", scope: ".")
All call sites are shown with their caller context
Check what a file imports/exports:
tilth_deps(path: "src/core/auth.ts")
Search for specific symbols from imports:
tilth_search(query: "JWTConfig", scope: "src/config/")
tilth uses tree-sitter for AST parsing, which means:
| Grep finds... | tilth_search finds... |
|---|---|
| All occurrences of text | Definitions vs usages |
| No structure awareness | File context (what else is nearby) |
| No call understanding | Callee resolution in results |
| False positives in strings | Only semantic code matches |
Languages supported: Rust, TypeScript, TSX, JavaScript, Python, Go, Java, Scala, C, C++, Ruby, PHP, C#, Swift
tilth_search(query: "AuthManager", scope: ".")
# Look for [definition] results
tilth_search(query: "validateToken", kind: "callers", scope: ".")
tilth_search(query: "handleAuth", scope: ".", expand: 1)
# Check the ── calls ── footer in expanded result
tilth_search(query: "UserRepository", scope: ".", kind: "symbol")
# Implementations show as [impl] tags
tilth_search(query: "invalid token format", kind: "content", scope: ".")
tilth_deps(path: "src/auth/index.ts")
# Check ── imported by ── section
JSON.parse(JSON.stringify(…)) deep-clone hack"sg --lang typescript -p 'JSON.parse(JSON.stringify($X))' --json src/
# Switch to sg whenever the pattern needs metavars; tilth has no $X.
tilth_search. sg (ast-grep) is the only
sanctioned shell escape, and only for AST-shape patterns tilth can't express.kind (symbol, callers,
content, regex) before reaching for sg.npx claudepluginhub paulnsorensen/cheese-flowProvides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.