filtering — Claude Code skill: what it does, how to install
Guides your AI agent on building filter expressions, handling dates, and structuring queries in Honeydew.
npx skills add honeydew-ai/honeydew-ai-coding-agents-plugins --skill filtering -a claude-codeWhat filtering does
The skill defines syntax and evaluation rules across four Honeydew contexts: structured queries in get_data_from_fields, metric aggregations, per-row attribute expressions, and post-aggregation metric filters. It covers exact comparison operators, pattern matching with ILIKE, NULL checks, and explicit type casting like ::DATE.
For dates, the rules prescribe functions such as CURRENT_DATE, DATE_TRUNC, and INTERVAL, explicitly barring relative interval math for specific calendar dates. Snowflake is the only platform supporting the SEARCH full-text function here, which strictly requires SEARCH_MODE => 'AND'. In metric aggregations, standard FILTER (WHERE ...) syntax replaces CASE WHEN.
What it helps with
- pass pre-aggregation conditions to
filtersinget_data_from_fields - restrict metric aggregation inputs using
FILTER (WHERE ...) - construct relative date filters using
DATE_TRUNCandCURRENT_DATE - run full-text searches on Snowflake with
SEARCH_MODE => 'AND'
Example prompts for the agent
- Query
detailed_listingsfiltered by price over 50 and room type set to Entire home/apt. - Add a completed status condition to the order count metric with
FILTER (WHERE ...). - Filter sales for the previous month using standard date truncation functions.
How to install filtering
1Skills CLI (Vercel)
npx skills add honeydew-ai/honeydew-ai-coding-agents-plugins --skill filtering -a claude-code2Manually: put the files in place
~/.claude/skills/filtering/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/filtering/
1Skills CLI (Vercel)
npx skills add honeydew-ai/honeydew-ai-coding-agents-plugins --skill filtering -a codex2Manually: put the files in place
.agents/skills/filtering/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add honeydew-ai/honeydew-ai-coding-agents-plugins --skill filtering -a cursor2Manually: put the files in place
.cursor/skills/filtering/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install honeydew-ai/honeydew-ai-coding-agents-plugins filtering2Manually: put the files in place
.github/skills/filtering/SKILL.md1Skills CLI (Vercel)
npx skills add honeydew-ai/honeydew-ai-coding-agents-plugins --skill filtering -a gemini-cli2Platform CLI
gemini skills install https://github.com/honeydew-ai/honeydew-ai-coding-agents-plugins --path skills/filteringManually: put the files in place
.devin/skills/filtering/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add honeydew-ai/honeydew-ai-coding-agents-plugins --skill filtering -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about filtering
How do I install filtering in Claude Code?
Run npx skills add honeydew-ai/honeydew-ai-coding-agents-plugins --skill filtering -a claude-code.
What does the filtering skill do?
It instructs your coding assistant on writing correct filter clauses for Honeydew queries, metrics, and attribute expressions.
When should I use FILTER (WHERE ...) versus CASE WHEN?
Use FILTER (WHERE ...) inside metric SQL aggregations, and reserve CASE WHEN for per-row logic inside attribute definitions.
Source text
SKILL.md · Apache-2.0
---
name: filtering
description: Use when the user needs to filter data — whether in a structured query, a metric aggregation, or an attribute expression. Covers filter syntax, date handling, and best practices.
---
## Overview
Filtering restricts which rows contribute to a result. The same expression language applies across three contexts in Honeydew:
| Context | Where it appears | When it runs |
| ------------------------ | --------------------------------------------------------- | ------------------ |
| **Structured query** | `filters` parameter in `get_data_from_fields` / `get_sql_from_fields` | Pre-aggregation |
| **Metric aggregation** | `FILTER (WHERE ...)` on an aggregation | During aggregation |
| **Attribute expression** | `CASE WHEN ... END` in attribute SQL | Per-row evaluation |
| **Metric value filter** | Metric expression in `filters` parameter | Post-aggregation |
---
## Filter Expression Syntax
### Comparisons
```sql
entity.field = 'value'
entity.field > 100
entity.field >= 3 AND entity.field < 10
```
Operators: `=`, `<`, `>`, `>=`, `<=`, `!=`
You can compare an attribute to a constant or to another attribute. Cast mismatching types when comparing (e.g., `entity.field::DATE`).
### Strings
```sql
entity.field = 'exact value'
entity.field IN ('val1', 'val2', 'val3')
entity.field ILIKE '%keyword%'
```
- `ILIKE` is case-insensitive pattern matching (`%` = any characters, `_` = one character)
### Full-Text Search (Snowflake only)
Use `SEARCH` when you don't know exact values and need to find possible matches.
```sql
-- Single search — always use SEARCH_MODE => 'AND'
SEARCH(entity.field, 'search terms', SEARCH_MODE => 'AND')
-- Multiple alternatives — use OR between SEARCH calls
SEARCH(entity.field, 'term1', SEARCH_MODE => 'AND') OR SEARCH(entity.field, 'term2', SEARCH_MODE => 'AND')
```
**Always use `SEARCH_MODE => 'AND'`.**
### NULL Checks
```sql
entity.field IS NULL
entity.field IS NOT NULL
```
### Booleans
```sql
entity.flag = true
entity.flag = false
```
### Date Comparisons
```sql
YEAR(entity.date_field) = 2023
entity.date_field >= '2024-01-01'
entity.date_field BETWEEN '2024-02-05'::DATE AND '2024-02-10'::DATE
```
### Combining Conditions
```sql
entity.price > 50 AND entity.room_type = 'Private room'
entity.status = 'active' OR entity.status = 'pending'
```
Use `AND` / `OR` to combine conditions. Use parentheses to control precedence.
### Type Casting
Cast when types don't match:
```sql
entity.string_field::DATE
entity.number_field::VARCHAR
'2024-01-01'::DATE
DATE('2024-01-01')
```
---
## Filtering Contexts
### 1. Structured Query Filters
Pass filters as a list of expressions in the `filters` parameter of `get_data_from_fields` or `get_sql_from_fields`. Filters are applied **before** aggregation (equivalent to SQL `WHERE`):
Call `get_data_from_fields` with:
- `attributes`: `["detailed_listings.neighbourhood_cleansed"]`
- `metrics`: `["detailed_listings.count"]`
- `filters`: `["detailed_listings.room_type = 'Entire home/apt'", "detailed_listings.price > 50"]`
Each entry in the `filters` list is ANDed together.
### 2. Metric Aggregation Filters
Inside a metric's SQL, use `FILTER (WHERE ...)` to restrict which rows feed the aggregation:
```sql
SUM(orders.price) FILTER (WHERE orders.color = 'red')
COUNT(orders.id) FILTER (WHERE orders.status = 'completed')
```
**Use `FILTER (WHERE ...)`, not `CASE WHEN`**, for filtered aggregations in metrics.
### 3. Attribute Expression Filters
In attribute SQL, use `CASE WHEN` for conditional per-row logic:
```sql
CASE
WHEN orders.amount > 1000 THEN 'high'
WHEN orders.amount > 100 THEN 'medium'
ELSE 'low'
END
```
### 4. Filtering by Metric Values
You can filter on aggregated metric values — the equivalent of SQL's `HAVING` clause. Use the metric expression (named or ad-hoc) in the `filters` parameter of a structured query. These filters are applied **after** aggregation.
This works with both named metrics (e.g., `entity.metric_name > 10`) and ad-hoc aggregations (e.g., `COUNT(entity.field) > 1`).
> For examples — including duplicate detection, minimum group size, and revenue thresholds — see `examples.md`.
---
## Date Handling
### Date Functions
| Function | Use |
| -------------- | ---------------------------------------------------- |
| `CURRENT_DATE` | Reference today |
| `DATE_TRUNC` | Get boundaries: `DATE_TRUNC(month, CURRENT_DATE())` |
| `INTERVAL` | Relative time: `CURRENT_DATE() - INTERVAL '1 month'` |
| Cast strings | `DATE('2024-01-01')` or `'2024-01-01'::DATE` |
### Example — Last Month Filter
```sql
DATE_TRUNC(month, order.order_date) = DATE_TRUNC(month, CURRENT_DATE() - INTERVAL '1 month')
```
> Do NOT use interval calculation when asked about specific dates (e.g., "November 2024"). Use explicit date values instead.
---
## Best Practices
- **Discover available values if needed** — if you're unsure what values a field contains, check its distinct values by querying it as an attribute with a COUNT metric (see the **query** skill's "Getting Distinct Values" tip)
- **Use `SEARCH` when values are unknown** — avoids hard-coding exact strings
- **Use `ILIKE` for pattern matching** — case-insensitive, good for partial matches
- **Cast types explicitly** — prevents silent type coercion errors
- **Use `FILTER (WHERE ...)` in metrics**, not `CASE WHEN` — cleaner, standard SQL
- **Use `CASE WHEN` in attributes** — for per-row conditional logic
- **Prefer `IN (...)` over multiple OR** — cleaner for known value lists
- **Use date functions for relative dates** — `CURRENT_DATE`, `DATE_TRUNC`, `INTERVAL`
- **Use explicit dates for specific periods** — don't compute "November 2024" via interval math
© honeydew-ai · Apache-2.0 · honeydew-ai/honeydew-ai-coding-agents-plugins