memory-metadata-search
Original:🇺🇸 English
Translated
Structured metadata search for Basic Memory: query notes by custom frontmatter fields using equality, range, array, and nested filters. Use when finding notes by status, priority, confidence, or any custom YAML field rather than free-text content.
8installs
Added on
NPX Install
npx skill4agent add basicmachines-co/basic-memory-skills memory-metadata-searchTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →Memory Metadata Search
Find notes by their structured frontmatter fields instead of (or in addition to) free-text content. Any custom YAML key in a note's frontmatter beyond the standard set (, , , , ) is automatically indexed as and becomes queryable.
titletypetagspermalinkschemaentity_metadataWhen to Use
- Filtering by status or priority — find all notes with or
status: draftpriority: high - Querying custom fields — any frontmatter key you invent is searchable
- Range queries — find notes with or
confidence > 0.7score between 0.3 and 0.8 - Combining text + metadata — narrow a text search with structured constraints
- Tag-based filtering — find notes tagged with specific frontmatter tags
- Schema-aware queries — filter by nested schema fields using dot notation
The Tool
All metadata searching uses . Pass filters via , or use the and convenience shortcuts. Omit (or pass ) for filter-only searches.
search_notesmetadata_filterstagsstatusqueryNoneFilter Syntax
Filters are a JSON dictionary. Each key targets a frontmatter field; the value specifies the match condition. Multiple keys combine with AND logic.
Equality
json
{"status": "active"}Array Contains (all listed values must be present)
json
{"tags": ["security", "oauth"]}$in
(match any value in list)
$injson
{"priority": {"$in": ["high", "critical"]}}Comparisons ($gt
, $gte
, $lt
, $lte
)
$gt$gte$lt$ltejson
{"confidence": {"$gt": 0.7}}Numeric values use numeric comparison; strings use lexicographic comparison.
$between
(inclusive range)
$betweenjson
{"score": {"$between": [0.3, 0.8]}}Nested Access (dot notation)
json
{"schema.version": "2"}Quick Reference
| Operator | Syntax | Example |
|---|---|---|
| Equality | | |
| Array contains | | |
| | |
| | |
| | |
| | |
| Nested | | |
Rules:
- Keys must match (dots separate nesting levels)
[A-Za-z0-9_-]+ - Operator dicts must contain exactly one operator
- and array-contains require non-empty lists
$in - requires exactly
$between[min, max]
Warning: Operators MUST include theprefix — write$, not$gte. Without the prefix the filter is treated as an exact-match key and will silently return no results. Correct:gte. Wrong:{"confidence": {"$gte": 0.7}}.{"confidence": {"gte": 0.7}}
Using search_notes
with Metadata
search_notesPass , , or to . Omit for filter-only searches, or combine text and filters together.
metadata_filterstagsstatussearch_notesquerypython
# Filter-only — find all notes with a given status
search_notes(metadata_filters={"status": "in-progress"})
# Filter-only — high-priority specs in a specific project
search_notes(
metadata_filters={"type": "spec", "priority": {"$in": ["high", "critical"]}},
project="research",
page_size=10,
)
# Filter-only — notes with confidence above a threshold
search_notes(metadata_filters={"confidence": {"$gt": 0.7}})
# Convenience shortcuts for tags and status
search_notes(status="active")
search_notes(tags=["security", "oauth"])
# Text search narrowed by metadata
search_notes("authentication", metadata_filters={"status": "draft"})
# Mix text, tag shortcut, and advanced filter
search_notes(
"oauth flow",
tags=["security"],
metadata_filters={"confidence": {"$gt": 0.7}},
)Merging rules: and are convenience shortcuts merged into via . If the same key exists in , the explicit filter wins.
tagsstatusmetadata_filterssetdefaultmetadata_filtersTag Search Shorthand
The prefix in a query converts to a tag filter automatically:
tag:python
# These are equivalent:
search_notes("tag:tier1")
search_notes("", tags=["tier1"])
# Multiple tags (comma or space separated) — all must match:
search_notes("tag:tier1,alpha")Example: Custom Frontmatter in Practice
A note with custom fields:
markdown
---
title: Auth Design
type: spec
tags: [security, oauth]
status: in-progress
priority: high
confidence: 0.85
---
# Auth Design
## Observations
- [decision] Use OAuth 2.1 with PKCE for all client types #security
- [requirement] Token refresh must be transparent to the user
## Relations
- implements [[Security Requirements]]Queries that find it:
python
# By status and type
search_notes(metadata_filters={"status": "in-progress", "type": "spec"})
# By numeric threshold
search_notes(metadata_filters={"confidence": {"$gt": 0.7}})
# By priority set
search_notes(metadata_filters={"priority": {"$in": ["high", "critical"]}})
# By tag shorthand
search_notes("tag:security")
# Combined text + metadata
search_notes("OAuth", metadata_filters={"status": "in-progress"})Guidelines
- Use metadata search for structured queries. If you're looking for notes by a known field value (status, priority, type), metadata filters are more precise than text search.
- Use text search for content queries. If you're looking for notes about something, text search is better. Combine both when you need precision.
- Custom fields are free. Any YAML key you put in frontmatter becomes queryable — no schema or configuration required.
- Multiple filters are AND. requires both conditions.
{"status": "active", "priority": "high"} - Omit for filter-only searches.
queryworks without a text query.search_notes(metadata_filters={"status": "active"}) - Dot notation for nesting. Access nested YAML structures with dots: queries the
{"schema.version": "2"}key inside aversionobject.schema - Tags shortcut is convenient but limited. and
tagsare sugar for common fields. For anything else, usestatusdirectly.metadata_filters