Skip to content

// 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:

Terminal window
$ halbert ask
usage: halbert [-h] [--port PORT] [--host HOST] [--reload] [--no-ollama-check]
[--find-port] [--version]
halbert: error: unrecognized arguments: ask

The command line lives in the checkout and is invoked through its own entry point:

Terminal window
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.

  • 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:11434 unless you tell it otherwise.
  • Node 22, to build the dashboard’s page. .nvmrc pins 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-python dependency is declared for platform_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.

From the root of the checkout:

Terminal window
python3 -m venv .venv
source .venv/bin/activate
pip install -e 'halbert_core/[dashboard]' aiohttp

Take 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:

Terminal window
python Halbert/main.py info
python Halbert/main.py --help

The first prints the version and the licence summary. The second lists every subcommand.

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:

Terminal window
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.

Terminal window
python Halbert/main.py config-validate

reads that file back and reports whether it is complete.

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.

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:

Terminal window
npm install
python3 scripts/sync_fonts.py
npm --prefix halbert_core/halbert_core/dashboard/frontend run build

npm 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.

Terminal window
halbert

serves 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.

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.