search-assets — Claude Code skill: what it does, how to install
Generates exact Lucene queries for ImageKit DAM search_media_library. Helps agents locate files and folders by metadata, tags, and attributes without code-level filtering.
npx skills add imagekit-developer/skills --skill search-assets -a claude-codeWhat search-assets does
This skill directs the agent to construct precise searchQuery filters for ImageKit DAM through search_media_library. Instead of pulling massive asset pages and filtering them in client code, the agent generates Lucene expressions directly from plain descriptions like brand names, regions, ratings, or SKUs.
Before assembling clauses, the agent discovers the actual schema. The schema check prevents broken queries. It runs list_custom_metadata_fields to map user terms against custom field names and select options, then calls list_client_tags for labels. The agent falls back to name HAS only when metadata and tag lookups yield nothing.
Passing searchQuery causes the tool's separate type parameter to be ignored. Results default to files. Folders require an explicit type = "folder" clause inside the query string.
What it helps with
- build ImageKit DAM searchQuery filters from natural language
- discover custom metadata fields and tags before querying
- filter assets by dimensions, video duration, format, or date
- locate DAM folders when the type parameter is ignored
Example prompts for the agent
- Find all approved banners for the EMEA summer campaign in ImageKit from last week
- Write a search_media_library query for mp4 videos longer than one minute
- Locate the folder named logos inside /products using Lucene searchQuery
How to install search-assets
1Skills CLI (Vercel)
npx skills add imagekit-developer/skills --skill search-assets -a claude-code2Manually: put the files in place
~/.claude/skills/search-assets/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/search-assets/
1Skills CLI (Vercel)
npx skills add imagekit-developer/skills --skill search-assets -a codex2Manually: put the files in place
.agents/skills/search-assets/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add imagekit-developer/skills --skill search-assets -a cursor2Manually: put the files in place
.cursor/skills/search-assets/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install imagekit-developer/skills search-assets2Manually: put the files in place
.github/skills/search-assets/SKILL.md1Skills CLI (Vercel)
npx skills add imagekit-developer/skills --skill search-assets -a gemini-cli2Platform CLI
gemini skills install https://github.com/imagekit-developer/skills --path skills/search-assetsManually: put the files in place
.devin/skills/search-assets/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add imagekit-developer/skills --skill search-assets -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 search-assets
How do I install search-assets in Claude Code?
Run npx skills add imagekit-developer/skills --skill search-assets -a claude-code. Alternatively, add the file at ~/.claude/skills/search-assets/SKILL.md.
What does the search-assets skill do?
It instructs the agent on building Lucene queries for ImageKit DAM media searches. The agent translates user words into exact metadata filters, tag lookups, and asset attributes.
Why does searching for folders fail when setting the type argument?
Whenever searchQuery is provided, ImageKit ignores the standalone type parameter and defaults to files. You must specify type = "folder" directly inside searchQuery.
Source text
SKILL.md · MIT
---
name: search-assets
description: "Lucene searchQuery cheatsheet for DAM search_media_library. Use when the user describes assets in everyday language (brand, campaign, region, status, colour, rating, SKU) or when building or debugging a search, filter, or list of ImageKit files and folders."
---
# `search_media_library` `searchQuery`
Call `search_media_library` on DAM with a tight filter. Do not fetch a broad page and filter in code.
## Discover fields before you guess
Accounts define arbitrary custom-metadata fields. The user will type normal words ("Nike", "summer campaign", "EMEA", "approved") that may be a **field name**, a **select option**, a **tag**, or only a **filename**. Never invent `"customMetadata.<name>"`.
For every descriptive word you might put on `name` or `tags`:
1. Call `list_custom_metadata_fields` once. Match the word against each field's `name`, `label`, and `schema.selectOptions` (case-insensitive). Use the field's `name` (not `label`) as `"customMetadata.<name>"`.
2. Call `list_client_tags` with that word as `label`. If tags come back, filter with `tags IN [...]` using the returned tag `name`s verbatim.
3. Only if neither call matches may you fall back to `name HAS "…"`. Literal filenames, extensions, and explicitly "named/called/titled X" go on `name` without this check.
A no-match is cheap: omit that custom-metadata clause rather than guessing a field. Skip filler words ("files", "show me", "assets").
Select types: `SingleSelect` → `=` / `IN`; `MultiSelect` → `IN` / `NOT IN`. Prefer a returned `selectOptions` value over the user's raw spelling. Text → `=` `:` `HAS`; Number/Date → `<` `<=` `>` `>=`; Boolean → `=` with unquoted `true`/`false`.
## Inputs
| Input | Use for |
|-------|---------|
| `searchQuery` | Lucene filter (below). |
| `path` | Folder scope, e.g. `/products`. |
| `type` | `file` / `file-version` / `folder` / `all`. Honored only when `searchQuery` is omitted. |
| `fileType` | `image` / `non-image` / `all`. |
| `sort` | `ASC_`/`DESC_` + `CREATED` (default `ASC_CREATED`), `UPDATED`, `NAME`, `SIZE`, `WIDTH`, `HEIGHT`, `DURATION`, `RELEVANCE`, `ORIGINAL_CREATION_DATE`. Pair `HAS` with `DESC_RELEVANCE`. `*_ORIGINAL_CREATION_DATE` orders by the reserved `_internal_original_created_datetime` field; files without a value fall back to upload time. |
| `limit` / `skip` | Page size (max 1000) and offset. Default page is 20. |
Put a simple folder scope in `path` and file vs non-image in `fileType`. Whenever `searchQuery` is set, put type in `searchQuery` (`type = "folder"`, or `(name HAS "logo") AND type = "folder"`). The `type` argument is ignored in that case and results default to files.
## Syntax
- **Operators:** `=` `:` `<` `<=` `>` `>=` `IN` `NOT IN` `NOT =` `HAS` `EXISTS` `NOT EXISTS`
- **Combine:** `AND`, `OR`. **Group:** `( ... )`
- **Quoting:** string values in `"double quotes"`; numbers and booleans (`true`/`false`) unquoted; `customMetadata` / `embeddedMetadata` field names must be quoted, e.g. `"customMetadata.brand"`.
- `:` = begins-with / within-subfolders. `=` = exact. `HAS` = case-insensitive full-text (tokenized).
## Fields
| Field | Operators | Value notes |
|-------|-----------|-------------|
| `name` | `=` `:` `IN` `NOT =` `NOT IN` `HAS` | `=` exact (case-sensitive), `:` begins-with, `HAS` case-insensitive full-text |
| `tags` | `IN` `NOT IN` `HAS` `EXISTS` `NOT EXISTS` | Matches both `tags` and `AITags` |
| `type` | `=` `IN` `NOT =` `NOT IN` | `"file"` \| `"file-version"` \| `"folder"` |
| `id` | `=` `IN` `NOT =` `NOT IN` | fileId or folderId |
| `createdAt` / `updatedAt` | `=` `<` `<=` `>` `>=` `IN` `NOT =` `NOT IN` | ISO 8601 or relative (`"1h"` `"2d"` `"3w"` `"4m"` `"1y"`) |
| `width` / `height` | `=` `<` `<=` `>` `>=` `IN` `NOT =` `NOT IN` | Pixels; images only |
| `size` | `=` `<` `<=` `>` `>=` `IN` `NOT =` `NOT IN` | Bytes (`1024`) or `"1mb"` / `"10kb"` |
| `videoDuration` | `=` `<` `<=` `>` `>=` `IN` `NOT =` `NOT IN` | Videos only. Quoted with unit: `"30sec"` `"1.5min"` `"2hr"` (or `s`/`m`/`h`); a bare number is seconds |
| `format` | `=` `IN` | `"jpg"` `"png"` `"webp"` `"gif"` `"svg"` `"avif"` `"pdf"` `"mp4"` … |
| `private` / `published` / `transparency` | `=` | Boolean, unquoted |
| `createdBy` | `=` `IN` `NOT =` `NOT IN` | Uploader email |
| `path` | `=` `:` `IN` `NOT =` `NOT IN` | `=` exact folder; `:` folder + subfolders |
| `"customMetadata.<field>"` | type-dependent | Quote the field name. Discover via `list_custom_metadata_fields`. The reserved `_internal_original_created_datetime` (Date, label "Original creation date") is listed with `reserved: true` only on accounts that enabled it |
| `"embeddedMetadata.<field>"` | type-dependent | From the file, not the DAM schema. `Keywords` uses `IN`/`EXISTS`; `DateTimeOriginal` uses date ops; `LocationTaken` supports geo (`"40,100 5km"`) |
## Examples
```text
name HAS "red dress"
name = "red-dress.jpg"
name : "red-dress"
createdAt > "7d" AND size > "2mb"
tags IN ["sale", "summer"]
tags NOT EXISTS
format IN ["jpg", "webp"]
path : "/sales-banner/"
"customMetadata.brand" = "nike"
"customMetadata.Region" IN ["EMEA"]
"customMetadata.rating" > 4.3
"embeddedMetadata.DateTimeOriginal" > "1y"
videoDuration > "1min" AND format = "mp4"
"customMetadata._internal_original_created_datetime" < "2021-01-01"
(size < "1mb" AND width > 500) OR (tags IN ["summer-sale", "banner"])
```
User says "Nike assets" → `list_custom_metadata_fields` finds `brand` / options including Nike → `"customMetadata.brand" = "Nike"`. Do not search `name HAS "Nike"` if a field or tag matched.
## Gotchas
- `name` `=` / `:` are case-sensitive; use `HAS` for case-insensitive matching.
- `tags` queries search both `tags` and `AITags`.
- `HAS` tokenizes on spaces/punctuation; the last token matches as a prefix. Pair with `sort: DESC_RELEVANCE`.
- Booleans (`private`, `published`, `transparency`) are unquoted; string values are quoted.
- `width` / `height` / `transparency` apply to images only; `videoDuration` applies to videos only. Units are `sec` / `min` / `hr`, not `minutes` / `hours`.
- Sort by `ASC_ORIGINAL_CREATION_DATE` / `DESC_ORIGINAL_CREATION_DATE` only when `list_custom_metadata_fields` returns `_internal_original_created_datetime`; otherwise use `*_CREATED`.
- `"customMetadata.<field>"` only matches fields defined on the account. Quote the whole token.
- The `type` tool argument is ignored whenever `searchQuery` is set. Put `type = "folder"` (or `type IN [...]`) in `searchQuery` instead.
© imagekit-developer · MIT · imagekit-developer/skills