agent-natalie 0.1.0__tar.gz
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.
- agent_natalie-0.1.0/.gitignore +24 -0
- agent_natalie-0.1.0/LICENSE +21 -0
- agent_natalie-0.1.0/Makefile +35 -0
- agent_natalie-0.1.0/PKG-INFO +48 -0
- agent_natalie-0.1.0/README.md +225 -0
- agent_natalie-0.1.0/install.sh +104 -0
- agent_natalie-0.1.0/natalie/__init__.py +0 -0
- agent_natalie-0.1.0/natalie/cli.py +279 -0
- agent_natalie-0.1.0/natalie/config.py +77 -0
- agent_natalie-0.1.0/natalie/db.py +68 -0
- agent_natalie-0.1.0/natalie/features/__init__.py +0 -0
- agent_natalie-0.1.0/natalie/features/contacts.py +58 -0
- agent_natalie-0.1.0/natalie/features/documents.py +36 -0
- agent_natalie-0.1.0/natalie/features/memory.py +262 -0
- agent_natalie-0.1.0/natalie/features/sync.py +47 -0
- agent_natalie-0.1.0/natalie/features/tasks.py +62 -0
- agent_natalie-0.1.0/natalie/generate.py +42 -0
- agent_natalie-0.1.0/natalie/personas/.gitkeep +0 -0
- agent_natalie-0.1.0/natalie/personas/april.md +28 -0
- agent_natalie-0.1.0/natalie/personas/donna.md +28 -0
- agent_natalie-0.1.0/natalie/personas/finch.md +27 -0
- agent_natalie-0.1.0/natalie/personas/gary.md +28 -0
- agent_natalie-0.1.0/natalie/personas/moneypenny.md +26 -0
- agent_natalie-0.1.0/natalie/personas/natalie.md +26 -0
- agent_natalie-0.1.0/natalie/personas/pam.md +29 -0
- agent_natalie-0.1.0/natalie/personas/smithers.md +28 -0
- agent_natalie-0.1.0/natalie/server.py +306 -0
- agent_natalie-0.1.0/natalie/snippets/MCL Multi Column.css +881 -0
- agent_natalie-0.1.0/natalie/snippets/MCL Wide Views.css +398 -0
- agent_natalie-0.1.0/natalie/snippets/natalie-dashboard.css +97 -0
- agent_natalie-0.1.0/natalie/templates/.gitkeep +0 -0
- agent_natalie-0.1.0/natalie/templates/Dashboard.md +47 -0
- agent_natalie-0.1.0/natalie/templates/agents.md.jinja +58 -0
- agent_natalie-0.1.0/natalie/templates/claude.md.jinja +58 -0
- agent_natalie-0.1.0/natalie/utils.py +12 -0
- agent_natalie-0.1.0/natalie/vault.py +16 -0
- agent_natalie-0.1.0/pyproject.toml +77 -0
- agent_natalie-0.1.0/scripts/pre-commit +4 -0
- agent_natalie-0.1.0/tests/__init__.py +0 -0
- agent_natalie-0.1.0/tests/conftest.py +26 -0
- agent_natalie-0.1.0/tests/helpers.py +9 -0
- agent_natalie-0.1.0/tests/test_cli.py +221 -0
- agent_natalie-0.1.0/tests/test_config.py +43 -0
- agent_natalie-0.1.0/tests/test_contacts.py +78 -0
- agent_natalie-0.1.0/tests/test_db.py +80 -0
- agent_natalie-0.1.0/tests/test_documents.py +55 -0
- agent_natalie-0.1.0/tests/test_generate.py +73 -0
- agent_natalie-0.1.0/tests/test_memory.py +745 -0
- agent_natalie-0.1.0/tests/test_path_security.py +82 -0
- agent_natalie-0.1.0/tests/test_server.py +288 -0
- agent_natalie-0.1.0/tests/test_sync.py +169 -0
- agent_natalie-0.1.0/tests/test_tasks.py +135 -0
- agent_natalie-0.1.0/tests/test_vault.py +33 -0
- agent_natalie-0.1.0/uninstall.sh +66 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*.egg-info/
|
|
4
|
+
dist/
|
|
5
|
+
build/
|
|
6
|
+
.venv/
|
|
7
|
+
.pytest_cache/
|
|
8
|
+
.hypothesis/
|
|
9
|
+
.mypy_cache/
|
|
10
|
+
.ruff_cache/
|
|
11
|
+
.claude/
|
|
12
|
+
*.db
|
|
13
|
+
|
|
14
|
+
# macOS
|
|
15
|
+
.DS_Store
|
|
16
|
+
|
|
17
|
+
# local knowledge graph (machine-specific)
|
|
18
|
+
.mnem/
|
|
19
|
+
|
|
20
|
+
# uv lockfile — not committed for library packages
|
|
21
|
+
uv.lock
|
|
22
|
+
|
|
23
|
+
# internal planning / spec artifacts — keep local only
|
|
24
|
+
docs/
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Simon Garnier
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
.PHONY: lint format typecheck security test check install-hooks publish
|
|
2
|
+
|
|
3
|
+
lint:
|
|
4
|
+
uv run ruff check natalie/ tests/
|
|
5
|
+
|
|
6
|
+
format:
|
|
7
|
+
uv run ruff format --check natalie/ tests/
|
|
8
|
+
|
|
9
|
+
typecheck:
|
|
10
|
+
uv run mypy natalie/
|
|
11
|
+
|
|
12
|
+
security:
|
|
13
|
+
uv run bandit -r natalie/ -ll
|
|
14
|
+
|
|
15
|
+
test:
|
|
16
|
+
uv run python -m pytest tests/ -v
|
|
17
|
+
|
|
18
|
+
check: lint format typecheck security test
|
|
19
|
+
|
|
20
|
+
install-hooks:
|
|
21
|
+
cp scripts/pre-commit .git/hooks/pre-commit
|
|
22
|
+
chmod +x .git/hooks/pre-commit
|
|
23
|
+
@echo "Pre-commit hook installed."
|
|
24
|
+
|
|
25
|
+
# PyPI publish checklist:
|
|
26
|
+
# 1. Bump version in pyproject.toml
|
|
27
|
+
# 2. Commit and tag: git tag vX.Y.Z && git push --tags
|
|
28
|
+
# 3. Set TWINE_USERNAME / TWINE_PASSWORD (or use a ~/.pypirc token)
|
|
29
|
+
# 4. Run: make publish
|
|
30
|
+
publish: check
|
|
31
|
+
@git diff --exit-code || (echo "ERROR: working tree is dirty — commit or stash changes before publishing"; exit 1)
|
|
32
|
+
@git diff --cached --exit-code || (echo "ERROR: staged changes present — commit before publishing"; exit 1)
|
|
33
|
+
rm -rf dist/
|
|
34
|
+
uv run python -m build
|
|
35
|
+
uv run twine upload dist/*
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agent-natalie
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server that turns an Obsidian vault into a personal-assistant backend for Claude Code and OpenCode
|
|
5
|
+
Author-email: Simon Garnier <simon.garnier@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Simon Garnier
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Classifier: Development Status :: 3 - Alpha
|
|
29
|
+
Classifier: Intended Audience :: Developers
|
|
30
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
31
|
+
Classifier: Programming Language :: Python :: 3
|
|
32
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
33
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
34
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
35
|
+
Classifier: Topic :: Office/Business :: Scheduling
|
|
36
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
37
|
+
Requires-Python: >=3.11
|
|
38
|
+
Requires-Dist: fastembed>=0.4
|
|
39
|
+
Requires-Dist: httpx>=0.27
|
|
40
|
+
Requires-Dist: jinja2>=3.1
|
|
41
|
+
Requires-Dist: mcp[cli]>=1.0
|
|
42
|
+
Requires-Dist: numpy>=1.24
|
|
43
|
+
Requires-Dist: python-frontmatter>=1.1
|
|
44
|
+
Requires-Dist: tomli-w>=1.0
|
|
45
|
+
Requires-Dist: typer>=0.12
|
|
46
|
+
Provides-Extra: dev
|
|
47
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
48
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# agent-natalie
|
|
2
|
+
|
|
3
|
+
A portable personal assistant plugin for Claude Code and OpenCode.
|
|
4
|
+
Natalie lives in your Obsidian vault and is only active when your agent
|
|
5
|
+
is working from that directory.
|
|
6
|
+
|
|
7
|
+
## What it does
|
|
8
|
+
|
|
9
|
+
- **Memory** — indexes your vault with FTS + semantic search (fastembed, fully offline)
|
|
10
|
+
- **Tasks** — discovers and manages checkbox tasks across your notes
|
|
11
|
+
- **Documents** — files and retrieves reference material
|
|
12
|
+
- **Contacts** — maintains entity/person reference cards
|
|
13
|
+
- **Conventions** — remembers your working rules and applies them before acting
|
|
14
|
+
- **Personas** — ships 8 preset personalities; drop a `.md` file to add your own
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Requirements
|
|
19
|
+
|
|
20
|
+
- Python 3.11+
|
|
21
|
+
- [`uv`](https://docs.astral.sh/uv/) (installed automatically by `install.sh` if missing)
|
|
22
|
+
- Obsidian (optional but recommended — Natalie falls back to direct file I/O without it)
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Install
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
git clone https://github.com/sjmgarnier/agent-natalie agent-natalie
|
|
30
|
+
bash agent-natalie/install.sh
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The script:
|
|
34
|
+
1. Installs `uv` if missing
|
|
35
|
+
2. Creates `~/.natalie/.venv/` with an isolated Python environment
|
|
36
|
+
3. Prompts for your vault path and persona
|
|
37
|
+
4. Scaffolds the vault (dashboard, CLAUDE.md, AGENTS.md, CSS snippets, MCP config)
|
|
38
|
+
5. Builds the initial search index
|
|
39
|
+
|
|
40
|
+
> **Note:** Step 5 downloads the embedding model (~130 MB) on first run. This is cached
|
|
41
|
+
> after the first sync. Allow extra time on slow connections.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Obsidian setup
|
|
46
|
+
|
|
47
|
+
After running `install.sh`, complete these steps in Obsidian before use.
|
|
48
|
+
|
|
49
|
+
### 1. Add the vault
|
|
50
|
+
|
|
51
|
+
Open Obsidian → **Open folder as vault** → select the vault path you provided to `install.sh`.
|
|
52
|
+
|
|
53
|
+
### 2. Enable the CSS snippets
|
|
54
|
+
|
|
55
|
+
The dashboard layout requires three CSS snippets that `install.sh` already copied into
|
|
56
|
+
`.obsidian/snippets/`. Enable them:
|
|
57
|
+
|
|
58
|
+
1. Go to **Settings → Appearance → CSS snippets**
|
|
59
|
+
2. Toggle on **natalie-dashboard**, **MCL Multi Column**, and **MCL Wide Views**
|
|
60
|
+
3. Press **Cmd+R** (Mac) / **Ctrl+R** (Windows) to reload Obsidian
|
|
61
|
+
|
|
62
|
+
If the snippets are not listed, click the folder icon to refresh the snippets directory.
|
|
63
|
+
|
|
64
|
+
### 3. Install and configure Dataview
|
|
65
|
+
|
|
66
|
+
The dashboard uses [Dataview](https://github.com/blacksmithgu/obsidian-dataview) for
|
|
67
|
+
live queries. Install it from the community plugin browser:
|
|
68
|
+
|
|
69
|
+
1. **Settings → Community plugins → turn off Restricted Mode → Browse**
|
|
70
|
+
2. Search **Dataview** → **Install** → **Enable**
|
|
71
|
+
3. Open **Dataview settings** → enable **Enable JavaScript Queries**
|
|
72
|
+
|
|
73
|
+
Without Dataview the dashboard will show raw code blocks instead of rendered tables and task lists.
|
|
74
|
+
|
|
75
|
+
### 4. Open the Dashboard
|
|
76
|
+
|
|
77
|
+
Click **Dashboard.md** in the vault root. Switch to Reading view if it doesn't render automatically.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## First run
|
|
82
|
+
|
|
83
|
+
Start Claude Code from inside the vault directory:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
cd /path/to/your/vault
|
|
87
|
+
claude
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Claude Code reads `.mcp.json` and connects to `natalie-server` automatically.
|
|
91
|
+
The Natalie tools (`memory_search`, `note_write`, `task_list`, …) will appear in the tool list.
|
|
92
|
+
|
|
93
|
+
Run `natalie sync` any time you add new notes outside of Claude Code.
|
|
94
|
+
(It runs automatically as a post-tool-use hook inside Claude Code sessions.)
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## CLI commands
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
natalie sync [--full] # Rebuild vault index (--full wipes and reindexes everything)
|
|
102
|
+
natalie config --persona donna # Switch persona and regenerate CLAUDE.md / AGENTS.md
|
|
103
|
+
natalie config --regen # Regenerate CLAUDE.md / AGENTS.md without changing persona
|
|
104
|
+
natalie init <vault-path> # Scaffold a new vault (called by install.sh)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## MCP tools
|
|
110
|
+
|
|
111
|
+
| Tool | Description |
|
|
112
|
+
|------|-------------|
|
|
113
|
+
| `ping` | Check that the server is running |
|
|
114
|
+
| `memory_search` | Hybrid FTS + semantic search across vault notes |
|
|
115
|
+
| `memory_store` | Store an outside-vault knowledge entry |
|
|
116
|
+
| `note_read` | Read a vault note by path |
|
|
117
|
+
| `note_write` | Write or update a vault note |
|
|
118
|
+
| `task_list` | List open (or all) tasks across the vault |
|
|
119
|
+
| `task_capture` | Add a task to a note |
|
|
120
|
+
| `task_complete` | Mark a task done |
|
|
121
|
+
| `document_file` | File a document to the documents cabinet |
|
|
122
|
+
| `document_retrieve` | Retrieve a document by filename |
|
|
123
|
+
| `document_list` | List all documents |
|
|
124
|
+
| `contact_get` | Get a contact card by slug |
|
|
125
|
+
| `contact_update` | Create or update a contact card |
|
|
126
|
+
| `contact_list` | List all contact slugs |
|
|
127
|
+
| `convention_list` | List conventions, optionally filtered by domain |
|
|
128
|
+
| `convention_add` | Add a convention |
|
|
129
|
+
| `convention_delete` | Delete a convention by ID |
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Personas
|
|
134
|
+
|
|
135
|
+
| Preset | Character | Source |
|
|
136
|
+
|--------|-----------|--------|
|
|
137
|
+
| `natalie` | Natalie Teeger | Monk |
|
|
138
|
+
| `donna` | Donna Paulsen | Suits |
|
|
139
|
+
| `moneypenny` | Miss Moneypenny | James Bond |
|
|
140
|
+
| `smithers` | Waylon Smithers | The Simpsons |
|
|
141
|
+
| `april` | April Ludgate | Parks & Recreation |
|
|
142
|
+
| `finch` | Dennis Finch | Just Shoot Me! |
|
|
143
|
+
| `gary` | Gary Walsh | Veep |
|
|
144
|
+
| `pam` | Pam Beesly | The Office |
|
|
145
|
+
|
|
146
|
+
### Custom personas
|
|
147
|
+
|
|
148
|
+
Drop a `.md` file in `<vault>/Natalie/personas/`:
|
|
149
|
+
|
|
150
|
+
```markdown
|
|
151
|
+
---
|
|
152
|
+
name: My Assistant
|
|
153
|
+
source: Original
|
|
154
|
+
tone:
|
|
155
|
+
- helpful
|
|
156
|
+
- direct
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
Your persona prose here.
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Then activate it:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
natalie config --persona my-assistant
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Configuration
|
|
171
|
+
|
|
172
|
+
Edit `<vault>/Natalie/config.toml`, then run `natalie config --regen`:
|
|
173
|
+
|
|
174
|
+
```toml
|
|
175
|
+
[persona]
|
|
176
|
+
name = "natalie"
|
|
177
|
+
|
|
178
|
+
[memory]
|
|
179
|
+
embedding_model = "BAAI/bge-small-en-v1.5"
|
|
180
|
+
|
|
181
|
+
[skills]
|
|
182
|
+
preferred = [] # e.g. ["superpowers", "r-lib"] — agent will prefer these
|
|
183
|
+
denied = []
|
|
184
|
+
|
|
185
|
+
[mcps]
|
|
186
|
+
preferred = [] # e.g. ["obsidian", "github"]
|
|
187
|
+
denied = []
|
|
188
|
+
|
|
189
|
+
[features.documents]
|
|
190
|
+
directory = "Natalie/Documents"
|
|
191
|
+
|
|
192
|
+
[features.contacts]
|
|
193
|
+
directory = "Natalie/Contacts"
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Known limitations
|
|
199
|
+
|
|
200
|
+
**Changing the embedding model** — Existing embeddings are incompatible with a new model.
|
|
201
|
+
After changing `embedding_model` in `config.toml`, run `natalie sync --full` to rebuild
|
|
202
|
+
the index from scratch.
|
|
203
|
+
|
|
204
|
+
**Single active session per vault** — `natalie.db` lives inside the vault. If you sync
|
|
205
|
+
your vault across machines (iCloud, Dropbox, Syncthing, or similar), running
|
|
206
|
+
`natalie-server` on two machines simultaneously against the same vault risks SQLite WAL
|
|
207
|
+
corruption. Keep one active session at a time.
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Upgrade
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
bash /path/to/agent-natalie/install.sh
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
The script detects an existing install and offers to upgrade in place.
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Uninstall
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
bash /path/to/agent-natalie/uninstall.sh
|
|
225
|
+
```
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
5
|
+
VENV_DIR="$HOME/.natalie/.venv"
|
|
6
|
+
|
|
7
|
+
# ── uv ────────────────────────────────────────────────────────────────────────
|
|
8
|
+
if ! command -v uv &>/dev/null; then
|
|
9
|
+
echo "Installing uv..."
|
|
10
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
11
|
+
[ -f "$HOME/.local/bin/env" ] && source "$HOME/.local/bin/env"
|
|
12
|
+
export PATH="$HOME/.local/bin:$HOME/.cargo/bin:$PATH"
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
NATALIE="$VENV_DIR/bin/natalie"
|
|
16
|
+
|
|
17
|
+
# ── Update detection ──────────────────────────────────────────────────────────
|
|
18
|
+
if [[ -d "$VENV_DIR" ]]; then
|
|
19
|
+
echo "Existing Natalie install found at $VENV_DIR."
|
|
20
|
+
read -rp "Upgrade agent-natalie? [Y/n] " _UPGRADE
|
|
21
|
+
_UPGRADE="${_UPGRADE:-Y}"
|
|
22
|
+
if [[ "$_UPGRADE" =~ ^[Yy]$ ]]; then
|
|
23
|
+
echo "Upgrading agent-natalie..."
|
|
24
|
+
uv pip install --python "$VENV_DIR" --upgrade "$SCRIPT_DIR"
|
|
25
|
+
echo ""
|
|
26
|
+
echo "Done. Run 'natalie sync --full' from your vault directory to rebuild the search index."
|
|
27
|
+
exit 0
|
|
28
|
+
fi
|
|
29
|
+
echo "Proceeding with full re-install..."
|
|
30
|
+
rm -rf "$VENV_DIR"
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
# ── Install agent-natalie ─────────────────────────────────────────────────────
|
|
34
|
+
echo "Creating Python environment at $VENV_DIR..."
|
|
35
|
+
mkdir -p "$HOME/.natalie"
|
|
36
|
+
uv venv "$VENV_DIR"
|
|
37
|
+
uv pip install --python "$VENV_DIR" "$SCRIPT_DIR"
|
|
38
|
+
|
|
39
|
+
# ── Prompt for vault path ─────────────────────────────────────────────────────
|
|
40
|
+
echo ""
|
|
41
|
+
read -rp "Vault path (default: $HOME/Natalie): " VAULT_PATH
|
|
42
|
+
VAULT_PATH="${VAULT_PATH:-$HOME/Natalie}"
|
|
43
|
+
VAULT_PATH="${VAULT_PATH/#\~/$HOME}"
|
|
44
|
+
|
|
45
|
+
# ── Prompt for persona ────────────────────────────────────────────────────────
|
|
46
|
+
echo ""
|
|
47
|
+
echo "Available personas: natalie, donna, moneypenny, smithers, april, finch, gary, pam"
|
|
48
|
+
read -rp "Persona (default: natalie): " PERSONA
|
|
49
|
+
PERSONA="${PERSONA:-natalie}"
|
|
50
|
+
|
|
51
|
+
# ── Confirm vault modification ────────────────────────────────────────────────
|
|
52
|
+
echo ""
|
|
53
|
+
echo "natalie will create or modify the following in: $VAULT_PATH"
|
|
54
|
+
echo " Dashboard.md, CLAUDE.md, AGENTS.md (skipped if already present)"
|
|
55
|
+
echo " .obsidian/snippets/ (3 CSS files, skipped if already present)"
|
|
56
|
+
echo " .obsidian/appearance.json (enables CSS snippets)"
|
|
57
|
+
echo " .mcp.json, .claude/settings.json, opencode.json, .opencode/hooks.json"
|
|
58
|
+
echo ""
|
|
59
|
+
read -rp "Proceed? [Y/n] " _PROCEED
|
|
60
|
+
_PROCEED="${_PROCEED:-Y}"
|
|
61
|
+
if [[ ! "$_PROCEED" =~ ^[Yy]$ ]]; then
|
|
62
|
+
echo "Aborted."
|
|
63
|
+
exit 1
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
# ── Initialize vault ─────────────────────────────────────────────────────────
|
|
67
|
+
echo ""
|
|
68
|
+
echo "Initializing vault at $VAULT_PATH..."
|
|
69
|
+
"$NATALIE" init "$VAULT_PATH" --persona "$PERSONA" --venv-path "$VENV_DIR"
|
|
70
|
+
|
|
71
|
+
# ── Build initial index ───────────────────────────────────────────────────────
|
|
72
|
+
echo ""
|
|
73
|
+
echo "Building initial search index..."
|
|
74
|
+
echo "On first run this downloads the embedding model (~130 MB)."
|
|
75
|
+
echo "A progress bar will appear below — this may take several minutes on slow connections."
|
|
76
|
+
echo ""
|
|
77
|
+
cd "$VAULT_PATH"
|
|
78
|
+
"$NATALIE" sync --full
|
|
79
|
+
|
|
80
|
+
echo ""
|
|
81
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
82
|
+
echo " Done! Here's what to do next:"
|
|
83
|
+
echo ""
|
|
84
|
+
echo " 1. Open Obsidian and add '$VAULT_PATH' as a vault."
|
|
85
|
+
echo " The Dashboard layout and CSS snippets are pre-configured."
|
|
86
|
+
echo " If the multi-column layout doesn't appear, go to:"
|
|
87
|
+
echo " Settings → Appearance → CSS snippets"
|
|
88
|
+
echo " and make sure natalie-dashboard, MCL Multi Column, and MCL Wide Views"
|
|
89
|
+
echo " are toggled on. Then reload Obsidian (Cmd+R)."
|
|
90
|
+
echo ""
|
|
91
|
+
echo " 2. Install the Dataview community plugin (required for the Dashboard):"
|
|
92
|
+
echo " Settings → Community Plugins → turn off Safe Mode → Browse"
|
|
93
|
+
echo " Search 'Dataview' → Install → Enable"
|
|
94
|
+
echo " Then open Dataview settings and enable 'Enable JavaScript Queries'."
|
|
95
|
+
echo ""
|
|
96
|
+
echo " 3. Start Claude Code from inside the vault:"
|
|
97
|
+
echo " cd '$VAULT_PATH' && claude"
|
|
98
|
+
echo " Claude Code reads .mcp.json and connects to natalie-server automatically."
|
|
99
|
+
echo " The natalie tools (memory_search, note_write, task_list, …) will appear"
|
|
100
|
+
echo " in the tool list."
|
|
101
|
+
echo ""
|
|
102
|
+
echo " 4. Run 'natalie sync' from the vault directory any time you add new notes."
|
|
103
|
+
echo " (It runs automatically as a Claude Code hook after every tool use.)"
|
|
104
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
File without changes
|