Metadata-Version: 2.4
Name: pensyve
Version: 5.0.0
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Rust
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Dist: httpx>=0.27 ; extra == 'http'
Requires-Dist: tenacity>=8.0 ; extra == 'http'
Provides-Extra: http
Summary: Universal memory runtime for AI agents — framework-agnostic, protocol-native, offline-first
Keywords: ai,agents,memory,llm,mcp,retrieval,embeddings
Home-Page: https://github.com/major7apps/pensyve
Author: Major7 Apps
License: Apache-2.0
Requires-Python: >=3.10
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Documentation, https://github.com/major7apps/pensyve/tree/main/docs
Project-URL: Homepage, https://github.com/major7apps/pensyve
Project-URL: Repository, https://github.com/major7apps/pensyve

![Pensyve Banner Logo](https://raw.githubusercontent.com/major7apps/pensyve/main/docs/images/logo.png)

# Pensyve

[![CI](https://github.com/major7apps/pensyve/actions/workflows/ci.yml/badge.svg)](https://github.com/major7apps/pensyve/actions/workflows/ci.yml)
[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
[![Rust 1.88+](https://img.shields.io/badge/rust-1.88+-orange.svg)](https://www.rust-lang.org/)

Universal memory runtime for AI agents. Framework-agnostic, protocol-native, offline-first.

Agents use Pensyve to remember across sessions, learn from outcomes, and share knowledge — all backed by a Rust core engine with zero cloud dependencies required.

## Why Pensyve

Most AI agents lose all context between sessions. Pensyve gives them durable, intelligent memory:

- **Three memory types** — Episodic (what happened), Semantic (what is known), Procedural (what works)
- **Multimodal content** — Text, code, images, tool outputs, structured data
- **8-signal fusion retrieval** — Vector similarity, BM25 lexical, graph proximity, intent classification, recency, access frequency, confidence, type boost
- **Learns from outcomes** — Bayesian tracking on action→outcome procedures automatically surfaces what works
- **Forgetting curve** — FSRS-based memory decay with retrieval-induced reinforcement (memories you use get stronger)
- **Consolidation** — Background "dreaming" promotes repeated episodic facts to semantic knowledge
- **Offline-first** — SQLite storage, ONNX embeddings, optional local LLM extraction. No API keys needed.
- **Scales to Postgres** — Feature-gated Postgres backend with pgvector for multi-node deployments
- **Cross-encoder reranking** — BGE reranker on top-k results for precision
- **Access control** — RBAC memory mesh with owner/writer/reader roles and private/shared/public visibility

## Install

```bash
pip install pensyve          # Python (PyPI)
npm install pensyve          # TypeScript (npm)
go get github.com/major7apps/pensyve/pensyve-go/v3@latest  # Go
```

Or use the MCP server directly with Claude Code, Cursor, or any MCP client — see [MCP Setup](https://github.com/major7apps/pensyve/blob/main/docs/GETTING_STARTED.md#mcp-server).

## Quick Start

### Prerequisites (building from source)

- Rust 1.88+
- Python 3.10+ with [uv](https://github.com/astral-sh/uv)
- [Bun](https://bun.sh) (optional, for TypeScript SDK)
- [Go 1.21+](https://go.dev) (optional, for Go SDK)

### Install

```bash
git clone https://github.com/major7apps/pensyve.git && cd pensyve

# Set up Python environment and install deps
uv sync --extra dev

# Build the Python SDK (compiles Rust → native Python module)
uv run maturin develop --release -m pensyve-python/Cargo.toml

# Verify
uv run python -c "import pensyve; print(pensyve.__version__)"
```

### 5-Line Demo

```python
import pensyve

p = pensyve.Pensyve()
with p.episode(p.entity("agent", kind="agent"), p.entity("user")) as ep:
    ep.message("user", "I prefer dark mode and use vim keybindings")
print(p.recall("what editor setup does the user prefer?"))
```

## Interfaces

Pensyve exposes its core engine through multiple interfaces — use whichever fits your stack.

### Python SDK

Direct in-process access via PyO3. Zero network overhead.

```python
import pensyve

p = pensyve.Pensyve(namespace="my-agent")
entity = p.entity("user", kind="user")

# Remember a fact
p.remember(entity=entity, fact="User prefers Python", confidence=0.95)

# Recall memories (flat list)
results = p.recall("programming language", entity=entity)

# Recall memories clustered by source session — the canonical entry point
# for "memory as input to an LLM reader" workflows. Each SessionGroup
# corresponds to one conversation episode and is sorted chronologically.
groups = p.recall_grouped("programming language", limit=50)
for g in groups:
    for m in g.memories:
        print(f"[{g.session_time}] {m.content}")

# Record an episode
with p.episode(entity) as ep:
    ep.message("user", "Can you fix the login bug?")
    ep.message("agent", "Fixed — the session token was expiring early")
    ep.outcome("success")

# Consolidate (promote repeated facts, decay unused memories)
p.consolidate()

# Forget everything about an entity
result = p.forget(entity)
print(result["forgotten_count"], result.get("snapshot_path"))
```

#### `forget` writes a snapshot before it deletes

`Pensyve.forget(entity)` permanently deletes every memory about the entity. Before
it deletes, it writes the rows it is about to remove to a snapshot file, so a
forget issued by mistake can be recovered from. This is the same behaviour the
MCP server and the REST gateway have.

- The snapshot is written to `<path>/snapshots/<namespace id>/`, where `<path>`
  is the storage directory the `Pensyve` object was opened on. Set
  `PENSYVE_SNAPSHOT_DIR` to use a different root. The variable is read when the
  `Pensyve` object is constructed.
- The result is `{"forgotten_count": n, "snapshot_path": "..."}`. `snapshot_path`
  is absent when the entity had no memories, because nothing is written then.
- If the snapshot cannot be written (for example the directory is read-only or
  the disk is full), `forget` raises `RuntimeError` and deletes nothing.
- Snapshots are pruned per namespace. `PENSYVE_SNAPSHOT_RETENTION_DAYS`
  (default `30`, at most `36500`) bounds their age and
  `PENSYVE_SNAPSHOT_MAX_PER_NAMESPACE` (default `50`, at most `1000000`) bounds
  their number. `0` turns a bound off. A value that is not a whole number, or
  is above its maximum, is ignored with a warning and the default applies.
- A snapshot holds the full content of the deleted memories. On Unix the files
  are created readable by their owner only. Deleting a snapshot file is how you
  make a forget permanent before retention removes it.

Before version 5.0.0 the Python `forget` deleted without writing a snapshot. If
you run it in a process whose storage directory is not writable for new files,
`forget` now fails instead of deleting.

### MCP Server

Works with Claude Code, Cursor, and any MCP-compatible client.

```bash
cargo install --path pensyve-mcp
```

```json
{
  "mcpServers": {
    "pensyve": {
      "command": "./target/release/pensyve-mcp",
      "env": { "PENSYVE_PATH": "~/.pensyve/default" }
    }
  }
}
```

**Tools exposed:** `recall`, `remember`, `episode_start`, `episode_end`, `forget`, `inspect`

### Claude Code Plugin

Full cognitive memory layer for Claude Code — install from the marketplace or manually.

```
pensyve-plugin/
├── 6 slash commands   /remember, /recall, /forget, /inspect, /consolidate, /memory-status
├── 4 skills           session-memory, memory-informed-refactor, context-loader, memory-review
├── 2 agents           memory-curator (background), context-researcher (on-demand)
└── 4 hooks            SessionStart, Stop, PreCompact, UserPromptSubmit
```

See [`integrations/claude-code/README.md`](integrations/claude-code/README.md) for details.

### REST API

Rust/Axum gateway serving REST + MCP with auth, rate limiting, and usage metering.

```bash
cargo build --release --bin pensyve-mcp-gateway
./target/release/pensyve-mcp-gateway  # listens on 0.0.0.0:3000
```

```bash
# Remember
curl -X POST http://localhost:3000/v1/remember \
  -H "Content-Type: application/json" \
  -d '{"entity": "seth", "fact": "Seth prefers Python", "confidence": 0.95}'

# Recall
curl -X POST http://localhost:3000/v1/recall \
  -H "Content-Type: application/json" \
  -d '{"query": "programming language", "entity": "seth"}'
```

**Endpoints:** `POST /v1/entities`, `POST /v1/episodes/{start,message,end}`, `POST /v1/recall`, `POST /v1/remember`, `POST /v1/inspect`, `GET /v1/stats`, `DELETE /v1/entities/{name}`, `POST /v1/consolidate`, `GET /v1/health`, `GET /metrics`

### TypeScript SDK

HTTP client with timeout, retry, and structured errors.

```typescript
import { Pensyve } from "pensyve";

const p = new Pensyve({
  baseUrl: "http://localhost:3000",
  timeoutMs: 10000,
  retries: 2,
});
await p.remember({ entity: "seth", fact: "Likes TypeScript", confidence: 0.9 });
const memories = await p.recall("programming", { entity: "seth" });
```

### Go SDK

Context-aware HTTP client with structured errors.

```go
import pensyve "github.com/major7apps/pensyve/pensyve-go/v3"

client := pensyve.NewClient(pensyve.Config{BaseURL: "http://localhost:3000"})
ctx := context.Background()
client.Remember(ctx, "seth", "Likes Go", 0.9)
memories, _ := client.Recall(ctx, "programming", nil)
```

### CLI

```bash
cargo build --bin pensyve-cli

# Recall memories
./target/debug/pensyve-cli recall "editor preferences" --entity user

# Show stats
./target/debug/pensyve-cli stats

# Inspect an entity
./target/debug/pensyve-cli inspect --entity user
```

## Architecture

![Pensyve Architecture](https://raw.githubusercontent.com/major7apps/pensyve/main/docs/images/architecture.png)

### Data Model

```
Namespace (isolation boundary)
  └── Entity (agent | user | team | tool)
        ├── Episodes (bounded interaction sequences)
        │     └── Messages (role + content)
        └── Memories
              ├── Episodic  — what happened (timestamped, multimodal content type)
              ├── Semantic  — what is known (SPO triples with temporal validity)
              └── Procedural — what works (action→outcome with Bayesian reliability)
```

### Retrieval Pipeline

1. **Embed** query via ONNX (Alibaba-NLP/gte-base-en-v1.5, 768 dims)
2. **Classify intent** — Question/Action/Recall/General (keyword heuristics)
3. **Vector search** — cosine similarity against stored embeddings
4. **BM25 search** — FTS5 lexical matching
5. **Graph traversal** — petgraph BFS from query entity
6. **Fusion scoring** — weighted sum of 8 signals (vector, BM25, graph, intent, recency, access, confidence, type boost)
7. **Cross-encoder reranking** — BGE reranker on top-20 candidates
8. **FSRS reinforcement** — retrieved memories get stability boost

## Project Structure

```
pensyve/
├── pensyve-core/       Rust engine (rlib) — storage, embedding, retrieval, graph, decay, mesh, observability
├── pensyve-python/     Python SDK via PyO3 (cdylib)
├── pensyve-mcp/        MCP server binary (stdio, rmcp)
├── pensyve-cli/        CLI binary (clap)
├── pensyve-ts/         TypeScript SDK (bun) — timeout, retry, PensyveError
├── pensyve-go/         Go SDK — context-aware HTTP client
├── pensyve-wasm/       WASM build — standalone minimal in-memory Pensyve
├── pensyve_server/       Shared Python utilities — usage quotas, extraction
├── integrations/       All integrations — IDE plugins, framework adapters, code harnesses
│   ├── claude-code/    Claude Code plugin (commands, skills, agents, hooks)
│   ├── vscode/         VS Code sidebar extension
│   ├── openclaw-plugin/ OpenClaw native memory plugin (TypeScript)
│   ├── opencode-plugin/ OpenCode native memory plugin (TypeScript)
│   ├── cursor/         Cursor MCP setup guide
│   ├── cline/          Cline MCP setup guide
│   ├── windsurf/       Windsurf MCP setup guide
│   ├── continue/       Continue MCP setup guide
│   ├── vscode-copilot/ VS Code Copilot Chat MCP setup guide
│   ├── langchain/      LangChain/LangGraph Python (PensyveStore + legacy PensyveMemory)
│   ├── langchain-ts/   LangChain.js/LangGraph.js TypeScript (PensyveStore)
│   ├── crewai/         CrewAI (PensyveStorage + standalone PensyveCrewMemory)
│   └── autogen/        Microsoft AutoGen multi-agent memory
├── tests/python/       Python integration tests
├── benchmarks/         LongMemEval_S evaluation + weight tuning
└── docs/               Architecture, roadmap, design specs, implementation plans
```

## Development

### First-Time Setup

```bash
# Install dependencies (creates .venv automatically)
uv sync --extra dev

# Build the native Python module (required before running any Python code)
uv run maturin develop --release -m pensyve-python/Cargo.toml

# Verify the module loads
uv run python -c "import pensyve; print(pensyve.__version__)"
```

> **Note:** The `pensyve` Python package is a native Rust extension built with PyO3.
> You must run `uv run maturin develop` before `pytest` or any Python import of `pensyve`,
> otherwise you will get `ModuleNotFoundError: No module named 'pensyve'`.

### Build & Test

```bash
make build      # Compile Rust + build PyO3 module
make test       # Run all tests (Rust + Python)
make lint       # clippy + ruff + pyright
make format     # cargo fmt + ruff format
make check      # lint + test (CI gate)
```

To run test suites individually:

```bash
cargo test --workspace                                       # Rust tests
uv run maturin develop --release -m pensyve-python/Cargo.toml  # Build PyO3 module first
uv run pytest tests/python/ -v                               # Python tests
cd pensyve-ts && bun test                                    # TypeScript tests
cd pensyve-go && go test ./...                               # Go tests
```

### Additional SDKs

```bash
cd pensyve-ts && bun test          # TypeScript (38 tests)
cd pensyve-go && go test ./...     # Go (17 tests)
cd pensyve-wasm && cargo check     # WASM (standalone)
```

### Benchmarks

```bash
# Synthetic recall smoke test (planted facts, no external dataset required)
python benchmarks/synthetic/run.py --generate --evaluate --verbose
```

## Competitive Landscape

| Feature                                  | Pensyve                 | Mem0      | Zep        | Honcho     |
| ---------------------------------------- | ----------------------- | --------- | ---------- | ---------- |
| Offline-first (no cloud required)        | **Yes**                 | No        | No         | No         |
| Procedural memory (learns from outcomes) | **Yes**                 | No        | No         | No         |
| Multi-signal fusion scoring              | **8 signals**           | 1         | 3          | 1          |
| Retrieval-induced reinforcement (FSRS)   | **Yes**                 | No        | No         | No         |
| Intent-aware retrieval                   | **Yes**                 | No        | No         | No         |
| Multimodal content types                 | **Yes**                 | Text only | Text only  | Text only  |
| RBAC memory mesh                         | **Yes**                 | No        | No         | No         |
| Cross-platform local LLM extraction      | **Yes**                 | No        | Cloud only | Cloud only |
| MCP server                               | **Yes**                 | No        | No         | Plugin     |
| Claude Code plugin                       | **Yes**                 | No        | No         | No         |
| VS Code extension                        | **Yes**                 | No        | No         | No         |
| Framework integrations                   | **5**                   | 3         | 1          | 1          |
| Postgres backend                         | **Yes** (feature-gated) | Yes       | Yes        | Yes        |
| Go SDK                                   | **Yes**                 | No        | No         | No         |
| WASM build                               | **Yes**                 | No        | No         | No         |
| Open source engine                       | Apache 2.0              | Yes       | Partial    | Yes        |

## License

[Apache 2.0](LICENSE)

