Skip to content

Getting Started

Eric Mey edited this page Apr 21, 2026 · 1 revision

Getting Started

This page walks you from zero to a local Musubi running on your laptop. For production deployment see Deployment Guide (coming soon).

Prerequisites

  • 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

1. Clone and install

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.

2. Run the backing services

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-instruct

TEI 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.

3. Configure

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 secrets

Key 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:11434 and qwen2.5:7b-instruct are 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

4. Bootstrap Qdrant collections

uv run python -m musubi.store.bootstrap

This creates the musubi_episodic, musubi_concept, musubi_curated, musubi_artifact, and musubi_thought collections with the right vector specs + payload indexes.

5. Run the API

uv run uvicorn musubi.api.app:app --host 0.0.0.0 --port 8100

The API is now reachable at http://localhost:8100. Sanity check:

curl http://localhost:8100/v1/ops/health
# → {"status":"ok","version":"v0"}

6. Run the lifecycle worker (optional)

In a separate terminal:

uv run python -m musubi.lifecycle.runner

This 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.

7. Capture your first memory

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.

Auth

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.

Common problems

  • "Collection already exists" — rerun with uv run python -m musubi.store.bootstrap --force-recreate or 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 list to confirm the model is pulled; some systems need OLLAMA_HOST=0.0.0.0 to accept non-localhost connections.
  • make check fails on mypy — make sure you ran make install in the current clone, not a stale venv.

Next steps

  • 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.

Home

Getting started

Operating

  • Deployment Guide (TBD)
  • The Lifecycle (TBD)
  • Supply Chain & Verification (TBD)

Building

  • SDK Guide (TBD)
  • Adapters (TBD)
  • Writing a new plane (TBD)

Reference

Community

Clone this wiki locally