project-brain 0.2.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/README.md +158 -0
- package/bin/project-brain +15 -0
- package/package.json +58 -0
- package/scripts/postinstall.js +77 -0
package/README.md
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# project-brain
|
|
2
|
+
|
|
3
|
+
Local-first MCP server that gives AI tools semantic memory of your codebase.
|
|
4
|
+
|
|
5
|
+
project-brain indexes your project files into a local LanceDB vector store using Ollama embeddings. Once indexed, AI assistants connected via MCP can search your codebase semantically, track module documentation, and maintain knowledge that persists across sessions.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# 1. Install globally
|
|
11
|
+
bun install -g project-brain
|
|
12
|
+
|
|
13
|
+
# 2. One-time: register in your AI tools (Claude, Codex, Cursor, Gemini)
|
|
14
|
+
project-brain setup
|
|
15
|
+
|
|
16
|
+
# 3. Per-project: initialize, index, and install git hook
|
|
17
|
+
cd my-project
|
|
18
|
+
project-brain init
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
After `init`, the following run **automatically** without any extra steps:
|
|
22
|
+
|
|
23
|
+
| Trigger | What happens |
|
|
24
|
+
|---|---|
|
|
25
|
+
| `git commit` | git hook runs `project-brain sync` — keeps the index fresh |
|
|
26
|
+
| File save (while server is running) | File watcher detects the change and re-indexes it |
|
|
27
|
+
| AI tool connects | MCP server starts on stdio, tools are ready |
|
|
28
|
+
|
|
29
|
+
## Prerequisites
|
|
30
|
+
|
|
31
|
+
- **Bun** ≥ 1.3.14 — required runtime ([install](https://bun.sh))
|
|
32
|
+
- **Ollama** (optional, for semantic search) — download from [ollama.com](https://ollama.com). Pull `nomic-embed-text` for embeddings: `ollama pull nomic-embed-text`
|
|
33
|
+
|
|
34
|
+
## Install
|
|
35
|
+
|
|
36
|
+
### Registry (recommended)
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
bun install -g project-brain
|
|
40
|
+
# or
|
|
41
|
+
npm install -g project-brain
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Standalone binary (no runtime required)
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
git clone https://github.com/jcsoftdev/project-brain
|
|
48
|
+
cd project-brain
|
|
49
|
+
bun build ./src/cli.ts --compile --outfile project-brain
|
|
50
|
+
./project-brain --help
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Usage modes
|
|
54
|
+
|
|
55
|
+
project-brain runs in two modes — CLI and inside AI tools. Both call the same underlying commands.
|
|
56
|
+
|
|
57
|
+
### CLI (terminal)
|
|
58
|
+
|
|
59
|
+
Run commands directly from your terminal in any project directory.
|
|
60
|
+
|
|
61
|
+
### Inside AI tools (slash commands)
|
|
62
|
+
|
|
63
|
+
Once `project-brain setup` has registered the MCP server in your AI tool, you can invoke commands as slash commands from within Claude Code, Codex, Cursor, or any MCP-compatible AI:
|
|
64
|
+
|
|
65
|
+
| Slash command | Equivalent CLI | What it does |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| `/brain-setup` | `project-brain setup` | One-time global registration in AI tools |
|
|
68
|
+
| `/brain-init` | `project-brain init` | Initialize current project + index + git hook |
|
|
69
|
+
| `/brain-sync` | `project-brain sync` | Incremental sync of changed files |
|
|
70
|
+
| `/brain-reindex` | `project-brain reindex` | Drop and rebuild full index |
|
|
71
|
+
| `/brain-health` | `project-brain health` | Diagnose Ollama, index staleness, git hook |
|
|
72
|
+
|
|
73
|
+
The slash commands are Claude Code skills installed globally at `~/.claude/skills/brain-*/SKILL.md`. They work in any session regardless of the current project.
|
|
74
|
+
|
|
75
|
+
## Commands
|
|
76
|
+
|
|
77
|
+
### `setup`
|
|
78
|
+
|
|
79
|
+
One-time global setup. Detects your environment and registers project-brain with AI tools (Claude, Cursor, Gemini, Codex).
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
project-brain setup
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### `init`
|
|
86
|
+
|
|
87
|
+
Initialize a project. Detects the stack, writes a `CLAUDE.md` with MCP instructions, installs a git hook, scaffolds module stubs in `docs/modules/`, and indexes the project.
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
project-brain init [--skip-index]
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
- `--skip-index` — skip the initial index pass (useful when Ollama is not yet running)
|
|
94
|
+
|
|
95
|
+
### `sync`
|
|
96
|
+
|
|
97
|
+
Incremental sync — re-indexes files that changed since the last sync.
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
project-brain sync
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### `reindex`
|
|
104
|
+
|
|
105
|
+
Full re-index — drops and rebuilds the entire vector index for the current project.
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
project-brain reindex
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### `health`
|
|
112
|
+
|
|
113
|
+
Check system health: Ollama availability, LanceDB status, and staleness of the index.
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
project-brain health
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### `serve`
|
|
120
|
+
|
|
121
|
+
Start the MCP server. Default mode uses stdio (for local AI tool connections).
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
project-brain serve
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
#### `serve --http`
|
|
128
|
+
|
|
129
|
+
Start the MCP server over Streamable HTTP with bearer-token authentication. Useful for remote access or multi-client setups.
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
BRAIN_HTTP_TOKEN=your-secret project-brain serve --http [--port 3000]
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Environment Variables
|
|
136
|
+
|
|
137
|
+
| Variable | Default | Description |
|
|
138
|
+
|---|---|---|
|
|
139
|
+
| `BRAIN_HTTP_PORT` | `3000` | Port for HTTP server mode |
|
|
140
|
+
| `BRAIN_HTTP_TOKEN` | — | **Required** for `serve --http`. Bearer secret. |
|
|
141
|
+
| `BRAIN_DATA_DIR` | `~/.project-brain/data` | LanceDB data directory |
|
|
142
|
+
| `BRAIN_EMBED_MODEL` | `nomic-embed-text` | Ollama embedding model name |
|
|
143
|
+
|
|
144
|
+
## Module Documentation Workflow
|
|
145
|
+
|
|
146
|
+
When you run `project-brain init`, it detects top-level source directories and creates stub files in `docs/modules/<name>.md`. These stubs are indexed immediately so semantic search works even before they are filled.
|
|
147
|
+
|
|
148
|
+
To populate a stub:
|
|
149
|
+
1. Open a project session with your AI assistant.
|
|
150
|
+
2. The AI reads `CLAUDE.md` and finds the `## Module Documentation` section.
|
|
151
|
+
3. The AI fills each stub (Purpose, Key Files, Dependencies, Data Flow, Gotchas, Last Updated).
|
|
152
|
+
4. The AI calls `add_knowledge` with the filled content so it is vectorized into project-brain.
|
|
153
|
+
|
|
154
|
+
Run `project-brain sync` after filling stubs to ensure they are re-indexed with their full content.
|
|
155
|
+
|
|
156
|
+
## Author
|
|
157
|
+
|
|
158
|
+
[jcsoftdev](https://github.com/jcsoftdev)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execFileSync } from "child_process";
|
|
3
|
+
import { join, dirname } from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
import { existsSync } from "fs";
|
|
6
|
+
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const nativeBin = join(__dirname, "project-brain-native");
|
|
9
|
+
|
|
10
|
+
if (!existsSync(nativeBin)) {
|
|
11
|
+
console.error("project-brain: binary not found. Run `npm install` to download it.");
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
execFileSync(nativeBin, process.argv.slice(2), { stdio: "inherit" });
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "project-brain",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Local-first MCP server that gives AI tools semantic memory of your codebase.",
|
|
6
|
+
"author": "jcsoftdev",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/jcsoftdev/project-brain.git"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"mcp",
|
|
14
|
+
"model-context-protocol",
|
|
15
|
+
"rag",
|
|
16
|
+
"codebase",
|
|
17
|
+
"embeddings",
|
|
18
|
+
"lancedb",
|
|
19
|
+
"ollama"
|
|
20
|
+
],
|
|
21
|
+
"files": [
|
|
22
|
+
"bin",
|
|
23
|
+
"scripts",
|
|
24
|
+
"templates",
|
|
25
|
+
"README.md",
|
|
26
|
+
"LICENSE"
|
|
27
|
+
],
|
|
28
|
+
"bin": {
|
|
29
|
+
"project-brain": "bin/project-brain"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"dev": "bun run src/cli.ts",
|
|
33
|
+
"test": "bun test",
|
|
34
|
+
"setup": "bun run src/cli.ts setup",
|
|
35
|
+
"init": "bun run src/cli.ts init",
|
|
36
|
+
"build": "bun build ./src/cli.ts --compile --outfile dist/project-brain",
|
|
37
|
+
"postinstall": "node scripts/postinstall.js"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
41
|
+
"@lancedb/lancedb": "^0.30.0",
|
|
42
|
+
"ollama": "^0.6.3",
|
|
43
|
+
"zod": "^4.4.3"
|
|
44
|
+
},
|
|
45
|
+
"optionalDependencies": {
|
|
46
|
+
"@lancedb/lancedb-darwin-arm64": "0.30.0",
|
|
47
|
+
"@lancedb/lancedb-linux-x64-gnu": "0.30.0",
|
|
48
|
+
"@lancedb/lancedb-linux-arm64-gnu": "0.30.0",
|
|
49
|
+
"@lancedb/lancedb-linux-x64-musl": "0.30.0",
|
|
50
|
+
"@lancedb/lancedb-linux-arm64-musl": "0.30.0",
|
|
51
|
+
"@lancedb/lancedb-win32-x64-msvc": "0.30.0",
|
|
52
|
+
"@lancedb/lancedb-win32-arm64-msvc": "0.30.0"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@types/bun": "latest",
|
|
56
|
+
"typescript": "^5.5.4"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createWriteStream, mkdirSync, chmodSync, existsSync } from "fs";
|
|
3
|
+
import { join, dirname } from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
import { get } from "https";
|
|
6
|
+
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const pkg = JSON.parse(
|
|
9
|
+
await import("fs").then((fs) =>
|
|
10
|
+
fs.promises.readFile(join(__dirname, "../package.json"), "utf-8")
|
|
11
|
+
)
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
const VERSION = pkg.version;
|
|
15
|
+
const REPO = "jcsoftdev/project-brain";
|
|
16
|
+
|
|
17
|
+
const platform = process.platform; // darwin, linux, win32
|
|
18
|
+
const arch = process.arch; // arm64, x64
|
|
19
|
+
|
|
20
|
+
const targetMap = {
|
|
21
|
+
"darwin-arm64": "darwin-arm64",
|
|
22
|
+
"linux-x64": "linux-x64",
|
|
23
|
+
"linux-arm64": "linux-arm64",
|
|
24
|
+
"win32-x64": "windows-x64",
|
|
25
|
+
"win32-arm64": "windows-arm64",
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const key = `${platform}-${arch}`;
|
|
29
|
+
const target = targetMap[key];
|
|
30
|
+
|
|
31
|
+
if (!target) {
|
|
32
|
+
console.error(`project-brain: unsupported platform ${key}. Skipping binary download.`);
|
|
33
|
+
process.exit(0);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const ext = platform === "win32" ? ".exe" : "";
|
|
37
|
+
const binaryName = `project-brain-${target}${ext}`;
|
|
38
|
+
const url = `https://github.com/${REPO}/releases/download/v${VERSION}/${binaryName}`;
|
|
39
|
+
const destDir = join(__dirname, "../bin");
|
|
40
|
+
const destPath = join(destDir, `project-brain-native${ext}`);
|
|
41
|
+
|
|
42
|
+
if (existsSync(destPath)) {
|
|
43
|
+
process.exit(0);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
mkdirSync(destDir, { recursive: true });
|
|
47
|
+
|
|
48
|
+
console.log(`project-brain: downloading binary for ${key}...`);
|
|
49
|
+
|
|
50
|
+
function download(url, dest) {
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
const file = createWriteStream(dest);
|
|
53
|
+
const request = (u) =>
|
|
54
|
+
get(u, (res) => {
|
|
55
|
+
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
56
|
+
return request(res.headers.location);
|
|
57
|
+
}
|
|
58
|
+
if (res.statusCode !== 200) {
|
|
59
|
+
reject(new Error(`HTTP ${res.statusCode} for ${u}`));
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
res.pipe(file);
|
|
63
|
+
file.on("finish", () => file.close(resolve));
|
|
64
|
+
}).on("error", reject);
|
|
65
|
+
request(url);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
await download(url, destPath);
|
|
71
|
+
chmodSync(destPath, 0o755);
|
|
72
|
+
console.log(`project-brain: binary installed.`);
|
|
73
|
+
} catch (err) {
|
|
74
|
+
console.error(`project-brain: failed to download binary — ${err.message}`);
|
|
75
|
+
console.error(`project-brain: manual download: ${url}`);
|
|
76
|
+
process.exit(0);
|
|
77
|
+
}
|