Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,7 @@ __pycache__/
# Local secrets — NEVER commit
.tokens.local


# counsel pre-brief packets (internal-only)
_counsel-packet/

4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!-- @wbx-modified copilot-a3f7·MTN | 2026-04-24 | v0.1.0 launch polish: badges, tighter hero, social previews | prev: copilot-a3f7@2026-04-23 -->
<!-- @wbx-modified copilot-b1c4 | 2026-04-27 23:58 MTN | v0.3.3 | added ™ to H1 brand | prev: copilot-a3f7@2026-04-24 -->
<div align="center">

# Recall
# Recall&trade;

**Open-source memory for AI agents. MCP-native. Self-hosted. One Docker image.**

Expand Down
12 changes: 8 additions & 4 deletions docker/single-tenant/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
# @wbx-modified copilot-c4a1·MTN | 2026-04-23 | single-tenant Dockerfile | prev: NEW
# @wbx-modified copilot-b1c4 | 2026-04-27 23:36 MTN | v0.3.3 | install [llm,mcp] so SSE + recall-mcp work | prev: copilot-a3f7@2026-04-26
# syntax=docker/dockerfile:1.6
#
# Recall — single-tenant agent-memory MCP server.
# Build: docker build -t recall:latest -f docker/single-tenant/Dockerfile .
# Run: docker run -p 8787:8787 -e API_KEY=secret -v recall-data:/data recall:latest
# Health: curl http://localhost:8787/health

FROM python:3.14-slim AS base
# Pinned to 3.12-slim: widest wheel coverage (chromadb, onnxruntime, etc.).
# pyproject requires-python >=3.11, so 3.12 is in-band. Avoid 3.14 until upstream
# wheel matrix catches up (was the cause of intermittent GHA build failures).
FROM python:3.12-slim AS base

# Install git for optional GIT_REPO_URL sync. Stay minimal otherwise.
RUN apt-get update \
Expand All @@ -19,10 +22,11 @@ RUN useradd --create-home --uid 10001 --shell /bin/bash recall
WORKDIR /app

# ---- Dependency layer (cached when src/ changes but pyproject doesn't) ----
# Pin pip and use --retries to ride through transient PyPI/index hiccups.
COPY pyproject.toml README.md ./
COPY src ./src
RUN pip install --no-cache-dir --upgrade pip \
&& pip install --no-cache-dir .
RUN pip install --no-cache-dir --upgrade "pip==24.2" \
&& pip install --no-cache-dir --retries 5 --timeout 60 ".[llm,mcp]"

# ---- Runtime layout ----
# Ephemeral local store (ChromaDB SQLite — must NOT be on a network share).
Expand Down
34 changes: 34 additions & 0 deletions docs/gated-workstreams.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<!-- @wbx-modified copilot-a3f7·MTN | 2026-04-24 | scope notes for two gated workstreams; agent does NO work until Steve picks one -->
# Gated Workstreams — Next Actions

