CLAUDE.md · git:20261020.eef4715 · 2026-10-20 · sha256 958d972ba54cc274
CLAUDE.md git:20261020.eef4715A
Immutable. This exact content never changes and is served at /api/v1/blob/958d972ba54cc274.
# Memex - CLI and Agent Plugins
Public code for a local knowledge base of collaborative memos and Claude Code transcripts.
Install the CLI from PyPI with `uv tool install memex-plugin`; the executable and
Python import remain `memex`. Claude Code supplies the lifecycle hooks and slash
commands; Codex and Kimi Code use portable skills. The vault layout below describes
user data separately from this public source checkout. See [README.md](README.md)
for installation and [DEVELOPMENT.md](DEVELOPMENT.md) for packaging and tests.
## Quick Start
The `memex` CLI and dreamer resolve the configured vault without changing directories. Run the source-only Obsidian wrapper by its checkout path; it selects a vault by name (`--vault`, default `memex`).
```bash
# Check vault status
memex status
# Search for something (RRF scoring is default)
memex search "authentication"
# Search recent docs only (7d, 2w, 3m)
memex search "plugin" --since=7d
# Rebuild index after changes
memex index rebuild --incremental
```
Semantic search uses a configured Gemini API key or a local LM Studio embedding server. For Gemini, use `op run --env-file ~/.secrets.op -- memex search "query"` only for an explicitly authorized 1Password-backed command, or `memex auth set-key` to opt into automatic loading from a local owner-only key file. Environment keys still work; keyword search remains available without a key. See [credential setup](docs/gemini-credentials.md).
## Your Role
When asked to act as the **memex curator**, condense project knowledge into `_project.md` overviews, maintain `[[wikilinks]]`, and cultivate the vault's knowledge topology. Search the vault when you need context for that work — don't rely on pre-loaded summaries.
## Folder Structure
```
memex-plugin/ # Public source checkout
├── src/memex/scripts/ # Core scripts (search, embeddings, etc.)
├── scripts/ # Compatibility shims and source-only helpers
├── hooks/ # Claude Code hooks (SessionStart, PreCompact, etc.)
├── commands/ # Slash commands (/memex:*)
├── skills/ # Intent-based skills
├── _templates/ # Bundled note templates
├── .claude-plugin/ # Claude Code plugin manifest + marketplace
├── plugins/memex/ # Codex root + generated portable skills (scripts/portable_plugin.py)
├── .agents/plugins/ # Codex marketplace → ./plugins/memex
└── kimi.plugin.json # Kimi skills manifest; no Claude commands/hooks
<vault>/ # Configured separately from the source checkout
├── projects/<name>/memos/ # Session memos and <memo>.obs.jsonl sidecars
├── projects/<name>/auto-memory/ # Synced Claude Code auto-memory files
├── projects/<name>/transcripts/ # Full conversation logs
├── topics/ # Cross-project concept notes + trails
├── _meta/ # Curator infrastructure, when configured
└── _views/ # Obsidian Base views, when configured
~/.memex/_index.sqlite # Default index location; see memex path --index
```
## Knowledge Artifacts
The vault stores three kinds of knowledge, each with a different temperature:
| Artifact | Temperature | Maintenance | Purpose |
|----------|------------|-------------|---------|
| **Memos** | Cold (append-only) | None — write once | "What happened" — session records |
| **Topics** | Warm (periodically updated) | Rewrite during tending | "What is X" — encyclopedic reference |
| **Trails** (`type: trail`) | Warm (periodically extended) | Append during tending | "How X evolved" — narrative across projects |
Topics and trails both live in `topics/`. Trails are distinguished by `type: trail` in frontmatter. Topics are rewritten (synthesized); trails are extended (new chapters appended). Trails are for concepts with genuine cross-project temporal evolution.
## Plugin Commands
- `/memex:save [title]` - Save current context as memo
- `/memex:status` - Show index stats and pending memos
- `/memex:open` - Open vault in Finder/Obsidian
Retrieval is skill-based — Claude searches automatically when you ask about past work. Vault maintenance is handled by the garden-tending skill. Use `memex search` or `memex timeline` CLI for direct access.
## CLI Commands
Shell commands — work from any terminal, any agent:
```bash
memex search <query> # Hybrid search (FTS + vector)
memex ask <question> # Deep retrieval with observations
memex timeline <date> # Browse by date (yesterday, 7d, last week)
memex read <path> # Read vault document to stdout
memex path # Print resolved vault path
memex check # Vault health — crystallization readiness
memex check --folders # Detect project-folder drift (cwd-fragment names, duplicate/split folders)
memex check --validate # Lint frontmatter (merged keys, missing title, dangling delimiter, no-frontmatter)
memex check --signals # Open Recent-signals per topic (closed-section-aware) — the fold backlog
memex check --condense # Project overviews lagging their memos (NEW after condensed:, ARR = git-added after condensed: but older-dated, GAP vs memos_digested)
memex status # Document count, chunks, last rebuild
memex context # Project detection and pending memo status
memex auth set-key # Save a key locally for automatic loading (hidden prompt)
memex auth status # Show credential source without exposing the key or calling Gemini
memex auth clear-key # Remove the saved local key
memex cloud login --url U # Save a memex cloud Worker URL + SYNC_TOKEN (hidden prompt)
memex cloud push # Mirror the index to the cloud (incremental; --include-transcripts, --dry-run)
memex cloud pull # Write memos saved by remote agents into the vault
memex cloud status # What the cloud holds; pending inbox memos
memex similarity # Detect near-duplicate topics (--threshold, --json)
memex scrub <path> # Detect API keys / secrets (--apply redacts in place)
memex mark-saved # Mark memo saved (prevents duplicate generation)
memex sync # Sync auto-memory into vault
memex graph <subcmd> # Backlinks, orphans, tags, stats
memex topic resolve <slug> # Resolve redirect_to chain (exit 0=ok, 1=skip/error)
memex index rebuild # Rebuild search index (--full for embeddings)
memex index status # Index health JSON (doc/chunk counts, embedding gaps)
memex index embed-missing # Embed chunks/obs missing from vec tables (retry after API failures)
memex index migrate-vec # Truncate vec tables to index_dimensions + add metadata cols (no re-embed)
memex index vacuum # VACUUM the index to reclaim free pages (e.g. after migrate-vec)
memex session discover # Find unprocessed sessions
memex session import # Import discovered sessions (--apply to execute, --exclude ID to skip)
memex session reconcile-orphans # Clear pending-memo signals whose memo carries their session_id (--apply; --trust-window also clears transcript/date matches)
memex obs topic <slug> # All observations for a topic (cluster lookup)
memex obs stats # Observation counts per topic
memex obs retag <old> <new> # Retag observations (for topic merges)
memex obs reassign --from-prefix X --to-prefix Y # Rewrite obs+chunks doc_path (folder rename SOP)
memex obs untagged # Observations with no topics (new-topic signals)
memex obs orphans # Mirror rows whose parent observation is gone (--apply to prune)
memex obs export-sidecars # One-off migration: write every doc's .obs.jsonl from the DB (--apply)
memex obs ingest-sidecars # Diff vault sidecars into the index without a full rebuild
memex obs sidecars # Sidecar health report (missing/orphan/stale/conflicts)
memex backfill obs # Store supplied observations; requires --replace or --append
memex backfill tokens # Backfill token counts on transcripts
memex backfill memos # Backfill has_memo on transcripts
memex backfill topic-tags # Propagate memo topics to observations
```
## Available Skills
| Skill | Purpose | When to Invoke |
|-------|---------|---------------|
| `recall` | Retrieve session memory — temporal browsing, keyword search, deep cross-session synthesis, or direct file loading | "what did I do yesterday?", "why did we...", "what patterns across...", "load the X topic" |
| `garden-tending` | Full vault lifecycle: diagnose, condense, connect, grow, maintain | "tend the garden", "update project overview", "check vault health", "find broken links" |
| `curator-practice` | Autonomous curator operating philosophy: attention, judgment, initiative | Autonomous tending, "what should I work on next?", scheduled/cron agents |
| `memo-writing` | Format and quality guidelines | `/memex:save`, "remember this", or when [memex] nudge appears |
| `project-consolidation` | Safely merge drifted/duplicate project folders (preserves obs via `obs reassign`) | "consolidate project folders", "merge duplicate projects", "fix detection drift", or after `memex check --folders` reports drift |
Skills are intent-based: Claude decides when to invoke based on user questions. This is more flexible than hooks which run on events.
## Gotchas
Domain-specific gotchas are in `.claude/rules/` and load automatically when working on relevant files. These are universal:
- **Vault selection is explicit or configured** — `memex` and dreamer use the configured vault; dreamer also accepts `--vault <path>`. The source-only `scripts/obsidian_cli.py` takes `--vault <name>`. Run relative script examples from the source checkout, not the vault
- **Observation topic slugs are not validated on insert** — `store_observation_topics` accepts any string. Use only slugs matching `topics/*.md` filenames. Invalid slugs leave tags pointing to nonexistent topics. `memex obs untagged` finds observations with no tags; it does not detect invalid slugs
- **Never delete from `observations` directly — route through `delete_observation_ids`** — three tables mirror it by observation id (`fts_observations`.rowid, `vec_observations`.rowid, `observation_topics`.observation_id). A bare `DELETE FROM observations` leaves mirror rows that every JOIN-ing read path silently discards, so the damage never surfaces in search — it shows up only as counters claiming observations the vault cannot return, and as orphan rows consuming vector-search KNN slots. `_OBS_MIRROR_TABLES` in `observations.py` is the single registry; a new mirror table must be added there or `test_mirror_registry_covers_every_table_referencing_observations` fails. Check any index with `memex obs orphans` (read-only; `--apply` prunes)
- **`memex backfill obs` requires an explicit write mode** — `--replace` deletes the document's existing observations and stores the supplied complete set; `--append` preserves them and adds observations. The Python `store_observations` API also requires `mode`. CLI output reports `mode`, `replaced`, and `skipped_duplicate` alongside stored/embedding counts and the sidecar path; net row loss emits a warning. Never use `--replace` for a partial addition.
- **memex cloud releases are tagged `cloud-v<version>` and are what deployed copies update to** — Deploy-button copies live in users' own repos and pull the newest `cloud-v*` tag through their `update-memex-cloud.yml` workflow (which fetches `cloud/scripts/update-from-upstream.mjs` from upstream on every run, so keep that script backward compatible). To release: bump `cloud/package.json` + `cloud/src/version.ts` together (a test enforces it), set `EXPECTED_SCHEMA` when adding a migration, set `CLOUD_SERVER_VERSION` in `src/memex/cloud.py`, tag `cloud-vX.Y.Z`, and start the release notes with `Server update: required | recommended | none`. Raise `MIN_SERVER_VERSION` only for "required" (push/pull then stop on older servers). Never rename or remove what button copies keep (`wrangler.jsonc` binding names, `package.json` name): the updater leaves those files alone and can only describe the change.
## Where to Go Next
Domain-specific details load automatically via `.claude/rules/` when you work on relevant files:
| Rules File | Covers | Loaded When Editing |
|------------|--------|-------------------|
| `architecture.md` | Memo generation layers, session lifecycle, search pipeline, frontmatter schema | `scripts/`, `src/memex/`, `hooks/`, `commands/`, `skills/` |
| `maintenance.md` | Periodic tasks, dev commands (rebuild, backfill, discover, sync) | `scripts/`, `src/memex/`, `_views/`, `topics/` |
| `configuration.md` | Config paths, path resolution, linking conventions, security | `scripts/`, `src/memex/`, `hooks/`, `.claude-plugin/` |
| `search-and-embeddings.md` | Embedding providers (Gemini primary, LM Studio fallback), chunking, search gotchas | `{scripts,src/memex/scripts}/{search,hybrid_search,embeddings,index_rebuild}.py` |
| `obsidian-cli.md` | Obsidian CLI 1.12.5 commands, SQLite fallback, graph navigation | `scripts/obsidian_cli.py`; `graph_queries.py` and `crystallization_check.py` under `scripts/` or `src/memex/scripts/` |
| `transcripts.md` | Transcript processing, JSONL format, system tag cleaning | transcript-related scripts |
| `hooks.md` | Hook implementation details, timing constraints | `hooks/` |
| `plugin-authoring.md` | Error patterns for commands, skills, hooks, scripts, plugin cache | `commands/`, `skills/`, `hooks/`, `scripts/`, `src/memex/`, `.claude-plugin/` |
| `python-patterns.md` | Python patterns used across the codebase | `scripts/`, `src/memex/`, `hooks/` |