-
Notifications
You must be signed in to change notification settings - Fork 1
Getting Started
This page walks you from zero to a local Musubi running on your laptop. For production deployment see Deployment Guide (coming soon).
-
Python 3.12 —
python --version -
uv — modern Python package manager; installs with
curl -LsSf https://astral.sh/uv/install.sh | sh - Docker + Docker Compose — for Qdrant, TEI, Ollama
- ~20 GB disk — models + vector store
- A GPU (optional but recommended) — CPU-only works for testing; TEI + Ollama both run ~10× slower without one
git clone https://github.com/ericmey/musubi && cd musubi
make install # uv sync --extra dev
make check # fmt + lint + typecheck + full test suite (~30s)If make check comes back green, the core code is fine on your machine.
Musubi needs four containers: Qdrant (vector store), three TEI instances (dense, sparse, reranker), and Ollama (LLM). The production deploy uses Ansible against a managed host; for local development the simplest path is to pull the same containers manually:
# Qdrant
docker run -d --name qdrant \
-p 6333:6333 \
qdrant/qdrant:v1.17.1
# Ollama + a small default model
docker run -d --name ollama \
-p 11434:11434 \
ollama/ollama:latest
docker exec ollama ollama pull qwen2.5:7b-instructTEI is fiddlier because each embedder needs its own port and model. A full-stack Docker Compose template is at deploy/ansible/templates/docker-compose.yml.j2 — it's Jinja-parametrised for Ansible, but you can copy it, hand-fill the {{ ... }} placeholders with local values, and docker compose up.
A fully self-contained, un-parametrised docker-compose.yml for local dev is on the roadmap — track the discussion or open an issue if you want to push it up.
Musubi reads everything from a .env file at the project root or env vars. Copy the example:
cp .env.example .env
# Edit .env with your Qdrant / Ollama / TEI URLs and secretsKey settings:
-
MUSUBI_QDRANT_HOST/MUSUBI_QDRANT_PORT— where Qdrant is -
MUSUBI_QDRANT_API_KEY— set this even for local use; Qdrant rejects cross-origin without it -
MUSUBI_TEI_DENSE_URL/MUSUBI_TEI_SPARSE_URL/MUSUBI_TEI_RERANKER_URL— the three TEI endpoints -
MUSUBI_OLLAMA_URL+MUSUBI_LLM_MODEL—http://localhost:11434andqwen2.5:7b-instructare sane defaults -
MUSUBI_VAULT_PATH— where the Obsidian curated vault lives on disk; even a scratch dir works for testing -
MUSUBI_JWT_SIGNING_KEY— any 32+ char secret for local dev
uv run python -m musubi.store.bootstrapThis creates the musubi_episodic, musubi_concept, musubi_curated, musubi_artifact, and musubi_thought collections with the right vector specs + payload indexes.
uv run uvicorn musubi.api.app:app --host 0.0.0.0 --port 8100The API is now reachable at http://localhost:8100. Sanity check:
curl http://localhost:8100/v1/ops/health
# → {"status":"ok","version":"v0"}In a separate terminal:
uv run python -m musubi.lifecycle.runnerThis boots the tick-driven scheduler and registers all five sweeps (maturation hourly, synthesis 03:00 UTC, promotion 04:00, demotion 05:00, reflection 06:00). Nothing will fire immediately unless your wall-clock lands on one of those times — the scheduler logs its job registry at startup so you can confirm wiring.
curl -X POST http://localhost:8100/v1/capture \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <JWT — see auth below>" \
-d '{
"namespace": "eric/default/episodic",
"content": "Musubi running locally on 2026-04-21.",
"tags": ["setup", "milestone"]
}'Queries come back via POST /v1/retrieve. See the OpenAPI spec for the full API surface.
Local dev can use a pre-signed JWT. The fast path:
uv run python -c "
from musubi.config import get_settings
import jwt, time
s = get_settings()
print(jwt.encode(
{'sub': 'dev', 'iat': int(time.time()), 'exp': int(time.time())+86400},
s.musubi_jwt_signing_key.get_secret_value(),
algorithm='HS256',
))
"For production, use a real token issuer.
-
"Collection already exists" — rerun with
uv run python -m musubi.store.bootstrap --force-recreateor drop the collection in Qdrant. - TEI returns 500 on embed — model download is slow on first start; wait 3-5 minutes and retry.
-
Ollama connection refused —
docker exec ollama ollama listto confirm the model is pulled; some systems needOLLAMA_HOST=0.0.0.0to accept non-localhost connections. -
make checkfails onmypy— make sure you ranmake installin the current clone, not a stale venv.
- Architecture Overview — understand why the system is shaped this way
- The Lifecycle (coming soon) — what happens to your capture over the next 48 hours
- Adapters (coming soon) — connecting MCP / LiveKit / OpenClaw agents
If you get stuck, the fastest way to get help is a post in Discussions.
Musubi • Apache 2.0 licensed • Report a vulnerability • 結び — to tie, to join, to bind
- Deployment Guide (TBD)
- The Lifecycle (TBD)
- Supply Chain & Verification (TBD)
- SDK Guide (TBD)
- Adapters (TBD)
- Writing a new plane (TBD)