I built a self-hosted AI workspace for macOS — meet Odysee A developer built Odysee, a self-hosted AI workspace for macOS that packages a FastAPI-based local LLM interface into a native macOS app bundle and DMG. The app supports multiple LLM providers including LM Studio, Ollama, and OpenAI, along with document RAG, email triage, and calendar sync features. Odysee uses pywebview to display the web UI in a native macOS window and includes a cleanup mechanism that terminates all child processes when the window closes. I've been running Odysseus https://github.com/pewdiepie-archdaemon/odysseus as my daily-driver AI interface — local LLMs, document RAG, email triage, calendar sync. It's a web-based FastAPI app that works great in the browser, but I wanted a proper macOS app I could launch from my dock and distribute as a DMG. So I built one. Here's what the app does and how I packaged it. | Layer | Tool | |---|---| | Web framework | FastAPI Python 3.11 | | Frontend | Vanilla JS + CSS PWA | | LLM providers | LM Studio, Ollama, DeepSeek, SiliconFlow, OpenAI, Anthropic | | Vector store | ChromaDB + fastembed | | Model serving | llama.cpp / vLLM | | macOS app | Shell launcher + pywebview + DMG | The base project already had a build-macos-app.sh script, but I rewrote it to produce a proper .app bundle and .dmg that anyone can build: ./build-macos-app.sh This creates two things: 1. dist/Odysseus.app — A macOS app bundle. The executable is a shell script that: uvicorn app:app 2. dist/Odysseus.dmg — A drag-to-Applications disk image for distribution. The .app is just a launcher — no embedded Python, no bundled binary. It drives the venv in the repo directory. The key piece is scripts/app window.py , which uses pywebview to open the web UI in a native macOS window — no browser chrome, feels like a real app. If pywebview isn't available, it falls back to opening a chromeless Chromium window via --app= . Closing the window stops everything: the web server, ChromaDB, all child processes. The cleanup trap in the launcher script makes sure no stray Python processes are left behind. Odysee/ ├── app.py FastAPI entry point ├── src/ Core logic │ ├── llm core.py Multi-provider LLM abstraction │ ├── agent loop.py Agent execution loop │ ├── chat handler.py Chat processing │ ├── model discovery.py Auto-detect local models │ └── mcp manager.py MCP server management ├── routes/ API endpoints ├── services/ Background services ├── static/ Frontend JS/CSS/HTML ├── scripts/ CLI tools + app window.py ├── tests/ ~350 tests └── data/ Created on first run uvicorn app:app --host 127.0.0.1 --port 7860 The flask-style backend runs on localhost:7860. The frontend is vanilla JS with no build step — just open index.html and it works. git clone https://github.com/AlexDesign420/Odysee-MacOS-App.git cd Odysee-MacOS-App python3.11 -m venv venv source venv/bin/activate pip install -r requirements.txt python setup.py ./venv/bin/uvicorn app:app --host 127.0.0.1 --port 7860 Open http://127.0.0.1:7860 http://127.0.0.1:7860 . First boot creates an admin account. To build the macOS app: ./build-macos-app.sh open dist/Odysseus.dmg GitHub: AlexDesign420/Odysee-MacOS-App https://github.com/AlexDesign420/Odysee-MacOS-App