A privacy-first, self-hosted AI assistant that plugs directly into your Home Assistant stack, this project turns local LLMs into a practical automation brain—capable of understanding natural language, calling tools, and orchestrating real-world actions across your devices without relying on the cloud. Designed for hackers and builders.
See the codeThis will be the last Nova interface release, please feel free to contribute, fork, make it your own. Nova plugins will continue to be added. I will be moving on to Omega, which will be able to use the Nova plugin system, but in the form of a streamlined desktop application, rather than a web interface, and focused on 20B+ models, as opposed to 4B+. I also plan to release a ligher weight Nova core, with most of the inbuilt conveniences carved out, meant purely as a plugin framework, so stay tuned and check out my AI suite.
Nova is a host-side AI orchestration application that combines:
It is designed to run continuously as an autonomous or semi-autonomous operator while still allowing direct user supervision.
The web UI includes dedicated tabs for:
Nova — identity, voice preferences, questions, trust recordsQueue — queued/in-progress/done/failed tasks, repairs, issues, schedules, historyBrains — model status, endpoints, base brains, specialists, routing configSecrets — keychain handles for retrieval, mail, IoT, and custom secretsCapabilities — tool catalog, installed skills, capability request trackingPlugins — installed plugins, interfaces, operationsSystem — gateway health, intake state, SSE logs, regression test runnerThe system supports:
/api/agent/run)/api/tasks/triage)Queue functionality includes:
Voice functionality includes:
Avatar system includes:
The system maintains internal queue-backed recurring jobs for:
Background logic includes:
The recreation subsystem:
Retrieval domain capabilities:
Tool governance includes:
normal, medium, high, approval)The system records unmet capability demand:
Skill features include:
Plugins extend the observer at runtime without modifying core code:
observer-compat browser host, supporting both native and legacy tab APIsTool loop and shell output compression reduces context bloat during long task execution:
Tool execution is isolated in a Docker container with:
--cap-drop ALL)no-new-privilegesSecrets are managed via OS keychain (keytar) with handles for:
Trust system supports:
unknown, known, trusted)See docs/API.md for the full endpoint-by-endpoint reference (methods, auth, request/response shapes).
Primary route groups:
/api/runtime/*, /events/*/api/agent/run, /api/tasks/triage, /api/prompts/review/api/tasks/*, /api/queue/control/api/cron/*/api/app/config, /api/brains/config, /api/tools/config, /api/secrets/*/api/inspect/*, /api/output/*/api/regressions/*Regression support includes:
run-regressions.js)Expected runtime stack:
node server.js)In practical terms, this application is:
This repo runs as a host-side Node observer with a Docker sandbox for LLM-controlled tools, plus Ollama for model execution. There is no gateway container.
Special note on security: the environment described is inherently secure, however, the interface is not currently suitable for open web-facing use.
The accuracy on the voice security is dubious. There is no spoofing protection on email trust. Use these features carefully and run this on a local environment.
Trust settings are under the Nova tab.
<your-repo-path>nova-observer/http://127.0.0.1:3220/nova-observer/server.jsnova-observer/observer.config.jsonnova-observer/.derpy-observer-runtime<your-repo-path>/observer-outputThe observer process runs directly on the host:
node server.jsnova-observer/The LLM does not get host shell access directly. Tool execution is isolated in Docker.
The LLM tool sandbox is the important security boundary.
derpy-observer-sandboxnova-safederpy-observer-sandbox-state/home/nova/home/nova/.observer-sandbox/workspace/home/nova/observer-outputThe observer creates this container automatically on startup if needed.
When adding or restoring a built-in tool for Nova, treat it as a runtime feature, not just a code change.
Required checks:
nova-safe image, not just on the hostDockerfilenova-safe after changing runtime dependenciesderpy-observer-sandbox so the live observer stops using the old imagedocker exec derpy-observer-sandbox sh -lc "command -v <tool>"Recent example:
unzip existed in server.js, but the sandbox image did not contain /usr/bin/unzipzip and unzip in Dockerfile, rebuild nova-safe, and let the observer recreate derpy-observer-sandboxThe container is started with:
--read-only--cap-drop ALL--security-opt no-new-privileges--pids-limit 200--memory 2g--cpus 2.0--tmpfs /tmpCurrent caveat:
nova usernova/tmp, and restricted mountsThe live sandbox is allowed to access exactly three locations:
<your-repo-path>/observer-input -> /home/nova/observer-inputderpy-observer-sandbox-state -> /home/nova/.observer-sandbox/workspace<your-repo-path>/observer-output -> /home/nova/observer-outputNo other host bind mounts are allowed into the Nova runtime sandbox.
Persistent internal sandbox state lives in the named Docker volume, not in the host repo.
This is the intended design:
observer-input, the sandbox workspace, and observer-outputThis is why the sandbox exists at all. Do not break the observer back out into direct host file/shell tooling.
Containers that should normally exist:
derpy-observer-sandbox (created dynamically by the observer on startup)nova-qdrant (via docker-compose)Enabled brains in nova-observer/observer.config.json:
Built-in (local):
intake — Gemma 4 E4B, local Ollama, conversation and direct repliesworker — Gemma 4 26B, local Ollama, queued tool-using workhelper — Gemma 3 1B (disabled by default), speculative sidecarRemote specialists:
remote_cpu — Qwen 3.5 4B, LAN CPU planner for triage and routingcreative_worker — Hermes 3, LAN GPU, creative and ideation taskscode_worker — Qwen 2.5 Coder 7B, LAN GPU, code tasksvision_worker — MiniCPM-V, LAN GPU, vision/image tasksretrieval_worker — MXBAI Embed Large, LAN GPU, embedding and retrievallappy_gpu_big — Qwen 3.5 9B, laptop GPU, general tool-capable worklan_73_p4 — Qwen 3.5 9B, LAN P4 endpoint, general tool-capable worklap_planner — FunctionGemma, laptop CPU, routingMail polling is configured in nova-observer/observer.config.json and handled by the observer process.
mail.example.commail.example.comnova@example.comThe observer supports:
The queue is local to this observer and stored under:
nova-observer/.derpy-observer-runtime/derpy-observer-task-queueTask folders:
inboxin_progressdoneclosedThere is no external cron service. Periodic work is implemented as self-perpetuating queued tasks.
Examples of internal recurring jobs:
Editable prompt/memory files on the host:
nova-observer/.agent-workspaces/nova/prompt-files/AGENTS.mdnova-observer/.agent-workspaces/nova/prompt-files/TOOLS.mdnova-observer/.agent-workspaces/nova/prompt-files/SOUL.mdnova-observer/.agent-workspaces/nova/prompt-files/USER.mdnova-observer/.agent-workspaces/nova/prompt-files/MEMORY.mdnova-observer/.agent-workspaces/nova/prompt-files/PERSONAL.mdnova-observer/.agent-workspaces/nova/memory/...These are copied into the sandbox workspace as seed content.
Host side:
<your-repo-path><your-repo-path>/nova-observer<your-repo-path>/observer-output<your-repo-path>/nova-observer/.derpy-observer-runtimeSandbox side:
/home/nova/.observer-sandbox/workspace/home/nova/observer-input/home/nova/observer-outputdocker version
docker info
wsl --status
Build the sandbox image from the repo root:
docker build -t nova-safe .
Then start Qdrant and the observer:
cd <your-repo-path>
docker compose up -d qdrant
$env:QDRANT_URL="http://127.0.0.1:6333"
cd <your-repo-path>\nova-observer
node server.js
Then verify:
http://127.0.0.1:3220/api/runtime/statushttp://127.0.0.1:3220/api/runtime/optionshttp://127.0.0.1:6333/collectionsnova-observer/observer.config.jsonobserver-outputobserver-input33 commits
JavaScript
96.8%
HTML
1.6%
CSS
1.4%
A privacy-first, self-hosted AI assistant that plugs directly into your Home Assistant stack, this project turns local LLMs into a practical automation brain—capable of understanding natural language, calling tools, and orchestrating real-world actions across your devices without relying on the cloud. Designed for hackers and builders.
See the codeThis will be the last Nova interface release, please feel free to contribute, fork, make it your own. Nova plugins will continue to be added. I will be moving on to Omega, which will be able to use the Nova plugin system, but in the form of a streamlined desktop application, rather than a web interface, and focused on 20B+ models, as opposed to 4B+. I also plan to release a ligher weight Nova core, with most of the inbuilt conveniences carved out, meant purely as a plugin framework, so stay tuned and check out my AI suite.
Nova is a host-side AI orchestration application that combines:
It is designed to run continuously as an autonomous or semi-autonomous operator while still allowing direct user supervision.
The web UI includes dedicated tabs for:
Nova — identity, voice preferences, questions, trust recordsQueue — queued/in-progress/done/failed tasks, repairs, issues, schedules, historyBrains — model status, endpoints, base brains, specialists, routing configSecrets — keychain handles for retrieval, mail, IoT, and custom secretsCapabilities — tool catalog, installed skills, capability request trackingPlugins — installed plugins, interfaces, operationsSystem — gateway health, intake state, SSE logs, regression test runnerThe system supports:
/api/agent/run)/api/tasks/triage)Queue functionality includes:
Voice functionality includes:
Avatar system includes:
The system maintains internal queue-backed recurring jobs for:
Background logic includes:
The recreation subsystem:
Retrieval domain capabilities:
Tool governance includes:
normal, medium, high, approval)The system records unmet capability demand:
Skill features include:
Plugins extend the observer at runtime without modifying core code:
observer-compat browser host, supporting both native and legacy tab APIsTool loop and shell output compression reduces context bloat during long task execution:
Tool execution is isolated in a Docker container with:
--cap-drop ALL)no-new-privilegesSecrets are managed via OS keychain (keytar) with handles for:
Trust system supports:
unknown, known, trusted)See docs/API.md for the full endpoint-by-endpoint reference (methods, auth, request/response shapes).
Primary route groups:
/api/runtime/*, /events/*/api/agent/run, /api/tasks/triage, /api/prompts/review/api/tasks/*, /api/queue/control/api/cron/*/api/app/config, /api/brains/config, /api/tools/config, /api/secrets/*/api/inspect/*, /api/output/*/api/regressions/*Regression support includes:
run-regressions.js)Expected runtime stack:
node server.js)In practical terms, this application is:
This repo runs as a host-side Node observer with a Docker sandbox for LLM-controlled tools, plus Ollama for model execution. There is no gateway container.
Special note on security: the environment described is inherently secure, however, the interface is not currently suitable for open web-facing use.
The accuracy on the voice security is dubious. There is no spoofing protection on email trust. Use these features carefully and run this on a local environment.
Trust settings are under the Nova tab.
<your-repo-path>nova-observer/http://127.0.0.1:3220/nova-observer/server.jsnova-observer/observer.config.jsonnova-observer/.derpy-observer-runtime<your-repo-path>/observer-outputThe observer process runs directly on the host:
node server.jsnova-observer/The LLM does not get host shell access directly. Tool execution is isolated in Docker.
The LLM tool sandbox is the important security boundary.
derpy-observer-sandboxnova-safederpy-observer-sandbox-state/home/nova/home/nova/.observer-sandbox/workspace/home/nova/observer-outputThe observer creates this container automatically on startup if needed.
When adding or restoring a built-in tool for Nova, treat it as a runtime feature, not just a code change.
Required checks:
nova-safe image, not just on the hostDockerfilenova-safe after changing runtime dependenciesderpy-observer-sandbox so the live observer stops using the old imagedocker exec derpy-observer-sandbox sh -lc "command -v <tool>"Recent example:
unzip existed in server.js, but the sandbox image did not contain /usr/bin/unzipzip and unzip in Dockerfile, rebuild nova-safe, and let the observer recreate derpy-observer-sandboxThe container is started with:
--read-only--cap-drop ALL--security-opt no-new-privileges--pids-limit 200--memory 2g--cpus 2.0--tmpfs /tmpCurrent caveat:
nova usernova/tmp, and restricted mountsThe live sandbox is allowed to access exactly three locations:
<your-repo-path>/observer-input -> /home/nova/observer-inputderpy-observer-sandbox-state -> /home/nova/.observer-sandbox/workspace<your-repo-path>/observer-output -> /home/nova/observer-outputNo other host bind mounts are allowed into the Nova runtime sandbox.
Persistent internal sandbox state lives in the named Docker volume, not in the host repo.
This is the intended design:
observer-input, the sandbox workspace, and observer-outputThis is why the sandbox exists at all. Do not break the observer back out into direct host file/shell tooling.
Containers that should normally exist:
derpy-observer-sandbox (created dynamically by the observer on startup)nova-qdrant (via docker-compose)Enabled brains in nova-observer/observer.config.json:
Built-in (local):
intake — Gemma 4 E4B, local Ollama, conversation and direct repliesworker — Gemma 4 26B, local Ollama, queued tool-using workhelper — Gemma 3 1B (disabled by default), speculative sidecarRemote specialists:
remote_cpu — Qwen 3.5 4B, LAN CPU planner for triage and routingcreative_worker — Hermes 3, LAN GPU, creative and ideation taskscode_worker — Qwen 2.5 Coder 7B, LAN GPU, code tasksvision_worker — MiniCPM-V, LAN GPU, vision/image tasksretrieval_worker — MXBAI Embed Large, LAN GPU, embedding and retrievallappy_gpu_big — Qwen 3.5 9B, laptop GPU, general tool-capable worklan_73_p4 — Qwen 3.5 9B, LAN P4 endpoint, general tool-capable worklap_planner — FunctionGemma, laptop CPU, routingMail polling is configured in nova-observer/observer.config.json and handled by the observer process.
mail.example.commail.example.comnova@example.comThe observer supports:
The queue is local to this observer and stored under:
nova-observer/.derpy-observer-runtime/derpy-observer-task-queueTask folders:
inboxin_progressdoneclosedThere is no external cron service. Periodic work is implemented as self-perpetuating queued tasks.
Examples of internal recurring jobs:
Editable prompt/memory files on the host:
nova-observer/.agent-workspaces/nova/prompt-files/AGENTS.mdnova-observer/.agent-workspaces/nova/prompt-files/TOOLS.mdnova-observer/.agent-workspaces/nova/prompt-files/SOUL.mdnova-observer/.agent-workspaces/nova/prompt-files/USER.mdnova-observer/.agent-workspaces/nova/prompt-files/MEMORY.mdnova-observer/.agent-workspaces/nova/prompt-files/PERSONAL.mdnova-observer/.agent-workspaces/nova/memory/...These are copied into the sandbox workspace as seed content.
Host side:
<your-repo-path><your-repo-path>/nova-observer<your-repo-path>/observer-output<your-repo-path>/nova-observer/.derpy-observer-runtimeSandbox side:
/home/nova/.observer-sandbox/workspace/home/nova/observer-input/home/nova/observer-outputdocker version
docker info
wsl --status
Build the sandbox image from the repo root:
docker build -t nova-safe .
Then start Qdrant and the observer:
cd <your-repo-path>
docker compose up -d qdrant
$env:QDRANT_URL="http://127.0.0.1:6333"
cd <your-repo-path>\nova-observer
node server.js
Then verify:
http://127.0.0.1:3220/api/runtime/statushttp://127.0.0.1:3220/api/runtime/optionshttp://127.0.0.1:6333/collectionsnova-observer/observer.config.jsonobserver-outputobserver-input33 commits
JavaScript
96.8%
HTML
1.6%
CSS
1.4%