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
2 changes: 1 addition & 1 deletion .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "chilon-recall",
"version": "0.1.3",
"version": "0.1.4",
"description": "Local-first knowledge retrieval for learning and serious knowledge work.",
"author": {
"name": "ctrlcakepro",
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.

## [Unreleased]

## [0.1.4] - 2026-09-18

- Add `chilon-recall key`: a hidden-input prompt for a provider API key that calls the provider's own `/models` endpoint, suggests an embedding and reranker model, and prints ready-to-run `$env:`/`setx`/`export` commands. The key is used for a single request and is never written to disk.
- Fix `doctor` reporting `configuration.ready`/`credentials_ready: true` while `embedding.base_url`/`model` were still the install template's placeholder values.
- Fix the CLI entrypoint always exiting `0`: `main()`'s return value (notably `doctor`'s pass/fail code) was never applied to `process.exitCode`, so scripted checks against the exit code always saw success.
- Warn when `chilon-recall qoder` is run from an `npx` temporary cache: the generated `.qoder/mcp.json` embeds that ephemeral path, which breaks silently on the next cache clear or version bump.

## [0.1.3] - 2026-09-18

- Add `rag_sync`: a staged, content-hash incremental synchronization of the knowledge index. Unchanged files reuse their existing vectors; added, modified, and deleted files are reconciled.
Expand Down
30 changes: 19 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

**Local-first knowledge retrieval for learning and serious knowledge work.**

