xiaobenben 0.0.0-stage → 0.4.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/LICENSE-Commercial.md +50 -0
- package/NOTICE +42 -0
- package/README.md +520 -2
- package/THIRD-PARTY-LICENSES.md +553 -0
- package/bin/xbb.mjs +93 -0
- package/package.json +77 -6
- package/scripts/lib/binary.mjs +90 -0
- package/scripts/lib/install.mjs +243 -0
- package/scripts/postinstall.mjs +73 -0
- package/server.json +30 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# 商业许可
|
|
2
|
+
|
|
3
|
+
<!-- SPDX-License-Identifier: LicenseRef-Commercial -->
|
|
4
|
+
|
|
5
|
+
> **关于 `LicenseRef-Commercial`**
|
|
6
|
+
>
|
|
7
|
+
> 本仓每个源码文件头都写着 `SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Commercial`。
|
|
8
|
+
> 前半段是标准 SPDX 许可编号;后半段 `LicenseRef-Commercial` 是 SPDX 规范定义的
|
|
9
|
+
> **自定义许可引用**(`LicenseRef-` 前缀表示"本地定义的、不在 SPDX 许可清单里的许可"),
|
|
10
|
+
> 其定义就是**本文档**——由世纪之城(广州)信息科技有限公司按双方合同提供的商业许可。
|
|
11
|
+
>
|
|
12
|
+
> 它没有、也不可能有 OSI 或 SPDX 的标准编号,所以不能用 `MIT`、`Apache-2.0` 之类的名字代替。
|
|
13
|
+
> 扫描工具读到 `LicenseRef-Commercial` 时若提示"未知许可",到此为止即为正解,不是配置错误。
|
|
14
|
+
|
|
15
|
+
本仓库以 **GNU Affero 通用公共许可协议第 3 版(AGPL-3.0-only)** 发布。绝大多数使用者——
|
|
16
|
+
个人、团队内部使用、企业内部部署、二次开发后仍以 AGPL 分发——**无需购买任何商业许可**。
|
|
17
|
+
|
|
18
|
+
只有下列情形需要单独取得商业许可:
|
|
19
|
+
|
|
20
|
+
1. **闭源分发**:把本项目的全部或部分代码嵌入自有产品,以不公开源代码的方式对外分发。
|
|
21
|
+
2. **闭源对外服务**:基于修改后的本项目对外提供网络服务,且不愿按 AGPL 第 13 条向使用者提供完整对应源码。
|
|
22
|
+
3. **OEM / 预装**:将本项目随硬件或其他商业软件捆绑交付,且不以 AGPL 条件开放源码。
|
|
23
|
+
4. **需要商业条款**:需要明示担保、赔偿条款、SLA、或不受 copyleft 约束的授权。
|
|
24
|
+
|
|
25
|
+
## 不需要商业许可的情形(常见误解)
|
|
26
|
+
|
|
27
|
+
- 公司内部自用、内部部署、内部二次开发——**不产生分发,不触发任何开源义务**。
|
|
28
|
+
- 用本软件处理自己的数据,无论数据量或商业价值大小。
|
|
29
|
+
- 通过 MCP、命令行、HTTP 等接口调用本软件——**调用不构成衍生作品**。
|
|
30
|
+
- 以 AGPL-3.0 条件分发修改版——这是许可允许的,只需一并提供源码。
|
|
31
|
+
|
|
32
|
+
## 如何取得
|
|
33
|
+
|
|
34
|
+
请通过以下任一方式联系版权方,说明用途、部署形态与分发方式:
|
|
35
|
+
|
|
36
|
+
- 邮箱:`admin@sji.xin`
|
|
37
|
+
- 官网:https://xiaobenben.net
|
|
38
|
+
|
|
39
|
+
商业许可与 AGPL-3.0 是**并列选项**,不是附加限制:你可以自由选择其一,二者不可同时适用于同一份使用行为。
|
|
40
|
+
|
|
41
|
+
## 版权归属
|
|
42
|
+
|
|
43
|
+
本项目著作权由 **[世纪之城(广州)信息科技有限公司](https://sji.xin)** 持有。
|
|
44
|
+
|
|
45
|
+
为使上述双许可长期成立,本项目要求所有外部贡献签署贡献者许可协议(CLA),
|
|
46
|
+
授予版权方以其他许可条件再许可的权利。详见 `CLAs/` 与 `signatures/`。
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
Copyright (C) 2026 世纪之城(广州)信息科技有限公司
|
package/NOTICE
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# NOTICE
|
|
2
|
+
|
|
3
|
+
小本本(XiaoBenBen)客户端 —— https://github.com/sji-xiaobenben/xiaobenben
|
|
4
|
+
Copyright (C) 2026 世纪之城(广州)信息科技有限公司 (https://sji.xin)
|
|
5
|
+
All rights reserved.
|
|
6
|
+
|
|
7
|
+
本产品以 **AGPL-3.0-only** 发布(见 `LICENSE`),并另有商业许可可选(见 `LICENSE-Commercial.md`)。
|
|
8
|
+
|
|
9
|
+
## 商标
|
|
10
|
+
|
|
11
|
+
「小本本」「xiaobenben」「SJi」及相关名称、标识、图标为 世纪之城(广州)信息科技有限公司(https://sji.xin)的商标或商业标识。
|
|
12
|
+
|
|
13
|
+
本项目的著作权许可**不包含商标许可**。你可以自由复制、修改、分发本项目的代码,但不得以「小本本」「xiaobenben」「SJi」或其近似标识命名、推广你的衍生版本,也不得暗示本项目作者为你的衍生版本背书。如需使用上述标识,请事先取得书面许可。
|
|
14
|
+
|
|
15
|
+
## 内置依赖
|
|
16
|
+
|
|
17
|
+
`@xbb/core`(领域纯规则:uuidv7 / 事件哈希链 / 端口与错误码)随本仓一同发布,位于 `core/`,著作权同上,许可同上。
|
|
18
|
+
|
|
19
|
+
## 第三方组件
|
|
20
|
+
|
|
21
|
+
直接依赖 4 个,全部以 MIT 分发:
|
|
22
|
+
|
|
23
|
+
| 组件 | 版本 | 许可证 | 用途 |
|
|
24
|
+
|---|---|---|---|
|
|
25
|
+
| `@modelcontextprotocol/sdk` | 1.30.1 | MIT | MCP 协议实现 |
|
|
26
|
+
| `onnxruntime-node` | 1.30.0 | MIT | 本地向量推理运行时 |
|
|
27
|
+
| `systray2` | 2.1.4 | MIT | 系统托盘 |
|
|
28
|
+
| `zod` | 3.25.76 | MIT | 运行时数据校验 |
|
|
29
|
+
|
|
30
|
+
`onnxruntime-node` 内含 ONNX Runtime,版权归 Microsoft Corporation 所有,同样以 MIT 许可分发。
|
|
31
|
+
|
|
32
|
+
`systray2` 内嵌三个平台的托盘二进制,该二进制由 systray-portable 编译,其中包含 getlantern/systray 的代码 —— **这部分的许可是 Apache-2.0,不是 MIT**。单独点出来是因为它藏在 MIT 包的 asset 里,只看直接依赖表会漏掉。
|
|
33
|
+
|
|
34
|
+
分发包实际包含的组件(含间接依赖)、各自版本与**完整许可全文**见 [`THIRD-PARTY-LICENSES.md`](THIRD-PARTY-LICENSES.md)。该文件按 `bun build --metafile` 的实际打包结果生成,而不是按 `bun.lock` 罗列 —— 后者是安装集,会把没进二进制的包也列进去。
|
|
35
|
+
|
|
36
|
+
## 嵌入模型
|
|
37
|
+
|
|
38
|
+
本程序使用 `bge-small-zh-v1.5`(int8 量化)作为本地嵌入模型,版权归北京智源人工智能研究院(BAAI),以 MIT 许可发布。
|
|
39
|
+
|
|
40
|
+
**模型权重不随本仓库分发**,也不随官方分发包一同提供:首次启动时会从公开源(HuggingFace 等)按清单下载,并做 sha256 与文件大小双重校验后才落盘。下载失败时程序降级为纯全文检索,不影响可用性。
|
|
41
|
+
|
|
42
|
+
相关代码见 `src/embedder.ts`、`src/models.ts`。
|
package/README.md
CHANGED
|
@@ -1,3 +1,521 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<a href="https://xiaobenben.net"><img src="assets/brand/logo.svg" width="96" height="96" alt="XiaoBenBen logo" /></a>
|
|
4
|
+
|
|
5
|
+
<h1>XiaoBenBen</h1>
|
|
6
|
+
|
|
7
|
+
**Local-first memory for AI agents.**
|
|
8
|
+
|
|
9
|
+
One SQLite file on your own disk. Any MCP client. Memory that outlives sessions, models and reinstalls.
|
|
10
|
+
|
|
11
|
+
<a href="https://github.com/sji-xiaobenben/xiaobenben/releases/latest"><img alt="Release" src="https://img.shields.io/github/v/release/sji-xiaobenben/xiaobenben?style=flat-square&label=release&color=F22222"></a>
|
|
12
|
+
<a href="LICENSE"><img alt="License: AGPL-3.0-only" src="https://img.shields.io/badge/license-AGPL--3.0--only-F22222?style=flat-square"></a>
|
|
13
|
+
<a href="https://github.com/sji-xiaobenben/xiaobenben/actions/workflows/ci.yml"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/sji-xiaobenben/xiaobenben/ci.yml?branch=master&style=flat-square&label=CI"></a>
|
|
14
|
+
<img alt="Platforms" src="https://img.shields.io/badge/platform-Windows%20%7C%20macOS%20%7C%20Linux-4a4a4a?style=flat-square">
|
|
15
|
+
<img alt="MCP stdio" src="https://img.shields.io/badge/MCP-stdio-4a4a4a?style=flat-square">
|
|
16
|
+
<a href="CONTRIBUTING.md"><img alt="PRs welcome" src="https://img.shields.io/badge/PRs-welcome-2ea44f?style=flat-square"></a>
|
|
17
|
+
|
|
18
|
+
[Website](https://xiaobenben.net) · [Docs](https://xiaobenben.net/docs/personal-local/intro/) · [Changelog](https://xiaobenben.net/docs/personal-local/changelog/) · [Leaderboard](#leaderboard) · [Install](#install) · [CLI](#cli-reference) · [FAQ](https://xiaobenben.net/docs/personal-local/faq/)
|
|
19
|
+
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
> [!IMPORTANT]
|
|
23
|
+
> **Download only from [xiaobenben.net](https://xiaobenben.net) or this repository's [Releases](https://github.com/sji-xiaobenben/xiaobenben/releases).**
|
|
24
|
+
> The self-updater only trusts manifests signed by the official key, and only official builds
|
|
25
|
+
> (compiled from this repository) look for updates at all. A mirrored binary or a copy of this
|
|
26
|
+
> README does not make anything official.
|
|
27
|
+
|
|
28
|
+
XiaoBenBen (小本本, "the little notebook") is a memory service that your AI client launches as an MCP stdio server. Memories live in a single SQLite file on your machine. Your AI queries it before answering, writes conclusions into it when a decision is made, and the next session — or the next model, or the next IDE — picks up where you left off.
|
|
29
|
+
|
|
30
|
+
No account. No login. No telemetry. Works fully offline (only cloud collaboration needs the network). One executable, no system service, no config file to write first, no companion archive — semantic retrieval is built in (see [Install](#install)).
|
|
31
|
+
|
|
32
|
+
## Why this exists
|
|
33
|
+
|
|
34
|
+
AI memory today breaks in three places:
|
|
35
|
+
|
|
36
|
+
1. **Every conversation starts from zero.** The context window closes and yesterday's design decisions, last week's traps, your preferences and dealbreakers are gone. You retype the same background over and over.
|
|
37
|
+
2. **Switching clients erases it.** What you told opencode, Cursor and Claude Code stays in opencode, Cursor and Claude Code. Nothing is shared.
|
|
38
|
+
3. **To be remembered, you have to hand it over.** Almost every "AI memory" product is a cloud service, so your project layout, customer names, internal decisions and key fragments pass through somebody else's servers.
|
|
39
|
+
|
|
40
|
+
XiaoBenBen puts the database on your disk and lets the AI reach it over MCP. Change client, change model, change machine (via the cloud organisation mode) — the memory follows you, not the app.
|
|
41
|
+
|
|
42
|
+
## What you get
|
|
43
|
+
|
|
44
|
+
### Memory model
|
|
45
|
+
|
|
46
|
+
| Capability | What it does |
|
|
47
|
+
|---|---|
|
|
48
|
+
| **Two layers** | `episodes` keeps the raw record (what was actually said, append-only cold storage) and `memories` keeps the distilled layer (what we decided, as retrievable atomic facts). They point at each other through `source_chunk`, so a conclusion can always be traced back to the sentence it came from |
|
|
49
|
+
| **Types and intents** | Five content types `fact` / `preference` / `decision` / `event` / `procedure`, plus four intents `kind` = `memory` / `directive` (time-boxed instruction) / `habit` (long-term habit) / `constraint` (hard rule). Same tools, same table — different retrieval semantics |
|
|
50
|
+
| **Supersede chains** | An update never deletes the old entry, it chains it: **the head of the chain is the current truth**, older rings stay queryable. A preference you changed cannot be recalled alongside its stale version |
|
|
51
|
+
| **Two timelines** | `occurred_at` (when it happened, may be month-precision only) is stored separately from `created_at` (when it was recorded). That is what makes "what were we doing this time last year" answerable |
|
|
52
|
+
| **Entities and aliases** | Case variants, abbreviations and former names of the same person / project / product collapse into one entity; `recall_topic` aggregates per entity |
|
|
53
|
+
| **Explicit links** | Four relations — `related_to` / `elaborates` / `caused_by` / `contradicts` — with Hebbian weights: links you keep recalling together get stronger, unused ones decay |
|
|
54
|
+
| **Attachments** | Images, PDFs, logs, design files addressed by content (sha256) and attached to memories. Locally the library **registers the reference and never copies the bytes**; the same file attached to twelve memories is stored once |
|
|
55
|
+
| **Secret extraction** | Credentials are pulled out of the body into a local vault, leaving a `[[xbb_secret_id:N]]` placeholder behind. Copy, export or sync a memory and the secret does not travel with it |
|
|
56
|
+
| **Auditable** | Every change lands in a SHA-256 hash chain (`events`, linked by `prev_hash`). One command — `xbb verify` — proves the whole library is intact |
|
|
57
|
+
| **Forget is a tombstone** | `forget` marks a tombstone instead of `DELETE`: it disappears from retrieval immediately, but the audit chain still shows it happened |
|
|
58
|
+
|
|
59
|
+
### Retrieval
|
|
60
|
+
|
|
61
|
+
| Capability | What it does |
|
|
62
|
+
|---|---|
|
|
63
|
+
| **Three lexical passes in parallel** | FTS5 trigram (substring matching that behaves for CJK) ∥ a landing-pad inverted index (synonyms / hypernyms / situational terms generated at write time) ∥ exact entity match — fused with IDF weighting |
|
|
64
|
+
| **A fourth, vector pass** | `bge-small-zh-v1.5` INT8 runs locally (24 MB, 512 dims) and joins the lexical results via RRF. **No network, no model API** |
|
|
65
|
+
| **Chain-head redirect** | A hit on a historical ring jumps to the chain head (current truth) and shows the old value as an annotation — the single most common memory failure is confidently recalling a stale fact |
|
|
66
|
+
| **1-hop expansion** | A hit brings along the neighbours it declares, ranked by link strength, expandable hop by hop |
|
|
67
|
+
| **Miss guidance** | On an empty result you get `related_tags` — "try these phrasings instead" — rather than a bare "nothing found" |
|
|
68
|
+
| **Hard budgets** | Row count and token count are both capped; the library is never dumped into a context window |
|
|
69
|
+
| **Silent degradation** | Model missing / load failure / inference error → quietly fall back to lexical-only. Plain text is still stored, and **a broken model never breaks the app** |
|
|
70
|
+
|
|
71
|
+
### Integration
|
|
72
|
+
|
|
73
|
+
| Capability | What it does |
|
|
74
|
+
|---|---|
|
|
75
|
+
| **MCP stdio** | One config stanza and the host spawns it, reaps it on exit. No client-side code |
|
|
76
|
+
| **Turn hooks for six hosts** | One zero-dependency script covers Claude Code / Cursor / Trae / WorkBuddy / Codex CLI, plus a dedicated plugin for opencode. Each turn is forwarded to the local service for in-memory retrieval, invisibly to the host |
|
|
77
|
+
| **Five session collectors** | Read the local session stores of opencode / Cursor / WorkBuddy / Claude Code / Codex — read-only, idempotent, in place |
|
|
78
|
+
| **Structure not client names** | A dedicated parser tries first, then a format descriptor, then generic sniffing. An upstream field rename is no longer fatal, and structural fingerprints show up in `xbb ingest --status` the day it changes |
|
|
79
|
+
|
|
80
|
+
### Privacy and sovereignty
|
|
81
|
+
|
|
82
|
+
- **No login** — no account, no email, no binding. Install and go
|
|
83
|
+
- **No telemetry** — the codebase contains no channel that reports usage, crashes or metrics
|
|
84
|
+
- **Local-first** — personal memory is 100% local SQLite; organisation (enterprise) memory is 100% not local
|
|
85
|
+
- **No silent upload** — outbound traffic happens only when you explicitly use a cloud feature
|
|
86
|
+
- **The raw layer never goes to the cloud** — `episodes` is local-only cold storage; the cloud backend does not implement it
|
|
87
|
+
- **Collection stays local** — reading other AI tools' data happens between memory and local file, nowhere else
|
|
88
|
+
|
|
89
|
+
### Security and supply chain
|
|
90
|
+
|
|
91
|
+
- **Verify before compare** — the update manifest is ed25519-signed; a bad signature is rejected outright. There is no "skip verification on failure" branch
|
|
92
|
+
- **Double check** — sha256 plus file size; either mismatch refuses the swap
|
|
93
|
+
- **Roll back on failure** — a build that will not start gets replaced by the previous one and blacklisted
|
|
94
|
+
- **Compiled builds only** — only a compiled single-file binary may be swapped in
|
|
95
|
+
- **Local service origin checks** — Host / Origin are checked **before any route**, defeating DNS rebinding and cross-site calls
|
|
96
|
+
- **Published threat model** — no inflated claims; [`SECURITY.md`](SECURITY.md) lists every known trade-off, including "the secret vault is masking, not encryption"
|
|
97
|
+
|
|
98
|
+
### Desktop experience
|
|
99
|
+
|
|
100
|
+
- **Start on login** — on by default on all three platforms (Windows registry / macOS launchd / Linux XDG); a windowless service plus a tray icon after login
|
|
101
|
+
- **Tray menu** — open the admin window, verify, export diagnostics, check for updates, switch local/cloud, toggle autostart, quit
|
|
102
|
+
- **Admin window** — `http://127.0.0.1:17630/ui`: browse, search, per-session recall, filter by intent (memory / directive / habit / constraint), edit, delete (tombstone), vault, cloud binding, cleanup preview, diagnostics
|
|
103
|
+
- **Desktop notifications** — when a colleague sends you a memory or acknowledges something you sent (Windows Toast / macOS Notification Center / libnotify)
|
|
104
|
+
- **Local ⇄ cloud in one switch** — switching back to local **keeps your key**, so you can switch on again without a new binding ceremony
|
|
105
|
+
|
|
106
|
+
## How it works
|
|
107
|
+
|
|
108
|
+
### Who writes what
|
|
109
|
+
|
|
110
|
+
MCP is request/response; the engine cannot see the conversation. So there are three entry points, each owning one layer:
|
|
111
|
+
|
|
112
|
+
| Entry point | How it arrives | Which layer it writes |
|
|
113
|
+
|---|---|---|
|
|
114
|
+
| `xbb mcp` | The AI host spawns it as an MCP stdio server | **Distilled layer**, `memories` — atomic facts the AI chose to distil |
|
|
115
|
+
| `xbb serve` turn hook | Plugin / hook POSTs to `/hooks/turn` | **Raw layer**, `episodes` — live turns |
|
|
116
|
+
| `xbb ingest` | Read-only scan of client session stores | **Raw layer**, `episodes` — historical sessions |
|
|
117
|
+
|
|
118
|
+
- **The distilled layer is written by the AI.** The AI decides what is worth keeping long term — conclusions, decisions, traps, your corrections — and distils it into atomic facts with retrieval landing pads. This is where memory quality comes from.
|
|
119
|
+
- **The raw layer is captured by the engine.** Hooks take live turns; collectors read what the clients already wrote to disk. No client cooperation required, so there is no "write a plugin for every new agent".
|
|
120
|
+
|
|
121
|
+
Both layers live in the same SQLite file and point at each other via `source_chunk`: the distilled layer records the conclusion, the raw layer keeps the evidence.
|
|
122
|
+
|
|
123
|
+
### The retrieval pipeline
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
query terms (expanded by the AI: synonyms / hypernyms / situational words / entity names)
|
|
127
|
+
├─ FTS5 trigram substring match
|
|
128
|
+
├─ landing-pad inverted index (>= 3 chars)
|
|
129
|
+
├─ landing-pad inverted index (1-2 chars)
|
|
130
|
+
└─ local vector cosine (512 dims)
|
|
131
|
+
↓
|
|
132
|
+
IDF-weighted fusion + RRF (vector track)
|
|
133
|
+
↓
|
|
134
|
+
chain-head redirect → budget cap → 1-hop expansion → miss guidance
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Everything is local SQL and local inference. **Zero network, zero model API.** The query terms are expanded by the AI before the call — which is the point of "mechanism, not semantics": the engine ships the retrieval machinery and leaves meaning to the model that can actually see the conversation.
|
|
138
|
+
|
|
139
|
+
### Three rules everything follows
|
|
140
|
+
|
|
141
|
+
1. **Mechanism, not semantics.** The engine presets no categories and enumerates no "domains". A constraint's `domain` is an empty container: which domains exist (UI design, code style, tone of voice) is merged dynamically as the AI writes. Memory `terms` are generated by the AI. There is no hard-coded business taxonomy in the code, so a new use case needs no engine change.
|
|
142
|
+
2. **Append-only.** Changes go through an event hash chain, forgetting is a tombstone, raw speech is cold storage. Every "edit" leaves a trace, and `xbb verify` proves the ledger was not rewritten.
|
|
143
|
+
3. **Conservative by default.** Cloud visibility defaults to private (sharing must be explicit); a library that is not where it is expected **refuses to start** (better to fail than to silently run on an empty database); creating a database requires an explicit `--force`; autostart can be switched off permanently and never quietly re-enabled.
|
|
144
|
+
|
|
145
|
+
### How this differs from cloud memory SaaS
|
|
146
|
+
|
|
147
|
+
| Dimension | XiaoBenBen (local-first) | Typical cloud memory SaaS |
|
|
148
|
+
|---|---|---|
|
|
149
|
+
| Where data lives | Your own disk, one SQLite file | Vendor servers |
|
|
150
|
+
| Offline | Works (except cloud collaboration) | Usually unavailable or degraded |
|
|
151
|
+
| Latency | Local SQL, no round trip | One round trip per retrieval |
|
|
152
|
+
| Secrets / sensitive data | Extracted into a local vault, never leaves the machine | Usually uploaded |
|
|
153
|
+
| Audit | Hash chain on your disk, self-verifiable | Depends on vendor logs |
|
|
154
|
+
| Cross-device | Personal: local; organisation: cloud API | Native |
|
|
155
|
+
| Switching clients | MCP is a standard, works everywhere | Each ecosystem its own |
|
|
156
|
+
|
|
157
|
+
Local is not the right answer for everything: for geographically distributed teams that need central retrieval, cloud is correct. XiaoBenBen's choice is **local by default, upstream only when you ask**.
|
|
158
|
+
|
|
159
|
+
## Leaderboard
|
|
160
|
+
|
|
161
|
+
Sixteen products, twenty-one capabilities, every cell scored 0–10 (0 means the mechanism does not exist). Scored October 2026.
|
|
162
|
+
|
|
163
|
+
| # | Product | Retrieval | Memory structure | Delivery & sovereignty | Storage & context | Overall |
|
|
164
|
+
|---:|---|---:|---:|---:|---:|---:|
|
|
165
|
+
| 1 | **XiaoBenBen** | **8.78** | **9.37** | **9.70** | **9.86** | **9.28** |
|
|
166
|
+
| 2 | Graphiti | 7.46 | 5.40 | 6.64 | 8.09 | 6.94 |
|
|
167
|
+
| 3 | Zep | 7.68 | 5.40 | 7.15 | 6.14 | 6.87 |
|
|
168
|
+
| 4 | MemOS | 7.01 | 4.83 | 6.09 | 7.32 | 6.40 |
|
|
169
|
+
| 5 | Mem0 | 6.80 | 4.83 | 6.22 | 7.09 | 6.31 |
|
|
170
|
+
| 6 | Cognee | 6.00 | 4.73 | 6.09 | 7.09 | 5.93 |
|
|
171
|
+
| 7 | Letta | 5.85 | 4.90 | 5.43 | 7.05 | 5.73 |
|
|
172
|
+
| 8 | Obsidian | 4.14 | 4.83 | 8.39 | 6.95 | 5.73 |
|
|
173
|
+
| 9 | QwenWork | 5.22 | 5.23 | 6.05 | 7.05 | 5.69 |
|
|
174
|
+
| 10 | DouBao Work | 5.65 | 6.17 | 5.43 | 4.80 | 5.58 |
|
|
175
|
+
| 11 | WorkBuddy | 5.17 | 4.47 | 6.34 | 6.23 | 5.47 |
|
|
176
|
+
| 12 | Supermemory | 5.27 | 4.23 | 6.46 | 5.32 | 5.36 |
|
|
177
|
+
| 13 | Qoder | 3.97 | 6.00 | 5.96 | 6.45 | 5.22 |
|
|
178
|
+
| 14 | Codex | 3.56 | 4.33 | 6.65 | 7.23 | 5.01 |
|
|
179
|
+
| 15 | Kimi Work | 4.89 | 4.73 | 4.68 | 5.09 | 4.83 |
|
|
180
|
+
| 16 | ima | 4.69 | 2.73 | 4.74 | 4.95 | 4.35 |
|
|
181
|
+
|
|
182
|
+
**How to read it.** The four groups are weighted means of the 21 capabilities (retrieval 7 columns, memory structure 4, delivery / portability / sovereignty / cost 6, storage / capacity / context cost 4), all summing to 151. Overall is the weighted mean of all 21 cells, which is why the group scores and the total always agree — re-weighting the groups gives you the same total back.
|
|
183
|
+
|
|
184
|
+
**Read a row, not the ranking.** A single number hides the interesting part. Obsidian scores 4.14 on retrieval and 8.39 on delivery, because it is a notebook rather than a memory engine — and if what you want is a notebook, it is the right answer.
|
|
185
|
+
|
|
186
|
+
**Where we don't lead.** Three of the 21 capabilities: **semantic retrieval** (7.5, behind Mem0's 8.5 — our vector track is a small local INT8 model, theirs is a hosted embedding service), **temporal** (8.5, behind Graphiti and Zep at 9 — their graph stores are built around time), and **cross-platform** (8.5, behind Zep's 9.5 — we ship desktop binaries, not a managed SaaS with a browser client). All three are deliberate trade-offs, not oversights.
|
|
187
|
+
|
|
188
|
+
**Scores are ours.** The matrix reflects what we think matters for a memory layer that an AI calls every turn, and it is arithmetic, not a survey: no external reviewers scored these cells. The full 21-column matrix — every cell, heat-mapped, with per-column weights — is on the [website](https://xiaobenben.net/#matrix), so you can check any single claim rather than trust the summary.
|
|
189
|
+
|
|
190
|
+
## Install
|
|
191
|
+
|
|
192
|
+
Download your platform's executable from <https://xiaobenben.net> or [Releases](https://github.com/sji-xiaobenben/xiaobenben/releases). **One file, nothing to install alongside it.** Since 0.4.50 the ONNX runtime (CPU backend only) is embedded in the binary and unpacked to `~/.xiaobenben/ort/` on first run — about a second, once.
|
|
193
|
+
|
|
194
|
+
| Platform | Binary | Semantic retrieval |
|
|
195
|
+
|---|:---:|---|
|
|
196
|
+
| Windows x64 · macOS arm64 · Linux x64 | ✅ | ✅ built in |
|
|
197
|
+
| macOS x64 (Intel) | ✅ | ❌ — upstream publishes no onnxruntime native library for this platform, so retrieval is lexical-only with no way to opt in |
|
|
198
|
+
|
|
199
|
+
Embedding it is not free in bytes but it is free in *steps*: the GPU backends (36 MB of DirectML) are dropped because the session is CPU-only, which keeps the single binary smaller than the old "binary + runtime archive" pair it replaces.
|
|
200
|
+
|
|
201
|
+
Nothing to initialise: the database is created on your first MCP handshake. `xbb home init` is only for non-default locations. After that the binary updates itself from the signed official manifest; what changed in each version is in the [changelog](https://xiaobenben.net/docs/personal-local/changelog/).
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
xbb --help # every command, zero side effects
|
|
205
|
+
xbb serve # start the local service (127.0.0.1:17630)
|
|
206
|
+
xbb stop # stop it
|
|
207
|
+
xbb stop --keep-mcp # stop the service but keep MCP connections
|
|
208
|
+
xbb version # version + build fingerprint
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
`--help` is intercepted before anything else runs, works anywhere in the line, and executes nothing — `xbb stop --help` will not stop anything.
|
|
212
|
+
|
|
213
|
+
### Via npm
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
npx -y xiaobenben mcp # run the MCP server without installing anything globally
|
|
217
|
+
npm i -g xiaobenben # or get the `xiaobenben` and `xbb` commands
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
The npm package is a ~47 kB wrapper, not the binary itself. `postinstall` fetches your platform's build from the signed manifest, **verifies its SHA-256 before writing anything**, and puts it in a per-version user cache (`%LOCALAPPDATA%\xiaobenben\pkg` · `~/Library/Caches/xiaobenben/pkg` · `~/.cache/xiaobenben/pkg`) so every project on the machine shares one copy. Installed with `--ignore-scripts`? The first run fetches it instead. Either way the binary keeps self-updating from the same signed manifest as the standalone download.
|
|
221
|
+
|
|
222
|
+
Available on Windows x64, macOS arm64/x64 and Linux x64 — the same four builds as above. On other architectures npm installs the wrapper but logs that no build exists yet.
|
|
223
|
+
|
|
224
|
+
## Connect your AI client
|
|
225
|
+
|
|
226
|
+
Add `xbb` as a stdio server in your client's MCP config. The host spawns the process; you do not run it by hand.
|
|
227
|
+
|
|
228
|
+
```json
|
|
229
|
+
{
|
|
230
|
+
"mcpServers": {
|
|
231
|
+
"xiaobenben": { "command": "xbb", "args": ["mcp"] }
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
On Windows, if the exe is not on `PATH`, use the full path (e.g. `C:\\Users\\you\\.xiaobenben\\bin\\xbb.exe`).
|
|
237
|
+
|
|
238
|
+
Or skip the download entirely and let npm handle it:
|
|
239
|
+
|
|
240
|
+
```json
|
|
241
|
+
{
|
|
242
|
+
"mcpServers": {
|
|
243
|
+
"xiaobenben": { "command": "npx", "args": ["-y", "xiaobenben", "mcp"] }
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Twelve hosts are verified. Six of them go beyond MCP:
|
|
249
|
+
|
|
250
|
+
| Host | MCP stdio | Turn hook | Session collector |
|
|
251
|
+
|---|:---:|:---:|:---:|
|
|
252
|
+
| opencode | ✅ | ✅ (dedicated plugin) | ✅ |
|
|
253
|
+
| Claude Code | ✅ | ✅ | ✅ |
|
|
254
|
+
| Cursor | ✅ | ✅ | ✅ |
|
|
255
|
+
| WorkBuddy | ✅ | ✅ | ✅ |
|
|
256
|
+
| Codex CLI | ✅ | ✅ | ✅ |
|
|
257
|
+
| Trae | ✅ | ✅ | — |
|
|
258
|
+
| Copilot · Qoder · Kimi Code · OpenClaw · MaxClaw · Muse | ✅ | — | — |
|
|
259
|
+
|
|
260
|
+
Per-client steps (and the screenshots) are in the [install guide](https://xiaobenben.net/docs/personal-local/install/).
|
|
261
|
+
|
|
262
|
+
### Tool surface
|
|
263
|
+
|
|
264
|
+
Tools are ordered as one retrieval journey: write → retrieve → fetch → rules → maintain → organisation.
|
|
265
|
+
|
|
266
|
+
The count is not a metric — the context window is scarce, and every extra tool costs a paragraph of description and one more chance to pick wrong. That is why there is deliberately **no** "manage memory categories" entry: categorisation is the AI's job at write time, it should not become a taxonomy tree users maintain.
|
|
267
|
+
|
|
268
|
+
| Group | Tools | What for |
|
|
269
|
+
|---|---|---|
|
|
270
|
+
| Write | `write_memory` `log_episodes` | Land 3–5 atomic facts in one call; backfill raw turns |
|
|
271
|
+
| Retrieve | `search_memory` `recall_topic` `recall_session` `recall_timeline` `recall_episodes` `recall_transcript` | Hybrid search, entity aggregation, session replay, timeline reconstruction, paging through the raw record |
|
|
272
|
+
| Fetch | `get_memory` `get_related` `get_asset` `reveal_secret` | Full text plus chain, 1-hop neighbours, attachment bytes, secret plaintext |
|
|
273
|
+
| Rules | `recall_directives` `recall_constraints` | Must-ask at session start: habits + time-boxed instructions + global constraints + domain constraints matched by task terms |
|
|
274
|
+
| Maintain | `supersede` `forget` `stats` `inbox` `ack` `outbox` | Repair chains, tombstones, usage, pending inbox, acknowledgement, sent box |
|
|
275
|
+
| Organisation | `list_spaces` `list_members` `set_memory_audience` | Space tree, members, visibility (cloud organisation mode) |
|
|
276
|
+
|
|
277
|
+
Tool descriptions are **judgement criteria for the model**, not parameter docs: what to remember, what never to remember ("skip anything the raw record already contains; keep the conclusions the raw record will never state"), when retrieval is mandatory, how to mark a secret. Those criteria are what the library's long-term quality actually rests on.
|
|
278
|
+
|
|
279
|
+
### Turn hooks (optional)
|
|
280
|
+
|
|
281
|
+
To have XiaoBenBen participate **on every turn** (relevant memories land in the inbox), install one zero-dependency script:
|
|
282
|
+
|
|
283
|
+
- `plugins/opencode/xbb-push.js` → drop into `~/.config/opencode/plugins/`
|
|
284
|
+
- `plugins/hooks/xbb-hook.mjs` → generic across six hosts, wiring in [`plugins/hooks/README.md`](plugins/hooks/README.md)
|
|
285
|
+
|
|
286
|
+
The hard rule is **candidates are never injected**: the script's stdout is always empty, so no memory content ever enters the host context (Trae and friends treat stdout as context). Any failure exits 0 silently and never blocks the host's turn.
|
|
287
|
+
|
|
288
|
+
## Cloud mode (optional, backend not open source)
|
|
289
|
+
|
|
290
|
+
**By default not a single byte leaves the machine.** Only after you explicitly run `xbb bind` (a one-shot ticket from the console) or `xbb bind-key` (reuse an existing key across machines) does the client talk to `api.xiaobenben.net` — and only while you use a cloud feature.
|
|
291
|
+
|
|
292
|
+
This layer solves **collaboration**, not storage:
|
|
293
|
+
|
|
294
|
+
- **Personal memory stays local** — what goes up is organisation (enterprise) memory, which is 100% not local and physically separate from your personal library
|
|
295
|
+
- **Private by default** — each memory is visible to its author only; sharing with a department or the whole organisation must be explicit, and the write response echoes the effective visibility instead of making you guess
|
|
296
|
+
- **Reversible** — `xbb cloud off` only pauses (the key is kept, `on` brings it back); only `xbb unbind` actually deletes. Without that, "going to the cloud" is a one-way door
|
|
297
|
+
- **Multi-device** — the same long-lived key works on any number of machines
|
|
298
|
+
|
|
299
|
+
### Getting access
|
|
300
|
+
|
|
301
|
+
No application, no invite list: after signing in you get 1 GB of free reads and writes per month, then ¥10/GB from your balance, which never expires (prices and quotas: <https://xiaobenben.net/versions/personal-cloud/#pricing>).
|
|
302
|
+
|
|
303
|
+
Binding takes two steps, and **the ticket is not the key**:
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
xbb register-protocol # one-off: point the xubb:// protocol at this exe
|
|
307
|
+
xbb bind "xubb://bind?ticket=…&api=…" # generated by "connect my XiaoBenBen", single use, 60 s
|
|
308
|
+
xbb bind-key <xbb_live_…> # existing long-lived key: another machine, or after losing config
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
`register-protocol` **does not run automatically**. Skip it and the console's "connect my XiaoBenBen" button does precisely nothing — with no error, no feedback. This is the single most common place to get stuck.
|
|
312
|
+
|
|
313
|
+
The ticket **establishes** trust (one-shot, expires in 60 seconds, must be generated fresh); the key **reuses** trust (long-lived, many machines). On a second machine, repeat only the last step.
|
|
314
|
+
|
|
315
|
+
Where to go: <https://account.xiaobenben.net> for quota and balance, <https://console.xiaobenben.net> to generate a binding ticket.
|
|
316
|
+
|
|
317
|
+
The server, console and organisation management are not in this repository and are not open source. That is a boundary statement, not a feature list — implementation details would not be verifiable anyway. **What is verifiable is this:** without binding, every local feature of `xbb mcp` and `xbb serve` works with the network unplugged, and none of that code path participates at all.
|
|
318
|
+
|
|
319
|
+
The client-side integration point is one file: [`src/cloud.ts`](src/cloud.ts) (six tools routed local/cloud by profile).
|
|
320
|
+
|
|
321
|
+
## Start on login (on by default)
|
|
322
|
+
|
|
323
|
+
The first `xbb serve` writes a startup entry, and every login afterwards starts a silent resident service — no console window, no admin page popping up, the XiaoBenBen icon in the taskbar / menu bar.
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
xbb autostart # inspect: where, pointing at what, what the user asked for
|
|
327
|
+
xbb autostart off # turn off, and do not write it back later
|
|
328
|
+
xbb autostart on # turn back on
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Every platform uses its native mechanism; no extra service is installed:
|
|
332
|
+
|
|
333
|
+
| Platform | Location | Runs at login |
|
|
334
|
+
|---|---|---|
|
|
335
|
+
| Windows | `HKCU\…\CurrentVersion\Run` → `小本本服务` | `"xbb.exe" serve --detach` (windowless) |
|
|
336
|
+
| macOS | `~/Library/LaunchAgents/net.xiaobenben.xbb.plist` | launchd runs `xbb serve --no-open` |
|
|
337
|
+
| Linux | `~/.config/autostart/xbb.desktop` | `xbb serve --detach` (XDG autostart) |
|
|
338
|
+
|
|
339
|
+
Two things worth knowing:
|
|
340
|
+
|
|
341
|
+
- **`xbb autostart off` is sticky.** It records `autostart: "off"` in `config.json`, and `serve` will not re-add the entry afterwards. The tray menu's "Start on login: on/off" is the same switch.
|
|
342
|
+
- **Keep the exe in a fixed location** (e.g. `~/.xiaobenben/bin/xbb`). The startup entry stores an absolute path: run it straight from Downloads, clean up Downloads, and the entry points at a file that no longer exists. Running the exe again fixes it, and `xbb autostart status` always shows where it currently points.
|
|
343
|
+
|
|
344
|
+
## CLI reference
|
|
345
|
+
|
|
346
|
+
```
|
|
347
|
+
Service and access
|
|
348
|
+
xbb status overview (mode / where the library is / common commands)
|
|
349
|
+
xbb serve [--detach|--no-open|--headless] start service + tray + admin window (:17630)
|
|
350
|
+
xbb mcp MCP stdio (the entry point AI hosts spawn)
|
|
351
|
+
xbb stop [--keep-mcp] stop every local xbb process
|
|
352
|
+
xbb autostart [on|off|status] start on login (on by default; all three platforms)
|
|
353
|
+
|
|
354
|
+
Data location
|
|
355
|
+
xbb home where the program is, where the library is, why it decided that
|
|
356
|
+
xbb home move <dir> move the library: copy → verify → only then switch config; no verify, no switch
|
|
357
|
+
xbb home set <dir> change config without moving (target must already hold memory.db)
|
|
358
|
+
xbb home find [--deep] scan drives for memory.db, sorted by memory count
|
|
359
|
+
xbb home reset drop the config, return to the default location
|
|
360
|
+
xbb home init --force create an empty library here (the only way to create one)
|
|
361
|
+
|
|
362
|
+
Cloud
|
|
363
|
+
xbb cloud [on|off|status] local ⇄ cloud switch (keeps the key)
|
|
364
|
+
xbb bind <ticket> bind the cloud (xubb:// invocation, or a 60 s single-use ticket)
|
|
365
|
+
xbb bind-key <key> bind with a long-lived key you already have
|
|
366
|
+
xbb unbind unbind and delete the local key (irreversible)
|
|
367
|
+
xbb register-protocol register the xubb:// protocol handler (three platforms)
|
|
368
|
+
|
|
369
|
+
Collection and maintenance
|
|
370
|
+
xbb ingest [--status|--dry-run|--source=…|--limit=N] collect session text from local AI clients
|
|
371
|
+
xbb verify audit: personal library hash-chain integrity
|
|
372
|
+
xbb version version banner + build fingerprint
|
|
373
|
+
|
|
374
|
+
Update
|
|
375
|
+
xbb update check for and apply updates (clears the rollback blacklist)
|
|
376
|
+
xbb update-status self-update status
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
The command set has the same discipline as the rest: `xbb home move` copies, then verifies integrity and compares row counts item by item, and only then switches the config — any failed step aborts and leaves the original library untouched. `xbb home init` requires an explicit `--force`, because "create an empty library" is irreversible and looks exactly like "all my memories vanished, but the app is fine".
|
|
380
|
+
|
|
381
|
+
## Where your data lives
|
|
382
|
+
|
|
383
|
+
| Content | Location |
|
|
384
|
+
|---|---|
|
|
385
|
+
| Library `memory.db` | The program directory (movable to any drive with `xbb home move`) |
|
|
386
|
+
| Config `config.json` | The program directory — **the anchor follows the program, never the library**, so "anchor present, cargo missing" is a detectable anomaly instead of a first run |
|
|
387
|
+
| Vector model | `models/` under the data directory (defaults to the program dir, ~24 MB, downloaded on first start) |
|
|
388
|
+
| Cloud key | `~/.xiaobenben/cloud.json` (cloud mode only) |
|
|
389
|
+
|
|
390
|
+
Forgot where the library is? `xbb home find --deep` — sorted by memory count, because empty databases with the same name are everywhere and only the count tells you which one is real.
|
|
391
|
+
|
|
392
|
+
## Engineering
|
|
393
|
+
|
|
394
|
+
| Item | Measured |
|
|
395
|
+
|---|---|
|
|
396
|
+
| Tests | Smoke tests pin **specific disasters**, not coverage numbers: a badly signed manifest must be rejected, a tampered manifest must be caught, a missing vector model must degrade silently instead of erroring, upstream field renames must still work through sniffing, the tray asset must really be embedded in the exe, the exe icon must be byte-identical to the source `.ico`, and migrations must be able to roll back. CI runs on Windows and Linux |
|
|
397
|
+
| Types | `tsc --noEmit` clean (`strict: true`) |
|
|
398
|
+
| Artifact | Single file: Windows ~87 MB / Linux ~83 MB / macOS ~65 MB (arm64) and ~71 MB (x64), including SQLite and the ONNX runtime |
|
|
399
|
+
| Cold start | `xbb --help` ~140 ms |
|
|
400
|
+
| Dependencies | 4 production dependencies (MCP SDK / ONNX Runtime / tray / zod), all from the official npmjs registry; `bun.lock` contains no internal mirrors |
|
|
401
|
+
|
|
402
|
+
Every third-party component that actually ships inside the binary (including transitive ones) and its full licence text is in [`THIRD-PARTY-LICENSES.md`](THIRD-PARTY-LICENSES.md) — generated from `bun build --metafile` output, i.e. what is really bundled, not a lockfile dump.
|
|
403
|
+
|
|
404
|
+
`core/` is a vendored copy of `@xbb/core` (uuidv7 / event hash chain / ports and error codes) published with this repository, so `git clone` builds without access to any private repo. **Do not edit files under `core/` directly**; see [`core/README.md`](core/README.md).
|
|
405
|
+
|
|
406
|
+
## Build from source
|
|
407
|
+
|
|
408
|
+
Requires [Bun](https://bun.sh) ≥ 1.4.2 (matching `package.json`'s `engines`; CI pins 1.4.2).
|
|
409
|
+
Nothing else — no private registry, no token, no clone of a second repository.
|
|
410
|
+
|
|
411
|
+
**One line, from nothing to a working binary for the machine you are on:**
|
|
412
|
+
|
|
413
|
+
```bash
|
|
414
|
+
git clone https://github.com/sji-xiaobenben/xiaobenben && cd xiaobenben && bun install && bun run build
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
`bun run build` compiles for the host platform and names the artifact accordingly, so the next
|
|
418
|
+
command works without you renaming anything:
|
|
419
|
+
|
|
420
|
+
| Host | Artifact |
|
|
421
|
+
|---|---|
|
|
422
|
+
| Windows x64 | `dist/xbb-windows-x64.exe` |
|
|
423
|
+
| Linux x64 | `dist/xbb-linux-x64` |
|
|
424
|
+
| macOS Apple Silicon | `dist/xbb-darwin-arm64` |
|
|
425
|
+
| macOS Intel | `dist/xbb-darwin-x64` |
|
|
426
|
+
|
|
427
|
+
Cross-compiling uses the explicit variants (a Bun target triple each):
|
|
428
|
+
|
|
429
|
+
```bash
|
|
430
|
+
bun run build:win # dist/xbb-windows-x64.exe
|
|
431
|
+
bun run build:linux # dist/xbb-linux-x64
|
|
432
|
+
bun run build:mac-arm # dist/xbb-darwin-arm64
|
|
433
|
+
bun run build:mac-intel
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
Verify the toolchain before building, if you want:
|
|
437
|
+
|
|
438
|
+
```bash
|
|
439
|
+
bun run typecheck
|
|
440
|
+
bun run test:ci
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
All of these go through `tools/build.ts`, which is the single definition of "how an artifact is
|
|
444
|
+
compiled": it stamps the icon, product name, publisher and file version into the Windows resource
|
|
445
|
+
section (from `assets/app.ico` and `package.json`), then reads the resource section back to prove
|
|
446
|
+
the icon landed. Regenerate the icons with `bun run gen:app-icon` (exe / logo) or
|
|
447
|
+
`bun run gen:tray-icon` (tray).
|
|
448
|
+
|
|
449
|
+
A locally built artifact reports `build local` in `xbb version` and **does not take part in self-update by default**: it embeds the official public key and CDN, so updating normally would only replace your build with the official exe. Point `XBB_UPDATE_URL` at the official source (or your own mirror) to opt in; to distribute your own version long term you also need your own key — see "Distributing your own build after forking" in [`CONTRIBUTING.md`](CONTRIBUTING.md).
|
|
450
|
+
|
|
451
|
+
The criterion is **publisher identity**, not "was it compiled": the artifact embeds `BUILD_REPO`, and the built-in update source is trusted only when it equals `OFFICIAL_REPO`. So even an exe from your own fork's CI will not ask the official site for updates, even though it has a real build timestamp. To check: `xbb update` reports a non-official build, disables self-update, and names the source repository.
|
|
452
|
+
|
|
453
|
+
> `bun.lock` records the official registry `registry.npmjs.org`. If installs are slow from mainland China, mirror it temporarily:
|
|
454
|
+
> `bun install --registry https://registry.npmmirror.com`
|
|
455
|
+
|
|
456
|
+
## Privacy
|
|
457
|
+
|
|
458
|
+
- **No telemetry** — there is no channel in the code that reports usage; self-update fetches a version manifest and carries no identifier
|
|
459
|
+
- **Model download on first start** — the embedding model ships separately and is downloaded from a public source (HuggingFace / hf-mirror) with sha256 verification; on failure it degrades to full-text retrieval, which does not affect usability
|
|
460
|
+
- **Collection scope** — it reads other AI tools' local data (`opencode.db`, only the `composerData:` and `bubbleId:` keys in Cursor's `state.vscdb`, `.claude`, `.codex`, `.workbuddy`). All processing is local and nothing is uploaded automatically
|
|
461
|
+
- **The raw layer never goes to the cloud** — `episodes` is local only; the cloud backend does not implement it
|
|
462
|
+
- **Cloud visibility defaults to private** — each memory is visible to its author; sharing with the organisation or a department must be explicit, and the write response echoes the effective visibility
|
|
463
|
+
|
|
464
|
+
The threat model of the local service and every known design trade-off are in [`SECURITY.md`](SECURITY.md) — worth reading before you use it. The short version: local HTTP has no authentication (the boundary is "same user on this machine"), the database is not encrypted (it relies on file permissions), and the secret vault is **masking, not encryption**.
|
|
465
|
+
|
|
466
|
+
## License
|
|
467
|
+
|
|
468
|
+
Released under the **GNU Affero General Public License v3.0 only (AGPL-3.0-only)** — see [`LICENSE`](LICENSE).
|
|
469
|
+
|
|
470
|
+
A commercial licence is available for closed-source distribution, closed-source hosted services, OEM bundling and similar; see [`LICENSE-Commercial.md`](LICENSE-Commercial.md) or write to `admin@sji.xin`.
|
|
471
|
+
|
|
472
|
+
**Internal use triggers no open-source obligation** — deploying inside your company, forking for internal development, or processing your own data with this software needs no commercial licence.
|
|
473
|
+
|
|
474
|
+
Every source file carries a machine-readable licence identifier:
|
|
475
|
+
|
|
476
|
+
```
|
|
477
|
+
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Commercial
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
`LicenseRef-Commercial` is the SPDX-spec way to reference a custom licence — in this case the commercial document above. A scanner reporting "unknown licence `LicenseRef-Commercial`" is expected: it is not a standard identifier, and it should not be replaced with `MIT`, `Apache-2.0` or anything similar. For compliance review, read [`LICENSE-Commercial.md`](LICENSE-Commercial.md).
|
|
481
|
+
|
|
482
|
+
## Trademark
|
|
483
|
+
|
|
484
|
+
"小本本", "xiaobenben", "SJi" and the associated names and marks are trademarks or business identifiers of [世纪之城(广州)信息科技有限公司](https://sji.xin) (SJI). The copyright licence **does not include a trademark licence**: you may modify and distribute the code, but you may not name or promote a derivative with the same or a confusingly similar mark. See [`NOTICE`](NOTICE).
|
|
485
|
+
|
|
486
|
+
## Contributing
|
|
487
|
+
|
|
488
|
+
Issues and pull requests are welcome. Please read [`CONTRIBUTING.md`](CONTRIBUTING.md) first — **every external contribution requires signing the CLA**, which is what lets the project keep running on the AGPL + commercial dual track. Also see [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md).
|
|
489
|
+
|
|
490
|
+
## Security
|
|
491
|
+
|
|
492
|
+
Do not open a public issue for a vulnerability. Report it as described in [`SECURITY.md`](SECURITY.md).
|
|
493
|
+
|
|
494
|
+
## Support
|
|
495
|
+
|
|
496
|
+
| Topic | Where |
|
|
497
|
+
|---|---|
|
|
498
|
+
| Usage questions, bugs, feature requests | Prefer an [issue](https://github.com/sji-xiaobenben/xiaobenben/issues) (public and searchable, so others benefit); `support@sji.xin` if it cannot be public |
|
|
499
|
+
| Commercial licence / OEM | [`LICENSE-Commercial.md`](LICENSE-Commercial.md), `admin@sji.xin` |
|
|
500
|
+
| Security vulnerabilities | [`SECURITY.md`](SECURITY.md) — never a public issue |
|
|
501
|
+
|
|
502
|
+
## A note on this repository's history
|
|
503
|
+
|
|
504
|
+
The public history starts at `v0.4.47`; earlier development history is retained privately by the copyright holder. This repository contains the client only — the server and cloud capabilities are not here and are not open source.
|
|
505
|
+
|
|
506
|
+
Release tags are SSH-signed by the copyright holder, and [`archive.yml`](.github/workflows/archive.yml)
|
|
507
|
+
refuses to publish an archive for a tag whose signature does not verify. The maintainer's public key
|
|
508
|
+
ships in this repository, so there is nothing to look up:
|
|
509
|
+
|
|
510
|
+
```bash
|
|
511
|
+
git -c gpg.ssh.allowedSignersFile=.github/signing-keys/allowed_signers tag -v v0.4.48
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
`v0.4.47`, `v0.4.48` and `oss-start` verify against it. `v0.4.49` was tagged before this became a
|
|
515
|
+
gate and carries no signature; every tag after it must pass. Individual commits are not signed —
|
|
516
|
+
the tag is what binds a version number to a signed identity, and that is the guarantee this
|
|
517
|
+
repository offers.
|
|
518
|
+
|
|
519
|
+
---
|
|
520
|
+
|
|
521
|
+
Copyright (C) 2026 [世纪之城(广州)信息科技有限公司](https://sji.xin)
|