metis manual

metis is a command-line second brain that feeds off anything you save. you give it a link or a file (a web page, PDF, youtube video, paper…), and it reads it, writes a clean summary into your notes folder, tags and files it, and then lets you search your notes by meaning and chat with them. it works on any folder of markdown files and pairs naturally with obsidian. everything it writes is a normal markdown file you own, so nothing is locked in.

the basic flow:

metis init                                           # one-time guided setup (vault, provider, key)
metis ingest https://en.wikipedia.org/wiki/Athena    # save a page: summarized, tagged, filed
metis search "what was athena the goddess of"        # find it by meaning, not exact words
metis chat "give me bullet point on greek mythology"     # ask your own notes a question

installation

metis needs python 3.10+. the PyPI package is metis-brain.

install metis in an isolated environment so its dependencies never collide with your other python packages. uv tool and pipx do that for you and put metis on your PATH, so you can run it from any folder.

installs metis in its own isolated environment, always on your PATH.

uv tool install metis-brain      # no uv yet? curl -LsSf https://astral.sh/uv/install.sh | sh

pipx

same isolation as uv, if you already use pipx.

pipx install metis-brain

pip (manual virtualenv)

pip installs into the current environment, so isolate it in a venv:

python3 -m venv .venv
source .venv/bin/activate        # windows: .venv\Scripts\activate
pip install metis-brain

caveat: a venv-installed metis only works while that venv is active. uv tool install and pipx avoid this (isolated and always on your PATH), which is why they are preferred for everyday use.

git clone (development)

for working on the metis code itself: an editable install reflects your source edits without reinstalling.

git clone https://github.com/itsautomata/metis
cd metis
uv tool install -e .             # global editable install (metis on your PATH)
uv tool install -e . --force     # update an existing global editable install
# or inside a venv:
uv venv && source .venv/bin/activate && uv pip install -e "."

then, however you installed

metis init                       # guided setup (vault, provider, key, models)
metis --install-completion       # tab completion for your current shell (run once per shell you use)
exec $SHELL                      # restart the shell to apply completion

upgrade

use the command that matches how you installed:

uv tool upgrade metis-brain                 # installed with uv
pipx upgrade metis-brain                    # installed with pipx
pip install --upgrade metis-brain           # installed with pip (venv active)
git pull && uv tool install -e . --force    # dev / git clone

uninstall

uv tool uninstall metis-brain    # uv (also removes the editable dev install)
pipx uninstall metis-brain       # pipx
pip uninstall metis-brain        # pip (venv active)

completion is separate: metis has no built-in uninstall for it, so to remove tab completion delete the file typer installed (~/.zfunc/_metis for zsh, ~/.bash_completions/metis.sh + its source line in ~/.bashrc for bash, ~/.config/fish/completions/metis.fish for fish).

setup

store api keys

metis secret set provider-key    # the LLM/embedding provider key (openai, openrouter, ...)
metis secret set embedding-key   # optional, only if embeddings run on a different provider
metis secret set x-token         # optional, for full X/twitter extraction
metis secret set                 # interactive: pick which key to set
metis secret list                # show which keys are set (no values)

keys are stored in your OS keychain (encrypted). also reads from env vars (METIS_PROVIDER_KEY, METIS_EMBEDDING_KEY, METIS_X_BEARER) or config file as fallback.

configure

quick changes via the config command:

metis config                     # show current settings (vault, folder, base_url)
metis config vault ~/obsidian/my-vault
metis config folder metis-ingested

the provider is set by openai.base_url in ~/.metis/config.yaml (empty = OpenAI):

vault_path: ~/obsidian/my-vault
output_folder: metis-ingested
openai:
  base_url: ""                   # "" = openai; or https://openrouter.ai/api/v1, ollama, etc.
  chat_model: gpt-4o
  embedding_model: text-embedding-3-small

metis init adds missing config sections automatically, without overwriting your settings.


commands

at a glance (run metis <command> --help for the full options of any one):

commandwhat it does
ingestsave a url, file, video, or tweet into your notes: summarized, tagged, filed, and searchable
searchfind notes by meaning, not exact keywords
chatask a question and get an answer built from your own notes, with sources cited
linkdiscover (and optionally write) connections between related notes
syncre-index after you add or edit notes by hand (in obsidian, say)
reindexrebuild the whole search index from scratch (after changing the embedding model)
initone-time guided setup
configview or change settings (vault path, folder, provider, link style)
secretstore your api keys safely in the OS keychain
modelsshow which models and provider are in use, and where the key comes from
doctorcheck the whole setup and print a ✓/✗ report
folderslist or edit the folder descriptions that metis uses to auto-file notes
healthcheck your vault’s structure: misplaced notes, folders worth splitting

global flags (place before the command, e.g. metis --yes reindex):

metis ingest

metis ingest https://en.wikipedia.org/wiki/Prometheus
metis ingest ~/books/the-odyssey.pdf
metis ingest oracle-of-delphi.md
metis ingest https://arxiv.org/abs/2401.12345
metis ingest https://www.youtube.com/watch?v=abc123
metis ingest https://www.youtube.com/watch?v=abc123 --pick-lang
metis ingest https://x.com/user/status/123456789
metis ingest bulfinch-mythology.pdf --folder myths/olympians
metis ingest iliad.pdf odyssey.pdf https://arxiv.org/abs/2402.00001   # batch

what happens (one command, and metis does the rest). it reads the source, understands it, and files a clean note in a single pass:

  1. checks whether this was saved before, and offers to update or skip if so
  2. extracts the text, auto-detecting the source type (PDF, web page, video, and so on)
  3. summarizes it and pulls out tags and key points
  4. sanitizes the model output, rejecting anything that looks unsafe
  5. splits the text so search can pinpoint the right passage
  6. turns each passage into a numeric fingerprint of its meaning (an embedding), which is what lets search match by meaning instead of exact words
  7. if that embedding step fails, the vault is left untouched: nothing is half-written
  8. writes a markdown note with tags, and a summary and a link back to the source
  9. remembers it, so saving the same source again is caught as a duplicate

supported sources: pdf, url, markdown, arxiv, youtube, X/twitter

folder:

batch: pass multiple sources in one call: each is ingested in sequence with a (n/total) progress marker.

youtube options:

youtube playlists: pass a playlist URL and metis lists the videos in a multi-select menu: space toggles, enter confirms to select which videos you want. each chosen video is then ingested through the normal pipeline. --yes ingests all; off a terminal without --yes, the playlist is skipped with a warning (other sources still ingest).

metis ingest "https://www.youtube.com/playlist?list=PLxxxx"          # pick which videos
metis ingest "https://www.youtube.com/watch?v=abc123&list=PLxxxx"    # video preselected
metis ingest --yes "https://www.youtube.com/playlist?list=PLxxxx"    # all videos

X/twitter: by default it grabs the single tweet. add an X access token to your config to pull full articles and threads.

no duplicates: ingesting the same URL twice shows “already ingested. update?” instead of creating duplicates.


metis search "which titans fought the olympians"
metis search "greek heroes" -n 10

semantic search: finds by meaning, not keywords. returns top results with similarity scores and a text preview, one per note (the best-matching passage).


metis chat

metis chat                                       # interactive chat session (back-and-forth)
metis chat "how did the trojan war begin?"
metis chat "what was athena the goddess of?" --note olympians/athena
metis chat "question" --note olympians/athena --save
metis chat "question" --expand
metis chat "what was athena the goddess of?" --pick

vault chat:

note-scoped chat (--note, --pick):

save Q&A (--save):

expand (wikipedia):


metis link                          # scan all notes
metis link olympians/athena         # connections for one note
metis link --pick                   # pick the note interactively
metis link --write                  # write [[wikilinks]] to files
metis link --verbose                # explain why notes are connected
metis link --min-score 0.5          # lower threshold for weaker connections

finds connections between notes you didn’t manually link. compares embeddings, surfaces nearest neighbors. pass a note path (or --pick, -p) to scope to one note; omit to scan the whole vault.

—write: inserts ## Connections section before Transcript/Content with [[wikilinks]]. obsidian graph view picks these up.

—verbose: explains the relationship in one sentence. terminal output only, not written to the note.

output shows folder paths for context: olympians/athena → heroes/odysseus [0.82]


metis sync

metis sync

re-indexes vault after you edit notes in obsidian.

run after deleting duplicate notes or editing content manually.


metis reindex

metis reindex
metis reindex --dry-run          # preview how many notes would re-embed, no provider calls

rebuilds the entire index from scratch. use after changing the embedding model in config.yaml, since old vectors live in a different space and cannot be compared to new ones.


