Record a meeting. Get a clean transcript, a sharp summary, and your action items β all on your own hardware.
Parley is a self-hosted meeting recorder and AI notebook. It captures audio, transcribes it with speaker labels, cleans it up, and runs a multi-pass analysis that pulls out the summary, decisions, action items, risks, and figures β then files them next to a full Obsidian-style notes & tasks workspace. No cloud. No API keys. No subscription. Your conversations never leave your machine.
![]() |
![]() |
![]() |
![]() |
Meeting-AI tools are everywhere β but they ship your most sensitive conversations to someone else's servers and bill you monthly for the privilege. Parley does the opposite:
- It's yours. Runs entirely on your own hardware against local models (Ollama, Parakeet + pyannote, Qdrant). Nothing is uploaded anywhere.
- It's honest about your data. Notes and meetings are plain Markdown files on disk β open them in Obsidian, grep them, back them up, leave any time.
- It actually does the work. Not just a transcript dump: speaker identification, transcript cleanup, a six-pass analysis, auto-tagging, and semantic links between your notes and the meetings they relate to.
- It's a notebook, not just a recorder. A real CodeMirror editor with wiki-links, backlinks, a tasks dashboard, file attachments, and a built-in sketch canvas.
Built for a homelab, in the spirit of Immich and Paperless: self-hosted, private, and genuinely pleasant to use.
- Upload (or record) audio β transcription with speaker diarization (
SPEAKER_00, β¦). - LLM transcript cleanup β fixes ASR mishearings, acronyms and punctuation while preserving every word.
- Speaker identification β infers real names and roles from what people actually say.
- A six-pass analysis (structured JSON, enforced) extracting: title & summary, topics, action items, decisions & open questions, concerns & risks, key figures, and sentiment.
- Auto-tagging β category, keywords, and entities (people / companies / projects / tech / dates).
- Hierarchical summarisation for long meetings and cross-meeting insights across a set.
- Semantic search and a RAG chat β ask questions across everything you've recorded.
- Markdown notes with a CodeMirror 6 editor: headings, checkboxes,
[[wiki-links]]+ backlinks, autocomplete, live preview. - Voice dictation β a mic button on the tasks quick-add box and in the notes editor transcribes speech locally and drops it straight into the text; notes are silently auto-polished by a local LLM a few seconds after you stop talking, with a byte-for-byte safety check so it never clobbers a hand-edit.
- A Kanban task board (To-do / Doing / Done) with drag-and-drop, plus a full-CRUD list view grouped by due date, owner, or priority. Meeting action items land right alongside your own tasks.
- AI quick-add β type a task in plain English ("chase John about the contract next Friday, high priority") and an LLM triages it into title / owner / due date / priority for you to confirm.
- A daily task digest email and an ICS calendar feed so due dates show up in your own calendar app.
- Automatic linking between notes and the meetings they relate to (and back again).
- File attachments (drag / drop / paste) and a built-in SVG sketch canvas.
- Installable PWA with an offline app shell and a light/dark theme.
ββββββββββββββββ audio βββββββββββββββββββββ
browser βββΆβ Parley β ββββββββββββββββΆ β Parakeet + pyannoteβ speech-to-text
(PWA) β (FastAPI) β βββββββββββββββββββββ + diarization
β β ββ prompts βββββΆ ββββββββββββββ
β β embeddings β Ollama β LLM + embeddings
β β ββββββββββββββββΆ ββββββββββββββ
β β ββ vectors βββββΆ ββββββββββββββ
ββββββββββββββββ β Qdrant β semantic search
ββββββββββββββ & auto-linking
Your meetings and notes are plain files on disk (MEETINGS_DIR, NOTES_DIR) β portable and Obsidian-compatible. Vector indexing is best-effort and off the request path, so the UI stays snappy.
Parley runs entirely on local Ollama out of the box β that's the whole point. But the AI backends are swappable:
- Analysis & embeddings (transcript cleanup, the six-pass extraction, auto-tagging, summaries, semantic search) run on your local Ollama models. OpenWebUI is not required β it's only an optional alternative backend for the chat box.
- Chat ("ask your meetings") can point at Ollama (default), an existing OpenWebUI instance, or any OpenAI-compatible endpoint β so you can use a different local server, or a cloud model, just for chat if you want.
- Transcription uses your local Parakeet (STT, OpenAI-compatible endpoint) + pyannote.audio (speaker diarization) β point
PARAKEET_URL/DIARIZER_URLat your own instances, or swap in any endpoint that speaks the same contract.
Nothing leaves your machine unless you explicitly configure the chat box to use a remote endpoint.
You'll need Docker, an Ollama instance (with an LLM such as qwen3:14b and an embedding model like qwen3-embedding:0.6b), a Qdrant instance, and Parakeet (STT) + pyannote (diarization) endpoints for transcription. (Notes & Tasks work without them β they're only needed to transcribe audio.)
git clone https://github.com/craiglush/parley.git
cd parley
cp .env.example .env # point URLs/models at your stack
cp docker-compose.example.yml docker-compose.yml
docker compose up -d --build
# open http://localhost:8191Ollama usually runs natively on the host β reach it from the container via host.docker.internal.
Everything is environment variables (see .env.example):
| Variable | Default | Purpose |
|---|---|---|
OLLAMA_URL |
http://host.docker.internal:11434 |
Ollama base URL |
OLLAMA_MODEL |
qwen3:14b |
LLM for analysis / cleanup / chat (also selectable at runtime from a dropdown of installed models) |
EMBEDDING_MODEL |
qwen3-embedding:0.6b |
Embedding model (1024-dim) |
QDRANT_URL |
http://qdrant:6333 |
Qdrant base URL |
PARAKEET_URL |
http://parakeet-asr:5092 |
Speech-to-text endpoint (OpenAI-compatible) |
PARAKEET_MODEL |
istupakov/parakeet-tdt-0.6b-v3-onnx |
Parakeet model tag |
DIARIZER_URL |
http://pyannote-diarizer:8000 |
Speaker diarization endpoint |
OPENWEBUI_URL / OPENWEBUI_API_KEY |
β | Optional: route chat via an OpenWebUI instance |
MEETINGS_DIR / NOTES_DIR |
/data/meetings /data/notes |
Data dirs (mount as volumes) |
MAX_UPLOAD_SIZE |
524288000 |
Max upload size (bytes) |
ALLOWED_CORS_ORIGINS / ALLOWED_FRAME_ORIGINS |
* |
CORS / iframe embedding |
Prompts, model, temperature, and the STT / diarization toggle are also editable at runtime in the in-app settings (persisted to MEETINGS_DIR/settings.json).
The CodeMirror 6 editor ships as a prebuilt offline bundle (static/vendor/codemirror.bundle.js, already included). To rebuild it:
cd frontend-build
npm install
node build.mjs # β ../static/vendor/codemirror.bundle.jspip install -r requirements.txt
python -m pytest tests/ -qapp.py FastAPI app: routes + the meeting pipeline
llm.py Ollama prompt/response helpers (num_ctx sizing, JSON parsing, think:false)
stt.py Parakeet + pyannote HTTP client + audio pre-processing
vector.py Qdrant + Ollama embeddings (meetings collection)
notes_store.py Notes CRUD (.md + frontmatter), folders, trash, attachments, auto-tags
notes_vectors.py Notes semantic index (separate Qdrant collection)
tasks_store.py GFM-checkbox + inline-metadata task parsing / rollup / CRUD
storage.py Pure helpers (artifact IDs, SRT, atomic writes)
static/ Vanilla-JS PWA (index.html, app.js, notes-tasks.*, service worker, icons)
frontend-build/ esbuild source for the CodeMirror bundle (host-only, not shipped in the image)
tests/ pytest suite
FastAPI Β· Ollama Β· Parakeet Β· pyannote.audio Β· Qdrant Β· a dependency-light vanilla-JS PWA Β· and CodeMirror 6, marked, and DOMPurify (all MIT) for the editor.
MIT Β© 2026 craiglush β do what you like, no warranty.



