// Start here
Install
Halbert runs on the machine it looks after. Installing it means putting a Python package and a checkout of the repository on that machine, pointing it at a model runtime, building the web interface, and opening its dashboard.
halbert.computer/get is where the software is distributed and what each way of getting it costs. This page picks up from the moment you have a checkout.
The command named halbert is not the command line
Section titled “The command named halbert is not the command line”Installing the package puts a command called halbert on your PATH. It starts the dashboard,
and it takes no subcommands at all:
$ halbert askusage: halbert [-h] [--port PORT] [--host HOST] [--reload] [--no-ollama-check] [--find-port] [--version]halbert: error: unrecognized arguments: askThe command line lives in the checkout and is invoked through its own entry point:
python Halbert/main.py <command>Halbert/ is not part of the packaged distribution — pyproject.toml packages halbert_core*
and nothing else — so after a pip install the 67 subcommands exist only where you cloned. Use
the checkout for anything on the CLI reference.
This is a known rough edge rather than a design decision. The roadmap tracks it as README-1.
What the machine needs
Section titled “What the machine needs”- Python 3.10 or newer. The package declares
requires-python = ">=3.10". - A model runtime. Halbert expects an Ollama-compatible endpoint and looks for one at
http://localhost:11434unless you tell it otherwise. - Node 22, to build the dashboard’s page.
.nvmrcpins the LTS line. The Python install does not build the web interface and no wheel carries it — Build the web interface below is what produces it. - systemd, on Linux. It is what the service units run under and what supplies the journal
Halbert reads. The
systemd-pythondependency is declared forplatform_system == 'Linux'and is skipped everywhere else, so the rest of Halbert still installs and runs on a Mac — without the journal or the units.
Install
Section titled “Install”From the root of the checkout:
python3 -m venv .venvsource .venv/bin/activatepip install -e 'halbert_core/[dashboard]' aiohttpTake the [dashboard] extra unless you know you do not want it. The base dependency set is the
engine alone — pydantic, PyYAML, watchdog, jsonschema, NumPy, APScheduler, SQLAlchemy and
rank-bm25. FastAPI and uvicorn, which serve the dashboard, arrive only with the extra. The other
extras (vision, audio-inference, cognition, cloud-apis) are listed in
halbert_core/pyproject.toml and can be added later.
Two commands confirm the install:
python Halbert/main.py infopython Halbert/main.py --helpThe first prints the version and the licence summary. The second lists every subcommand.
Point it at a model
Section titled “Point it at a model”There is no separate init step. Halbert creates its directories the first time it writes to them, and the first thing worth writing is the model configuration, which the wizard sizes to the hardware it finds:
python Halbert/main.py config-wizard --auto--auto runs without prompts and takes the wizard’s own recommendation. Drop the flag and it asks
instead, showing what the endpoint is already serving and what fits in the memory it measured.
Either way it writes models.yml into the configuration directory and prints the path.
python Halbert/main.py config-validatereads that file back and reports whether it is complete.
Where it keeps things
Section titled “Where it keeps things”| Linux | macOS | |
|---|---|---|
| Configuration | ~/.config/halbert |
~/Library/Application Support/Halbert |
| Data | ~/.local/share/halbert |
~/.local/share/halbert |
| Runtime state | ~/.local/state/halbert |
~/.local/state/halbert |
Configuration is the only row that follows each platform’s own convention. Data and runtime state
are XDG on both, which is the one that surprises people on a Mac: the conversation store, memory,
findings, knowledge, the vector index and the machine scan written during
first run all sit under ~/.local/share/halbert, and that is the directory to
back up. It is the only data folder. Installs from before 2026-09-23 also kept the scan in
~/Library/Application Support/Halbert/Data on a Mac, and a model-call log in ~/.halbert; both
are left where they were and no longer read.
Run Halbert as root and it configures the machine instead of an account, reading /etc/halbert
and /var/lib/halbert.
HALBERT_CONFIG_DIR and HALBERT_DATA_DIR move configuration and data, and nothing else. Runtime
state ignores both and follows XDG_STATE_HOME; logs follow runtime state unless HALBERT_LOG_DIR
names somewhere else. A second instance on one machine therefore needs all three — set only the
first two and both instances still share ~/.local/state/halbert, where the API token and the peer
TLS key live.
Build the web interface
Section titled “Build the web interface”The dashboard serves a page that is built, and nothing installed so far produces it. It is not kept
in the repository, and no wheel carries it: the packaged distribution declares three directories of
non-Python files — config, integrations and prompts — and the built interface is not among
them. Build it from the checkout, from the repo root:
npm installpython3 scripts/sync_fonts.pynpm --prefix halbert_core/halbert_core/dashboard/frontend run buildnpm install belongs at the root so that the two shared packages the dashboard draws on resolve to
this checkout rather than to downloads. sync_fonts.py copies the vendored typefaces to where the
build can see them; skip it and the dashboard warns at startup and falls back to system faces. The
last command writes halbert_core/halbert_core/dashboard/frontend/dist/.
Without that directory the dashboard still starts and the API underneath it still answers, but the address in the next section returns 404 — the route that serves the page is registered only when the build output is there.
Run it
Section titled “Run it”halbertserves on http://127.0.0.1:8000. --host and --port move it, and --find-port walks forward
until it finds a free one. Start it with this command rather than through the command line: both
put a server on that port, but only halbert prints the one-time link that lets your browser in.
The page at that address needs the build above, and First run picks up from
the moment the process is up.
Running it as a service
Section titled “Running it as a service”On Linux, Halbert ships five systemd units under packaging/systemd/system/: two that ingest, one
that watches configuration with a .path unit to trigger it, and one for the dashboard. The three
that ingest and watch each run a subcommand of the same command line you have been using; the
dashboard’s serves the API directly.
The dashboard’s is a template — [email protected] — instantiated once per login user
and run as that user, so each instance reads and writes inside that one home and can see no other.
That is also why installing the units does not start it: there is no single user the installer
could choose for you, so it puts the template in place and leaves the choice.
Installing the units, what each one runs, and the system-scope alternative under a dedicated service account are on systemd units. They need root and a machine running systemd.