sense · ambient relevance for multi-project ecosystems

Prior work that surfaces as you work.

Your AI agent sees the repo it's sitting in. Sense indexes the rest of your portfolio and quietly injects what's relevant — weighted by recency, shaped by your working mode, corrected by your feedback. No search box. No paste. Context that arrives.

MCP server · UserPromptSubmit hook · sub-second startup OpenAI embeddings · SQLite WAL · trajectory-aware Apache 2.0 · ~1,250 file corpus tested in production

You don't work on one project. Your AI agent acts like you do.

The relevant piece is rarely in the project you're currently looking at. A decision made three repos away shaped this code. A note from six months ago is the context the agent is missing.

What you have today

An agent that sees one repo and is contextually blind to the portfolio it sits inside.

A RAG pipeline that dumps chunks into the prompt without discrimination — useful connections get buried under volume.

A search box you only use when you already know what you're looking for, which means it can't surface what you didn't.

What sense gives you

Ambient retrieval. A hook fires on every prompt and injects the top results as <sense-context> tags. No invocation needed.

Trajectory-aware queries. When the conversation converges, the aperture narrows. When it diverges, it widens. Your last few queries shape the next one.

Source-classified diversity. Confirmation, divergence, and serendipity slots — the result mix follows what you're doing, not just relevance scores.

From a prompt to context the agent didn't know to ask for.

Five moments from a real session: prompt fires, hook injects, trajectory narrows, mode reshapes, feedback rewrites the weights. Click through.

01
Sync the corpus
SHA-256 change detection; unchanged files skipped.
02
Hook fires on every prompt
Top 3 results injected as <sense-context>.
03
Trajectory narrows
Frenet-Serret curvature: converging → tighter aperture.
04
Mode reshapes the mix
Explore widens. Build narrows. Same corpus, different surface.
05
Correct a result
Bayesian feedback shifts retrieval weights.
sense · session
$ sense-mcp sync

[scan]     walking corpus root …            ✓ 1,258 files
[hash]     SHA-256 change detection         ✓ 47 changed
[chunk]    section + paragraph splitting    ✓ 312 chunks
[embed]    text-embedding-3-small (1536d)   ✓ batch 256
[store]    SQLite WAL                       ✓ 12,177 total

classified:
   · trace               232 chunks · 30d half-life
   · documentation       618 chunks · 90d half-life
   · research            64 chunks · evergreen
   · code                177 chunks · 90d half-life
   · reference           9 chunks · evergreen

# Source type drives decay rate. Reference and research never fade.
user  How did we resolve the landing page hero copy?

[hook]  sense-mcp-hook fires (0.2s)
[hook]  embed prompt · query corpus · classify slots
[hook]  inject <sense-context> tag

surfaced:
  ├─ trace       "hero h1 — three drafts"        sim 0.93  2 days ago
  ├─ trace       "sub-head register check"       sim 0.81  2 days ago
  └─ research    "voice and audience register"   sim 0.62  evergreen

# The agent sees the trace before it sees the question.
# No paste. No "what did we decide last time?"
user  And the about section bios?

[trajectory]  embedding history: 4 queries · all landing-page · copy
[trajectory]  Frenet-Serret curvature  Δκ = 0.04
[trajectory]  state: converging

aperture:  narrowed   context_weight 0.6 → 0.2
surfaced:
  ├─ trace       "team block — affiliations cleaned"  sim 0.97
  └─ trace       "author bio refined in-place"       sim 0.84

# Trajectory is converging — narrow on the thread.
# When you next pivot to a new topic, the aperture widens automatically.
$ # mode shifts the same corpus

user  [mode = explore]   what does coupling mean across projects?

surfaced:  cross-project boost · diversity slots wide
  ├─ research     coupling-modes/preprint          primary
  ├─ trace        peer-review thread               framing
  ├─ code         harness/temporal.py              history log
  └─ research     adjacent-lit/relational-cognition cross-field

user  [mode = build]    what does coupling mean across projects?

surfaced:  same-project · code-heavy · narrow
  ├─ code         scripts/join_signals.py          current repo
  ├─ code         scripts/describe_session.py      current repo
  └─ documentation SPEC-010-bridge.md             current repo

# Mode is an additive bias — never buries highly-relevant results,
# but reorders near-ties to fit what you're actually doing.
$ # dashboard at http://localhost:8111
$ # click a result label to toggle useful / noise

[click]   trace  "old planning notes"   → noise

[feedback]  recorded · weight cache invalidated
[bayes]     prior 2.0 + observations  →  weight 0.74

$ sense_feedback_stats

total labels:      247
auto:hook:         231
manual:            12
corrected:         4              correction rate 1.6%

weight previews:
  · old-planning-notes.md         0.74   noise tendency
  · TRACE_landing-page-revisions.md 1.31 consistently useful

# Append-only feedback table. Latest-wins for weighting.
# The full correction history is available as training data.

Three properties no retrieval system combines.

01 · Ambient

Context arrives. You don't ask.

