ai/personal-notes-skill.md

Personal Notes skill and semantic search

The personal-notes skill lives at ~/.agents/skills/personal-notes/. It lets an agent find a note by meaning, then use normal filesystem tools to read or edit the original Markdown. It does not depend on OpenClaw's memory_search or the old searchNotes MCP tool. Agents outside OpenClaw can use it if they load the skill, have Python execution permission, and can reach Ollama.

Components

  • Instructions: ~/.agents/skills/personal-notes/SKILL.md tells the agent to search before selecting a note, read the original file, then re-index after a write.
  • CLI: ~/.agents/skills/personal-notes/scripts/personal_notes_search.py uses Python 3's standard library. No pip package, MCP server, or scheduler is needed.
  • Vault: ~/Work/personal-notes/ contains the source Markdown. The CLI scans .md files recursively, skips symlinks and tool directories such as .git, and does not modify notes.
  • Embedding service: local Ollama at http://127.0.0.1:11434/api/embed, using nomic-embed-text by default. Neither the note text nor the query is sent to a hosted embedding API by this CLI.
  • Index: SQLite under ~/.cache/personal-notes/, with a database named from a hash of the vault's absolute path. The directory is created with private permissions; the database and lock file are permissioned for the user. The index stores note text chunks and their embeddings, so treat it as another local copy of note content, not a disposable public artifact. It is outside Git.

Use

python3 ~/.agents/skills/personal-notes/scripts/personal_notes_search.py search 'Astrid school early release calendar' --limit 3
python3 ~/.agents/skills/personal-notes/scripts/personal_notes_search.py index
python3 ~/.agents/skills/personal-notes/scripts/personal_notes_search.py index --force

search returns JSON with mode, synchronization counts, and ranked relative paths, scores, offsets, and short snippets. It scores chunk embeddings with cosine similarity, adds a small exact-word boost for filenames and content, and returns the best chunk for each file. Read the source file before quoting more context or editing.

index is an explicit refresh after create/edit. --force rebuilds embeddings for every Markdown file. The CLI accepts PERSONAL_NOTES_ROOT, PERSONAL_NOTES_CACHE, PERSONAL_NOTES_OLLAMA_URL, and PERSONAL_NOTES_EMBED_MODEL environment overrides (or corresponding flags before the subcommand) for another vault or host. Changing the configured model, endpoint, or root invalidates the old index identity and rebuilds it.

Freshness and failures

Every search scans the vault and hashes file contents, embedding only new or changed files and removing deleted or renamed paths. The skill also calls index immediately after an edit. This means edits from other editors are caught on the next search, with no watcher or timer. If a file changes while indexing is in progress, a later search sees its new hash and refreshes it.

If Ollama cannot index or answer a query, search returns mode: lexical and a warning, searching current Markdown text directly. This fallback is literal keyword matching, not semantic search. index fails rather than claiming success, and the next search/index retries. Ollama needs the nomic-embed-text model installed and the endpoint reachable.

The CLI is Unix/macOS-oriented: it uses fcntl to serialize simultaneous agent searches and SQLite updates. An agent with a restricted exec allowlist still needs permission for this script. In particular, the OpenClaw family-planner's current gog-only exec allowlist does not permit it, even though it has a separate family-scoped copy of the personal-notes skill. Do not assume giving an agent a skill grants execution or broader vault access.

Verification (2026-10-11)

The full vault indexed 185 Markdown files. A search for Astrid's school early-release calendar ranked family/astrid.md first, and a second search reported zero updates. A temporary test vault covered initial index, edited text, renamed/deleted paths, offline lexical fallback, and forced rebuild. SKILL.md passed the skill validator; the CLI passed Python syntax checking.

The local-notes service at port 8007 is a separate web app. Its old MCP search is not part of this workflow; removing MCP references does not require stopping the web app.