@titan-design/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/dist/cli.js +2114 -0
- package/package.json +60 -0
- package/scripts/.gitkeep +0 -0
- package/scripts/install.sh +63 -0
- package/scripts/postinstall.js +22 -0
- package/scripts/preuninstall.js +14 -0
- package/skill/SKILL.md +56 -0
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@titan-design/brain",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Developer second brain with hybrid RAG search",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/titan-design/brain.git"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"skill",
|
|
14
|
+
"scripts"
|
|
15
|
+
],
|
|
16
|
+
"bin": {
|
|
17
|
+
"brain": "dist/cli.js"
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"dev": "tsx src/cli.ts",
|
|
21
|
+
"build": "tsup",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"test:watch": "vitest",
|
|
24
|
+
"typecheck": "tsc --noEmit",
|
|
25
|
+
"lint": "eslint src __tests__ --no-error-on-unmatched-pattern",
|
|
26
|
+
"postinstall": "node scripts/postinstall.js",
|
|
27
|
+
"preuninstall": "node scripts/preuninstall.js"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"commander": "^13.1.0",
|
|
31
|
+
"@commander-js/extra-typings": "^13.1.0",
|
|
32
|
+
"better-sqlite3": "^11.8.1",
|
|
33
|
+
"sqlite-vec": "^0.1.6",
|
|
34
|
+
"ollama": "^0.5.14",
|
|
35
|
+
"gray-matter": "^4.0.3",
|
|
36
|
+
"glob": "^11.0.1",
|
|
37
|
+
"env-paths": "^3.0.0"
|
|
38
|
+
},
|
|
39
|
+
"optionalDependencies": {
|
|
40
|
+
"@huggingface/transformers": "^3.3.3"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"typescript": "^5.7.3",
|
|
44
|
+
"vitest": "^3.0.5",
|
|
45
|
+
"tsup": "^8.3.6",
|
|
46
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
47
|
+
"@types/node": "^22.13.4",
|
|
48
|
+
"tsx": "^4.19.2",
|
|
49
|
+
"eslint": "^9.20.0",
|
|
50
|
+
"@eslint/js": "^9.20.0",
|
|
51
|
+
"typescript-eslint": "^8.24.1"
|
|
52
|
+
},
|
|
53
|
+
"publishConfig": {
|
|
54
|
+
"access": "public",
|
|
55
|
+
"provenance": true
|
|
56
|
+
},
|
|
57
|
+
"engines": {
|
|
58
|
+
"node": ">=22"
|
|
59
|
+
}
|
|
60
|
+
}
|
package/scripts/.gitkeep
ADDED
|
File without changes
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
REPO_URL="https://github.com/hjewkes/brain.git"
|
|
5
|
+
INSTALL_DIR="${BRAIN_INSTALL_DIR:-$HOME/.local/share/brain-cli}"
|
|
6
|
+
BIN_DIR="${HOME}/.local/bin"
|
|
7
|
+
SKILL_NAME="second-brain"
|
|
8
|
+
|
|
9
|
+
info() { echo "[brain] $*"; }
|
|
10
|
+
error() { echo "[brain] ERROR: $*" >&2; exit 1; }
|
|
11
|
+
|
|
12
|
+
# Clone or update the repo
|
|
13
|
+
if [ -d "$INSTALL_DIR/.git" ]; then
|
|
14
|
+
info "Updating existing installation at $INSTALL_DIR"
|
|
15
|
+
git -C "$INSTALL_DIR" pull --ff-only
|
|
16
|
+
else
|
|
17
|
+
info "Cloning brain to $INSTALL_DIR"
|
|
18
|
+
mkdir -p "$(dirname "$INSTALL_DIR")"
|
|
19
|
+
git clone "$REPO_URL" "$INSTALL_DIR"
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
# Build
|
|
23
|
+
info "Installing dependencies and building..."
|
|
24
|
+
cd "$INSTALL_DIR"
|
|
25
|
+
npm ci
|
|
26
|
+
npm run build
|
|
27
|
+
|
|
28
|
+
# Symlink binary
|
|
29
|
+
mkdir -p "$BIN_DIR"
|
|
30
|
+
ln -sf "$INSTALL_DIR/dist/cli.js" "$BIN_DIR/brain"
|
|
31
|
+
chmod +x "$BIN_DIR/brain"
|
|
32
|
+
info "Linked brain to $BIN_DIR/brain"
|
|
33
|
+
|
|
34
|
+
# Ensure bin dir is on PATH
|
|
35
|
+
if ! echo "$PATH" | tr ':' '\n' | grep -q "^$BIN_DIR$"; then
|
|
36
|
+
info "WARNING: $BIN_DIR is not on your PATH"
|
|
37
|
+
info "Add this to your shell profile: export PATH=\"$BIN_DIR:\$PATH\""
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# Initialize brain if not already done
|
|
41
|
+
if ! brain status --json >/dev/null 2>&1; then
|
|
42
|
+
info "Running brain init..."
|
|
43
|
+
brain init
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
# Install skill
|
|
47
|
+
SKILL_SOURCE="$INSTALL_DIR/skills/$SKILL_NAME"
|
|
48
|
+
if command -v chezmoi >/dev/null 2>&1; then
|
|
49
|
+
CHEZMOI_SOURCE="$(chezmoi source-path)"
|
|
50
|
+
SKILL_DEST="$CHEZMOI_SOURCE/dot_claude/skills/$SKILL_NAME"
|
|
51
|
+
mkdir -p "$SKILL_DEST"
|
|
52
|
+
cp "$SKILL_SOURCE/SKILL.md" "$SKILL_DEST/SKILL.md"
|
|
53
|
+
chezmoi apply
|
|
54
|
+
info "Installed skill via chezmoi"
|
|
55
|
+
else
|
|
56
|
+
SKILL_DEST="$HOME/.claude/skills/$SKILL_NAME"
|
|
57
|
+
mkdir -p "$SKILL_DEST"
|
|
58
|
+
ln -sf "$SKILL_SOURCE/SKILL.md" "$SKILL_DEST/SKILL.md"
|
|
59
|
+
info "Linked skill to $SKILL_DEST"
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
info "Installation complete!"
|
|
63
|
+
info "Run 'brain --help' to get started."
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { mkdirSync, copyFileSync, existsSync } from 'node:fs'
|
|
2
|
+
import { join, dirname } from 'node:path'
|
|
3
|
+
import { homedir } from 'node:os'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
7
|
+
const skillSource = join(__dirname, '..', 'skill', 'SKILL.md')
|
|
8
|
+
const claudeDir = join(homedir(), '.claude')
|
|
9
|
+
const claudeSkillsDir = join(claudeDir, 'skills', 'brain')
|
|
10
|
+
|
|
11
|
+
// Skip silently if ~/.claude doesn't exist (user doesn't use Claude Code)
|
|
12
|
+
if (!existsSync(claudeDir)) {
|
|
13
|
+
process.exit(0)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
mkdirSync(claudeSkillsDir, { recursive: true })
|
|
18
|
+
copyFileSync(skillSource, join(claudeSkillsDir, 'SKILL.md'))
|
|
19
|
+
console.log(`brain: installed Claude Code skill to ${claudeSkillsDir}`)
|
|
20
|
+
} catch {
|
|
21
|
+
// Don't fail npm install if skill copy fails
|
|
22
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { rmSync, existsSync } from 'node:fs'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
import { homedir } from 'node:os'
|
|
4
|
+
|
|
5
|
+
const claudeSkillsDir = join(homedir(), '.claude', 'skills', 'brain')
|
|
6
|
+
|
|
7
|
+
if (existsSync(claudeSkillsDir)) {
|
|
8
|
+
try {
|
|
9
|
+
rmSync(claudeSkillsDir, { recursive: true })
|
|
10
|
+
console.log(`brain: removed Claude Code skill from ${claudeSkillsDir}`)
|
|
11
|
+
} catch {
|
|
12
|
+
// Don't fail npm uninstall if cleanup fails
|
|
13
|
+
}
|
|
14
|
+
}
|
package/skill/SKILL.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: brain
|
|
3
|
+
description: Search and manage your second brain knowledge base. Use when the user asks about their notes, wants to find information, or needs to add/organize knowledge.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Brain -- Knowledge Management
|
|
7
|
+
|
|
8
|
+
A CLI for managing a developer second brain with hybrid BM25 + vector search over markdown notes.
|
|
9
|
+
|
|
10
|
+
## When to Use
|
|
11
|
+
|
|
12
|
+
- User asks "what do I know about X" or "find my notes on Y"
|
|
13
|
+
- User wants to save something to their knowledge base
|
|
14
|
+
- User asks about stale or outdated notes
|
|
15
|
+
- User wants to check their knowledge base status
|
|
16
|
+
|
|
17
|
+
## Commands
|
|
18
|
+
|
|
19
|
+
Use `--json` flag on all commands when processing output programmatically.
|
|
20
|
+
|
|
21
|
+
| Command | Purpose | Example |
|
|
22
|
+
|---------|---------|---------|
|
|
23
|
+
| `brain search "<query>" --json` | Hybrid search (BM25 + vector) | `brain search "authentication patterns" --json --limit 5` |
|
|
24
|
+
| `brain search "<query>" --json --expand` | Search with graph-connected notes | `brain search "auth" --json --expand` |
|
|
25
|
+
| `brain add <file>` | Add a note from file | `brain add ~/draft.md --type research --tier slow` |
|
|
26
|
+
| `brain add --title "X" --type note` | Add from stdin | `echo "content" \| brain add --title "My Note" --type note` |
|
|
27
|
+
| `brain status --json` | Database stats | Shows note count, embeddings, staleness |
|
|
28
|
+
| `brain stale --json` | Notes needing review | `brain stale --tier slow --json` |
|
|
29
|
+
| `brain index` | Re-index all notes | Only run when user asks -- this is slow |
|
|
30
|
+
| `brain template <type>` | Output frontmatter template | `brain template research` |
|
|
31
|
+
| `brain graph <note-id> --json` | Show note relations | `brain graph my-note --json` |
|
|
32
|
+
| `brain config get` | Show config | `brain config get` |
|
|
33
|
+
|
|
34
|
+
## Search Filters
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
brain search "query" --tier slow --tags "typescript,patterns" --confidence high --since 2025-01-01 --json
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Note Conventions
|
|
41
|
+
|
|
42
|
+
**Types:** `note`, `decision`, `pattern`, `research`, `meeting`, `session-log`, `guide`
|
|
43
|
+
|
|
44
|
+
**Tiers:**
|
|
45
|
+
- `slow` -- permanent knowledge (notes, decisions, patterns, research). Has review intervals.
|
|
46
|
+
- `fast` -- ephemeral (meetings, session logs). Has expiry dates. Auto-archived.
|
|
47
|
+
|
|
48
|
+
**Key frontmatter fields:** `title`, `type`, `tier`, `tags`, `summary`, `confidence` (high/medium/low/speculative), `status` (current/outdated/deprecated/draft), `review-interval`, `related`
|
|
49
|
+
|
|
50
|
+
## Rules
|
|
51
|
+
|
|
52
|
+
- Always use `--json` when you need to parse output
|
|
53
|
+
- Search before claiming information isn't in the knowledge base
|
|
54
|
+
- Do NOT run `brain index` unless the user explicitly asks -- it processes all files and is slow
|
|
55
|
+
- When adding notes, include frontmatter with at minimum: title, type, tier
|
|
56
|
+
- Present search results with score, file path, and excerpt
|