brein 0.0.1 → 0.1.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 CHANGED
@@ -1,6 +1,34 @@
1
- # brein
1
+ # brein (npm)
2
2
 
3
- > Stub release reserving the name. Real package coming soon.
3
+ Thin Node wrapper for [brein](https://github.com/brein-sh/brein) — the MCP server for a company memory that lives in git.
4
4
 
5
- A policy-aware MCP server for an org-wide knowledge brain.
6
- See [brein.dev](https://brein.dev) for updates.
5
+ ## Quickstart
6
+
7
+ ```bash
8
+ npx brein init
9
+ ```
10
+
11
+ Verifies Python 3.11+ and [`uv`](https://docs.astral.sh/uv/), installs the brein Python package via `uv tool install`, then runs the setup wizard.
12
+
13
+ After install, the wrapper forwards subcommands to the real CLI:
14
+
15
+ ```bash
16
+ npx brein doctor
17
+ npx brein mcp claude
18
+ npx brein setup mcp
19
+ ```
20
+
21
+ Or use the installed binary directly (`brein`, `brain-mcp`, `brain-eval`).
22
+
23
+ ## Requirements
24
+
25
+ - Node 18+
26
+ - Python 3.11+
27
+ - [`uv`](https://docs.astral.sh/uv/) (single static binary, no Python prereq for install)
28
+ - `git`
29
+
30
+ The wrapper prints actionable install hints if anything is missing.
31
+
32
+ ## License
33
+
34
+ MIT.
package/bin/brein.js ADDED
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env node
2
+ // Thin Node shim. Verifies python3 + uv, installs the brein Python package
3
+ // from git, then execs the real `brein` CLI. No deps.
4
+
5
+ const { spawnSync, spawn } = require("node:child_process");
6
+ const { platform } = require("node:os");
7
+ const path = require("node:path");
8
+
9
+ const REPO_URL = "git+https://github.com/brein-sh/brein.git";
10
+ const MIN_PY = [3, 11];
11
+
12
+ const C = {
13
+ dim: (s) => `\x1b[2m${s}\x1b[0m`,
14
+ red: (s) => `\x1b[31m${s}\x1b[0m`,
15
+ yellow: (s) => `\x1b[33m${s}\x1b[0m`,
16
+ green: (s) => `\x1b[32m${s}\x1b[0m`,
17
+ bold: (s) => `\x1b[1m${s}\x1b[0m`,
18
+ };
19
+
20
+ function which(cmd) {
21
+ const r = spawnSync(platform() === "win32" ? "where" : "which", [cmd], {
22
+ encoding: "utf8",
23
+ });
24
+ return r.status === 0 ? r.stdout.trim().split(/\r?\n/)[0] : null;
25
+ }
26
+
27
+ function pythonVersion(bin) {
28
+ const r = spawnSync(bin, ["-c", "import sys; print(sys.version_info[0], sys.version_info[1])"], { encoding: "utf8" });
29
+ if (r.status !== 0) return null;
30
+ const [maj, min] = r.stdout.trim().split(/\s+/).map(Number);
31
+ return [maj, min];
32
+ }
33
+
34
+ function findPython() {
35
+ for (const cmd of ["python3.13", "python3.12", "python3.11", "python3", "python"]) {
36
+ if (!which(cmd)) continue;
37
+ const v = pythonVersion(cmd);
38
+ if (!v) continue;
39
+ if (v[0] > MIN_PY[0] || (v[0] === MIN_PY[0] && v[1] >= MIN_PY[1])) {
40
+ return { bin: cmd, version: v };
41
+ }
42
+ }
43
+ return null;
44
+ }
45
+
46
+ function pythonInstallHint() {
47
+ const p = platform();
48
+ if (p === "darwin") return "brew install python@3.12 # or visit https://www.python.org/downloads/";
49
+ if (p === "linux") return "sudo apt install python3.12 # or your distro's equivalent";
50
+ if (p === "win32") return "winget install Python.Python.3.12 # or https://www.python.org/downloads/";
51
+ return "Install Python 3.11+ from https://www.python.org/downloads/";
52
+ }
53
+
54
+ function uvInstallHint() {
55
+ if (platform() === "win32") return "powershell -c \"irm https://astral.sh/uv/install.ps1 | iex\"";
56
+ return "curl -LsSf https://astral.sh/uv/install.sh | sh";
57
+ }
58
+
59
+ function run(cmd, args, opts = {}) {
60
+ const r = spawnSync(cmd, args, { stdio: "inherit", ...opts });
61
+ return r.status === 0;
62
+ }
63
+
64
+ function execReplace(cmd, args) {
65
+ // No exec() in Node; spawn with inherited stdio and forward the exit code.
66
+ const child = spawn(cmd, args, { stdio: "inherit" });
67
+ child.on("exit", (code) => process.exit(code ?? 0));
68
+ }
69
+
70
+ function preflight() {
71
+ const py = findPython();
72
+ if (!py) {
73
+ console.error(C.red("✗") + " Python " + MIN_PY.join(".") + "+ not found.");
74
+ console.error(" → " + pythonInstallHint());
75
+ process.exit(2);
76
+ }
77
+ console.log(C.green("✓") + ` python ${py.version.join(".")} (${py.bin})`);
78
+
79
+ const uv = which("uv");
80
+ if (!uv) {
81
+ console.error(C.red("✗") + " uv not found.");
82
+ console.error(" → " + uvInstallHint());
83
+ console.error(" (uv is a single static binary, no Python prereq.)");
84
+ process.exit(2);
85
+ }
86
+ console.log(C.green("✓") + ` uv (${uv})`);
87
+ }
88
+
89
+ function installBrein(branch) {
90
+ const url = branch ? `${REPO_URL}@${branch}` : REPO_URL;
91
+ console.log(C.bold("\nInstalling brein from") + " " + C.dim(url));
92
+ const ok = run("uv", ["tool", "install", "--force", url]);
93
+ if (!ok) {
94
+ console.error(C.red("\nuv tool install failed."));
95
+ process.exit(1);
96
+ }
97
+ }
98
+
99
+ function uvToolBin() {
100
+ // Resolve the installed brein binary directly via uv. PATH lookup is
101
+ // unreliable inside `npx` (which prepends its own .bin and finds this
102
+ // wrapper instead of the Python CLI → recursion).
103
+ const r = spawnSync("uv", ["tool", "dir", "--bin"], { encoding: "utf8" });
104
+ if (r.status !== 0) return null;
105
+ const dir = r.stdout.trim();
106
+ const exe = platform() === "win32" ? "brein.exe" : "brein";
107
+ return path.join(dir, exe);
108
+ }
109
+
110
+ function resolveInstalledBrein() {
111
+ const direct = uvToolBin();
112
+ if (direct) {
113
+ const fs = require("node:fs");
114
+ if (fs.existsSync(direct)) return direct;
115
+ }
116
+ // Fallback: trust PATH (only safe outside npx, but worth a try).
117
+ const onPath = which("brein");
118
+ if (onPath && onPath !== process.argv[1]) return onPath;
119
+ return null;
120
+ }
121
+
122
+ function usage() {
123
+ console.log(`brein — npm wrapper for the brein MCP server
124
+
125
+ Usage:
126
+ npx brein init [--branch <name>] Install Python package + run setup wizard
127
+ npx brein <subcommand> [args...] Forward to the installed brein CLI
128
+ (setup | doctor | mcp | config)
129
+
130
+ Examples:
131
+ npx brein init
132
+ npx brein doctor
133
+ npx brein mcp claude
134
+ `);
135
+ }
136
+
137
+ function main() {
138
+ const [, , cmd, ...rest] = process.argv;
139
+
140
+ if (!cmd || cmd === "--help" || cmd === "-h") {
141
+ usage();
142
+ process.exit(cmd ? 0 : 1);
143
+ }
144
+
145
+ if (cmd === "init") {
146
+ const branchIdx = rest.indexOf("--branch");
147
+ const branch = branchIdx >= 0 ? rest[branchIdx + 1] : null;
148
+ preflight();
149
+ installBrein(branch);
150
+ const installed = resolveInstalledBrein();
151
+ if (!installed) {
152
+ console.error(C.red("✗") + " brein installed but binary not found.");
153
+ console.error(" → run: " + C.bold("uv tool update-shell"));
154
+ process.exit(1);
155
+ }
156
+ console.log(C.bold("\nRunning ") + C.bold("brein setup") + C.bold("...\n"));
157
+ execReplace(installed, ["setup"]);
158
+ return;
159
+ }
160
+
161
+ // Forward anything else to the installed CLI.
162
+ const installed = resolveInstalledBrein();
163
+ if (!installed) {
164
+ console.error(C.red("✗") + " brein is not installed. Run: npx brein init");
165
+ process.exit(1);
166
+ }
167
+ execReplace(installed, [cmd, ...rest]);
168
+ }
169
+
170
+ main();
package/package.json CHANGED
@@ -1,14 +1,29 @@
1
1
  {
2
2
  "name": "brein",
3
- "version": "0.0.1",
4
- "description": "Brein a policy-aware MCP server for an org-wide knowledge brain. Stub release reserving the name; real package coming soon.",
3
+ "version": "0.1.1",
4
+ "description": "npx wrapper for brein installs the Python MCP server and runs the setup wizard.",
5
5
  "license": "MIT",
6
- "homepage": "https://brein.dev",
6
+ "homepage": "https://brein.sh",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "https://github.com/brainincorp/brain-mcp.git"
9
+ "url": "git+https://github.com/brein-sh/brein.git",
10
+ "directory": "npm"
10
11
  },
11
- "keywords": ["mcp", "llm", "knowledge-base", "rag"],
12
- "main": "index.js",
13
- "files": ["index.js", "README.md"]
12
+ "bin": {
13
+ "brein": "bin/brein.js"
14
+ },
15
+ "files": [
16
+ "bin/",
17
+ "README.md"
18
+ ],
19
+ "engines": {
20
+ "node": ">=18"
21
+ },
22
+ "keywords": [
23
+ "mcp",
24
+ "llm",
25
+ "knowledge-base",
26
+ "rag",
27
+ "brain"
28
+ ]
14
29
  }
package/index.js DELETED
@@ -1,3 +0,0 @@
1
- // brein — stub release. Real package coming soon. See https://brein.dev
2
- console.error("brein: stub release — real package coming soon. https://brein.dev");
3
- process.exit(0);