basic-memory-pi-setup
Set up Basic Memory for a Pi workspace. Use when Basic Memory is not configured, /bm-status…
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.
$ npx -y skills add basicmachines-co/basic-memory --skill memory-metadata-search --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/memory-metadata-searchContext preview
The summary Claude sees to decide when to auto-load this skill.
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.
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."
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 (`title`, `type`, `tags`, `permalink`, `schema`) is automatically indexed as `entity_metadata` and becomes queryable.
All 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.
Filters are a JSON dictionary. Each key targets a frontmatter field; the value specifies the match condition. Multiple keys combine with **AND** logic.
{"status": "active"}{"tags": ["security", "oauth"]}{"priority": {"$in": ["high", "critical"]}}{"confidence": {"$gt": 0.7}}Numeric values use numeric comparison; strings use lexicographic comparison.
{"score": {"$between": [0.3, 0.8]}}{"owner": null}Matches notes with no `owner` key and notes whose `owner` is explicitly null. Null works only as a plain equality value — inside `$in`, `$between`, an array-contains list, or a comparison it is rejected, because those compare against the value and a comparison with null is never true.
{"schema.version": "2"}| Operator | Syntax | Example | |----------|--------|---------| | Equality | `{"field": "value"}` | `{"status": "active"}` | | Is null | `{"field": null}` | `{"owner": null}` | | Array contains | `{"field": ["a", "b"]}` | `{"tags": ["security", "oauth"]}` | | `$in` | `{"field": {"$in": [...]}}` | `{"priority": {"$in": ["high", "critical"]}}` | | `$gt` / `$gte` | `{"field": {"$gt": N}}` | `{"confidence": {"$gt": 0.7}}` | | `$lt` / `$lte` | `{"field": {"$lt": N}}` | `{"score": {"$lt": 0.5}}` | | `$between` | `{"field": {"$between": [lo, hi]}}` | `{"score": {"$between": [0.3, 0.8]}}` | | Nested | `{"a.b": "value"}` | `{"schema.version": "2"}` |
**Rules:**
can hold (a 400-digit integer, which JSON keeps as an ordinary `int`) is refused rather than compared against an infinite bound
regular files carry no frontmatter and are never hits, not even for `null`
> **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}}`.
Pass `metadata_filters`, `tags`, or `status` to `search_notes`. Omit `query` for filter-only searches, or combine text and filters together.
# 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:** `tags` and `status` are convenience shortcuts merged into `metadata_filters` via `setdefault`. If the same key exists in `metadata_filters`, the explicit filter wins.
The `tag:` prefix in a query converts to a tag filter automatically:
# 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")A note with custom fields:
--- 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:
# By status and type
search_notes(metadata_filters={AI conversations that actually remember. Never re-explain your project to your AI again. Join our Discord: https://discord.gg/tyvKNccgqN
Repo: basicmachines-co/basic-memory
Set up Basic Memory for a Pi workspace. Use when Basic Memory is not configured, /bm-status…
Use Basic Memory from Pi for durable continuity. Capture checkpoints with bm_capture, recall…
Guide Basic Memory setup in Tau. Use when a user wants to install or configure the Tau memory…
Save a deliberate work checkpoint to Basic Memory with the story, changed files,…
Capture a durable engineering decision in Basic Memory with rationale, alternatives,…
Orient Claude from Basic Memory before substantial repo work by reading active tasks, open…