Skip to main content
skill CX Codex

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.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add imagekit-developer/skills --skill search-assets -a claude-code
Open on GitHub

What 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-code

2Manually: put the files in place

~/.claude/skills/search-assets/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/search-assets/

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

Similar skills

All skills for Backend and APIs →

From the same set8

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor