Max Headbox: a voice agent that lives on the Pi, not in a datacenter
Tiny truly local voice-activated LLM Agent that runs on a Raspberry Pi
At a glance
- What is it?
- Max Headbox is a GPL-3.0 voice-activated LLM agent that runs entirely on a Raspberry Pi 5, with a React front end talking straight to Ollama and a small Express and Python layer for microphone and transcription work. It is a hobbyist-grade desktop companion, and the README is candid about the trade-offs baked into that choice.
- Who is it for?
- Adopt Max Headbox if you already own a Raspberry Pi 5 with 8GB or more, an active cooler, and roughly 6GB of RAM to spare for local models, and you want a spoken interface to Pi hardware rather than a cloud assistant. Skip it if you need a supported product with releases, a documented API surface, or predictable latency: there are no tagged releases in the repository metadata, the README documents no test suite or versioning scheme, and the model choice is left to you.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 43 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem Max Headbox solves: a spoken agent with no network round trip
Most voice assistants are thin clients. You speak, audio leaves the machine, a remote model answers, and the reply comes back. Max Headbox inverts that. The README states the project operates 100% locally on-device, which the author frames as eliminating reliance on cloud-based AI providers. The stated audience is narrow and concrete: someone with a Raspberry Pi 5 who wants an animated character on a small screen that listens for voice commands and can act on the Pi itself. The repository topics point at the same target, listing raspberry-pi-5, gemma3, qwen3 and agentic-ai alongside express and react. This is not a library you import into a service. It is an appliance you assemble, and the hardware section reads like a parts list rather than a compatibility matrix: a Pi 5, a microphone, and an optional screen, case and cooler bundle. The README adds a useful escape hatch, noting that if you do not want the exact box form factor you can run it anywhere as long as about 6GB is available for the LLMs. That sentence is the real specification. Everything else in the project is arranged around fitting a language model, a speech recogniser and a transcription model into a single-board computer's memory.
Architecture: React talks to Ollama, Express and Python touch the hardware
The split is unusual enough that the README devotes an FAQ entry to defending it. The front end holds the agent logic. The README says the author wanted the web app to be the most important part of the project, containing the logic of the actual Agent, and thought of the Express plus Python backend layer only for interacting with Raspberry Pi hardware such as the microphone and transcription services. The consequence is that the browser connects directly to Ollama. The .env file carries a separate VITE_OLLAMA_URL, so the model endpoint is configured independently of the application backend, and the README notes you must specify Ollama's network address if it runs on a different device. That design has a practical benefit the author calls out: the backend could easily be rewritten in a different stack and reconnected to the front end, which is exactly what happened when the original Ruby Sinatra version was replaced. A recent update dated 9/3/2026 confirms the backend was rewritten in Express.js and that Ruby is no longer needed. The cost is that the agent's reasoning loop lives in client-side JavaScript, so anything you want the Pi to do has to be exposed as a REST route before the front end can reach it.
Voice pipeline: Vosk for wake, faster-whisper for transcription
Two separate speech components are listed under external resources, and they do different jobs. Vosk handles voice activation, meaning the always-listening trigger. faster-whisper handles transcription of the actual command. That division matters on a Pi because a wake-word detector can run continuously at low cost while the heavier transcription model only spins up after activation. The README does not specify which Vosk model or which faster-whisper size is used, and it does not state latency figures for either stage. It links to an external video tutorial for setting faster-whisper up locally rather than documenting the install inline, which means the transcription half of the pipeline depends on a resource outside the repository. Recording defaults to /dev/shm/whisper_recordings, a tmpfs path, so audio clips are held in RAM rather than written to the SD card. The README notes this is configurable through RECORDINGS_DIR for development on another OS. That default is a sensible choice for card longevity, but it also means recordings consume the same memory budget the models need, and on an 8GB board that budget is not generous.
Getting it running: clone, two package managers, three env variables
The setup sequence assumes Node 22, Python 3 and Ollama are already present. Clone the repository and install Node dependencies with nvm use followed by npm install. Then move into backend/ and run pip3 install -r requirements.txt. Models come from Ollama: the README gives ollama pull gemma3:1b and ollama pull gemma4:e2b. If Ollama runs on another machine, the README shows enabling network exposure with sudo systemctl edit ollama.service, adding Environment="OLLAMA_HOST=0.0.0.0" under [Service], then running sudo systemctl daemon-reload && sudo systemctl restart ollama. Configuration lives in .env with three keys: VITE_BACKEND_URL and VITE_WEBSOCKET_URL, which share an address because the WebSocket app also runs on Express, and VITE_OLLAMA_URL. The README's example values use port 4567 for the backend and WebSocket, and 11434 for Ollama. Start it with npm run prod-start from the project root, or npm run dev-start during development. Note that the README writes the second model as gemma4:e2b while the repository topics mention gemma3 and qwen3; treat the pull commands as the authoritative list and verify the tag resolves before you build anything on top of it.
Writing tools, and the dangerous flag that gates them
A tool is a JavaScript module in src/tools/ exporting an object with four properties: name, parameters, a describe field, and the execution body. Anything the front end cannot reach directly, such as Pi hardware state, needs a matching Express route, and the README points to backend/notions/ as the place those routes live. Reference tools ship with a .txt extension and must be renamed to .js to be loaded, which is a deliberate safety catch: nothing in that folder executes until you opt in. The more interesting mechanism is the dangerous property. Setting dangerous: true on a tool means that when the model selects it, the agent asks for confirmation before executing, and you answer YES or NO. The README links a demo video showing this flow with a light bulb. This is a coarse control. It is per-tool and decided at authoring time, so a tool that is safe in one context and destructive in another cannot express that distinction. There is also no described allowlist, rate limit or audit log around tool execution, and the README does not claim one exists. If you wire a tool to something that changes system state, the YES prompt is the only gate the documentation describes.
Where the design strains: memory, animation cost and an admitted dependency
The constraints are stated plainly, which is rare and worth crediting. About 6GB must be free for the LLMs, which effectively rules out a 4GB Pi 5 and leaves little headroom on an 8GB board once the browser, Express, Python, Vosk and faster-whisper are resident. The README also says an active cooler is definitely needed, not optional. The animation question gets an honest answer in the FAQ: yes, the animations slow inference, but the author says the impact is not very significant after testing and would rather show UI feedback than a black screen. That is a defensible product decision, though it is a decision against raw throughput. The largest caveat is the model runtime. The FAQ asks why llama.cpp is not used and answers that the author is aware of Ollama's practices and of issues with llama.cpp's creator, that migration is planned eventually, and that Ollama served its purpose for rapid prototyping. So the project currently depends on a runtime its own maintainer describes as a temporary choice. Anyone adopting this should treat a future runtime swap as likely, and should not build tooling that assumes Ollama-specific behaviour beyond the HTTP endpoint configured in VITE_OLLAMA_URL.
Alternatives and the licence you inherit
The closest comparison is not another voice assistant but a different assembly of the same parts. Home Assistant's voice pipeline, for instance, also runs locally and also pairs a wake-word engine with a speech-to-text model, but it approaches the problem as a device-integration platform: the assistant is one component among hundreds of integrations, and the interface is a dashboard or a satellite speaker rather than an animated character in a browser. Max Headbox inverts that priority. Its agent logic sits in the React app, its tool surface is a folder of JavaScript modules you write yourself, and its output is a face on a screen. If your goal is to control lights and sensors across a house, Max Headbox is the wrong tool and you would spend your time reimplementing what an integration platform already provides. If your goal is a self-contained Pi that hears you, answers you and runs your own scripts, the tool-as-module model is smaller and easier to reason about than a plugin ecosystem. On licensing, the repository is GPL-3.0. That is a copyleft licence, and it applies to the project as distributed. If you fork it, modify it and distribute the result, the usual copyleft obligations follow; running it privately on your own Pi is a different situation. This is a description of the licence, not legal advice, and anyone embedding this code in a product should read the GPL-3.0 text and take their own counsel. One maintenance note: the repository metadata shows no tagged releases, so there is no version to pin and no changelog to read. Upgrades mean pulling from main and re-running npm install and pip3 install -r requirements.txt, and the Ruby-to-Express rewrite is the concrete example of what that can cost you.
Editorial conclusion
Adopt Max Headbox if you already own a Raspberry Pi 5 with 8GB or more, an active cooler, and roughly 6GB of RAM to spare for local models, and you want a spoken interface to Pi hardware rather than a cloud assistant. Skip it if you need a supported product with releases, a documented API surface, or predictable latency: there are no tagged releases in the repository metadata, the README documents no test suite or versioning scheme, and the model choice is left to you. Before committing, run npm run prod-start, confirm the three VITE_ variables in .env point at the right host, and check whether gemma3:1b and gemma4:e2b actually load on your board, because the README's hardware note about 6GB of available memory is the constraint that decides whether this project works for you at all.
Community notes