chat-recall 0.5.32 → 0.6.1
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/README.md +45 -2
- package/dist/cli.js +74 -14
- package/dist/cli.js.map +1 -1
- package/dist/mcp-relay.d.ts +3 -0
- package/dist/mcp-relay.d.ts.map +1 -0
- package/dist/mcp-relay.js +229 -0
- package/dist/mcp-relay.js.map +1 -0
- package/dist/mcp-socket.d.ts +98 -0
- package/dist/mcp-socket.d.ts.map +1 -0
- package/dist/mcp-socket.js +249 -0
- package/dist/mcp-socket.js.map +1 -0
- package/dist/mcp.js +861 -609
- package/dist/mcp.js.map +1 -1
- package/dist/update-notice.d.ts +23 -2
- package/dist/update-notice.d.ts.map +1 -1
- package/dist/update-notice.js +50 -5
- package/dist/update-notice.js.map +1 -1
- package/dist/watch.js +5 -5
- package/package.json +6 -6
- package/skills/chat-recall/SKILL.md +9 -7
- package/skills/chat-recall-project/SKILL.md +19 -1
- package/skills/chat-recall-security/SKILL.md +91 -0
- package/skills/chat-recall-tasks/SKILL.md +100 -0
package/README.md
CHANGED
|
@@ -12,9 +12,17 @@
|
|
|
12
12
|
|
|
13
13
|
**[chatrecall.dev](https://chatrecall.dev)** · [How it works](https://chatrecall.dev/how-it-works/) · [MCP tools](https://chatrecall.dev/mcp/) · [Pricing](https://chatrecall.dev/pricing/) · [Self-host](https://chatrecall.dev/self-hosting/) · [Security](https://chatrecall.dev/security/)
|
|
14
14
|
|
|
15
|
-
>
|
|
15
|
+
> Memory, secret scanning and code findings across every AI coding tool you use. They all share a single searchable history — and the agent works it itself.
|
|
16
16
|
|
|
17
|
-
Your coding agents each keep their own transcripts, in their own format, in their own directory, and none of them can read another's. `chat-recall` indexes all of them into one place, redacts secrets on the way, and exposes the result to your agent through **61 MCP tools
|
|
17
|
+
Your coding agents each keep their own transcripts, in their own format, in their own directory, and none of them can read another's. `chat-recall` indexes all of them into one place, redacts secrets on the way, and exposes the result to your agent through **61 MCP tools**.
|
|
18
|
+
|
|
19
|
+
Memory is the foundation, not the whole product. One index, read three ways:
|
|
20
|
+
|
|
21
|
+
| | What it does | Tools |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| **Recall** | Resume a session, search what you actually typed, read the diffs and commits it produced, recall a decision and why it was made | 37 |
|
|
24
|
+
| **Security** | Flag credentials pasted into past conversations, per session, and track each one until it is rotated or dismissed | 4 |
|
|
25
|
+
| **Code findings** | Rank what is worth fixing in a project and turn it into actionable tasks, with code intelligence over the repo itself | 12 |
|
|
18
26
|
|
|
19
27
|
That cross-tool part is the point. A single tool's built-in history stops at its own boundary; this does not.
|
|
20
28
|
|
|
@@ -61,6 +69,24 @@ It only touches a config whose tool is on this machine, it never overwrites an e
|
|
|
61
69
|
/plugin install chat-recall@chat-recall
|
|
62
70
|
```
|
|
63
71
|
|
|
72
|
+
Any other MCP client (Claude Desktop, Windsurf, Zed, Cline, or a tool `init` does
|
|
73
|
+
not know) takes the same server as a JSON entry. The bin is `chat-recall-mcp`,
|
|
74
|
+
which is why the package name alone is not enough — `npx -y chat-recall` starts
|
|
75
|
+
the CLI, not the server:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"mcpServers": {
|
|
80
|
+
"chat-recall": {
|
|
81
|
+
"command": "npx",
|
|
82
|
+
"args": ["-y", "-p", "chat-recall", "chat-recall-mcp"]
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The same command as one line, for a `claude mcp add`-style client: `npx -y -p chat-recall chat-recall-mcp`.
|
|
89
|
+
|
|
64
90
|
Then:
|
|
65
91
|
|
|
66
92
|
```bash
|
|
@@ -163,6 +189,23 @@ any of it. Secrets are masked client-side before anything leaves the machine.
|
|
|
163
189
|
}
|
|
164
190
|
```
|
|
165
191
|
|
|
192
|
+
`chat-recall-mcp` is a relay, not the server. It finds the background daemon for
|
|
193
|
+
your tool profile, starts one if there is none, and passes bytes to it. Every
|
|
194
|
+
session on a machine therefore shares one loaded engine instead of carrying its
|
|
195
|
+
own: a session costs about 50 MB rather than 87 MB, against a single shared
|
|
196
|
+
daemon, and background sync runs in one process instead of racing a lock in all
|
|
197
|
+
of them. The daemon exits 15 minutes after the last session closes.
|
|
198
|
+
|
|
199
|
+
Two knobs, both optional:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
CHAT_RECALL_NO_DAEMON=1 # load the whole server in each session instead
|
|
203
|
+
CHAT_RECALL_DAEMON_IDLE_SECS=0 # keep the daemon resident (default 900)
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
If the daemon cannot be reached for any reason, the session loads the server
|
|
207
|
+
itself and works exactly as it did before — slower, never broken.
|
|
208
|
+
|
|
166
209
|
Then install the hooks (one command sets up auto-save, pre-compact backup, and the resume-hint that warns when you're about to redo work):
|
|
167
210
|
|
|
168
211
|
```bash
|
package/dist/cli.js
CHANGED
|
@@ -19742,7 +19742,7 @@ var init_http = __esm({
|
|
|
19742
19742
|
CLI_VERSION = JSON.parse(readFileSync33(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
|
|
19743
19743
|
} catch {
|
|
19744
19744
|
try {
|
|
19745
|
-
if (true) CLI_VERSION = "0.
|
|
19745
|
+
if (true) CLI_VERSION = "0.6.1";
|
|
19746
19746
|
} catch {
|
|
19747
19747
|
}
|
|
19748
19748
|
}
|
|
@@ -20262,7 +20262,7 @@ var init_telemetry = __esm({
|
|
|
20262
20262
|
init_sync_client();
|
|
20263
20263
|
cliVersion2 = () => {
|
|
20264
20264
|
try {
|
|
20265
|
-
return true ? "0.
|
|
20265
|
+
return true ? "0.6.1" : "dev";
|
|
20266
20266
|
} catch {
|
|
20267
20267
|
return "dev";
|
|
20268
20268
|
}
|
|
@@ -22352,7 +22352,7 @@ var init_sync_client = __esm({
|
|
|
22352
22352
|
ownVersion = JSON.parse(readFileSync37(join44(dir, "../package.json"), "utf-8")).version || ownVersion;
|
|
22353
22353
|
} catch {
|
|
22354
22354
|
try {
|
|
22355
|
-
if (true) ownVersion = "0.
|
|
22355
|
+
if (true) ownVersion = "0.6.1";
|
|
22356
22356
|
} catch {
|
|
22357
22357
|
}
|
|
22358
22358
|
}
|
|
@@ -22387,12 +22387,17 @@ var init_sync_client = __esm({
|
|
|
22387
22387
|
// src/update-notice.ts
|
|
22388
22388
|
var update_notice_exports = {};
|
|
22389
22389
|
__export(update_notice_exports, {
|
|
22390
|
+
newestKnown: () => newestKnown,
|
|
22390
22391
|
printUpdateNotice: () => printUpdateNotice,
|
|
22391
22392
|
refreshUpdateCheck: () => refreshUpdateCheck,
|
|
22392
22393
|
updateNotice: () => updateNotice
|
|
22393
22394
|
});
|
|
22394
22395
|
import { readFileSync as readFileSync38, writeFileSync as writeFileSync10 } from "node:fs";
|
|
22395
22396
|
import { join as join45 } from "node:path";
|
|
22397
|
+
function newestKnown(c) {
|
|
22398
|
+
const npm = c.npmVersion ?? "0.0.0";
|
|
22399
|
+
return compareVersions(npm, c.serverVersion) > 0 ? { version: npm, source: "npm" } : { version: c.serverVersion, source: "server" };
|
|
22400
|
+
}
|
|
22396
22401
|
function readCheck() {
|
|
22397
22402
|
try {
|
|
22398
22403
|
const c = JSON.parse(readFileSync38(checkPath(), "utf-8"));
|
|
@@ -22411,8 +22416,24 @@ function updateNotice() {
|
|
|
22411
22416
|
const c = readCheck();
|
|
22412
22417
|
if (!c) return null;
|
|
22413
22418
|
const own = cliVersion();
|
|
22414
|
-
|
|
22415
|
-
|
|
22419
|
+
const { version: version2, source } = newestKnown(c);
|
|
22420
|
+
if (compareVersions(version2, own) <= 0) return null;
|
|
22421
|
+
const how = source === "npm" ? "The server you sync to has not rolled it yet \u2014 install it with: npm install -g chat-recall@latest" : "Auto-update should apply it; force it now with: chat-recall update";
|
|
22422
|
+
return `chat-recall ${version2} is available (you have ${own}). ${how}`;
|
|
22423
|
+
}
|
|
22424
|
+
async function fetchNpmLatest() {
|
|
22425
|
+
if (process.env.CHAT_RECALL_NO_NPM_CHECK === "1") return null;
|
|
22426
|
+
try {
|
|
22427
|
+
const res = await fetchWithTimeout(NPM_LATEST_URL, {
|
|
22428
|
+
headers: { accept: "application/vnd.npm.install-v1+json" }
|
|
22429
|
+
}, 5e3);
|
|
22430
|
+
if (!res.ok) return null;
|
|
22431
|
+
const body = await res.json();
|
|
22432
|
+
const v = body["dist-tags"]?.latest;
|
|
22433
|
+
return typeof v === "string" && v ? v : null;
|
|
22434
|
+
} catch {
|
|
22435
|
+
return null;
|
|
22436
|
+
}
|
|
22416
22437
|
}
|
|
22417
22438
|
async function refreshUpdateCheck(force = false) {
|
|
22418
22439
|
const prev = readCheck();
|
|
@@ -22437,8 +22458,14 @@ async function refreshUpdateCheck(force = false) {
|
|
|
22437
22458
|
} catch {
|
|
22438
22459
|
return prev;
|
|
22439
22460
|
}
|
|
22440
|
-
|
|
22441
|
-
|
|
22461
|
+
const npmVersion = await fetchNpmLatest();
|
|
22462
|
+
if (newest === "0.0.0" && !npmVersion) return prev;
|
|
22463
|
+
const next = {
|
|
22464
|
+
// A server that answered nothing must not erase what we last knew from one.
|
|
22465
|
+
serverVersion: newest !== "0.0.0" ? newest : prev?.serverVersion ?? "0.0.0",
|
|
22466
|
+
checkedAt: Date.now()
|
|
22467
|
+
};
|
|
22468
|
+
if (npmVersion) next.npmVersion = npmVersion;
|
|
22442
22469
|
writeCheck(next);
|
|
22443
22470
|
return next;
|
|
22444
22471
|
}
|
|
@@ -22458,7 +22485,7 @@ function printUpdateNotice() {
|
|
|
22458
22485
|
} catch {
|
|
22459
22486
|
}
|
|
22460
22487
|
}
|
|
22461
|
-
var CHECK_TTL_MS, checkPath, printed;
|
|
22488
|
+
var CHECK_TTL_MS, NPM_LATEST_URL, checkPath, printed;
|
|
22462
22489
|
var init_update_notice = __esm({
|
|
22463
22490
|
"src/update-notice.ts"() {
|
|
22464
22491
|
"use strict";
|
|
@@ -22466,6 +22493,7 @@ var init_update_notice = __esm({
|
|
|
22466
22493
|
init_auto_update();
|
|
22467
22494
|
init_http();
|
|
22468
22495
|
CHECK_TTL_MS = 6 * 3600 * 1e3;
|
|
22496
|
+
NPM_LATEST_URL = "https://registry.npmjs.org/chat-recall";
|
|
22469
22497
|
checkPath = () => join45(getDataDir(), "update-check.json");
|
|
22470
22498
|
printed = false;
|
|
22471
22499
|
}
|
|
@@ -26116,7 +26144,7 @@ var init_intent_drain = __esm({
|
|
|
26116
26144
|
ownVersion2 = JSON.parse(readFileSync46(join55(dir, "../package.json"), "utf-8")).version || ownVersion2;
|
|
26117
26145
|
} catch {
|
|
26118
26146
|
try {
|
|
26119
|
-
if (true) ownVersion2 = "0.
|
|
26147
|
+
if (true) ownVersion2 = "0.6.1";
|
|
26120
26148
|
} catch {
|
|
26121
26149
|
}
|
|
26122
26150
|
}
|
|
@@ -28149,7 +28177,7 @@ program.command("init").description("Set up chat-recall: connect to your server,
|
|
|
28149
28177
|
const projectRoot = join60(import.meta.dirname, "..");
|
|
28150
28178
|
let mcpBinOnPath = false;
|
|
28151
28179
|
mcpBinOnPath = isOnPath("chat-recall-mcp");
|
|
28152
|
-
const launch = mcpBinOnPath ? { command: "chat-recall-mcp" } : { command: "node", args: [join60(projectRoot, "dist", "mcp.js")] };
|
|
28180
|
+
const launch = mcpBinOnPath ? { command: "chat-recall-mcp" } : { command: "node", args: [join60(projectRoot, "dist", "mcp-relay.js")] };
|
|
28153
28181
|
const MCP_ENV = { NODE_OPTIONS: "--max-old-space-size=1024" };
|
|
28154
28182
|
const { registerMcpEverywhere: registerMcpEverywhere2 } = await Promise.resolve().then(() => (init_mcp_clients(), mcp_clients_exports));
|
|
28155
28183
|
const MCP_CLIENT_FOR_BIN = {
|
|
@@ -30773,9 +30801,9 @@ program.command("reconcile").description("Reconcile DERIVED FIELDS (e.g. native
|
|
|
30773
30801
|
process.exit(1);
|
|
30774
30802
|
}
|
|
30775
30803
|
});
|
|
30776
|
-
program.command("update").description("Update this CLI now from the server you sync to (same-origin, checksum-pinned) and report exactly why if it cannot").action(async () => {
|
|
30777
|
-
const { runAutoUpdate: runAutoUpdate2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
|
|
30778
|
-
const { refreshUpdateCheck: refreshUpdateCheck2 } = await Promise.resolve().then(() => (init_update_notice(), update_notice_exports));
|
|
30804
|
+
program.command("update").description("Update this CLI now from the server you sync to (same-origin, checksum-pinned) and report exactly why if it cannot. Use --from-npm when the server has not rolled the newest release yet.").option("--from-npm", "Install the newest published release straight from the npm registry instead of the server tarball").action(async (opts) => {
|
|
30805
|
+
const { runAutoUpdate: runAutoUpdate2, compareVersions: compareVersions2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
|
|
30806
|
+
const { refreshUpdateCheck: refreshUpdateCheck2, newestKnown: newestKnown2 } = await Promise.resolve().then(() => (init_update_notice(), update_notice_exports));
|
|
30779
30807
|
const { cliVersion: cliVersion3 } = await Promise.resolve().then(() => (init_http(), http_exports));
|
|
30780
30808
|
const targets = loadAllCredentials();
|
|
30781
30809
|
if (!targets.length) {
|
|
@@ -30795,11 +30823,43 @@ program.command("update").description("Update this CLI now from the server you s
|
|
|
30795
30823
|
if (/install failed|download failed|checksum/.test(r.reason)) installFailed = true;
|
|
30796
30824
|
console.log((benign ? chalk2.dim("\u2022 ") : chalk2.red("\u2717 ")) + r.reason + chalk2.dim(` (${base3})`));
|
|
30797
30825
|
}
|
|
30798
|
-
await refreshUpdateCheck2(true);
|
|
30826
|
+
const check = await refreshUpdateCheck2(true);
|
|
30799
30827
|
if (installFailed) {
|
|
30800
30828
|
console.log(chalk2.dim("\nThe update was available but did not install \u2014 usually npm cannot write the global prefix. Retry with:"));
|
|
30801
30829
|
console.log(chalk2.dim(` npm install -g chat-recall (or re-run the installer: curl -fsSL ${targets[0].serverUrl.replace(/\/+$/, "")}/install | sh)`));
|
|
30802
30830
|
}
|
|
30831
|
+
if (check) {
|
|
30832
|
+
const own = cliVersion3();
|
|
30833
|
+
const { version: version2, source } = newestKnown2(check);
|
|
30834
|
+
const behind = source === "npm" && compareVersions2(version2, own) > 0;
|
|
30835
|
+
if (behind && !opts.fromNpm) {
|
|
30836
|
+
console.log(chalk2.yellow(`
|
|
30837
|
+
npm has ${version2}; the server you sync to still serves ${check.serverVersion}.`));
|
|
30838
|
+
console.log(chalk2.dim("The server tarball cannot deliver it until that deployment rolls. Get it now with:"));
|
|
30839
|
+
console.log(chalk2.dim(" chat-recall update --from-npm"));
|
|
30840
|
+
} else if (behind && opts.fromNpm) {
|
|
30841
|
+
console.log(chalk2.dim(`
|
|
30842
|
+
Installing ${version2} from npm\u2026`));
|
|
30843
|
+
try {
|
|
30844
|
+
const { execFileSync: execFileSync4 } = await import("node:child_process");
|
|
30845
|
+
execFileSync4("npm", ["install", "-g", `chat-recall@${version2}`], { stdio: "inherit" });
|
|
30846
|
+
const { installedVersion: installedVersion2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
|
|
30847
|
+
const landed = installedVersion2();
|
|
30848
|
+
if (landed && compareVersions2(landed, version2) >= 0) {
|
|
30849
|
+
console.log(chalk2.green(`\u2713 updated to ${landed} from npm`));
|
|
30850
|
+
} else {
|
|
30851
|
+
console.error(chalk2.red(`\u2717 npm reported success but ${landed ?? "an unknown version"} is still on disk \u2014 the package that runs is not the one npm wrote.`));
|
|
30852
|
+
process.exit(1);
|
|
30853
|
+
}
|
|
30854
|
+
} catch (e) {
|
|
30855
|
+
console.error(chalk2.red(`\u2717 npm install failed: ${e instanceof Error ? e.message : e}`));
|
|
30856
|
+
process.exit(1);
|
|
30857
|
+
}
|
|
30858
|
+
} else if (opts.fromNpm) {
|
|
30859
|
+
console.log(chalk2.dim(`
|
|
30860
|
+
npm has nothing newer than ${own} \u2014 nothing to do.`));
|
|
30861
|
+
}
|
|
30862
|
+
}
|
|
30803
30863
|
});
|
|
30804
30864
|
program.hook("preAction", () => {
|
|
30805
30865
|
printUpdateNotice();
|