metis-brain 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.
- metis_brain-0.1.0/.gitignore +9 -0
- metis_brain-0.1.0/LICENSE +21 -0
- metis_brain-0.1.0/PKG-INFO +251 -0
- metis_brain-0.1.0/README.md +212 -0
- metis_brain-0.1.0/pyproject.toml +70 -0
- metis_brain-0.1.0/src/metis/.trace +1 -0
- metis_brain-0.1.0/src/metis/__init__.py +3 -0
- metis_brain-0.1.0/src/metis/chat.py +210 -0
- metis_brain-0.1.0/src/metis/classify.py +291 -0
- metis_brain-0.1.0/src/metis/cli.py +1207 -0
- metis_brain-0.1.0/src/metis/client.py +69 -0
- metis_brain-0.1.0/src/metis/config.py +279 -0
- metis_brain-0.1.0/src/metis/expand.py +110 -0
- metis_brain-0.1.0/src/metis/health.py +314 -0
- metis_brain-0.1.0/src/metis/index/__init__.py +0 -0
- metis_brain-0.1.0/src/metis/index/canary.py +134 -0
- metis_brain-0.1.0/src/metis/index/embed.py +47 -0
- metis_brain-0.1.0/src/metis/index/store.py +186 -0
- metis_brain-0.1.0/src/metis/index/sync.py +220 -0
- metis_brain-0.1.0/src/metis/ingest/__init__.py +0 -0
- metis_brain-0.1.0/src/metis/ingest/extract.py +636 -0
- metis_brain-0.1.0/src/metis/ingest/process.py +217 -0
- metis_brain-0.1.0/src/metis/ingest/write.py +179 -0
- metis_brain-0.1.0/src/metis/link.py +299 -0
- metis_brain-0.1.0/src/metis/pick.py +172 -0
- metis_brain-0.1.0/src/metis/search.py +60 -0
- metis_brain-0.1.0/src/metis/secrets.py +67 -0
- metis_brain-0.1.0/src/metis/textio.py +17 -0
- metis_brain-0.1.0/tests/__init__.py +0 -0
- metis_brain-0.1.0/tests/conftest.py +50 -0
- metis_brain-0.1.0/tests/test_canary.py +156 -0
- metis_brain-0.1.0/tests/test_canary_width.py +21 -0
- metis_brain-0.1.0/tests/test_categorization_corrupt.py +31 -0
- metis_brain-0.1.0/tests/test_chat.py +158 -0
- metis_brain-0.1.0/tests/test_chat_expand_save.py +56 -0
- metis_brain-0.1.0/tests/test_chat_note_scope.py +39 -0
- metis_brain-0.1.0/tests/test_chat_repl.py +221 -0
- metis_brain-0.1.0/tests/test_chunk_text.py +27 -0
- metis_brain-0.1.0/tests/test_chunking.py +52 -0
- metis_brain-0.1.0/tests/test_client.py +99 -0
- metis_brain-0.1.0/tests/test_config.py +136 -0
- metis_brain-0.1.0/tests/test_config_defaults.py +50 -0
- metis_brain-0.1.0/tests/test_config_guard.py +52 -0
- metis_brain-0.1.0/tests/test_config_section_guard.py +49 -0
- metis_brain-0.1.0/tests/test_doctor.py +102 -0
- metis_brain-0.1.0/tests/test_embed_alignment.py +63 -0
- metis_brain-0.1.0/tests/test_embedding_model_alias.py +36 -0
- metis_brain-0.1.0/tests/test_embedding_stamp.py +37 -0
- metis_brain-0.1.0/tests/test_empty_choices.py +57 -0
- metis_brain-0.1.0/tests/test_errors.py +60 -0
- metis_brain-0.1.0/tests/test_expand.py +36 -0
- metis_brain-0.1.0/tests/test_expand_cli_graceful.py +33 -0
- metis_brain-0.1.0/tests/test_extract.py +159 -0
- metis_brain-0.1.0/tests/test_extract_browser.py +52 -0
- metis_brain-0.1.0/tests/test_extract_http_errors.py +24 -0
- metis_brain-0.1.0/tests/test_extract_pdf_corrupt.py +21 -0
- metis_brain-0.1.0/tests/test_extract_pdf_guard.py +39 -0
- metis_brain-0.1.0/tests/test_health.py +28 -0
- metis_brain-0.1.0/tests/test_health_split.py +30 -0
- metis_brain-0.1.0/tests/test_ingest_folder.py +44 -0
- metis_brain-0.1.0/tests/test_ingest_pick_cancel.py +28 -0
- metis_brain-0.1.0/tests/test_ingest_sync_state.py +45 -0
- metis_brain-0.1.0/tests/test_ingest_update.py +147 -0
- metis_brain-0.1.0/tests/test_knn_votes.py +40 -0
- metis_brain-0.1.0/tests/test_link.py +37 -0
- metis_brain-0.1.0/tests/test_link_style.py +173 -0
- metis_brain-0.1.0/tests/test_models.py +78 -0
- metis_brain-0.1.0/tests/test_pick_cancel.py +26 -0
- metis_brain-0.1.0/tests/test_pick_suggested.py +62 -0
- metis_brain-0.1.0/tests/test_process.py +19 -0
- metis_brain-0.1.0/tests/test_process_guards.py +47 -0
- metis_brain-0.1.0/tests/test_provider_guard_no_key.py +55 -0
- metis_brain-0.1.0/tests/test_qa_save_fences.py +37 -0
- metis_brain-0.1.0/tests/test_query_dimension.py +32 -0
- metis_brain-0.1.0/tests/test_readability.py +63 -0
- metis_brain-0.1.0/tests/test_sanitize.py +62 -0
- metis_brain-0.1.0/tests/test_secret_list.py +46 -0
- metis_brain-0.1.0/tests/test_secrets.py +59 -0
- metis_brain-0.1.0/tests/test_secrets_keychain.py +26 -0
- metis_brain-0.1.0/tests/test_security.py +49 -0
- metis_brain-0.1.0/tests/test_sources_index.py +35 -0
- metis_brain-0.1.0/tests/test_ssrf.py +56 -0
- metis_brain-0.1.0/tests/test_store.py +55 -0
- metis_brain-0.1.0/tests/test_store_dimension.py +34 -0
- metis_brain-0.1.0/tests/test_sync_empty_vault.py +68 -0
- metis_brain-0.1.0/tests/test_sync_skips_unreadable.py +60 -0
- metis_brain-0.1.0/tests/test_sync_state.py +35 -0
- metis_brain-0.1.0/tests/test_textio.py +35 -0
- metis_brain-0.1.0/tests/test_vault_scope.py +78 -0
- metis_brain-0.1.0/tests/test_write.py +201 -0
- metis_brain-0.1.0/tests/test_write_links.py +34 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 itsautomata
|
|
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,251 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: metis-brain
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: CLI second brain for your markdown notes
|
|
5
|
+
Project-URL: Homepage, https://github.com/itsautomata/metis
|
|
6
|
+
Project-URL: Repository, https://github.com/itsautomata/metis
|
|
7
|
+
Project-URL: Issues, https://github.com/itsautomata/metis/issues
|
|
8
|
+
Author: itsautomata
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: cli,embeddings,knowledge-base,markdown,note-taking,obsidian,rag,second-brain,semantic-search
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Text Processing :: Indexing
|
|
21
|
+
Classifier: Topic :: Utilities
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Requires-Dist: chromadb>=0.6.0
|
|
24
|
+
Requires-Dist: httpx>=0.27.0
|
|
25
|
+
Requires-Dist: keyring>=25.0.0
|
|
26
|
+
Requires-Dist: lxml-html-clean>=0.4.0
|
|
27
|
+
Requires-Dist: openai>=1.0.0
|
|
28
|
+
Requires-Dist: pymupdf>=1.24.0
|
|
29
|
+
Requires-Dist: pyyaml>=6.0
|
|
30
|
+
Requires-Dist: questionary>=2.0.0
|
|
31
|
+
Requires-Dist: rich>=13.0.0
|
|
32
|
+
Requires-Dist: scikit-learn>=1.5.0
|
|
33
|
+
Requires-Dist: trafilatura>=1.12.0
|
|
34
|
+
Requires-Dist: typer>=0.15.0
|
|
35
|
+
Requires-Dist: youtube-transcript-api>=1.0.0
|
|
36
|
+
Provides-Extra: test
|
|
37
|
+
Requires-Dist: pytest>=8.0.0; extra == 'test'
|
|
38
|
+
Description-Content-Type: text/markdown
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
<p align="center">
|
|
42
|
+
<img src="https://raw.githubusercontent.com/itsautomata/metis/main/assets/metis_draft.gif" alt="metis" width="330">
|
|
43
|
+
</p>
|
|
44
|
+
|
|
45
|
+
## metis
|
|
46
|
+
a cli second brain for your markdown notes: [obsidian](https://obsidian.md/download) (recommended), an alternative, or just a normal folder.
|
|
47
|
+
|
|
48
|
+
ingest anything. search by meaning. chat with your knowledge. discover connections.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## setup
|
|
53
|
+
|
|
54
|
+
### install
|
|
55
|
+
|
|
56
|
+
**pip.** requires python 3.10+
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install metis-brain
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**uv**
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
uv tool install metis-brain # if you don't have uv installed run: curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
66
|
+
```
|
|
67
|
+
**git (for development):**
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
git clone https://github.com/itsautomata/metis
|
|
71
|
+
cd metis
|
|
72
|
+
uv tool install -e . # global, editable
|
|
73
|
+
uv tool install -e . --force # update the global install
|
|
74
|
+
# or in a virtualenv:
|
|
75
|
+
uv venv && source .venv/bin/activate && uv pip install -e "."
|
|
76
|
+
```
|
|
77
|
+
### upgrade
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
uv tool upgrade metis-brain # installed with uv
|
|
81
|
+
pip install --upgrade metis-brain # installed with pip
|
|
82
|
+
git pull && uv tool install -e . --force # dev / editable clone
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
then set up, whichever way you installed:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
metis init
|
|
90
|
+
metis --install-completion # enable tab completion for commands
|
|
91
|
+
exec $SHELL # restart shell to apply
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
store your api keys securely:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
metis secret set provider-key # your one key (works for any provider via base_url)
|
|
98
|
+
metis secret set x-token # optional, for full x/twitter extraction
|
|
99
|
+
metis secret set # interactive, you pick which key you want to set
|
|
100
|
+
metis secret list # show which keys are set (no values)
|
|
101
|
+
metis doctor # verify the whole setup: key, provider, models, index
|
|
102
|
+
metis models # show the chat + embedding models (and provider) in use
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
quick changes via `metis config vault <path>`. for everything else, edit `~/.metis/config.yaml`.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## commands
|
|
110
|
+
|
|
111
|
+
run `metis --help` or `metis <command> --help` for all options.
|
|
112
|
+
|
|
113
|
+
### ingest
|
|
114
|
+
|
|
115
|
+
save anything to your vault: summarized, tagged, embedded, and linked back to the source.
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
metis ingest https://en.wikipedia.org/wiki/Metis_(mythology)
|
|
119
|
+
metis ingest ~/books/project-hail-mary.pdf
|
|
120
|
+
metis ingest lecture-notes.md
|
|
121
|
+
metis ingest paper.pdf --folder research/ai
|
|
122
|
+
metis ingest https://www.youtube.com/watch?v=abc123 --lang fr
|
|
123
|
+
metis ingest https://arxiv.org/abs/2401.12345
|
|
124
|
+
metis ingest paper1.pdf paper2.pdf https://arxiv.org/abs/2402.00001
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
accepts one source or many at once. supports pdfs, urls, markdown, arxiv papers, youtube videos, and x/twitter posts. `--folder` organizes into vault subfolders.
|
|
128
|
+
|
|
129
|
+
> interactive: `--pick-folder` (vault folders) / `--pick-lang` (transcript languages)
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
### search
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
metis search "what role did titans play in greek mythos"
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
semantic search. finds by meaning, not keywords. pick a result to chat about it.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
### chat
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
metis chat "how does project hail mary handle the fermi paradox?"
|
|
147
|
+
metis chat "what does he say about nash equilibrium?" --note game_theory/intro
|
|
148
|
+
metis chat "question" --note game_theory/intro --save
|
|
149
|
+
metis chat "question" --expand
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
answers grounded in your vault with sources cited. `--note` scopes to a specific note and offers to save the Q&A. `--save` saves without prompting. `--expand` searches wikipedia when your vault doesn't have enough.
|
|
153
|
+
|
|
154
|
+
> interactive: `--pick` (choose vault note to ask about)
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
### link
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
metis link
|
|
162
|
+
metis link --write
|
|
163
|
+
metis link --verbose
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
discovers connections between notes. `--write` adds links in your vault's style, auto-detected: `[[wikilinks]]` for obsidian and similar apps, `[markdown](links)` for a plain folder (override with `metis config link-style`). `--verbose` explains why notes are connected.
|
|
167
|
+
|
|
168
|
+
> interactive: `--pick` (choose vault note to find connections for)
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
### sync
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
metis sync
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
re-indexes the vault after you edit notes.
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
### reindex
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
metis reindex
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
rebuilds the whole vector index from scratch. run it after changing your
|
|
189
|
+
`embedding_model`: the old vectors live in a different space, so metis refuses
|
|
190
|
+
search/link/health until you reindex.
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## classification & clustering
|
|
195
|
+
|
|
196
|
+
metis learns from your vault to help you organize.
|
|
197
|
+
|
|
198
|
+
**auto-categorization:** when you ingest without `--folder`, metis suggests a folder based on your vault's content. accept, override, or pick from menu. every choice improves future suggestions.
|
|
199
|
+
|
|
200
|
+
**vault health:**
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
metis health
|
|
204
|
+
metis health --misplaced
|
|
205
|
+
metis health --split hermes_folder
|
|
206
|
+
metis health --unique
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
checkup on your vault structure. shows folder alignment, suggests which notes might belong in a different folder, and proposes subfolder splits for large folders.
|
|
210
|
+
|
|
211
|
+
**folder descriptions:**
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
metis folders
|
|
215
|
+
metis folders --edit
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
list folders with their ML descriptions. `--edit` opens in your editor to refine how the classifier understands each folder.
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## config
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
metis config # show current settings
|
|
226
|
+
metis config vault ~/obsidian/my-vault
|
|
227
|
+
metis config folder metis-ingested
|
|
228
|
+
metis config link-style wikilink # or markdown, or auto (default: detect from the vault)
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
for anything not covered above, edit `~/.metis/config.yaml`:
|
|
232
|
+
|
|
233
|
+
```yaml
|
|
234
|
+
# ~/.metis/config.yaml
|
|
235
|
+
|
|
236
|
+
vault_path: ~/obsidian/my-vault
|
|
237
|
+
output_folder: metis-ingested
|
|
238
|
+
|
|
239
|
+
openai:
|
|
240
|
+
# base_url points at any OpenAI-compatible provider.
|
|
241
|
+
# leave empty for OpenAI; set it for OpenRouter, Ollama, a local server, etc.
|
|
242
|
+
base_url: "" # e.g. https://openrouter.ai/api/v1
|
|
243
|
+
chat_model: gpt-4o
|
|
244
|
+
embedding_model: text-embedding-3-small
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
api keys live in your os keychain via `metis secret set`, or a `METIS_*` env var for automation (`METIS_PROVIDER_KEY`, `METIS_EMBEDDING_KEY`, `METIS_X_BEARER`). keys never go in the config file. one key covers both chat and embeddings; set an `embedding-key` only if you split embeddings to a different provider. run `metis doctor` to check your setup: it verifies the key, the provider, the models, and the index in one pass.
|
|
248
|
+
|
|
249
|
+
> changing `embedding_model` re-spaces the whole index. metis will refuse until you run `metis reindex`.
|
|
250
|
+
>
|
|
251
|
+
> on a gateway like OpenRouter, embedding ids are vendor-prefixed; metis auto-adapts the default `text-embedding-3-small` to `openai/text-embedding-3-small`.
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
|
|
2
|
+
<p align="center">
|
|
3
|
+
<img src="https://raw.githubusercontent.com/itsautomata/metis/main/assets/metis_draft.gif" alt="metis" width="330">
|
|
4
|
+
</p>
|
|
5
|
+
|
|
6
|
+
## metis
|
|
7
|
+
a cli second brain for your markdown notes: [obsidian](https://obsidian.md/download) (recommended), an alternative, or just a normal folder.
|
|
8
|
+
|
|
9
|
+
ingest anything. search by meaning. chat with your knowledge. discover connections.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## setup
|
|
14
|
+
|
|
15
|
+
### install
|
|
16
|
+
|
|
17
|
+
**pip.** requires python 3.10+
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install metis-brain
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**uv**
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
uv tool install metis-brain # if you don't have uv installed run: curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
27
|
+
```
|
|
28
|
+
**git (for development):**
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
git clone https://github.com/itsautomata/metis
|
|
32
|
+
cd metis
|
|
33
|
+
uv tool install -e . # global, editable
|
|
34
|
+
uv tool install -e . --force # update the global install
|
|
35
|
+
# or in a virtualenv:
|
|
36
|
+
uv venv && source .venv/bin/activate && uv pip install -e "."
|
|
37
|
+
```
|
|
38
|
+
### upgrade
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
uv tool upgrade metis-brain # installed with uv
|
|
42
|
+
pip install --upgrade metis-brain # installed with pip
|
|
43
|
+
git pull && uv tool install -e . --force # dev / editable clone
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
then set up, whichever way you installed:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
metis init
|
|
51
|
+
metis --install-completion # enable tab completion for commands
|
|
52
|
+
exec $SHELL # restart shell to apply
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
store your api keys securely:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
metis secret set provider-key # your one key (works for any provider via base_url)
|
|
59
|
+
metis secret set x-token # optional, for full x/twitter extraction
|
|
60
|
+
metis secret set # interactive, you pick which key you want to set
|
|
61
|
+
metis secret list # show which keys are set (no values)
|
|
62
|
+
metis doctor # verify the whole setup: key, provider, models, index
|
|
63
|
+
metis models # show the chat + embedding models (and provider) in use
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
quick changes via `metis config vault <path>`. for everything else, edit `~/.metis/config.yaml`.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## commands
|
|
71
|
+
|
|
72
|
+
run `metis --help` or `metis <command> --help` for all options.
|
|
73
|
+
|
|
74
|
+
### ingest
|
|
75
|
+
|
|
76
|
+
save anything to your vault: summarized, tagged, embedded, and linked back to the source.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
metis ingest https://en.wikipedia.org/wiki/Metis_(mythology)
|
|
80
|
+
metis ingest ~/books/project-hail-mary.pdf
|
|
81
|
+
metis ingest lecture-notes.md
|
|
82
|
+
metis ingest paper.pdf --folder research/ai
|
|
83
|
+
metis ingest https://www.youtube.com/watch?v=abc123 --lang fr
|
|
84
|
+
metis ingest https://arxiv.org/abs/2401.12345
|
|
85
|
+
metis ingest paper1.pdf paper2.pdf https://arxiv.org/abs/2402.00001
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
accepts one source or many at once. supports pdfs, urls, markdown, arxiv papers, youtube videos, and x/twitter posts. `--folder` organizes into vault subfolders.
|
|
89
|
+
|
|
90
|
+
> interactive: `--pick-folder` (vault folders) / `--pick-lang` (transcript languages)
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
### search
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
metis search "what role did titans play in greek mythos"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
semantic search. finds by meaning, not keywords. pick a result to chat about it.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
### chat
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
metis chat "how does project hail mary handle the fermi paradox?"
|
|
108
|
+
metis chat "what does he say about nash equilibrium?" --note game_theory/intro
|
|
109
|
+
metis chat "question" --note game_theory/intro --save
|
|
110
|
+
metis chat "question" --expand
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
answers grounded in your vault with sources cited. `--note` scopes to a specific note and offers to save the Q&A. `--save` saves without prompting. `--expand` searches wikipedia when your vault doesn't have enough.
|
|
114
|
+
|
|
115
|
+
> interactive: `--pick` (choose vault note to ask about)
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
### link
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
metis link
|
|
123
|
+
metis link --write
|
|
124
|
+
metis link --verbose
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
discovers connections between notes. `--write` adds links in your vault's style, auto-detected: `[[wikilinks]]` for obsidian and similar apps, `[markdown](links)` for a plain folder (override with `metis config link-style`). `--verbose` explains why notes are connected.
|
|
128
|
+
|
|
129
|
+
> interactive: `--pick` (choose vault note to find connections for)
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
### sync
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
metis sync
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
re-indexes the vault after you edit notes.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
### reindex
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
metis reindex
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
rebuilds the whole vector index from scratch. run it after changing your
|
|
150
|
+
`embedding_model`: the old vectors live in a different space, so metis refuses
|
|
151
|
+
search/link/health until you reindex.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## classification & clustering
|
|
156
|
+
|
|
157
|
+
metis learns from your vault to help you organize.
|
|
158
|
+
|
|
159
|
+
**auto-categorization:** when you ingest without `--folder`, metis suggests a folder based on your vault's content. accept, override, or pick from menu. every choice improves future suggestions.
|
|
160
|
+
|
|
161
|
+
**vault health:**
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
metis health
|
|
165
|
+
metis health --misplaced
|
|
166
|
+
metis health --split hermes_folder
|
|
167
|
+
metis health --unique
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
checkup on your vault structure. shows folder alignment, suggests which notes might belong in a different folder, and proposes subfolder splits for large folders.
|
|
171
|
+
|
|
172
|
+
**folder descriptions:**
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
metis folders
|
|
176
|
+
metis folders --edit
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
list folders with their ML descriptions. `--edit` opens in your editor to refine how the classifier understands each folder.
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## config
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
metis config # show current settings
|
|
187
|
+
metis config vault ~/obsidian/my-vault
|
|
188
|
+
metis config folder metis-ingested
|
|
189
|
+
metis config link-style wikilink # or markdown, or auto (default: detect from the vault)
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
for anything not covered above, edit `~/.metis/config.yaml`:
|
|
193
|
+
|
|
194
|
+
```yaml
|
|
195
|
+
# ~/.metis/config.yaml
|
|
196
|
+
|
|
197
|
+
vault_path: ~/obsidian/my-vault
|
|
198
|
+
output_folder: metis-ingested
|
|
199
|
+
|
|
200
|
+
openai:
|
|
201
|
+
# base_url points at any OpenAI-compatible provider.
|
|
202
|
+
# leave empty for OpenAI; set it for OpenRouter, Ollama, a local server, etc.
|
|
203
|
+
base_url: "" # e.g. https://openrouter.ai/api/v1
|
|
204
|
+
chat_model: gpt-4o
|
|
205
|
+
embedding_model: text-embedding-3-small
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
api keys live in your os keychain via `metis secret set`, or a `METIS_*` env var for automation (`METIS_PROVIDER_KEY`, `METIS_EMBEDDING_KEY`, `METIS_X_BEARER`). keys never go in the config file. one key covers both chat and embeddings; set an `embedding-key` only if you split embeddings to a different provider. run `metis doctor` to check your setup: it verifies the key, the provider, the models, and the index in one pass.
|
|
209
|
+
|
|
210
|
+
> changing `embedding_model` re-spaces the whole index. metis will refuse until you run `metis reindex`.
|
|
211
|
+
>
|
|
212
|
+
> on a gateway like OpenRouter, embedding ids are vendor-prefixed; metis auto-adapts the default `text-embedding-3-small` to `openai/text-embedding-3-small`.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.27"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "metis-brain"
|
|
7
|
+
description = "CLI second brain for your markdown notes"
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
license = "MIT"
|
|
10
|
+
license-files = ["LICENSE"]
|
|
11
|
+
authors = [{ name = "itsautomata" }]
|
|
12
|
+
requires-python = ">=3.10"
|
|
13
|
+
dynamic = ["version"]
|
|
14
|
+
keywords = ["second-brain", "obsidian", "markdown", "cli", "rag", "embeddings", "knowledge-base", "semantic-search", "note-taking"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 4 - Beta",
|
|
17
|
+
"Environment :: Console",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Topic :: Utilities",
|
|
25
|
+
"Topic :: Text Processing :: Indexing",
|
|
26
|
+
]
|
|
27
|
+
dependencies = [
|
|
28
|
+
"typer>=0.15.0",
|
|
29
|
+
"rich>=13.0.0",
|
|
30
|
+
"pyyaml>=6.0",
|
|
31
|
+
"openai>=1.0.0",
|
|
32
|
+
"chromadb>=0.6.0",
|
|
33
|
+
"pymupdf>=1.24.0",
|
|
34
|
+
"httpx>=0.27.0",
|
|
35
|
+
"trafilatura>=1.12.0",
|
|
36
|
+
"lxml-html-clean>=0.4.0",
|
|
37
|
+
"youtube-transcript-api>=1.0.0",
|
|
38
|
+
"keyring>=25.0.0",
|
|
39
|
+
"questionary>=2.0.0",
|
|
40
|
+
"scikit-learn>=1.5.0",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[project.optional-dependencies]
|
|
44
|
+
test = [
|
|
45
|
+
"pytest>=8.0.0",
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
[project.scripts]
|
|
49
|
+
metis = "metis.cli:app"
|
|
50
|
+
|
|
51
|
+
[project.urls]
|
|
52
|
+
Homepage = "https://github.com/itsautomata/metis"
|
|
53
|
+
Repository = "https://github.com/itsautomata/metis"
|
|
54
|
+
Issues = "https://github.com/itsautomata/metis/issues"
|
|
55
|
+
|
|
56
|
+
# suppress chromadb's SWIG deprecation warnings in test output
|
|
57
|
+
[tool.pytest.ini_options]
|
|
58
|
+
filterwarnings = ["ignore::DeprecationWarning"]
|
|
59
|
+
|
|
60
|
+
[tool.hatch.version]
|
|
61
|
+
path = "src/metis/__init__.py"
|
|
62
|
+
|
|
63
|
+
[tool.hatch.build.targets.wheel]
|
|
64
|
+
packages = ["src/metis"]
|
|
65
|
+
|
|
66
|
+
[tool.hatch.build.targets.sdist]
|
|
67
|
+
include = [
|
|
68
|
+
"/src",
|
|
69
|
+
"/tests",
|
|
70
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
architecture with love. automata.
|