From tea-rags
Translates implicit user scope (domain, language, author, time, ticket, test vs. production) into typed sugar fields, pathPattern negation, or raw Qdrant filters for tea-rags searches.
How this skill is triggered — by the user, by Claude, or both
Slash command
/tea-rags:filter-buildingThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Two ways to constrain a tea-rags search beyond `query` + `pathPattern`. Pick the
Two ways to constrain a tea-rags search beyond query + pathPattern. Pick the
right mechanism — they compose.
Triggers in agent reasoning chain. If thinking any of these BEFORE composing a tea-rags search, this skill applies — translate the SCOPE into typed sugar:
| User said... (paraphrased) | Filter to add |
|---|---|
| "in the X domain / module / area" | pathPattern: "**/X/**" |
| "tests of X" / "test coverage of X" | testFile: "only" (+ symbolId or query) |
| "production code for X" / "actual implementation" | testFile: "exclude" |
| "Ruby / TypeScript / Python code" | language: "<lang>" (NOT pathPattern **/*.rb) |
| "modified recently" / "changed this week" | modifiedAfter: <ISO> + level: "file" |
| "old code" / "legacy" / "untouched for a while" | minAgeDays: <N> + level: "file" |
| "what's new" / "fresh additions" / "sprint review" | modifiedAfter: <ISO> + level: "file" |
| "who's been working on X" / "Alice's code" | author: "Alice" (blame-dominant) |
| "related to ticket JIRA-X" / "for issue #N" | taskId: "JIRA-X" |
| "drop one-off scripts" / "real code, not snippets" | minCommitCount: 5+ |
| "docs about X" / "what's documented" | documentation: "only" |
| "code, not docs" | documentation: "exclude" |
| "AuthService class" (specific class) | symbolId: "AuthService" OR hybrid_search |
| "in /full/abs/path/" (subagent context) | pathPattern: "/full/abs/path/**" |
| "exclude vendor / generated / migrations" | pathPattern: "!**/vendor/**" (no typed sugar) |
Rule of thumb: user almost never says "filter". They name a SCOPE — domain,
language, author, time window, ticket, prod-vs-test. Translate the scope into
the right typed sugar; never leave it ambient ("query alone will sort it out").
An unfiltered semantic_search over a broad project returns results dominated
by the highest-churn domain — the rest is invisible.
Top-level params on every search request. Prefer over raw filter: whenever a
typed field expresses the constraint — intent-clear, schema-checked, survives
directory restructures.
| Field | Values / type | When to use |
|---|---|---|
language | string (e.g. "ruby", "typescript") | scope to one language layer |
fileExtension | string | string[] | constrain by file extension(s) |
chunkType | string (e.g. "method", "class") | only chunks of this type |
documentation | "only" | "exclude" | "include" | docs vs code (string enum, not boolean) |
testFile | "only" | "exclude" | "include" | tests vs production (string enum) |
symbolId | string | scope to one symbol |
author | string | files where this author dominates blame |
modifiedAfter | ISO date string | Date | recent changes |
modifiedBefore | ISO date string | Date | exclude recent changes |
minAgeDays | number | min file age (use level: "file") |
maxAgeDays | number | max file age (use level: "file") |
minCommitCount | number | drop one-off scripts |
taskId | string (e.g. "RAGS-142") | code linked to a ticket via git.taskIds |
Two test-related filters address different granularity. They compose freely.
| Need | Filter combo |
|---|---|
| Any chunk from test files (helpers, imports, DSL chunks) | testFile: "only" |
| Only leaf-scope DSL test scenarios | chunkType: "test" |
| Only DSL fixture / setup chunks | chunkType: "test_setup" |
| Strict DSL leaves in test files only (defense-in-depth) | testFile: "only" + chunkType: "test" |
| Production code, not tests | testFile: "exclude" |
chunkType: "test" and chunkType: "test_setup" require DSL test chunking.
Currently supported:
| Language | Frameworks | Hook file |
|---|---|---|
| TypeScript | Vitest, Jest, Mocha | src/core/domains/ingest/pipeline/chunker/hooks/typescript/test-scope-chunker.ts |
| Ruby | RSpec | src/core/domains/ingest/pipeline/chunker/hooks/ruby/rspec-scope-chunker.ts |
For Python / Go / others, file-level testFile: "only" is the only option.
Detect availability via prime digest: DSL chunks absent if no git.chunk.*
signal shows a test: threshold row. Recipes depending on DSL chunks, see
tea-rags:tests-as-context (Step 0 preflight handles this automatically). New
language added → update this table in lock-step with the matching block in
tea-rags:tests-as-context and dinopowers:test-driven-development — see
.claude/rules/test-spec-chunking.md.
level: "chunk" (default) — filters against git.chunk.* fields.level: "file" — filters against git.file.* fields.Warning: At chunk level, ageDays = 0 means "no git history for this
chunk", NOT "just created". For ALL time-based filters (modifiedAfter,
modifiedBefore, minAgeDays, maxAgeDays) — use level: "file".
Otherwise the filter silently rejects every chunk whose git data is missing.
| Sugar field | Resolves to | Pair with |
|---|---|---|
minAgeDays / maxAgeDays | git.file.ageDays range | level: "file" (mandatory) |
minCommitCount | git.file.commitCount lower bound | drop one-off scripts |
modifiedAfter / modifiedBefore | git.file.lastModifiedAt range | level: "file" |
author | blame-dominant author equals | ownership analysis |
taskId | git.file.taskIds array contains | trace code to a ticket |
testFile | "only" | "exclude" | "include" | scope to prod vs test |
documentation | "only" | "exclude" | "include" | scope to docs vs code |
fileExtension | one or more extensions | language-adjacent constraints |
language | one language | polyglot scoping |
Concrete payload examples:
// Ruby tests modified after 2026-01-01, dropping one-off scripts:
{
"query": "user signup",
"language": "ruby",
"testFile": "only",
"modifiedAfter": "2026-01-01",
"level": "file",
"minCommitCount": 5
}
// Code linked to a Jira ticket, author-scoped:
{
"query": "retry logic",
"taskId": "JIRA-1234",
"author": "[email protected]",
"level": "file"
}
pathPattern is for arbitrary directory globs where no typed filter applies.
Compose with typed filters (e.g. language: "ruby" +
pathPattern: "**/services/**").
**/enrichment/** (directory prefix){file1.rb,file2.rb} (flat file names, no slashes)!**/test/** (picomatch negation — exclude a directory subtree)!**/vendor/** (exclude non-test dirs that have no typed sugar){app/services/foo.rb,app/models/bar.rb} (slashes inside braces — breaks
picomatch)When to prefer negation over typed sugar. Use testFile: "exclude" for test
exclusion — intent-clear, survives test-directory renames. Use !**/dir/** only
for directories that have no typed sugar (vendor, generated, migrations).
pathPatternFor language, documentation, testFile — use the typed filter, not a
pathPattern. The typed filter is intent-clear, schema-checked, survives
directory restructures. pathPattern is for arbitrary directory globs. Compose
freely.
filter param (escape hatch)Use only when typed filters cannot express the constraint: custom payload key, OR-of-conditions across different fields, range on a non-typed numeric field.
{
"filter": {
"must": [{ "key": "git.file.bugFixRate", "range": { "gte": 30 } }],
"should": [
{ "key": "language", "match": { "value": "ruby" } },
{ "key": "language", "match": { "value": "typescript" } },
],
"must_not": [{ "key": "git.file.ageDays", "range": { "lt": 30 } }],
},
}
For exact syntax and the full list of payload keys, read the resource — do not invent syntax:
ReadMcpResourceTool(server: "tea-rags", uri: "tea-rags://schema/filters")
Resource generated from the live registry; always reflects what THIS build supports. Do NOT memorize the payload key list — read it on demand.
The codegraph.file.* / codegraph.chunk.* payload keys exist ONLY when prime
## Enrichment lists codegraph.symbols; filtering on them against an index
built without codegraph matches nothing. Examples:
// Architectural hubs — high-fan-in backbone files
{ "filter": { "must": [{ "key": "codegraph.file.isHub", "match": { "value": true } }] } }
// High blast radius — many incoming call/import edges
{ "filter": { "must": [{ "key": "codegraph.file.fanIn", "range": { "gte": 10 } }] } }
// Efferent-coupling sources (instability near 1 = depends on many, few depend on it)
{ "filter": { "must": [{ "key": "codegraph.file.instability", "range": { "gte": 0.8 } }] } }
fanIn / isHub are the edge-truth replacements for the git/imports proxy.
When codegraph is off, filter on imports instead and treat it as approximate.
Common analytics pattern: an unfiltered scan of a broad project returns results dominated by the highest-churn domain. To surface the rest, run a SECOND scan with the dominant domain negated:
// Pass 1: full project, no pathPattern → identifies dominant domain (say "ingest")
// Pass 2: same query, pathPattern: "!**/ingest/**"
// → surfaces risk zones in the rest of the codebase
Same mechanism tea-rags:risk-assessment uses for domain-stratified scanning,
but apply it manually whenever a single scan is dominated by one directory.
language: "ruby"
AND testFile: "exclude").pathPattern: AND across both.filter: AND across both — raw filter adds its
must/should/must_not on top of the typed constraints.level: "file" applies to typed time-based fields uniformly. If you mix a
file-level typed time filter with a chunk-level raw filter, understand what
scope each part lives in — payload paths differ (git.file.* vs
git.chunk.*).tea-rags:analytics-rerank.tea-rags:explore.tea-rags:bug-hunt.tea-rags:risk-assessment.For composing the filter shape itself — payload keys, operators, level — stay here.
npx claudepluginhub artk0de/tearags-mcp --plugin tea-ragsProvides semantic search, grep, and call graph tracing across CodeAlive-indexed codebases. Use to search code, fetch artifacts, or query data sources.
Semantic codebase search — use for exploring code, finding implementations, and answering questions about any project. Searches using natural language queries, identifier names, or file paths. Returns ranked results using embedding-based similarity, BM25 keyword matching, symbol matching, import graph analysis, and git recency. Use this as the default exploration tool instead of grep when you don't know the exact text to search for.
Orchestrates parallel agents to find all query-relevant files in codebase with orthogonal exploration. Delivers topic overview + file lists with line ranges. Scales thoroughness from quick single-agent to multi-wave thorough searches.