[![version](https://img.shields.io/badge/version-0.1.3-blue.svg)](CHANGELOG.md)
[![version](https://img.shields.io/badge/version-0.1.4-blue.svg)](CHANGELOG.md)
[![license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![node](https://img.shields.io/badge/node-%3E%3D20-brightgreen.svg)](https://nodejs.org)
[![python](https://img.shields.io/badge/python-%3E%3D3.10-brightgreen.svg)](https://www.python.org)
Expand Down Expand Up @@ -45,19 +45,21 @@ It is an independent retrieval companion in the [Chilon Knowledge Work Harness](
Run the command below once. It creates a private configuration and a managed Python engine; it never stores API keys in the package or configuration file.

```powershell
npx -y chilon-recall@0.1.3 install C:\path\to\your\documents
npx -y chilon-recall@0.1.4 install C:\path\to\your\documents
```

### 2. Set your provider key

Open the generated `chilon-recall.json` to choose the provider endpoint and model, then set the key only in your environment. Run `doctor` to confirm the setup.
Open the generated `chilon-recall.json` and replace the placeholder `embedding.base_url` (`https://api.example.com/v1`) and `embedding.model` (`your-embedding-model`) with your real provider values, then set the key only in your environment. `doctor` treats those placeholders as not-ready and will not report `configuration.ready: true` until you edit them.

```powershell
$env:RAG_MANAGER_CONFIG = "C:\path\to\your\documents\chilon-recall.json"
$env:RAG_API_KEY = "your-provider-key"
npx -y chilon-recall@0.1.3 doctor
npx -y chilon-recall@0.1.4 doctor
```

Not sure which model to pick? `chilon-recall key --base-url https://api.example.com/v1` prompts for the key once (hidden input), calls the provider's own `/models` endpoint to suggest an embedding and reranker model, and prints ready-to-run `$env:`/`setx`/`export` commands with the key already filled in. The key is used for that one request only — it is never written to a file.

### 3. Connect one client

Start with [Codex](#codex), [Claude Desktop](#claude-desktop), or [Qoder](#qoder). The client starts the local server for you; you do not need to keep a separate terminal open.
Expand Down Expand Up @@ -96,7 +98,7 @@ Requires Node.js 20+ and Python 3.10+.
Use the published, pinned npm release to create a private configuration and install the isolated Python engine with one command:

```powershell
npx -y chilon-recall@0.1.3 install C:\path\to\your\documents
npx -y chilon-recall@0.1.4 install C:\path\to\your\documents
```

This writes `chilon-recall.json` in the document directory and creates a persistent managed Python engine in the operating system's user-data area. Both files are required for local operation; credentials remain outside both of them.
Expand All @@ -110,9 +112,11 @@ To validate the runtime and private configuration:
```powershell
$env:RAG_MANAGER_CONFIG = "C:\path\to\your\documents\chilon-recall.json"
$env:RAG_API_KEY = "your-provider-key"
npx -y chilon-recall@0.1.3 doctor
npx -y chilon-recall@0.1.4 doctor
```

`doctor` exits `0` only when Python, the managed engine, the configuration, and its credentials are all ready — otherwise `1`, so it is safe to gate a script on. It also refuses to call the placeholder `embedding.base_url`/`model` from the install template "ready".

> If you installed from npm, skip ahead to [Connect an MCP client](#connect-an-mcp-client). The remaining subsections are for source checkouts and custom configurations.

### 2. Manual private configuration
Expand Down Expand Up @@ -149,6 +153,8 @@ The server uses `stdio`, so it normally runs under an MCP client rather than in

Use absolute paths in client configuration. They are more reliable than assuming a launch directory.

> **Windows:** prefer `"command": "node"` with an absolute path to `cli.mjs`/`server.mjs` over `"command": "npx"`. Some MCP clients spawn `command` directly (bypassing the shell), and on Windows `npx` is a `.cmd` shim that a direct, non-shell spawn cannot resolve — the client reports the command as not found even though it works from a terminal. `node <absolute path>` avoids the shim entirely.

| Client | Configuration entry point |
| --- | --- |
| [Codex](#codex) | `~/.codex/config.toml`, `codex mcp add`, or ChatGPT desktop **Settings → MCP servers** |
Expand All @@ -172,12 +178,12 @@ tool_timeout_sec = 1800
default_tools_approval_mode = "writes"
```

**npm release** — run `npx -y chilon-recall@0.1.3 setup` first under the same OS account. A pinned version prevents an unexpected package upgrade from changing a working MCP server.
**npm release** — run `npx -y chilon-recall@0.1.4 setup` first under the same OS account. A pinned version prevents an unexpected package upgrade from changing a working MCP server.

```toml
[mcp_servers.chilon-recall]
command = "npx"
args = ["-y", "chilon-recall@0.1.3", "mcp"]
args = ["-y", "chilon-recall@0.1.4", "mcp"]
env_vars = ["RAG_MANAGER_CONFIG", "RAG_API_KEY", "RAG_RERANK_API_KEY"]
startup_timeout_sec = 15
tool_timeout_sec = 1800
Expand Down Expand Up @@ -236,7 +242,7 @@ For an npm release, replace `command` and `args` with the following and omit `CH

```json
"command": "npx",
"args": ["-y", "chilon-recall@0.1.3", "mcp"]
"args": ["-y", "chilon-recall@0.1.4", "mcp"]
```

Set `RAG_API_KEY` in the environment inherited by Claude Desktop, or add it only to your private local client configuration when your operating system cannot provide it. Claude Desktop stores `env` values in a local JSON file, so restrict file permissions and never commit that file. On Windows, use the virtual environment's `python.exe` path.
Expand All @@ -246,11 +252,13 @@ Set `RAG_API_KEY` in the environment inherited by Claude Desktop, or add it only
The Qoder client loads MCP servers from its own settings, and project-level skills and rules from the `.qoder/` directory. Generate all three from a checkout or an npm install:

```powershell
npx -y chilon-recall@0.1.3 qoder C:\path\to\your\project
npx -y chilon-recall@0.1.4 qoder C:\path\to\your\project
```

This writes `.qoder/mcp.json`, `.qoder/skills/<name>/SKILL.md` for every bundled skill, and `.qoder/rules/chilon-recall.md`. Add `--force` to regenerate over existing files.

> **Generating from `npx` embeds an unstable path.** `npx` unpacks the package into a temporary per-run cache (e.g. `...\npm-cache\_npx\<hash>\...` on Windows), and the `node`/`cli.mjs` path written into `.qoder/mcp.json` points there. Clearing the npm cache or bumping the pinned version moves that path and the MCP server stops starting, with no error beyond Qoder failing to load it. The command detects this and prints a warning; prefer running `chilon-recall qoder` from a stable install (`npm install -g chilon-recall@0.1.4`, or a source checkout) so the generated path survives cache clears.

Qoder does not read `.qoder/mcp.json` automatically; it is a shareable snippet. Open **Qoder client Settings → MCP → My Servers → + Add**, paste its contents, and replace the `RAG_MANAGER_CONFIG` placeholder with your private configuration path:

```json
Expand Down Expand Up @@ -338,7 +346,7 @@ The publication check rejects likely secrets, personal email addresses, and user

## Limits

- Version 0.1.3 indexes UTF-8 `.md`, `.txt`, `.rst`, and `.csv` text. Convert PDFs to reviewed text first; scanned PDFs need OCR.
- Version 0.1.4 indexes UTF-8 `.md`, `.txt`, `.rst`, and `.csv` text. Convert PDFs to reviewed text first; scanned PDFs need OCR.
- The included chunker recognizes Markdown `#` and `##` headings. It does not yet parse tables, citations, or document-native structure semantically.
- `rag_build` is a deliberate full rebuild. Use `rag_sync` for content-hash incremental synchronization; it always writes a new staged FAISS index so row IDs remain aligned with metadata.
- Local embedding and reranker models are not bundled in the first release.
Expand Down
30 changes: 19 additions & 11 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

**面向学习与严肃知识工作的本地优先知识检索引擎。**

[![version](https://img.shields.io/badge/version-0.1.3-blue.svg)](CHANGELOG.md)
[![version](https://img.shields.io/badge/version-0.1.4-blue.svg)](CHANGELOG.md)
[![license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![node](https://img.shields.io/badge/node-%3E%3D20-brightgreen.svg)](https://nodejs.org)
[![python](https://img.shields.io/badge/python-%3E%3D3.10-brightgreen.svg)](https://www.python.org)
Expand Down Expand Up @@ -45,19 +45,21 @@ Chilon Recall 可将你自己的文本资料转换为私有、来源可追溯的
运行一次下面的命令。它会创建私有配置与受管 Python engine;不会把 API key 写入 package 或配置文件。

```powershell
npx -y chilon-recall@0.1.3 install C:\path\to\your\documents
npx -y chilon-recall@0.1.4 install C:\path\to\your\documents
```

### 2. 设置 provider key

打开生成的 `chilon-recall.json`,选择 provider endpoint 与 model,再只在环境变量中设置密钥。运行 `doctor` 确认环境可用。
打开生成的 `chilon-recall.json`,把占位的 `embedding.base_url`(`https://api.example.com/v1`)和 `embedding.model`(`your-embedding-model`)改成你实际使用的 provider 值,再只在环境变量中设置密钥。`doctor` 会把这两个占位值视为"未就绪",在你修改之前不会报告 `configuration.ready: true`。

```powershell
$env:RAG_MANAGER_CONFIG = "C:\path\to\your\documents\chilon-recall.json"
$env:RAG_API_KEY = "your-provider-key"
npx -y chilon-recall@0.1.3 doctor
npx -y chilon-recall@0.1.4 doctor
```

不确定该填哪个 model?`chilon-recall key --base-url https://api.example.com/v1` 会提示你粘贴一次 key(终端隐藏输入),调用该 provider 自己的 `/models` 接口,推荐一个 embedding 和一个 reranker 模型,并打印出已经填好真实 key、可直接复制运行的 `$env:` / `setx` / `export` 命令。这个 key 只用于这一次请求,绝不会被写入任何文件。

### 3. 连接一个客户端

从 [Codex](#codex)、[Claude Desktop](#claude-desktop) 或 [Qoder](#qoder) 开始即可。客户端会替你启动本地 server,无需另开终端长期运行。
Expand Down Expand Up @@ -96,7 +98,7 @@ Chilon Recall 同时支持直接检索和可复用的学习工作流:
使用已发布且固定版本的 npm package,只需一条命令即可创建私有配置并安装独立 Python engine:

```powershell
npx -y chilon-recall@0.1.3 install C:\path\to\your\documents
npx -y chilon-recall@0.1.4 install C:\path\to\your\documents
```

该命令会在资料目录写入 `chilon-recall.json`,并在操作系统用户数据目录创建持久的受管 Python engine。这两个文件是本地运行所必需的;凭据不会写入其中任何一个。
Expand All @@ -110,9 +112,11 @@ npx -y chilon-recall@0.1.3 install C:\path\to\your\documents
```powershell
$env:RAG_MANAGER_CONFIG = "C:\path\to\your\documents\chilon-recall.json"
$env:RAG_API_KEY = "your-provider-key"
npx -y chilon-recall@0.1.3 doctor
npx -y chilon-recall@0.1.4 doctor
```

只有当 Python、托管 engine、配置文件及其凭据都就绪时,`doctor` 才会以退出码 `0` 结束;否则退出码为 `1`,可以放心用于脚本化验收。安装模板里的占位 `embedding.base_url`/`model` 也不会被视为"就绪"。

> 如果你通过 npm 安装,现在可以直接前往 [连接 MCP 客户端](#连接-mcp-客户端)。以下小节面向源码 checkout 和需要自定义配置的用户。

### 2. 手动私有配置
Expand Down Expand Up @@ -151,6 +155,8 @@ npm start

客户端配置应使用绝对路径,避免依赖不确定的启动目录。

> **Windows 提示:** 建议用 `"command": "node"` 加 `cli.mjs`/`server.mjs` 的绝对路径,而不是 `"command": "npx"`。部分 MCP 客户端会直接 spawn `command`(绕过 shell),而 Windows 上的 `npx` 是一个 `.cmd` shim,直接、非 shell 的 spawn 无法解析它——客户端会报"找不到该命令",即使它在终端里能正常运行。用 `node <绝对路径>` 可以完全绕开这个 shim。

| 客户端 | 配置入口 |
| --- | --- |
| [Codex](#codex) | `~/.codex/config.toml`、`codex mcp add`,或 ChatGPT 桌面端 **Settings → MCP servers** |
Expand All @@ -174,12 +180,12 @@ tool_timeout_sec = 1800
default_tools_approval_mode = "writes"
```

**npm 已发布版本** —— 先在同一操作系统账户下运行 `npx -y chilon-recall@0.1.3 setup`。固定版本可避免 package 意外升级改变已正常工作的 MCP server。
**npm 已发布版本** —— 先在同一操作系统账户下运行 `npx -y chilon-recall@0.1.4 setup`。固定版本可避免 package 意外升级改变已正常工作的 MCP server。

```toml
[mcp_servers.chilon-recall]
command = "npx"
args = ["-y", "chilon-recall@0.1.3", "mcp"]
args = ["-y", "chilon-recall@0.1.4", "mcp"]
env_vars = ["RAG_MANAGER_CONFIG", "RAG_API_KEY", "RAG_RERANK_API_KEY"]
startup_timeout_sec = 15
tool_timeout_sec = 1800
Expand Down Expand Up @@ -238,7 +244,7 @@ bundle 会在 `CHILON_RECALL_ROOT` 中运行 `node scripts/cli.mjs mcp`。如果

```json
"command": "npx",
"args": ["-y", "chilon-recall@0.1.3", "mcp"]
"args": ["-y", "chilon-recall@0.1.4", "mcp"]
```

应在 Claude Desktop 能继承的系统环境中设置 `RAG_API_KEY`;若操作系统无法提供,只能把它加入你本机的私有客户端配置。Claude Desktop 会把 `env` 值保存在本地 JSON 中,因此请限制文件权限,且绝不能提交该配置。Windows 用户应指向虚拟环境中的 `python.exe`。
Expand All @@ -248,11 +254,13 @@ bundle 会在 `CHILON_RECALL_ROOT` 中运行 `node scripts/cli.mjs mcp`。如果
Qoder 客户端从自身设置中加载 MCP server,并从项目内的 `.qoder/` 目录加载项目级 skills 与 rules。可用一条命令生成这三部分:

```powershell
npx -y chilon-recall@0.1.3 qoder C:\path\to\your\project
npx -y chilon-recall@0.1.4 qoder C:\path\to\your\project
```

该命令会写入 `.qoder/mcp.json`、每个内置 skill 对应的 `.qoder/skills/<name>/SKILL.md`,以及 `.qoder/rules/chilon-recall.md`。若要覆盖已有文件,请加 `--force`。

> **用 `npx` 生成会写入一个不稳定的路径。** `npx` 会把包解压到一个临时的、按次运行的缓存目录(Windows 上类似 `...\npm-cache\_npx\<hash>\...`),写入 `.qoder/mcp.json` 的 `node`/`cli.mjs` 路径就指向那里。清理 npm 缓存或升级固定版本号都会移动这个路径,导致 MCP server 悄悄起不来,且没有明显报错——只会看到 Qoder 加载失败。该命令会检测到这种情况并打印警告;建议先做一次稳定安装(`npm install -g chilon-recall@0.1.4`,或使用源码 checkout),再从那个安装位置运行 `chilon-recall qoder`,这样生成的路径才不会因清缓存而失效。

Qoder 不会自动读取 `.qoder/mcp.json`,它只是一份可共享的配置片段。请打开 **Qoder 客户端 Settings → MCP → My Servers → + Add**,粘贴其内容,并把 `RAG_MANAGER_CONFIG` 占位符替换为你的私有配置路径:

```json
Expand Down Expand Up @@ -340,7 +348,7 @@ npm audit --audit-level=high

## 已知限制

- v0.1.3 只索引 UTF-8 `.md`、`.txt`、`.rst`、`.csv`。PDF 应先转换为经过核对的文本,扫描版需 OCR。
- v0.1.4 只索引 UTF-8 `.md`、`.txt`、`.rst`、`.csv`。PDF 应先转换为经过核对的文本,扫描版需 OCR。
- 分块器识别 Markdown `#` 与 `##` 标题,尚未语义解析表格、引文或原生文档结构。
- `rag_build` 保留为全量重建入口;`rag_sync` 使用内容哈希做增量同步,并在 staging 中重建 FAISS,以保持行 ID 与元数据严格对齐。
- 首版不内置本地 embedding/reranker 模型。
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "chilon-recall",
"version": "0.1.3",
"version": "0.1.4",
"description": "A local-first MCP knowledge engine for grounded learning, document recall, and serious knowledge work.",
"type": "module",
"bin": {
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "chilon-recall-engine"
version = "0.1.3"
version = "0.1.4"
description = "FAISS indexing and retrieval engine for Chilon Recall"
readme = "README.md"
requires-python = ">=3.10"
Expand Down
2 changes: 1 addition & 1 deletion python/chilon_recall/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Chilon Recall indexing and retrieval engine."""

__version__ = "0.1.3"
__version__ = "0.1.4"
12 changes: 11 additions & 1 deletion python/chilon_recall/providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,21 @@ def _headers(api_key: str) -> dict[str, str]:
return {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}


def _join_endpoint(base_url: str, suffix: str) -> str:
trimmed = base_url.rstrip("/")
# base_url is documented as the provider's OpenAI-compatible root (e.g. ".../v1"),
# but a config that already points at the full endpoint (e.g. ".../v1/embeddings",
# copied from provider docs) must not get the suffix appended a second time.
if trimmed.lower().endswith(suffix.lower()):
return trimmed
return trimmed + suffix


def embed_texts(config: dict[str, Any], texts: list[str], *, document: bool) -> np.ndarray:
settings = config["embedding"]
prefix = settings.get("doc_prefix" if document else "query_prefix", "")
inputs = [prefix + text for text in texts]
endpoint = settings["base_url"].rstrip("/") + "/embeddings"
endpoint = _join_endpoint(settings["base_url"], "/embeddings")
with httpx.Client(timeout=60.0, trust_env=False) as client:
response = client.post(
endpoint,
Expand Down
Loading
Loading