A UserPromptSubmit hook fires on every prompt — sub-second, gated by length and cooldown. The hook reads SQLite read-only and coexists with the running MCP server. Surfaces what's relevant; never interrupts.

  • UserPromptSubmit hook for Claude Code
  • Sub-second startup via uv tool install
  • Gated by prompt length, cooldown, continuation signals
  • File-locked JSON session state shared with the MCP server
02 · Trajectory-aware

Knows whether you're converging or diverging.

Sense tracks the geometry of your conversation — accumulating embeddings, computing local curvature (Δκ) via Frenet-Serret. Convergence narrows the aperture; divergence widens it. The query you send is shaped by the queries that came before.

  • Frenet-Serret curvature on the embedding trajectory
  • Aperture adjusts: 0.2 converging · 0.6 diverging
  • Resurfacing penalty halved when diverging (anchoring)
  • Reset after configurable inactivity timeout
03 · Source-aware diversity

Confirmation, divergence, serendipity.

Files are classified into source types — traces, code, research, reference — each with its own decay rate and mode disposition. Results fill confirmation, divergence, and serendipity slots adaptively, so the mix shifts with the spread of relevance.

  • Per-type half-lives (trace 30d · code 90d · research evergreen)
  • Adaptive slot allocation by relevance spread
  • Bayesian feedback prior on result usefulness
  • Mode-aware: explore widens, build narrows

An MCP server, a hook, and a local SQLite index.

Sense indexes your corpus into a local SQLite database with WAL. The MCP server exposes search tools to the agent. The hook fires on every prompt and injects context. Optional pairing with vibe harness shapes results by working mode; with zetl, by graph adjacency; with ebs, by physiological state.

┌──────────────────┐ ┌────────────────────┐ ┌──────────────────┐ │ your corpus │ │ sense runtime │ │ Claude Code │ │ │ │ │ │ │ │ traces │─────►│ embed + classify │ │ UserPromptSubmit│ │ code │ │ trajectory track │◄─────│ hook fires │ │ research │ │ diversity slots │ │ │ │ documentation │ │ feedback weights │─────►│ <sense-context> │ │ reference │ │ │ │ │ └──────────────────┘ │ SQLite WAL │ └──────────────────┘ │ shared session │ ▲ │ state (JSON) │ │ └────────┬───────────┘ │ │ │ ▼ │ ┌─────────────────────────────┐ │ │ dashboard · localhost:8111 │ │ │ bias breakdown · trajectory│ │ │ click a label → correct it │───────────┘ └─────────────────────────────┘ corrections shift weights ┌──────────────────────────────────────────────────────┐ │ optional: vibe-harness → mode-aware retrieval │ │ optional: zetl graph → adjacency signal │ │ optional: ebs biosignal → physiological state input │ └──────────────────────────────────────────────────────┘

Local-first, no phone-home

Your corpus stays on disk. Embeddings call OpenAI; nothing else leaves the machine. SQLite WAL lets the hook read while the MCP server writes.

Five signals, additively combined

Semantic similarity, temporal decay, mode, trajectory, feedback. The composition is bounded — mode reorders near-ties but never buries a highly-relevant result.

Slot allocation is adaptive

When top results cluster tightly, confirmation expands and diversity shrinks. When results are spread, diversity earns its full allocation.

Feedback closes the loop

Sense observes → auto-labels → the dashboard renders the observation → you correct → weights shift → sense changes what it surfaces.

Configurable from one TOML

Source types, decay half-lives, mode profiles, trajectory window, feedback prior — all in sense.toml. Defaults are sensible; the knobs are there when you need them.

Resurfacing penalty is trajectory-aware

Diverging conversations treat recurring content as anchoring (penalty halved). Converging conversations treat it as circling (penalty applied).

Frequently asked questions.

How is this different from a RAG pipeline?
RAG retrieves chunks and lets the LLM reason over them. Sense decides what to retrieve in the first place — by source type, by working mode, by conversation trajectory, and by your past corrections. The retrieval is the point, not the synthesis.
Does it work without vibe harness?
Yes. With no mode signal, sense falls back to flat cosine similarity plus temporal decay. Adding vibe harness gives you mode-aware retrieval; the rest is independent.
How big a corpus does it handle?
The reference deployment runs on a ~1,250-file ecosystem (~12,000 chunks, ~3.8M tokens, ~$0.02 to embed full). It's tuned for portfolios, not web-scale corpora — single-digit gigabytes is the sweet spot.
What's a "source type" and why does it matter?
A classification of the file's role: trace, code, research, documentation, reference. Each has a distinct half-life and mode disposition. A reference document is evergreen; a session trace from yesterday weighs more than one from a year ago.
Does it phone home?
Embeddings call the OpenAI API; nothing else. The index is SQLite on your disk. The hook reads it locally. The dashboard runs on localhost. You can self-host an embedding model and remove the only outbound call.
Where's the source?
Open source, Apache 2.0, on GitHub. Python 3.11+ via uv. Install with uv tool install sense-mcp and register with claude mcp add.

The relevant piece is rarely where you are.

Index your portfolio once. Sense surfaces what matters in every conversation — without being asked. Apache 2.0, local-first, MCP-native.

install: uv tool install sense-mcp --from git+https://github.com/m3data/sense-mcp