Both items below are referenced in [`/memories/05-audit-trail.md`](file:///c%3A/Users/StevePaltridge/AppData/Roaming/Code/User/globalStorage/github.copilot-chat/memory/05-audit-trail.md)
as "Steve-gated". Agent has done **zero work** on either; this file just
captures the scope so picking one up later is fast.

## SettingsPilot batch-9

- **Where**: `C:\Dev\EncompassSettingsPlugin\schema-extract\generate-batch9.ps1` (to be created); recipes land in `C:\Dev\EncompassSettingsPlugin\_pending-batch9\`.
- **Predecessor**: batch-8 (per memory `S-20260422-batch8`) shipped 50 read-only recipes targeting uncovered `ConfigManager`/`OrgManager`/`BpmManager`/`ServerManager` methods using probe v3.0 reflection dumps.
- **Inputs ready**: `_probe-iconfig-methods.json`, `_probe-ibpm-methods.json`, `_probe-iorg-methods.json`, `_probe-iserver-methods.json` (1020 manager method signatures total).
- **Verb-allowlist guard**: must filter to read-only verbs (`Get|List|Read|Find|Query|Count|Has|Is|Can|Calculate`). Batch-8 blocked 436 mutating-verb method calls.
- **Coverage target**: get from current 226/323 deep-probe keys (70%) to 90% — needs ~65 new probe-eligible methods after dedup vs batch-8.
- **Validation path**: ICE Encompass FormBuilder → Tools → Package Import Wizard → install .empkg → form reopen → export results JSON → diff vs prior batch.
- **Blocker**: batch-9 needs PluginAudit ClientContext blocker resolved first per memory `S-20260422-pluginaudit` ("Server.dll statics") — otherwise probe v3.0 is the ceiling.
- **Owner gate**: Steve confirms (a) priority vs other lender outreach, (b) acceptable to ship recipe-only update without resolving ClientContext blocker (i.e. ship at 80% coverage).

## IceWhisperer Edge variant

- **Where**: New `IceWhisperer/extension/edge/` sibling to existing `IceWhisperer/extension/` (Chrome MV3).
- **Status**: Existing extension is Chrome MV3 with Firefox compat shipped this session (per prior batch B+C+D+E+F summary in conversation history — `extension/firefox/` exists).
- **Edge specifics**:
1. Edge is Chromium-based — most MV3 manifest is identical.
2. Differs in: extension store submission (Microsoft Partner Center, not CWS), `update_url` field in manifest, optional `browser_specific_settings` for legacy compat.
3. No code changes likely needed in `background.js`/`content.js`/`popup.*`. Just a separate manifest + store listing.
- **Deliverable**: `extension/edge/manifest.json` + `extension/edge/README.md` describing Microsoft Partner Center submission flow + screenshots.
- **Owner gate**: Steve confirms whether Edge is worth the dual-listing maintenance burden vs telling Edge users "install from Chrome Web Store" (Edge supports CWS extensions natively since 2020).

## Items NOT in this list (deliberately)

- **Channel-brain endpoint deploy** — Rule 4 forbids deploy without explicit per-deploy approval. Steve must say "deploy" before any `azd up`/`func publish`/`docker push`.
- **Real Chrome load test** — needs interactive browser; agent cannot drive.
- **Outside-counsel call** — see [`outside-counsel-checklist.md`](./outside-counsel-checklist.md). Steve schedules.
68 changes: 68 additions & 0 deletions docs/license-boundary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<!-- @wbx-modified copilot-a3f7·MTN | 2026-04-24 | MIT/BSL boundary one-pager -->
# Recall License Boundary

> One-pager for contributors and customers. The legal text is in
> [`LICENSE`](./LICENSE) (MIT) and [`LICENSE-COMMERCIAL.md`](./LICENSE-COMMERCIAL.md) (BSL 1.1).

## TL;DR

| Tree | License | What it covers | Production use |
|------|---------|----------------|----------------|
| `src/recall/` | MIT | Single-tenant memory engine, tools, transports, CLI, store interfaces, the OSS Docker image | Free, forever, any scale |
| `clients/` | MIT | Python + TypeScript SDKs (`recall-client`, `@recallworks/recall-client`) | Free, forever |
| `docker/single-tenant/` | MIT | The image at `ghcr.io/recallworks/recall:0.1.0` | Free, forever |
| `docs/`, `examples/`, `tests/` | MIT | Quickstarts, conventions, conformance tests | Free, forever |
| `enterprise/` | BSL 1.1 | Multi-tenant isolation, SSO connectors, hash-chain audit log, managed-cloud control plane | Free for non-prod and ≤5-seat single-org prod; commercial license for larger; converts to MIT 3 years after each tagged release |

## Why two licenses

The OSS core stays MIT so anyone can run it on their own boxes for any
purpose, commercially or otherwise, without a conversation with us. That's
the deal: own your memory, on your hardware, forever.

The `enterprise/` tree adds the things a hosted competitor would need to
spin up a paid clone overnight: per-tenant isolation, SSO, audit-grade
exports, control plane. We license that under BSL 1.1 — free for small
production and any non-production use, paid only when you're at scale, and
auto-converted to MIT three years after each release.

## Hard rule: dependency direction

> **`src/recall/*` MUST NOT import from `enterprise/*`.**
> The reverse is fine.

The CI test [`tests/test_no_oss_to_enterprise_imports.py`](./tests/test_no_oss_to_enterprise_imports.py)
walks every `.py` under `src/recall/` and fails the build if it finds a
`from enterprise.*` or `import enterprise.*` line.

If MIT code took a runtime dependency on BSL code, the boundary would be
unilateral: an OSS user could no longer run the OSS core without pulling in
BSL terms. Refuse the dep instead — design the OSS core's interface to be
satisfied by either side.

## How to build a feature

Ask: "would a hosted-Recall competitor copy this on day one?"

* **No** → MIT, lands in `src/recall/`. Examples: a new tool, a new
embedder backend, a CLI flag, an SDK helper.
* **Yes** → BSL, lands in `enterprise/`. Examples: a new SSO connector,
multi-tenant ABAC, a managed-cloud quota service, an audit exporter.

When you're not sure, default to MIT and move it later. It's easier to
relicense towards proprietary than away from it.

## Contributing under each license

Both trees accept external contributions. The CLA + DCO requirements in
[`CONTRIBUTING.md`](./CONTRIBUTING.md) apply uniformly. By contributing to
`enterprise/` you are accepting that your contribution lands under BSL 1.1
and converts to MIT on the same 3-year clock as the rest of the tree.

## Buying a commercial license

If your production deployment exceeds the BSL Additional Use Grant
(more than 5 seats per organization), reach out via the contact in
[`README.md`](./README.md). Commercial licenses are flat-rate per
deployment and include the SOC 2 evidence pack pulled from
`HashChainAuditLog`.
160 changes: 160 additions & 0 deletions docs/mcp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# @wbx-modified copilot-b1c4 | 2026-04-27 22:25 MTN | v1.0 | MCP integration guide for Claude Desktop / Cursor / Cline | prev: NEW
# Recall as an MCP server

Recall ships with first-class support for the [Model Context Protocol](https://modelcontextprotocol.io/),
so you can wire it into Claude Desktop, Cursor, Cline, Continue.dev, or any
other MCP client as a memory tool. Your AI assistant gets persistent memory
across sessions — locally, on your machine, no SaaS in the loop.

## Two transports, same 16 tools

Recall exposes the same tool surface over two MCP transports:

| Transport | Use when | Entry point |
|-----------|---------------------------------------------------------|-------------|
| **stdio** | Running locally, used by Claude Desktop / Cursor / Cline | `recall-mcp` (or `python -m recall.mcp_stdio`) |
| **SSE** | Running as a network service, multiple agents share it | `recall-server` exposes `/sse` automatically when `mcp` extras installed |

Both serve all 16 tools: `recall`, `recall_filtered`, `answer`, `remember`,
`reindex`, `index_file`, `memory_stats`, `forget`, `reflect`, `anti_pattern`,
`session_close`, `checkpoint`, `pulse`, `maintenance`, `snapshot_index`,
`backfill_epoch`.

## Install

```bash
pip install "recall[mcp]"
```

That installs the server, all 16 tools, and the MCP runtime (`mcp>=1.27.0`).

## Claude Desktop

Edit `~/Library/Application Support/Claude/claude_desktop_config.json`
(macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):

```json
{
"mcpServers": {
"recall": {
"command": "recall-mcp",
"env": {
"RECALL_STORE_DIR": "/Users/you/.recall/store",
"RECALL_LOG_LEVEL": "WARNING"
}
}
}
}
```

Restart Claude Desktop. You'll see a new wrench icon — click it and you'll
see all 16 Recall tools available to the conversation.

## Cursor

Cursor reads MCP servers from `~/.cursor/mcp.json`:

```json
{
"mcpServers": {
"recall": {
"command": "recall-mcp",
"env": {
"RECALL_STORE_DIR": "/Users/you/.recall/store"
}
}
}
}
```

After Cursor restart, the tools show up in Composer.

## Cline (VS Code extension)

In VS Code: open Cline settings → "MCP Servers" → click "+":

```json
{
"recall": {
"command": "recall-mcp",
"args": [],
"env": {
"RECALL_STORE_DIR": "/Users/you/.recall/store"
}
}
}
```

## Continue.dev

In `~/.continue/config.json`:

```json
{
"mcpServers": [
{
"name": "recall",
"command": "recall-mcp",
"env": {
"RECALL_STORE_DIR": "/Users/you/.recall/store"
}
}
]
}
```

## Verify it's working

After your client restarts, ask: **"What Recall tools do you have access to?"**

A working setup will list all 16 tools. Then ask:

> *"Remember that I prefer concise answers."*

The model should call `remember`. In the next session, ask:

> *"How do I like my answers?"*

The model should call `recall` and answer "concise."

## Bring your own embedding model

By default Recall uses a small offline embedding model bundled with chroma —
this runs on a laptop with no API keys.

To use a stronger model, add to your client's `env`:

```json
"env": {
"RECALL_EMBEDDER": "openai",
"OPENAI_API_KEY": "sk-...",
"RECALL_STORE_DIR": "/Users/you/.recall/store"
}
```

## Privacy posture

- **Stdio mode is fully local.** The MCP client launches `recall-mcp` as a
subprocess on your machine. No network calls unless you opted into a
cloud embedder.
- **No telemetry. Ever.** Recall doesn't phone home about tool calls,
tool counts, or anything else. Read [`auth.py`](../src/recall/auth.py)
and [`app.py`](../src/recall/app.py) — the only network code is the
optional git_sync if you set `RECALL_GIT_REPO_URL`.
- **Store path is yours.** Set `RECALL_STORE_DIR` to anywhere you control.
Default is `~/.recall/store/`.

## Troubleshooting

| Symptom | Likely cause | Fix |
|---------|--------------|-----|
| Client shows 0 tools | `pip install "recall[mcp]"` not run | Install with the `mcp` extra |
| `recall-mcp: command not found` | Not in client's PATH | Use absolute path: `"command": "/Users/you/.venv/bin/recall-mcp"` |
| Tools list but calls fail | Store init failed at startup | Check stderr — likely a permissions issue on `RECALL_STORE_DIR` |
| Stdout corruption / parse errors | Something logged to stdout | Recall logs to stderr only — if you wrote a custom plugin, fix it |

## Source

- [`src/recall/mcp_stdio.py`](../src/recall/mcp_stdio.py) — stdio entry
- [`src/recall/transport/mcp_sse.py`](../src/recall/transport/mcp_sse.py) — FastMCP wiring
- [`src/recall/tools/__init__.py`](../src/recall/tools/__init__.py) — tool registry
80 changes: 80 additions & 0 deletions docs/outside-counsel-checklist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<!-- @wbx-modified copilot-a3f7·MTN | 2026-04-24 | outside-counsel-review checklist -->
# Outside-Counsel Review — Pre-Brief Checklist

> Internal-only. Not committed in any release zip. Used to brief outside
> counsel before they look at Recall's license stack and IceWhisperer's
> commercial posture.

## What we want counsel to confirm

1. **MIT/BSL boundary holds.** Confirm `src/recall/*` (MIT) takes no runtime
dep on `enterprise/*` (BSL 1.1), and that the CI test
[`tests/test_no_oss_to_enterprise_imports.py`](../tests/test_no_oss_to_enterprise_imports.py)
is the right enforcement mechanism.
2. **BSL 1.1 Additional Use Grant** as drafted in
[`LICENSE-COMMERCIAL.md`](../LICENSE-COMMERCIAL.md) is enforceable and
matches the intent: free for non-prod and ≤5-seat single-org prod, paid
above that, auto-converts to MIT 3 years after each tagged release.
3. **License-boundary one-pager** at [`docs/license-boundary.md`](./license-boundary.md)
accurately summarises the legal stack for a commercial buyer.
4. **IceWhisperer EULA** at `IceWhisperer/bundle/EULA.md` is enforceable in
the United States (Steve's first 5 ICPs are US lenders). Confirm the
binding-arbitration clause survives state-law variance.
5. **ICE non-affiliation disclosure** on the IceWhisperer landing + pricing
pages is sufficient to defeat any trademark-confusion claim by ICE
Mortgage Technology.
6. **Corpus posture (v1.0.2)** described in
`/memories/icewhisperer-corpus-legal.md` v1.2: SDK XML + Developer
Connect + Resource Center articles authored by ICE, scraped under
Steve's senior-ICE standing, redistributed inside customer perimeter
only. Confirm this is defensible.

## Hard rule for counsel

> **Counsel may quote any text in this file or in `docs/license-boundary.md`
> directly back at us.** Do not assume any of this is privileged advice
> until they say so in writing.

## Pre-brief packet (assemble before the call)

- [ ] [`LICENSE`](../LICENSE) (MIT)
- [ ] [`LICENSE-COMMERCIAL.md`](../LICENSE-COMMERCIAL.md) (BSL 1.1 + grant)
- [ ] [`docs/license-boundary.md`](./license-boundary.md)
- [ ] [`tests/test_no_oss_to_enterprise_imports.py`](../tests/test_no_oss_to_enterprise_imports.py)
- [ ] `IceWhisperer/bundle/EULA.md`
- [ ] `IceWhisperer/_strategy/non-affiliation.md` (if it exists; otherwise
the disclosure block from `pricing.html`)
- [ ] `/memories/icewhisperer-corpus-legal.md` v1.2 — printed/exported
- [ ] One-page founder summary (Steve to write 5 lines)

## Logistics

- Engage at least 2 weeks before first paid Team customer onboards
(current pilot is 60-day pre-paid, no Team tier active).
- Counsel must specialise in **OSS licensing AND fintech vendor contracts**.
Not just one of the two. Likely candidate firms: Heather Meeker
(license + OSS), Outside GC (fintech vendor contracts).
- Budget envelope: typically $5-15k for a 4-hour review of this scope.

## What we are NOT asking counsel to do

- Re-draft any of these documents. We will iterate based on red-line.
- Review individual customer contracts. Each Team contract uses a stock
MSA + Order Form template that needs its own review pass.
- Opine on patent posture. Recall + IceWhisperer file no patents.

## Open questions for counsel

1. Does the BSL Additional Use Grant need a per-deployment seat-counter
audit clause to be enforceable? Or does honor-system + telemetry suffice?
2. Is "powered by Recall" co-branding sufficient to satisfy MIT attribution
in the IceWhisperer bundle? The bundle re-distributes the Recall MIT
image — the MIT attribution lives in `bundle/THIRD-PARTY-NOTICES.md`.
3. Is the Resource Center scrape (ICE-authored articles, partner login
under Steve's name) safer characterised as "fair use" or "agency"
under our reseller agreement? We've documented as agency in
`/memories/icewhisperer-corpus-legal.md` v1.2 — confirm.

## Owner

Steve Paltridge. Schedule via Calendly; no agent action.
Loading
Loading