# https://github.com/n0mad-ai/bastra-recall Project Manual

Generated at: 2026-07-04 02:26:21 UTC

## Table of Contents

- [Overview and Installation (Guided Wizard, Distros, First-Run)](#page-1)
- [System Architecture and Memory Pipeline (Vault, Index, Recall/Save, Schema)](#page-2)
- [AI Client Integration, Reflex Layer, and Transport (MCP Forwarder, REST, Hooks)](#page-3)
- [Self-Improving Lifecycle, Telemetry, and Operational Concerns](#page-4)

<a id='page-1'></a>

## Overview and Installation (Guided Wizard, Distros, First-Run)

### Related Pages

Related topics: [AI Client Integration, Reflex Layer, and Transport (MCP Forwarder, REST, Hooks)](#page-3)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [README.md](https://github.com/n0mad-ai/bastra-recall/blob/main/README.md)
- [package.json](https://github.com/n0mad-ai/bastra-recall/blob/main/package.json)
- [distribution/Install Bastra.command](https://github.com/n0mad-ai/bastra-recall/blob/main/distribution/Install%20Bastra.command)
- [distribution/homebrew/bastra-recall.rb](https://github.com/n0mad-ai/bastra-recall/blob/main/distribution/homebrew/bastra-recall.rb)
- [packages/bastra-recall/bin/bastra.mjs](https://github.com/n0mad-ai/bastra-recall/blob/main/packages/bastra-recall/bin/bastra.mjs)
- [packages/bastra-recall/package.json](https://github.com/n0mad-ai/bastra-recall/blob/main/packages/bastra-recall/package.json)
</details>

# Overview and Installation (Guided Wizard, Distros, First-Run)

`bastra-recall` is a self-improving memory layer for AI coding assistants. It persists a vault of long-term memories (Markdown + sidecars) and exposes them to MCP-aware clients through a small daemon. The current distribution model revolves around three channels: an `npx` runner, a macOS double-clickable shell helper, and a Homebrew formula. All three ultimately delegate to the same CLI entry point, `bastra`, defined in the workspace's `bin/` directory. Source: [packages/bastra-recall/bin/bastra.mjs]()

## Distribution Channels

### `npx bastra-recall@latest`

The fastest first-run path. Running `npx bastra-recall@latest install all` resolves the latest published package, builds nothing locally, and registers the daemon's MCP forwarder into each selected AI client's config. Source: [README.md]()

A known limitation surfaces when the npx cache is later evicted: surface registrations point inside `~/.npm/_npx/<hash>/node_modules/@bastra-recall/daemon/dist/mcp-forwarder.js`, which is ephemeral. Issue #180 documents this — recommended remediation is a global `npm i -g @bastra-recall/daemon` or a Homebrew install so the forwarder path is stable. Source: [issues #180]()

### macOS `Install Bastra.command`

A double-clickable shell helper at the repository root that wraps the npx invocation and pre-fills common flags. Source: [distribution/Install Bastra.command](). It is the recommended path for non-technical macOS users and is the artifact exercised by the clean-VM smoke run tracked in issue #90.

### Homebrew tap

`brew install n0mad-ai/tap/bastra-recall`. The formula runs `npm install` and `npm run build` for the daemon workspace. Source: [distribution/homebrew/bastra-recall.rb](). Two clean-VM defects were filed in v0.7.0-beta.4: the formula built only the `daemon` workspace, omitting `core` and `statusline` dists from the tarball (issue #184), and modern Homebrew refuses third-party taps by default — users must run `brew trust --formula n0mad-ai/tap/bastra-recall` first (issue #182). Both are fixed in v0.7.0-beta.5.

## The Guided Install Wizard

Beginning with v0.7.0-beta.5, `bastra install` (no arguments, in an interactive terminal) launches a guided wizard that replaces the previous y/n prompt chain. The flow is:

1. **Memory vault** — choose `~/BastraVault` (default), a custom folder, or an existing vault.
2. **AI clients** — multi-select arrow-key list across Claude Code, Claude Desktop, and other MCP surfaces.
3. **Embedding model** — Ollama provisioning, with skip / already-active / dry-run branches.

The wizard exists precisely because v0.7.0-beta.4's first-run wall surfaced in clean-VM testing: `install all` failed for every surface with `✗ error: vault path required` when no `--vault` flag or `BASTRA_VAULT_PATH` env var was set (issue #178). The wizard now collects this value before any surface registration, eliminating the error class entirely.

Source: [v0.7.0-beta.5 release notes]()

## CLI Surface and Workspace Layout

The CLI entry point dispatches subcommands (`install`, `uninstall`, `doctor`, `status`, `uninstall all`) to workspace packages. Source: [packages/bastra-recall/bin/bastra.mjs](). The monorepo is split into `@bastra-recall/core`, `@bastra-recall/daemon`, and `@bastra-recall/statusline`, each with its own `package.json`; the daemon is the only one required to run the MCP forwarder. Source: [package.json]()

```mermaid
flowchart LR
  A["npx / Install.command / brew"] --> B["bastra CLI"]
  B --> C["@bastra-recall/core"]
  B --> D["@bastra-recall/daemon"]
  D --> E["Claude Code"]
  D --> F["Claude Desktop"]
  D --> G["Other MCP surfaces"]
  C --> H[(BastraVault)]
```

## First-Run Verification

After install, the standard check sequence is:

- `bastra doctor` — validates vault path, daemon reachability, Ollama status, and per-surface registration integrity.
- `bastra status` — prints the active forwarder path (must not point inside an `_npx` cache) and per-surface state.

Two additional clean-VM findings are worth noting for any operator running the wizard on a fresh machine:

- `uninstall all` may report `skill: kept (shared with Claude Desktop)` even when the Claude Desktop surface was uninstalled in the same run — a false positive in the dependency-detection heuristic (issue #181).
- The Ollama fresh-install path on clean macOS (issue #90) is the one branch that cannot be exercised on a pre-provisioned dev box; it is verified only in the clean-VM harness.

Source: [issues #90, #181]()

## Choosing a Distribution

| Channel | Best for | Stability of forwarder path | Requires build |
|---|---|---|---|
| `npx bastra-recall@latest` | One-shot tryout, CI smoke | Ephemeral until globally installed | No |
| `Install Bastra.command` | macOS non-technical users | Ephemeral (wraps npx) | No |
| Homebrew tap | Daily-driver macOS | Stable under `/opt/homebrew` | Yes |
| Global npm `-g` | Linux / Windows | Stable under `npm config get prefix` | No |

For any user planning to keep `bastra-recall` installed across cache cleanups or system reboots, the Homebrew or global-npm path is preferred over the npx-only flow.

---

<a id='page-2'></a>

## System Architecture and Memory Pipeline (Vault, Index, Recall/Save, Schema)

### Related Pages

Related topics: [AI Client Integration, Reflex Layer, and Transport (MCP Forwarder, REST, Hooks)](#page-3), [Self-Improving Lifecycle, Telemetry, and Operational Concerns](#page-4)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [docs/architecture.md](https://github.com/n0mad-ai/bastra-recall/blob/main/docs/architecture.md)
- [docs/memory-schema.md](https://github.com/n0mad-ai/bastra-recall/blob/main/docs/memory-schema.md)
- [docs/triggers.md](https://github.com/n0mad-ai/bastra-recall/blob/main/docs/triggers.md)
- [docs/taxonomy.md](https://github.com/n0mad-ai/bastra-recall/blob/main/docs/taxonomy.md)
- [docs/openapi.yaml](https://github.com/n0mad-ai/bastra-recall/blob/main/docs/openapi.yaml)
- [packages/core/src/index.ts](https://github.com/n0mad-ai/bastra-recall/blob/main/packages/core/src/index.ts)
- [packages/core/src/vault/layout.ts](https://github.com/n0mad-ai/bastra-recall/blob/main/packages/core/src/vault/layout.ts)
- [packages/core/src/recall/recall.ts](https://github.com/n0mad-ai/bastra-recall/blob/main/packages/core/src/recall/recall.ts)
- [packages/core/src/save/save.ts](https://github.com/n0mad-ai/bastra-recall/blob/main/packages/core/src/save/save.ts)
- [packages/core/src/index/embeddings.ts](https://github.com/n0mad-ai/bastra-recall/blob/main/packages/core/src/index/embeddings.ts)
- [packages/core/src/enrich/related.ts](https://github.com/n0mad-ai/bastra-recall/blob/main/packages/core/src/enrich/related.ts)
- [packages/daemon/src/server.ts](https://github.com/n0mad-ai/bastra-recall/blob/main/packages/daemon/src/server.ts)
</details>

# System Architecture and Memory Pipeline (Vault, Index, Recall/Save, Schema)

## 1. Purpose and Scope

bastra-recall is a local-first memory layer that gives MCP-capable AI clients (Claude Code, Claude Desktop, and friends) long-term recall and save capabilities over a human-readable Markdown vault. The product is shaped by two non-negotiable constraints: the vault must remain browsable in Obsidian, and the daemon must speak the Model Context Protocol so it can attach to any registered surface without code changes. Everything in the architecture exists to keep those two contracts intact while still surfacing memories fast enough to be useful inside a model turn. Source: [docs/architecture.md:1-40]()

The system is split into a Rust-style layered workspace:

- `packages/core` — pure library: vault layout, schema, save/recall pipeline, embeddings, enrichers, curator, telemetry.
- `packages/daemon` — long-running MCP server that hosts the forwarder registration and exposes the core over a JSON-RPC surface.
- `packages/statusline` — the CLI status reader that visualises context-tax and lifecycle state.

The vault path is resolved at install time (`--vault`, `BASTRA_VAULT_PATH`, or the guided wizard default `~/BastraVault`). The first-run wall described in issue #178 was caused by failing that resolution up-front instead of guiding the user through it. Source: [docs/architecture.md:42-78]()

## 2. Vault Layout and Memory Schema

The vault is a directory of Markdown files plus a hidden index directory. The on-disk shape is fixed by `vault/layout.ts` and consists of three top-level zones:

| Zone | Purpose | Visibility |
|------|---------|------------|
| `memories/` | One Markdown file per memory (the canonical record) | Obsidian-readable |
| `.bastra/index/` | Vector index, lock files, embeddings cache | Hidden (`.*`) |
| `.bastra/telemetry/` | Events JSONL + per-memory sidecars | Hidden (`.*`) |

Each memory is a Markdown document with YAML front-matter carrying the structured fields and a Markdown body carrying the human prose. The schema is documented in [docs/memory-schema.md](https://github.com/n0mad-ai/bastra-recall/blob/main/docs/memory-schema.md) and enforced by the loader in `core/src/vault/schema.ts`. Source: [docs/memory-schema.md:1-60]()

Key front-matter fields:

- `id` — stable, ULID-derived; used as the wikilink target inside Obsidian.
- `kind` — one of `note`, `decision`, `snippet`, `reference`, `doc`.
- `tags` — taxonomy slugs from [docs/taxonomy.md](https://github.com/n0mad-ai/bastra-recall/blob/main/docs/taxonomy.md).
- `created_at`, `updated_at`, `last_surfaced_at` — time-driven staleness inputs.
- `embedding` — opaque, regenerated on save; not for human editing.
- `related` — list of `[[<id>]]` cross-links produced by the RelatedEnricher.

`doc`-kind memories are special: they are paired with a `*.md` sidecar that holds parsed metadata about an external document (e.g. an inbox photo). The sidecar carries the body the model sees, while the linked file stays on disk unchanged. Source: [docs/memory-schema.md:62-110]()

A real-vault incident (issue #188, 2026-07-04) showed that the RelatedEnricher was emitting `[[<doc-id>]]` wikilinks that Obsidian could not resolve because the target file did not exist by that slug — a 0-byte `doc-inbox-photo-….md` sat in the vault root for 11 days referenced by 11 links. Source: [packages/core/src/enrich/related.ts:40-88]() — relevant issue: [#188](https://github.com/n0mad-ai/bastra-recall/issues/188)

## 3. Index, Recall, and Save Pipeline

```mermaid
flowchart LR
    A[User prompt] --> B[Daemon /recall]
    B --> C[recall.ts: embed query]
    C --> D[Vector index top-K]
    D --> E[Staleness + ranking]
    E --> F[Hint surface]
    F --> G[Model loads /act_on]
    G --> H[Telemetry event]
    S[User /save] --> I[Daemon /save]
    I --> J[save.ts: parse + classify]
    J --> K[Embed + upsert]
    K --> L[RelatedEnricher]
    L --> M[Curator scan]
    M --> N[Markdown + front-matter]
    N --> O[Vault file]
```

The **recall** path begins when a surface tool call hits the daemon. `recall.ts` embeds the query (Ollama by default, pluggable through `core/src/index/embeddings.ts`), retrieves the top-K nearest neighbours from the vector store, applies a time-based staleness decay, ranks, and emits a compact hint payload — small enough that the model can decide whether to load any of it. Source: [packages/core/src/recall/recall.ts:1-90]()

The **save** path is more involved. `save.ts` normalises the incoming payload (kind, tags, body), writes or merges the front-matter, regenerates the embedding, upserts into the index, and then hands the file to the enricher chain. The chain runs the RelatedEnricher (cosine ≥0.9 against the same scan batch) and any taxonomy back-fillers. The end state is a single Markdown file on disk plus a delta applied to the index — there is no separate “database” to keep in sync. Source: [packages/core/src/save/save.ts:1-130]()

Embedding and recall configuration live in `core/src/index/embeddings.ts`; the daemon passes them through as MCP tool parameters. The MCP surface is documented in [docs/openapi.yaml](https://github.com/n0mad-ai/bastra-recall/blob/main/docs/openapi.yaml). Source: [packages/daemon/src/server.ts:30-120]()

## 4. Lifecycle: Curator and Telemetry

Every recall episode writes an append-only event to `.bastra/telemetry/events.jsonl` carrying `surfaced`, `loaded`, and `acted_on` markers per memory. The schema is in [docs/memory-schema.md](https://github.com/n0mad-ai/bastra-recall/blob/main/docs/memory-schema.md). Issue #154 points out that this is the only durable usage signal — the per-memory aggregate is currently recomputed on each `stats` call, which makes lifecycle decisions brittle once logs rotate. The proposed fix is a per-memory sidecar that the curator writes next to each memory. Source: [packages/core/src/telemetry/events.ts:1-70]() — relevant issue: [#154](https://github.com/n0mad-ai/bastra-recall/issues/154)

The curator is the first *acting* lifecycle component (lifecycle wave C, v0.7.0-beta.5). Phase A is a deterministic, score-only, idle-gated staleness pass: it scans the sidecars, flags memories surfaced ≥3× with zero `acted_on` as archival candidates, and writes a score delta. It does not delete or move files — it only mutates the score used by the recall ranker. The motivation, recorded in issue #155, is that the context-tax list in `stats.ts` has always been report-only and the candidate surface accumulates dead weight that keeps costing hint tokens. Source: [packages/core/src/curator/curate.ts:1-95]() — relevant issue: [#155](https://github.com/n0mad-ai/bastra-recall/issues/155)

## 5. Operational Notes from the Field

Three install/lifecycle failures surfaced during the clean-VM smoke run (issue #90) and are worth knowing for anyone operating the pipeline:

- **Ephemeral forwarder paths.** `npx` installs register the MCP forwarder at `~/.npm/_npx/<hash>/node_modules/@bastra-recall/daemon/dist/mcp-forwarder.js`, which is wiped on cache eviction. The fix is to install globally before registering surfaces. Source: [#180](https://github.com/n0mad-ai/bastra-recall/issues/180)
- **Surface state on uninstall.** `uninstall all` correctly removes registrations but the Claude Code step mis-reports the skill as kept when Desktop is also uninstalled in the same run. Source: [#181](https://github.com/n0mad-ai/bastra-recall/issues/181)
- **Homebrew tap trust.** Current Homebrew refuses third-party taps; the user must run `brew trust --formula n0mad-ai/tap/bastra-recall` before install. Source: [#182](https://github.com/n0mad-ai/bastra-recall/issues/182)

These do not change the pipeline semantics, but they shape the install story and explain why the v0.7.0-beta.5 guided wizard was introduced. Source: [docs/triggers.md:1-50]() — release: [v0.7.0-beta.5](https://github.com/n0mad-ai/bastra-recall/releases/tag/v0.7.0-beta.5)

---

<a id='page-3'></a>

## AI Client Integration, Reflex Layer, and Transport (MCP Forwarder, REST, Hooks)

### Related Pages

Related topics: [Overview and Installation (Guided Wizard, Distros, First-Run)](#page-1), [System Architecture and Memory Pipeline (Vault, Index, Recall/Save, Schema)](#page-2)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [docs/hooks.md](https://github.com/n0mad-ai/bastra-recall/blob/main/docs/hooks.md)
- [docs/issues/cc-mcp-progress-rendering.md](https://github.com/n0mad-ai/bastra-recall/blob/main/docs/issues/cc-mcp-progress-rendering.md)
- [packages/skill/SKILL.md](https://github.com/n0mad-ai/bastra-recall/blob/main/packages/skill/SKILL.md)
- [packages/daemon/src/index.ts](https://github.com/n0mad-ai/bastra-recall/blob/main/packages/daemon/src/index.ts)
- [packages/daemon/src/http.ts](https://github.com/n0mad-ai/bastra-recall/blob/main/packages/daemon/src/http.ts)
- [packages/daemon/src/mcp-forwarder.ts](https://github.com/n0mad-ai/bastra-recall/blob/main/packages/daemon/src/mcp-forwarder.ts)
</details>

# AI Client Integration, Reflex Layer, and Transport (MCP Forwarder, REST, Hooks)

## Purpose and Scope

Bastra-recall exposes its recall, store, enrich, and audit capabilities to AI clients (Claude Code, Claude Desktop, Codex CLI) through three coordinated surfaces that all live inside the daemon workspace (`packages/daemon`): an **MCP forwarder** speaking JSON-RPC over stdio, a **REST/HTTP** surface for tooling and health checks, and a **hooks/reflex** layer that observes session events emitted by each client. The daemon process (`packages/daemon/src/index.ts`) owns the lifecycle of all three transports and routes them into the unified core pipeline; nothing client-facing bypasses it. Source: [packages/daemon/src/index.ts:1-60]().

## MCP Forwarder Transport

The forwarder (`packages/daemon/src/mcp-forwarder.ts`) is the only transport the AI clients themselves speak. It implements the Model Context Protocol over stdio and forwards tool calls (`recall`, `store`, `enrich`, `audit`, etc.) to the daemon's tool surface. Surface registration writes the absolute path of the compiled `dist/mcp-forwarder.js` into each client's MCP config so the client can launch the forwarder as an MCP server process. Source: [packages/daemon/src/mcp-forwarder.ts:1-120]().

A known footgun: when the user installs via `npx`, the registered path lives inside `~/.npm/_npx/<hash>/node_modules/@bastra-recall/daemon/dist/mcp-forwarder.js` — the npx cache is ephemeral, so `npm cache clean` or eviction breaks every surface registration. Issue #180 tracks this; the fix is to copy the forwarder to a stable location during install and re-register against that. Source: issue #180.

Forwarded MCP progress notifications are rendered with Claude-Code-specific rules documented in [docs/issues/cc-mcp-progress-rendering.md](), which exists precisely because MCP progress semantics differ across clients.

## REST / HTTP Surface

The REST layer (`packages/daemon/src/http.ts`) is the second transport. It is bound to a loopback interface and serves the install wizard, the statusline surface, and developer/CI tooling — AI clients do **not** call it directly. It exposes health, vault stats, and recall endpoints that share the daemon's lifecycle and event log with the forwarder. Source: [packages/daemon/src/http.ts:1-80]().

The HTTP surface is what the Homebrew formula and the clean-VM smoke tests exercise; when the daemon dist is missing from the tarball, the formula's daemon build still ships, but anything that probes HTTP on a clean machine fails (issue #184).

## Hooks — The Reflex Layer

The third transport is the **hooks layer**, defined in [docs/hooks.md](). Hooks are thin per-surface shell hooks installed by the surface installer that observe client session events (`session.start`, `session.end`, `prompt.submit`, tool invocations) and emit structured events back to the daemon through the forwarder's event channel. The reflex layer is read-only with respect to memory content — it only writes telemetry. Source: [docs/hooks.md:1-120]().

This is the layer that records the `surfaced / loaded / acted_on` episodes referenced by issue #154 (telemetry sidecar) and feeds the deterministic usage-driven staleness pass proposed in issue #155 (curator phase A). The reflex layer is intentionally narrow so lifecycle decisions stay auditable: events in, score deltas out, no silent rewrites.

## Skill Package and Surface Lifecycle

The Skill package (`packages/skill/SKILL.md`) carries Claude Code's skill instructions and the per-surface registration descriptor used by the installer. Each surface — `claude-code`, `claude-desktop`, `codex` — registers (a) the forwarder path and (b) its own hook scripts. Uninstallation must remove both; issue #181 documents a case where the Claude Code skill was kept under the predicate "shared with Claude Desktop" even after the `claude-desktop` surface had been uninstalled in the same run, because the predicate looked at filesystem state from the wrong surface's view. Source: [packages/skill/SKILL.md:1-80](), issue #181.

## Transport Summary

| Transport | Wire | Direction | Primary Consumer |
|---|---|---|---|
| MCP Forwarder | stdio / JSON-RPC | Bidirectional tool calls | Claude Code, Claude Desktop, Codex CLI |
| REST HTTP | loopback HTTP | Daemon → tooling | Statusline, install wizard, CI |
| Hooks | shell → forwarder event channel | Client → daemon telemetry | Reflex / curator pipeline |

All three transports are owned by the daemon and terminated at `packages/daemon/src/index.ts`; they share the same event log and lifecycle, which is what makes the per-memory usage sidecar (#154) and the curator staleness pass (#155) possible without per-surface adapters.

---

<a id='page-4'></a>

## Self-Improving Lifecycle, Telemetry, and Operational Concerns

### Related Pages

Related topics: [System Architecture and Memory Pipeline (Vault, Index, Recall/Save, Schema)](#page-2)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [PLAN.md](https://github.com/n0mad-ai/bastra-recall/blob/main/PLAN.md)
- [CHANGELOG.md](https://github.com/n0mad-ai/bastra-recall/blob/main/CHANGELOG.md)
- [docs/eval-geometry.md](https://github.com/n0mad-ai/bastra-recall/blob/main/docs/eval-geometry.md)
- [docs/commons.md](https://github.com/n0mad-ai/bastra-recall/blob/main/docs/commons.md)
- [docs/survival.md](https://github.com/n0mad-ai/bastra-recall/blob/main/docs/survival.md)
- [packages/daemon/src/curator.ts](https://github.com/n0mad-ai/bastra-recall/blob/main/packages/daemon/src/curator.ts)
- [packages/daemon/src/stats.ts](https://github.com/n0mad-ai/bastra-recall/blob/main/packages/daemon/src/stats.ts)
- [packages/daemon/src/enricher.ts](https://github.com/n0mad-ai/bastra-recall/blob/main/packages/daemon/src/enricher.ts)
- [packages/daemon/src/cli/install.ts](https://github.com/n0mad-ai/bastra-recall/blob/main/packages/daemon/src/cli/install.ts)
- [packages/daemon/src/cli/uninstall.ts](https://github.com/n0mad-ai/bastra-recall/blob/main/packages/daemon/src/cli/uninstall.ts)
- [Formula/bastra-recall.rb](https://github.com/n0mad-ai/bastra-recall/blob/main/Formula/bastra-recall.rb)
</details>

# Self-Improving Lifecycle, Telemetry, and Operational Concerns

## Overview and Scope

The bastra-recall daemon persists a long-lived, file-backed memory vault for AI surfaces (Claude Code, Claude Desktop, etc.). Over time the vault accumulates: (a) recall episodes written to an append-only events JSONL, (b) document and memory sidecars created by the Enricher, and (c) surface registrations written to each host AI client. The "self-improving lifecycle" is the layer that watches this state and decides what to keep, demote, cross-link, or audit, while the telemetry pipeline feeds the decisions with durable per-memory usage data. Operational concerns (install, uninstall, brew taps, npx cache) sit alongside because every cleanup decision is exercised through the same CLI surface that ships the daemon.

The scope of this page is the boundary between **curator** (acts on vault state), **telemetry** (observes recall episodes), and **operational plumbing** (install/uninstall/brew). See [PLAN.md]() for the high-level project layout and [CHANGELOG.md]() for shipped behavior.

## Curator: Deterministic Usage-Driven Staleness

Phase A of the curator is a deterministic, score-only, idle-gated staleness pass. It exists because the existing query-time staleness heuristic is purely time-driven and the `stats.ts` context-tax list (memories surfaced ≥3× with 0 `acted_on`) is report-only — nothing acts on it. The candidate surface therefore accumulates dead weight that keeps costing hint tokens. Source: [packages/daemon/src/curator.ts:1-120]() and the proposal in issue #155.

The pass has three required properties:

- **Deterministic** — given the same inputs and the same sidecar aggregate, it must produce the same score.
- **Score-only** — the phase writes a staleness score to a sidecar field; it never mutates, archives, or deletes a memory in this phase.
- **Idle-gated** — it runs only when the vault is otherwise quiet, so curator work never contends with active recall episodes.

Source: [packages/daemon/src/curator.ts:120-260]() describes the score composition and the idle gate. The score is built from the per-memory usage aggregate (see next section) and a half-life decay, both of which are pure functions of sidecar data — hence the determinism guarantee.

## Telemetry: Per-Memory Usage Sidecar

The events JSONL already records recall episodes per memory (`surfaced`, `loaded`, `acted_on`), but it is rotated and recomputed by `stats.ts` on every read. There is no durable per-memory aggregate, so lifecycle decisions cannot be made from a stable source. The fix proposed in issue #154 is a per-memory usage sidecar: an append-only aggregate written next to the memory it describes, containing running counters for the three episode types.

The aggregate is what the curator reads in phase A. Because the sidecar is append-only and lives in the vault tree, lifecycle decisions (staleness scoring, ranking feedback, archival candidacy) survive log rotation and are reproducible from the vault alone. Source: [packages/daemon/src/curator.ts:40-90]() consumes the sidecar; [packages/daemon/src/stats.ts:1-80]() is the report layer that stays backward-compatible over both raw logs and the new sidecar.

| Event | Source | Persisted to | Read by |
| --- | --- | --- | --- |
| surfaced | recall pipeline | events JSONL + sidecar | curator, stats |
| loaded | recall pipeline | events JSONL + sidecar | curator, stats |
| acted_on | host AI client hook | events JSONL + sidecar | curator, stats |

## Operational Concerns Surfaced by the Clean-VM Run

The clean-VM smoke (issue #90) is the only path that exercises the entire install → use → uninstall surface on a machine that does not already have Ollama or a prior install. Several issues that affect the lifecycle were filed from it and remain relevant:

1. **Guided install wizard** — `bastra install` with no arguments now launches an interactive wizard (memory vault choice, AI clients, etc.) instead of failing with `vault path required` (issue #178). Source: [packages/daemon/src/cli/install.ts:1-160]() and the v0.7.0-beta.5 release notes in [CHANGELOG.md]().
2. **npx cache ephemerality** — `npx bastra-recall@latest install all` was registering surface forwarders pointing inside `~/.npm/_npx/<hash>/node_modules/...`, which is wiped by `npm cache clean` (issue #180). Surface registrations must point at a stable location; the fix is reflected in [packages/daemon/src/cli/install.ts:160-280]().
3. **Homebrew tap trust** — modern Homebrew refuses third-party taps without an explicit trust step (issue #182). The docs and `Install.command` must call `brew trust --formula n0mad-ai/tap/bastra-recall` before `brew install`.
4. **Brew formula build scope** — the formula only built the daemon workspace, leaving core/statusline `dist/` missing from the tarball and producing 67 TS7006/TS7016 errors (issue #184). The formula in [Formula/bastra-recall.rb]() must build every workspace it ships.
5. **Uninstall cross-surface check** — `uninstall all` reported `skill: kept (shared with Claude Desktop)` even though the claude-desktop surface had been uninstalled in the same run (issue #181). Source: [packages/daemon/src/cli/uninstall.ts:1-200]().
6. **Vault self-audit surfaces** — issue #140 proposes rendering audit zones (`sync-conflict`, `dangling`, `light/heavy index`) as Markdown in the vault so Obsidian becomes the viewer; the audit reads from the same sidecars the curator writes.
7. **Enricher wikilink resolution** — the RelatedEnricher cross-links sibling sidecars with `[[<doc-id>]]` which Obsidian cannot resolve to a real file, creating 0-byte stray notes (issue #188). Source: [packages/daemon/src/enricher.ts:1-160]().

## Putting It Together

The lifecycle, telemetry, and operational layers share one invariant: every decision is derivable from the vault tree alone. The curator reads the per-memory sidecar; the audit reads the sidecar graph; the enricher writes cross-link sidecars; the install/uninstall CLI mutates surface registrations, not the vault. When the brew formula, the npx cache, or the install wizard gets a path wrong, the symptom surfaces as a lifecycle anomaly (a missing sidecar, a stale forwarder, a dangling surface) — which is why the clean-VM run is the canary for all of these concerns. Source: [PLAN.md]() for the layered design and [docs/survival.md]() for the operational boundary.

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Pitfall Log

Project: n0mad-ai/bastra-recall

Summary: Found 32 structured pitfall item(s), including 1 high/blocking item(s). Top priority: Security or permission risk - Security or permission risk requires verification.

## 1. Security or permission risk - Security or permission risk requires verification

- Severity: high
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/n0mad-ai/bastra-recall/issues/140

## 2. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: brew install fails on untrusted tap — docs and Install.command miss the new 'brew trust' step
- User impact: Developers may fail before the first successful local run: brew install fails on untrusted tap — docs and Install.command miss the new 'brew trust' step
- Evidence: failure_mode_cluster:github_issue | https://github.com/n0mad-ai/bastra-recall/issues/182

## 3. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: homebrew formula build fails — builds only the daemon workspace, core/statusline dist missing from the tarball
- User impact: Developers may fail before the first successful local run: homebrew formula build fails — builds only the daemon workspace, core/statusline dist missing from the tarball
- Evidence: failure_mode_cluster:github_issue | https://github.com/n0mad-ai/bastra-recall/issues/184

## 4. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: install via npx registers the forwarder path inside the ephemeral npx cache
- User impact: Developers may fail before the first successful local run: install via npx registers the forwarder path inside the ephemeral npx cache
- Evidence: failure_mode_cluster:github_issue | https://github.com/n0mad-ai/bastra-recall/issues/180

## 5. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: install: first-run wall — 'vault path required' error instead of a guided vault choice
- User impact: Developers may fail before the first successful local run: install: first-run wall — 'vault path required' error instead of a guided vault choice
- Evidence: failure_mode_cluster:github_issue | https://github.com/n0mad-ai/bastra-recall/issues/178

## 6. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: test: verify the Ollama fresh-install (brew) path on a clean macOS env
- User impact: Developers may fail before the first successful local run: test: verify the Ollama fresh-install (brew) path on a clean macOS env
- Evidence: failure_mode_cluster:github_issue | https://github.com/n0mad-ai/bastra-recall/issues/90

## 7. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: uninstall all: skill kept as 'shared with Claude Desktop' although Desktop was uninstalled in the same run
- User impact: Developers may fail before the first successful local run: uninstall all: skill kept as 'shared with Claude Desktop' although Desktop was uninstalled in the same run
- Evidence: failure_mode_cluster:github_issue | https://github.com/n0mad-ai/bastra-recall/issues/181

## 8. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: v0.6.0-beta.1
- User impact: Upgrade or migration may change expected behavior: v0.6.0-beta.1
- Evidence: failure_mode_cluster:github_release | https://github.com/n0mad-ai/bastra-recall/releases/tag/v0.6.0-beta.1

## 9. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: v0.6.5-beta.1
- User impact: Upgrade or migration may change expected behavior: v0.6.5-beta.1
- Evidence: failure_mode_cluster:github_release | https://github.com/n0mad-ai/bastra-recall/releases/tag/v0.6.5-beta.1

## 10. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: v0.6.6-beta.1
- User impact: Upgrade or migration may change expected behavior: v0.6.6-beta.1
- Evidence: failure_mode_cluster:github_release | https://github.com/n0mad-ai/bastra-recall/releases/tag/v0.6.6-beta.1

## 11. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: v0.7.0-beta.3
- User impact: Upgrade or migration may change expected behavior: v0.7.0-beta.3
- Evidence: failure_mode_cluster:github_release | https://github.com/n0mad-ai/bastra-recall/releases/tag/v0.7.0-beta.3

## 12. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: v0.7.0-beta.5 — guided install + lifecycle wave C
- User impact: Upgrade or migration may change expected behavior: v0.7.0-beta.5 — guided install + lifecycle wave C
- Evidence: failure_mode_cluster:github_release | https://github.com/n0mad-ai/bastra-recall/releases/tag/v0.7.0-beta.5

## 13. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/n0mad-ai/bastra-recall/issues/182

## 14. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/n0mad-ai/bastra-recall/issues/184

## 15. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/n0mad-ai/bastra-recall/issues/180

## 16. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/n0mad-ai/bastra-recall/issues/178

## 17. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/n0mad-ai/bastra-recall/issues/90

## 18. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/n0mad-ai/bastra-recall/issues/181

## 19. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: capability.host_targets | https://github.com/n0mad-ai/bastra-recall

## 20. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: Vault self-audit surfaced as Markdown in the vault (Obsidian as the viewer) — conflicts, demand-gaps, dangling
- User impact: Developers may misconfigure credentials, environment, or host setup: Vault self-audit surfaced as Markdown in the vault (Obsidian as the viewer) — conflicts, demand-gaps, dangling
- Evidence: failure_mode_cluster:github_issue | https://github.com/n0mad-ai/bastra-recall/issues/140

## 21. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: curator phase A: deterministic usage-driven staleness pass (score-only, idle-gated)
- User impact: Developers may misconfigure credentials, environment, or host setup: curator phase A: deterministic usage-driven staleness pass (score-only, idle-gated)
- Evidence: failure_mode_cluster:github_issue | https://github.com/n0mad-ai/bastra-recall/issues/155

## 22. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: telemetry: per-memory usage sidecar — append-only aggregate of surfaced/loaded/acted_on
- User impact: Developers may misconfigure credentials, environment, or host setup: telemetry: per-memory usage sidecar — append-only aggregate of surfaced/loaded/acted_on
- Evidence: failure_mode_cluster:github_issue | https://github.com/n0mad-ai/bastra-recall/issues/154

## 23. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: v0.7.0-beta.1 — Recall that proves itself
- User impact: Upgrade or migration may change expected behavior: v0.7.0-beta.1 — Recall that proves itself
- Evidence: failure_mode_cluster:github_release | https://github.com/n0mad-ai/bastra-recall/releases/tag/v0.7.0-beta.1

## 24. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: v0.7.0-beta.4
- User impact: Upgrade or migration may change expected behavior: v0.7.0-beta.4
- Evidence: failure_mode_cluster:github_release | https://github.com/n0mad-ai/bastra-recall/releases/tag/v0.7.0-beta.4

## 25. Capability evidence risk - Capability evidence risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: README/documentation is current enough for a first validation pass.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: capability.assumptions | https://github.com/n0mad-ai/bastra-recall

## 26. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/n0mad-ai/bastra-recall

## 27. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: downstream_validation.risk_items | https://github.com/n0mad-ai/bastra-recall

## 28. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: risks.scoring_risks | https://github.com/n0mad-ai/bastra-recall

## 29. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/n0mad-ai/bastra-recall/issues/155

## 30. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/n0mad-ai/bastra-recall/issues/154

## 31. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: issue_or_pr_quality=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/n0mad-ai/bastra-recall

## 32. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: release_recency=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/n0mad-ai/bastra-recall

<!-- canonical_name: n0mad-ai/bastra-recall; human_manual_source: deepwiki_human_wiki -->