metis secret

metis secret set provider-key    # prompts securely, stores in keychain
metis secret set embedding-key
metis secret set x-token
metis secret set                 # interactive: pick which key to set
metis secret list                # show which keys are set (no values)
metis secret delete provider-key # removes from keychain

manages API keys in the OS keychain. lookup chain: keychain → env var → config file.

actions: set, delete, list. key names: provider-key, embedding-key, x-token.

note: list reports on the keychain only. a key provided via env var or config file still works but shows as not set.


metis init

metis init                       # guided wizard (on a terminal)
metis --no-input init            # write defaults, no prompts (CI)
metis --yes init                 # accept every default

on a terminal, runs a guided wizard for the vault path, provider, api key, and models, then creates the config and directories. adds missing sections to an existing config without overwriting your settings. with --no-input or --yes, it writes defaults without prompting (for CI).


metis config

metis config                        # show current settings
metis config vault ~/obsidian/my-vault
metis config folder metis-ingested
metis config link-style wikilink    # wikilink, markdown, or auto (default: detect from the vault)

view or change settings without editing the yaml. keys: vault, folder, link-style (validated: an unknown key is rejected at parse time).

settings not covered by these keys (base_url, chat/embedding models, chromadb path) require editing the yaml directly.


metis models

metis models

shows the resolved chat and embedding models, their provider endpoints, the key source, and whether the index was built with the current embedding model.


metis doctor

metis doctor
metis doctor --json              # emit the checklist as JSON

validates the setup and prints a ✓/✗ checklist: key source, chat model, embedding model, index stamp, and an embedding-drift check. exits non-zero if anything is off. --json emits the same checklist as machine-readable JSON.


metis folders

metis folders                       # list all folders with descriptions
metis folders olympians             # list one folder
metis folders --edit                # edit all descriptions in $EDITOR
metis folders olympians --edit      # edit one folder's description
metis folders --edit --pick         # pick the folder from a menu, then edit it

lists every vault folder with its note count and auto-generated description. descriptions drive auto-categorization: they are the text metis embeds to match new notes against folders.

arguments:

options:


metis health

metis health                        # folder alignment overview
metis health --misplaced            # notes that cluster with a different folder
metis health --split olympians      # propose a 2-way split for a folder
metis health --unique               # notes that don't cluster with anything

vault structure checkup. metis groups the notes by similarity (clustering over their embeddings) to spot folders that have drifted into holding several unrelated topics, and notes that seem out of place.

needs 2+ notes to analyze. these are suggestions only: health never moves or edits files.


obsidian integration

metis notes are native obsidian citizens:

recommended obsidian setup:


config reference

~/.metis/config.yaml:

keydefaultdescription
vault_path~/obsidian/vaultpath to obsidian vault
output_foldermetis-ingesteddefault subfolder for ingested content
openai.base_url""provider endpoint; "" = OpenAI, else OpenRouter/Ollama/custom URL
openai.chat_modelgpt-4ochat/summary model id
openai.embedding_modeltext-embedding-3-smallembedding model id
x_api.bearer_token""optional, for full X article extraction
chromadb.path~/.metis/chromadblocal vector store

vault_path and output_folder can also be set via metis config <key> <value> (as vault/folder). the rest require editing the yaml.

api keys: metis secret set <name> (keychain) or env vars (METIS_PROVIDER_KEY, METIS_EMBEDDING_KEY, METIS_X_BEARER).


environment variables

variableused bypurpose
METIS_PROVIDER_KEYall LLM/embedding callsprovider api key (fallback after keychain)
METIS_EMBEDDING_KEYembedding callsseparate embedding-provider key (fallback after keychain)
METIS_X_BEARERX/twitter ingestX api bearer token (fallback after keychain)
METIS_ACCESSIBLEinteractive pickersset to 1 to use numbered/typed prompts instead of arrow-key menus (also honors ACCESSIBLE)
VISUALfolders --editpreferred editor for folder descriptions
EDITORfolders --editeditor fallback when VISUAL is unset (then nano)

running tests

uv run --extra test pytest tests/ -q

tests covering: extraction, chunking, config, writing, dedup, chat Q&A, query simplification, secrets fallback chain, path traversal security, embedding-drift detection, youtube canonicalization and playlists, shell completion, markup escaping, title-boosted ranking, and concurrency-safe sidecar writes.