← Basic Memory CloudCONTENT HISTORYWHAT CHANGED · RULE-BASED ANALYSIS
Update to Basic Memory Cloud
Snapshot Sep 30, 2026 · 22:48 UTC · version 2.0.0
Collection source: not recorded for this historical snapshot.
First saved snapshot
No earlier snapshot is available to establish a change.
Compare saved observations
Download comparison JSONFull technical diff · 0 changed fields
Full snapshot data
{
"name": "memory-metadata-search",
"description": "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.",
"included_files": [
{
"relative_path": "agents/openai.yaml",
"size_in_bytes": 405
}
],
"skill_md_contents": "---\nname: memory-metadata-search\ndescription: \"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.\"\n---\n\n# Memory Metadata Search\n\nFind 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 (`title`, `type`, `tags`, `permalink`, `schema`) is automatically indexed as `entity_metadata` and becomes queryable.\n\n## When to Use\n\n- **Filtering by status or priority** — find all notes with `status: draft` or `priority: high`\n- **Querying custom fields** — any frontmatter key you invent is searchable\n- **Range queries** — find notes with `confidence > 0.7` or `score between 0.3 and 0.8`\n- **Combining text + metadata** — narrow a text search with structured constraints\n- **Tag-based filtering** — find notes tagged with specific frontmatter tags\n- **Schema-aware queries** — filter by nested schema fields using dot notation\n\n## The Tool\n\nAll metadata searching uses `search_notes`. Pass filters via `metadata_filters`, or use the `tags` and `status` convenience shortcuts. Omit `query` (or pass `None`) for filter-only searches.\n\n## Filter Syntax\n\nFilters are a JSON dictionary. Each key targets a frontmatter field; the value specifies the match condition. Multiple keys combine with **AND** logic.\n\n### Equality\n\n```json\n{\"status\": \"active\"}\n```\n\n### Array Contains (all listed values must be present)\n\n```json\n{\"tags\": [\"security\", \"oauth\"]}\n```\n\n### `$in` (match any value in list)\n\n```json\n{\"priority\": {\"$in\": [\"high\", \"critical\"]}}\n```\n\n### Comparisons (`$gt`, `$gte`, `$lt`, `$lte`)\n\n```json\n{\"confidence\": {\"$gt\": 0.7}}\n```\n\nNumeric values use numeric comparison; strings use lexicographic comparison.\n\n### `$between` (inclusive range)\n\n```json\n{\"score\": {\"$between\": [0.3, 0.8]}}\n```\n\n### Nested Access (dot notation)\n\n```json\n{\"schema.version\": \"2\"}\n```\n\n### Quick Reference\n\n| Operator | Syntax | Example |\n|----------|--------|---------|\n| Equality | `{\"field\": \"value\"}` | `{\"status\": \"active\"}` |\n| Array contains | `{\"field\": [\"a\", \"b\"]}` | `{\"tags\": [\"security\", \"oauth\"]}` |\n| `$in` | `{\"field\": {\"$in\": [...]}}` | `{\"priority\": {\"$in\": [\"high\", \"critical\"]}}` |\n| `$gt` / `$gte` | `{\"field\": {\"$gt\": N}}` | `{\"confidence\": {\"$gt\": 0.7}}` |\n| `$lt` / `$lte` | `{\"field\": {\"$lt\": N}}` | `{\"score\": {\"$lt\": 0.5}}` |\n| `$between` | `{\"field\": {\"$between\": [lo, hi]}}` | `{\"score\": {\"$between\": [0.3, 0.8]}}` |\n| Nested | `{\"a.b\": \"value\"}` | `{\"schema.version\": \"2\"}` |\n\n**Rules:**\n- Keys must match `[A-Za-z0-9_-]+` (dots separate nesting levels)\n- Operator dicts must contain exactly one operator\n- `$in` and array-contains require non-empty lists\n- `$between` requires exactly `[min, max]`\n\n> **Warning:** Operators MUST include the `$` prefix — write `$gte`, not `gte`. Without the prefix the filter is treated as an exact-match key and will silently return no results. Correct: `{\"confidence\": {\"$gte\": 0.7}}`. Wrong: `{\"confidence\": {\"gte\": 0.7}}`.\n\n## Using `search_notes` with Metadata\n\nPass `metadata_filters`, `tags`, or `status` to `search_notes`. Omit `query` for filter-only searches, or combine text and filters together.\n\n```python\n# Filter-only — find all notes with a given status\nsearch_notes(metadata_filters={\"status\": \"in-progress\"})\n\n# Filter-only — high-priority specs in a specific project\nsearch_notes(\n metadata_filters={\"type\": \"spec\", \"priority\": {\"$in\": [\"high\", \"critical\"]}},\n project=\"research\",\n page_size=10,\n)\n\n# Filter-only — notes with confidence above a threshold\nsearch_notes(metadata_filters={\"confidence\": {\"$gt\": 0.7}})\n\n# Convenience shortcuts for tags and status\nsearch_notes(status=\"active\")\nsearch_notes(tags=[\"security\", \"oauth\"])\n\n# Text search narrowed by metadata\nsearch_notes(\"authentication\", metadata_filters={\"status\": \"draft\"})\n\n# Mix text, tag shortcut, and advanced filter\nsearch_notes(\n \"oauth flow\",\n tags=[\"security\"],\n metadata_filters={\"confidence\": {\"$gt\": 0.7}},\n)\n```\n\n**Merging rules:** `tags` and `status` are convenience shortcuts merged into `metadata_filters` via `setdefault`. If the same key exists in `metadata_filters`, the explicit filter wins.\n\n## Tag Search Shorthand\n\nThe `tag:` prefix in a query converts to a tag filter automatically:\n\n```python\n# These are equivalent:\nsearch_notes(\"tag:tier1\")\nsearch_notes(\"\", tags=[\"tier1\"])\n\n# Multiple tags (comma or space separated) — all must match:\nsearch_notes(\"tag:tier1,alpha\")\n```\n\n## Example: Custom Frontmatter in Practice\n\nA note with custom fields:\n\n```markdown\n---\ntitle: Auth Design\ntype: spec\ntags: [security, oauth]\nstatus: in-progress\npriority: high\nconfidence: 0.85\n---\n\n# Auth Design\n\n## Observations\n- [decision] Use OAuth 2.1 with PKCE for all client types #security\n- [requirement] Token refresh must be transparent to the user\n\n## Relations\n- implements [[Security Requirements]]\n```\n\nQueries that find it:\n\n```python\n# By status and type\nsearch_notes(metadata_filters={\"status\": \"in-progress\", \"type\": \"spec\"})\n\n# By numeric threshold\nsearch_notes(metadata_filters={\"confidence\": {\"$gt\": 0.7}})\n\n# By priority set\nsearch_notes(metadata_filters={\"priority\": {\"$in\": [\"high\", \"critical\"]}})\n\n# By tag shorthand\nsearch_notes(\"tag:security\")\n\n# Combined text + metadata\nsearch_notes(\"OAuth\", metadata_filters={\"status\": \"in-progress\"})\n```\n\n## Guidelines\n\n- **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.\n- **Use text search for content queries.** If you're looking for notes *about* something, text search is better. Combine both when you need precision.\n- **Custom fields are free.** Any YAML key you put in frontmatter becomes queryable — no schema or configuration required.\n- **Multiple filters are AND.** `{\"status\": \"active\", \"priority\": \"high\"}` requires both conditions.\n- **Omit `query` for filter-only searches.** `search_notes(metadata_filters={\"status\": \"active\"})` works without a text query.\n- **Dot notation for nesting.** Access nested YAML structures with dots: `{\"schema.version\": \"2\"}` queries the `version` key inside a `schema` object.\n- **Tags shortcut is convenient but limited.** `tags` and `status` are sugar for common fields. For anything else, use `metadata_filters` directly.\n"
}SHA-256: b7ebff5015ebe05348d1dd0b691df0a40335eb84a4d259ddefa16ff35516f5b5