Geist is a local first, privacy first, voice enabled harness for AI agents.
The Geist Architecture consists of three main components: a world model, a task creation model, and an execution-based model. The diagram below illustrates the architecture and relationships between these components.
Geist now supports a flexible agent architecture with two main agent types:
Both agents inherit from BaseAgent and support:
See docs/agents.md for detailed documentation.
flowchart LR
A[World Model] -->|Updates| B[Task Creation Model]
B -->|Generates Tasks| C[Execution-based LLM Model]
C -->|Execution Results| A
D[Plugin System] -->|Provides Capabilities| C
E[Long-term Memory] -->|Base Knowledge| A
F[Short-term Memory] -->|Context-specific Info| C
The default local setup uses uv with the committed uv.lock and a local SQLite database — no Docker, conda, or PostgreSQL required:
# install uv (one time): https://docs.astral.sh/uv/getting-started/installation/
make sync # create the environment from uv.lock (uv manages Python 3.11 for you)
make run # initialize the SQLite database (data/geist.sqlite3) and start the backend
Optional extras:
uv sync --extra postgres # psycopg2 driver, for GEIST_DATABASE_PROVIDER=postgresql
uv sync --extra voice # sounddevice/sphn for the voice client tooling
uv sync --extra local-transformers # Torch/Transformers local runner (Docker/Linux)
uv sync --extra local-mlx # Apple-silicon MLX local runner
Note for Linux CPU runs: MLX and Moshi can JIT-compile kernels with the system compiler and fail on some compiler/architecture combinations. Docker defaults to portable interpreted paths with MLX_DISABLE_COMPILE=1 and NO_TORCH_COMPILE=1; native runs can set the same values when needed. (MLX inference is primarily intended for Apple silicon.)
SQLite is the default database provider, including in Docker Compose. To use PostgreSQL instead, install version 16.2, configure its connection values, and set GEIST_DATABASE_PROVIDER=postgresql.
Select the SQLAlchemy provider with GEIST_DATABASE_PROVIDER. SQLite is the default and stores its database at data/geist.sqlite3 unless overridden:
GEIST_DATABASE_PROVIDER=sqlite # default; may be omitted
SQLITE_DATABASE_PATH=/absolute/path/to/geist.sqlite3
To use PostgreSQL instead, select it explicitly; it uses the existing POSTGRES_*, DB_HOST, and DB_PORT settings:
GEIST_DATABASE_PROVIDER=postgresql
SQLITE_DATABASE_URL can be used instead of SQLITE_DATABASE_PATH. SQLALCHEMY_DATABASE_URL overrides provider-specific URL construction when its URL scheme matches the selected provider.
Tests and alternate application entry points can inject DatabaseConfig(provider=..., database_url=...) directly into configure_database() without changing environment variables.
llama-server.HF_TOKEN or
HUGGING_FACE_HUB_TOKEN for the gated repository.GEIST_MODEL_HOME/data directory.
LOCAL_WEIGHTS_DIR remains available for legacy MLX installations.python scripts/download_models.py --voice_model <name|all>; list the
available names with --list_voice_models.client/geist/.env settings: - REACT_APP_API_BASE_URL = http://localhost:3000
Use lockfile-based installs and exact pins. Avoid ad hoc install commands that resolve new dependency versions without review.
Install the committed frontend lockfile without running package lifecycle scripts:
cd client/geist
npm ci --ignore-scripts --audit=false --fund=false
When adding or updating a frontend package, pin the exact version and update only the manifest and lockfile first:
cd client/geist
npm install --package-lock-only --ignore-scripts --save-exact PACKAGE@VERSION
npm audit --package-lock-only
Review both package.json and package-lock.json before committing. Do not use bare npm install or npm i for project setup.
Native backend dependencies are declared with exact == pins in pyproject.toml and frozen in uv.lock. To add or update a package:
uv add PACKAGE==VERSION # updates pyproject.toml and uv.lock together
Review the pyproject.toml and uv.lock diff before committing.
The Docker image installs from the same pyproject.toml/uv.lock via uv, so container and native dependencies stay in sync automatically — no separate environment files to maintain.
Install hooks after creating the environment:
pre-commit install
pre-commit run --all-files
The dependency policy hook rejects npm version ranges, unsafe frontend Docker installs, missing npm lockfile integrity entries, and unpinned Python dependencies in pyproject.toml.
make run (SQLite by default; initializes the database and starts the backend natively via uv)To run against PostgreSQL natively instead:
PATH/pg_ctl -D DATA_PATH -l LOG_PATH start.GEIST_DATABASE_PROVIDER=postgresql make runmake run-docker (or docker compose up). The compose stack uses SQLite by default.make services then make run
GEIST_MLX_IMPLEMENTATION=mlx_lm to use the pinned mlx-lm runtime.GEIST_MLX_IMPLEMENTATION=manual to select the in-repo implementation explicitly.Python
74.6%
TypeScript
20.9%
CSS
3.6%
Geist is a local first, privacy first, voice enabled harness for AI agents.
The Geist Architecture consists of three main components: a world model, a task creation model, and an execution-based model. The diagram below illustrates the architecture and relationships between these components.
Geist now supports a flexible agent architecture with two main agent types:
Both agents inherit from BaseAgent and support:
See docs/agents.md for detailed documentation.
flowchart LR
A[World Model] -->|Updates| B[Task Creation Model]
B -->|Generates Tasks| C[Execution-based LLM Model]
C -->|Execution Results| A
D[Plugin System] -->|Provides Capabilities| C
E[Long-term Memory] -->|Base Knowledge| A
F[Short-term Memory] -->|Context-specific Info| C
The default local setup uses uv with the committed uv.lock and a local SQLite database — no Docker, conda, or PostgreSQL required:
# install uv (one time): https://docs.astral.sh/uv/getting-started/installation/
make sync # create the environment from uv.lock (uv manages Python 3.11 for you)
make run # initialize the SQLite database (data/geist.sqlite3) and start the backend
Optional extras:
uv sync --extra postgres # psycopg2 driver, for GEIST_DATABASE_PROVIDER=postgresql
uv sync --extra voice # sounddevice/sphn for the voice client tooling
uv sync --extra local-transformers # Torch/Transformers local runner (Docker/Linux)
uv sync --extra local-mlx # Apple-silicon MLX local runner
Note for Linux CPU runs: MLX and Moshi can JIT-compile kernels with the system compiler and fail on some compiler/architecture combinations. Docker defaults to portable interpreted paths with MLX_DISABLE_COMPILE=1 and NO_TORCH_COMPILE=1; native runs can set the same values when needed. (MLX inference is primarily intended for Apple silicon.)
SQLite is the default database provider, including in Docker Compose. To use PostgreSQL instead, install version 16.2, configure its connection values, and set GEIST_DATABASE_PROVIDER=postgresql.
Select the SQLAlchemy provider with GEIST_DATABASE_PROVIDER. SQLite is the default and stores its database at data/geist.sqlite3 unless overridden:
GEIST_DATABASE_PROVIDER=sqlite # default; may be omitted
SQLITE_DATABASE_PATH=/absolute/path/to/geist.sqlite3
To use PostgreSQL instead, select it explicitly; it uses the existing POSTGRES_*, DB_HOST, and DB_PORT settings:
GEIST_DATABASE_PROVIDER=postgresql
SQLITE_DATABASE_URL can be used instead of SQLITE_DATABASE_PATH. SQLALCHEMY_DATABASE_URL overrides provider-specific URL construction when its URL scheme matches the selected provider.
Tests and alternate application entry points can inject DatabaseConfig(provider=..., database_url=...) directly into configure_database() without changing environment variables.
llama-server.HF_TOKEN or
HUGGING_FACE_HUB_TOKEN for the gated repository.GEIST_MODEL_HOME/data directory.
LOCAL_WEIGHTS_DIR remains available for legacy MLX installations.python scripts/download_models.py --voice_model <name|all>; list the
available names with --list_voice_models.client/geist/.env settings: - REACT_APP_API_BASE_URL = http://localhost:3000
Use lockfile-based installs and exact pins. Avoid ad hoc install commands that resolve new dependency versions without review.
Install the committed frontend lockfile without running package lifecycle scripts:
cd client/geist
npm ci --ignore-scripts --audit=false --fund=false
When adding or updating a frontend package, pin the exact version and update only the manifest and lockfile first:
cd client/geist
npm install --package-lock-only --ignore-scripts --save-exact PACKAGE@VERSION
npm audit --package-lock-only
Review both package.json and package-lock.json before committing. Do not use bare npm install or npm i for project setup.
Native backend dependencies are declared with exact == pins in pyproject.toml and frozen in uv.lock. To add or update a package:
uv add PACKAGE==VERSION # updates pyproject.toml and uv.lock together
Review the pyproject.toml and uv.lock diff before committing.
The Docker image installs from the same pyproject.toml/uv.lock via uv, so container and native dependencies stay in sync automatically — no separate environment files to maintain.
Install hooks after creating the environment:
pre-commit install
pre-commit run --all-files
The dependency policy hook rejects npm version ranges, unsafe frontend Docker installs, missing npm lockfile integrity entries, and unpinned Python dependencies in pyproject.toml.
make run (SQLite by default; initializes the database and starts the backend natively via uv)To run against PostgreSQL natively instead:
PATH/pg_ctl -D DATA_PATH -l LOG_PATH start.GEIST_DATABASE_PROVIDER=postgresql make runmake run-docker (or docker compose up). The compose stack uses SQLite by default.make services then make run
GEIST_MLX_IMPLEMENTATION=mlx_lm to use the pinned mlx-lm runtime.GEIST_MLX_IMPLEMENTATION=manual to select the in-repo implementation explicitly.Python
74.6%
TypeScript
20.9%
CSS
3.6%