recallmem 0.1.0
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 +201 -0
- package/NOTICE +28 -0
- package/README.md +735 -0
- package/bin/commands/doctor.js +129 -0
- package/bin/commands/setup.js +296 -0
- package/bin/commands/start.js +59 -0
- package/bin/commands/upgrade.js +77 -0
- package/bin/lib/detect.js +215 -0
- package/bin/lib/install-hints.js +94 -0
- package/bin/lib/install-mode.js +141 -0
- package/bin/lib/output.js +78 -0
- package/bin/lib/prompt.js +43 -0
- package/bin/recallmem.js +196 -0
- package/package.json +40 -0
package/bin/recallmem.js
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* RecallMEM CLI
|
|
4
|
+
*
|
|
5
|
+
* The npx entry point. Pure Node.js, no React/Next imports.
|
|
6
|
+
*
|
|
7
|
+
* Auto-detects install mode and supports two workflows:
|
|
8
|
+
*
|
|
9
|
+
* Use case 1 - "just run it" (most users):
|
|
10
|
+
* $ npx recallmem
|
|
11
|
+
* CLI clones the repo to ~/.recallmem on first run, then starts the app.
|
|
12
|
+
* Subsequent runs use ~/.recallmem and start instantly.
|
|
13
|
+
*
|
|
14
|
+
* Use case 3 - "fork and hack on it" (developers):
|
|
15
|
+
* $ git clone https://github.com/RealChrisSean/RecallMEM.git
|
|
16
|
+
* $ cd RecallMEM && npm install
|
|
17
|
+
* $ npx recallmem
|
|
18
|
+
* CLI detects it's already inside a recallmem checkout and uses cwd.
|
|
19
|
+
* Hot reload works, edits are reflected immediately.
|
|
20
|
+
*
|
|
21
|
+
* Commands:
|
|
22
|
+
* recallmem - run setup if needed, then start the server
|
|
23
|
+
* recallmem init - setup only (deps check, migrations, models, env)
|
|
24
|
+
* recallmem start - start the server (assumes init was done)
|
|
25
|
+
* recallmem doctor - diagnose what's missing or broken
|
|
26
|
+
* recallmem upgrade - git pull, run pending migrations, restart
|
|
27
|
+
* recallmem version - print version
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
const { setupCommand } = require("./commands/setup");
|
|
31
|
+
const { startCommand } = require("./commands/start");
|
|
32
|
+
const { doctorCommand } = require("./commands/doctor");
|
|
33
|
+
const { upgradeCommand } = require("./commands/upgrade");
|
|
34
|
+
const {
|
|
35
|
+
detectInstallMode,
|
|
36
|
+
cloneAndInstall,
|
|
37
|
+
gitInstalled,
|
|
38
|
+
RECALLMEM_HOME,
|
|
39
|
+
} = require("./lib/install-mode");
|
|
40
|
+
const {
|
|
41
|
+
printHeader,
|
|
42
|
+
color,
|
|
43
|
+
step,
|
|
44
|
+
success,
|
|
45
|
+
fail,
|
|
46
|
+
info,
|
|
47
|
+
section,
|
|
48
|
+
blank,
|
|
49
|
+
} = require("./lib/output");
|
|
50
|
+
|
|
51
|
+
const COMMANDS = {
|
|
52
|
+
init: { fn: initCommand, desc: "Run setup only (deps check, DB, models, env)" },
|
|
53
|
+
start: { fn: startWrapper, desc: "Start the server (assumes setup was done)" },
|
|
54
|
+
doctor: { fn: doctorCommand, desc: "Diagnose what's missing or broken" },
|
|
55
|
+
upgrade: { fn: upgradeCommand, desc: "Git pull and run pending migrations" },
|
|
56
|
+
version: { fn: versionCommand, desc: "Print version" },
|
|
57
|
+
help: { fn: helpCommand, desc: "Show this help" },
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Resolve the install path AND tell the caller whether we're in dev mode.
|
|
62
|
+
* Dev mode = the user is running from inside a recallmem git checkout.
|
|
63
|
+
* In dev mode we skip the production build so they get hot reload via next dev.
|
|
64
|
+
*/
|
|
65
|
+
async function resolveInstall() {
|
|
66
|
+
const mode = detectInstallMode();
|
|
67
|
+
|
|
68
|
+
if (mode.mode === "dev") {
|
|
69
|
+
info(`Using local checkout: ${mode.path}`);
|
|
70
|
+
return { path: mode.path, devMode: true };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (mode.mode === "user") {
|
|
74
|
+
info(`Using install at: ${mode.path}`);
|
|
75
|
+
return { path: mode.path, devMode: false };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// First run - clone the repo
|
|
79
|
+
section("First-time setup");
|
|
80
|
+
info(`Cloning RecallMEM to ${mode.path}`);
|
|
81
|
+
|
|
82
|
+
if (!gitInstalled()) {
|
|
83
|
+
fail("git is not installed");
|
|
84
|
+
blank();
|
|
85
|
+
console.log("Install git first:");
|
|
86
|
+
console.log(" Mac: brew install git");
|
|
87
|
+
console.log(" Linux: sudo apt install git");
|
|
88
|
+
console.log(" Win: https://git-scm.com/download/win");
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const result = cloneAndInstall(mode.path);
|
|
93
|
+
if (!result.ok) {
|
|
94
|
+
fail(`Install failed: ${result.error}`);
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
success(`Installed RecallMEM to ${mode.path}`);
|
|
99
|
+
return { path: mode.path, devMode: false };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async function initCommand() {
|
|
103
|
+
printHeader();
|
|
104
|
+
const install = await resolveInstall();
|
|
105
|
+
if (!install) process.exit(1);
|
|
106
|
+
const result = await setupCommand({
|
|
107
|
+
installPath: install.path,
|
|
108
|
+
devMode: install.devMode,
|
|
109
|
+
});
|
|
110
|
+
if (!result.ok) process.exit(1);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async function startWrapper() {
|
|
114
|
+
const install = await resolveInstall();
|
|
115
|
+
if (!install) process.exit(1);
|
|
116
|
+
await startCommand({ installPath: install.path });
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async function defaultCommand() {
|
|
120
|
+
printHeader();
|
|
121
|
+
const install = await resolveInstall();
|
|
122
|
+
if (!install) process.exit(1);
|
|
123
|
+
const setupResult = await setupCommand({
|
|
124
|
+
installPath: install.path,
|
|
125
|
+
devMode: install.devMode,
|
|
126
|
+
skipIfDone: true,
|
|
127
|
+
});
|
|
128
|
+
if (!setupResult.ok) process.exit(1);
|
|
129
|
+
await startCommand({ installPath: install.path });
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async function main() {
|
|
133
|
+
const args = process.argv.slice(2);
|
|
134
|
+
const cmd = args[0];
|
|
135
|
+
|
|
136
|
+
// Default behavior: setup if needed, then start
|
|
137
|
+
if (!cmd) {
|
|
138
|
+
return defaultCommand();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (cmd === "--help" || cmd === "-h") {
|
|
142
|
+
return helpCommand();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (cmd === "--version" || cmd === "-v") {
|
|
146
|
+
return versionCommand();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const command = COMMANDS[cmd];
|
|
150
|
+
if (!command) {
|
|
151
|
+
console.error(color.red(`Unknown command: ${cmd}`));
|
|
152
|
+
console.error("");
|
|
153
|
+
helpCommand();
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
try {
|
|
158
|
+
await command.fn();
|
|
159
|
+
} catch (err) {
|
|
160
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
161
|
+
console.error(color.red(`✗ ${message}`));
|
|
162
|
+
process.exit(1);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function helpCommand() {
|
|
167
|
+
printHeader();
|
|
168
|
+
console.log("Usage:");
|
|
169
|
+
console.log(` ${color.bold("recallmem")} Setup if needed, then start the app`);
|
|
170
|
+
console.log("");
|
|
171
|
+
console.log("Commands:");
|
|
172
|
+
for (const [name, { desc }] of Object.entries(COMMANDS)) {
|
|
173
|
+
console.log(` ${color.bold(name.padEnd(10))} ${desc}`);
|
|
174
|
+
}
|
|
175
|
+
console.log("");
|
|
176
|
+
console.log("Options:");
|
|
177
|
+
console.log(` ${color.bold("--help, -h")} Show this help`);
|
|
178
|
+
console.log(` ${color.bold("--version, -v")} Show version`);
|
|
179
|
+
console.log("");
|
|
180
|
+
console.log("Install location:");
|
|
181
|
+
console.log(` ${color.dim("Default: ~/.recallmem")}`);
|
|
182
|
+
console.log(` ${color.dim("Override: RECALLMEM_HOME=/custom/path npx recallmem")}`);
|
|
183
|
+
console.log("");
|
|
184
|
+
console.log("Docs: https://github.com/RealChrisSean/RecallMEM");
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function versionCommand() {
|
|
188
|
+
const pkg = require("../package.json");
|
|
189
|
+
console.log(`recallmem ${pkg.version}`);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
main().catch((err) => {
|
|
193
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
194
|
+
console.error(color.red(`✗ ${message}`));
|
|
195
|
+
process.exit(1);
|
|
196
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "recallmem",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Private, local-first AI chatbot with persistent working memory. One command install via npx.",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"author": "Chris Sean",
|
|
7
|
+
"homepage": "https://github.com/RealChrisSean/RecallMEM",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/RealChrisSean/RecallMEM.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/RealChrisSean/RecallMEM/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"ai",
|
|
17
|
+
"chatbot",
|
|
18
|
+
"local",
|
|
19
|
+
"private",
|
|
20
|
+
"ollama",
|
|
21
|
+
"gemma",
|
|
22
|
+
"claude",
|
|
23
|
+
"memory",
|
|
24
|
+
"rag",
|
|
25
|
+
"vector-search",
|
|
26
|
+
"self-hosted"
|
|
27
|
+
],
|
|
28
|
+
"bin": {
|
|
29
|
+
"recallmem": "./bin/recallmem.js"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"bin",
|
|
33
|
+
"README.md",
|
|
34
|
+
"LICENSE",
|
|
35
|
+
"NOTICE"
|
|
36
|
+
],
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=20"
|
|
39
|
+
}
|
|
40
|
+
}
|