mirror of
https://github.com/krcnow/manex-brain.git
synced 2026-07-22 06:56:49 +00:00
first commit
This commit is contained in:
commit
598a5be4a8
7 changed files with 1733 additions and 0 deletions
21
LICENSE
Normal file
21
LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2025 Manex
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
70
README.md
Normal file
70
README.md
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
# Manex Brain
|
||||
|
||||
A local AI brain for your Obsidian vault. Indexes all your notes and answers questions privately using a local Apple Silicon MLX model — no cloud, no API keys, no data leaves your machine.
|
||||
|
||||
## Requirements
|
||||
|
||||
- **macOS with Apple Silicon** (M1 or later)
|
||||
- **Python 3** (via Homebrew: `brew install python`)
|
||||
- **Obsidian 1.5.0** or later
|
||||
|
||||
## How It Works
|
||||
|
||||
On first load, the plugin:
|
||||
|
||||
1. Creates a Python virtual environment at `~/.obsidian-study-room/venv`
|
||||
2. Installs [mlx-lm](https://github.com/ml-explore/mlx-lm) into the venv (~2 min on first run)
|
||||
3. Downloads and starts `mlx-community/Qwen3-4B-4bit` (~2.3 GB, downloaded once)
|
||||
4. Indexes all your vault notes in the background for vault-wide semantic search
|
||||
|
||||
After that, the server starts automatically every time Obsidian opens.
|
||||
|
||||
## Features
|
||||
|
||||
- **Fully local** — inference runs on-device via Apple's MLX framework; nothing is sent to the cloud
|
||||
- **Vault-wide RAG** — all notes are indexed; relevant chunks are automatically included in every answer
|
||||
- **Active note context** — the currently open note is semantically embedded and prioritised
|
||||
- **Graph-aware** — linked notes, backlinks, and shared-tag notes are included as context
|
||||
- **Clickable sources** — note links in answers open the corresponding note in Obsidian
|
||||
- **Chat memory** — conversation history is maintained within a session
|
||||
- **Automatic re-indexing** — notes are re-indexed on create, edit, rename, or delete
|
||||
|
||||
## Usage
|
||||
|
||||
1. Open Obsidian — the MLX server starts automatically in the background
|
||||
2. Click the brain icon in the ribbon, or run **Open Manex Brain panel** from the command palette
|
||||
3. Open any note and start asking questions — the plugin automatically uses it as context
|
||||
4. Click any note link in an answer to open that note
|
||||
|
||||
## Commands
|
||||
|
||||
| Command | Description |
|
||||
|---|---|
|
||||
| Open Manex Brain panel | Opens the chat sidebar |
|
||||
| Open Manex Brain web app | Opens manex.app |
|
||||
| Ask Study Room about current note | Focuses the panel on the current note |
|
||||
|
||||
## Settings
|
||||
|
||||
| Setting | Description |
|
||||
|---|---|
|
||||
| Include frontmatter | Whether to include YAML frontmatter when reading notes |
|
||||
|
||||
## Privacy
|
||||
|
||||
All processing is local. The plugin:
|
||||
- Makes no network requests except to `http://localhost:8080` (the local MLX server)
|
||||
- Stores the vault index at `~/.obsidian-study-room/vault-index.json` (text only, no embeddings)
|
||||
- Does not collect, transmit, or store any user data
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**"MLX server not available"** — The model may still be downloading or loading. Wait 2–5 minutes on first run; the panel will update automatically once the server is ready.
|
||||
|
||||
**Python not found** — Install Python via Homebrew: `brew install python`
|
||||
|
||||
**Slow first response** — Normal. The model (~2.3 GB) is downloaded and loaded into memory once; subsequent responses are fast.
|
||||
|
||||
## Support
|
||||
|
||||
Visit [manex.app](https://manex.app) to learn more or support development.
|
||||
11
manifest.json
Normal file
11
manifest.json
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"id": "manex-brain",
|
||||
"name": "Manex Brain",
|
||||
"version": "1.0.0",
|
||||
"minAppVersion": "1.5.0",
|
||||
"description": "Local AI brain for your Obsidian vault. Indexes all your notes and answers questions privately using a local Apple Silicon MLX model — no cloud, no API keys.",
|
||||
"author": "Manex",
|
||||
"authorUrl": "https://manex.app",
|
||||
"fundingUrl": "https://manex.app",
|
||||
"isDesktopOnly": true
|
||||
}
|
||||
20
package.json
Normal file
20
package.json
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"name": "manex-brain",
|
||||
"version": "1.0.0",
|
||||
"description": "Local AI brain for your Obsidian vault using Apple Silicon MLX.",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"check": "node --check main.js",
|
||||
"pack": "zip -r manex-brain.zip manifest.json versions.json main.js styles.css README.md LICENSE"
|
||||
},
|
||||
"keywords": [
|
||||
"obsidian",
|
||||
"ai",
|
||||
"mlx",
|
||||
"local-ai",
|
||||
"knowledge-management"
|
||||
],
|
||||
"author": "Manex",
|
||||
"license": "MIT",
|
||||
"devDependencies": {}
|
||||
}
|
||||
336
styles.css
Normal file
336
styles.css
Normal file
|
|
@ -0,0 +1,336 @@
|
|||
.manex-study-room-panel {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.manex-scroll-area {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
padding: 14px 20px 8px;
|
||||
}
|
||||
|
||||
.manex-panel-header h2 {
|
||||
margin: 0 0 6px;
|
||||
}
|
||||
|
||||
.manex-panel-header p,
|
||||
.manex-empty span,
|
||||
.manex-context-card span {
|
||||
color: var(--text-muted);
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.manex-panel-header p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.manex-vault-status {
|
||||
margin-top: 4px;
|
||||
color: var(--text-faint);
|
||||
font-size: var(--font-ui-smaller);
|
||||
}
|
||||
|
||||
.manex-workspace-status,
|
||||
.manex-settings-status {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
margin-top: 10px;
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 12px;
|
||||
padding: 10px 12px;
|
||||
background: var(--background-secondary);
|
||||
}
|
||||
|
||||
.manex-workspace-status span,
|
||||
.manex-settings-status strong {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.manex-workspace-status small,
|
||||
.manex-settings-status p {
|
||||
margin: 0;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.manex-workspace-status button {
|
||||
justify-self: start;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.manex-entitlement-card {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
margin-top: 10px;
|
||||
border: 1px solid color-mix(in srgb, var(--interactive-accent) 28%, var(--background-modifier-border));
|
||||
border-radius: 12px;
|
||||
padding: 10px 12px;
|
||||
background: color-mix(in srgb, var(--interactive-accent) 8%, var(--background-secondary));
|
||||
}
|
||||
|
||||
.manex-entitlement-card.is-active {
|
||||
border-color: color-mix(in srgb, var(--color-green) 45%, var(--background-modifier-border));
|
||||
background: color-mix(in srgb, var(--color-green) 8%, var(--background-secondary));
|
||||
}
|
||||
|
||||
.manex-entitlement-card span {
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.manex-entitlement-card small {
|
||||
color: var(--text-muted);
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.manex-entitlement-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.manex-entitlement-actions button {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.manex-settings-entitlement {
|
||||
border-color: color-mix(in srgb, var(--interactive-accent) 30%, var(--background-modifier-border));
|
||||
}
|
||||
|
||||
.manex-settings-entitlement.is-active {
|
||||
border-color: color-mix(in srgb, var(--color-green) 45%, var(--background-modifier-border));
|
||||
}
|
||||
|
||||
.manex-chat-toolbar .setting-item {
|
||||
align-items: flex-start;
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 12px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.manex-chat-toolbar .setting-item-control {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.manex-chat-toolbar button,
|
||||
.manex-message-actions button,
|
||||
.manex-chat-form button {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.manex-context-card {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 12px;
|
||||
padding: 10px 12px;
|
||||
background: var(--background-secondary);
|
||||
}
|
||||
|
||||
.manex-context-card .manex-graph-context {
|
||||
display: block;
|
||||
margin-top: 4px;
|
||||
color: var(--text-muted);
|
||||
font-size: var(--font-ui-smaller);
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.manex-chat-log {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
min-height: 220px;
|
||||
overflow: auto;
|
||||
padding-right: 2px;
|
||||
}
|
||||
|
||||
.manex-empty {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
border: 1px dashed var(--background-modifier-border);
|
||||
border-radius: 14px;
|
||||
padding: 18px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.manex-message {
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 14px;
|
||||
padding: 12px;
|
||||
background: var(--background-primary);
|
||||
}
|
||||
|
||||
.manex-message-user {
|
||||
align-self: flex-end;
|
||||
max-width: 92%;
|
||||
background: var(--interactive-accent);
|
||||
color: var(--text-on-accent);
|
||||
}
|
||||
|
||||
.manex-message-assistant {
|
||||
align-self: flex-start;
|
||||
max-width: 96%;
|
||||
}
|
||||
|
||||
.manex-message.is-error {
|
||||
border-color: var(--text-error);
|
||||
}
|
||||
|
||||
.manex-message.is-error .manex-upgrade-box {
|
||||
border-color: color-mix(in srgb, var(--interactive-accent) 36%, var(--background-modifier-border));
|
||||
}
|
||||
|
||||
.manex-message-label {
|
||||
margin-bottom: 6px;
|
||||
color: var(--text-muted);
|
||||
font-size: var(--font-ui-smaller);
|
||||
font-weight: 700;
|
||||
letter-spacing: .08em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.manex-message-user .manex-message-label {
|
||||
color: color-mix(in srgb, var(--text-on-accent) 72%, transparent);
|
||||
}
|
||||
|
||||
.manex-message-text {
|
||||
line-height: 1.5;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
.manex-message-text > :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.manex-message-text > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.manex-message-text h1,
|
||||
.manex-message-text h2,
|
||||
.manex-message-text h3 {
|
||||
margin: 12px 0 6px;
|
||||
font-size: var(--font-ui-medium);
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
.manex-message-text p,
|
||||
.manex-message-text ul,
|
||||
.manex-message-text ol {
|
||||
margin: 6px 0;
|
||||
}
|
||||
|
||||
.manex-message-text li {
|
||||
margin: 4px 0;
|
||||
}
|
||||
|
||||
.manex-message-meta {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.manex-message-meta span {
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 999px;
|
||||
padding: 2px 8px;
|
||||
color: var(--text-muted);
|
||||
font-size: var(--font-ui-smaller);
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.manex-sources {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
margin-top: 12px;
|
||||
border-top: 1px solid var(--background-modifier-border);
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.manex-sources span {
|
||||
color: var(--text-muted);
|
||||
font-size: var(--font-ui-smaller);
|
||||
font-weight: 700;
|
||||
letter-spacing: .08em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.manex-sources p {
|
||||
margin: 0;
|
||||
color: var(--text-muted);
|
||||
font-size: var(--font-ui-small);
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.manex-message-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.manex-upgrade-box {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
margin-top: 12px;
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 12px;
|
||||
padding: 10px;
|
||||
background: color-mix(in srgb, var(--interactive-accent) 8%, var(--background-secondary));
|
||||
}
|
||||
|
||||
.manex-upgrade-box p {
|
||||
margin: 0;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.manex-upgrade-box button {
|
||||
justify-self: start;
|
||||
}
|
||||
|
||||
.manex-chat-form {
|
||||
display: grid;
|
||||
flex-shrink: 0;
|
||||
gap: 8px;
|
||||
border-top: 1px solid var(--background-modifier-border);
|
||||
padding: 10px 20px 16px;
|
||||
background: var(--background-primary);
|
||||
}
|
||||
|
||||
.manex-chat-form textarea {
|
||||
min-height: 72px;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.manex-chat-form button {
|
||||
justify-self: end;
|
||||
}
|
||||
|
||||
.manex-actions {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.manex-actions .setting-item {
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 10px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.manex-memory-textarea {
|
||||
width: 100%;
|
||||
min-height: 160px;
|
||||
}
|
||||
3
versions.json
Normal file
3
versions.json
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"1.0.0": "1.5.0"
|
||||
}
|
||||
Loading…
Reference in a new issue