A small, fully offline chat UI for local Ollama models, built to get the most out of small models.
Docker runs Flint only. Ollama stays the normal app on your machine,
where it already has your GPU and your models, and the container talks
to it. The image is published at ghcr.io/lusan-sapkota/flint (see
Image tags), and the compose files in
the repository root are ready-to-use examples. Download one; there’s no
need to clone the repository.
Linux:
mkdir flint && cd flint && mkdir data
curl -O https://raw.githubusercontent.com/Lusan-sapkota/Flint/main/docker-compose.yml
docker compose up -d
The container uses host networking, so it reaches Ollama at
localhost:11434 exactly as a native Flint would, and Ollama never has to
listen beyond localhost.
Mac and Windows (Docker Desktop):
mkdir flint && cd flint && mkdir data
curl -O https://raw.githubusercontent.com/Lusan-sapkota/Flint/main/docker-compose.desktop.yml
docker compose -f docker-compose.desktop.yml up -d
Host networking doesn’t work there the same way, because Docker runs in a
small VM. This file uses ordinary port mapping, and reaches Ollama through
host.docker.internal, which Docker Desktop forwards to your machine.
This setup is untested so far, since it was built on Linux; if it doesn’t
reach Ollama, please open an issue.
Then open http://localhost:3141. Notes:
FLINT_PORT to use another
(FLINT_PORT=4000 docker compose up -d). Either way it’s published on
127.0.0.1 only.data/ folder next to the compose
file. It’s a plain folder, not a Docker volume, so it survives
docker compose down -v and rebuilds, and you can back it up like any
other files. It’s gone only when you delete the folder. Create it
yourself before the first start: if Docker creates it, it’s owned by
root and the container can’t write to it. The container runs as uid
1000, the usual first user on Linux. It’s separate from
backend/data/, which a native go run . uses.volumes: entry
such as - /home/you/project:/home/flint/project), or run Flint natively.sh. Commands only have the tools Alpine ships.Listening address: the image sets HOST=0.0.0.0, so a plain
docker run -p works. The Linux compose file narrows it back to
127.0.0.1, since host networking would otherwise expose it to the
network.
docker compose pull && docker compose up -d fetches the
newest latest, and ./data is kept. latest only moves for normal
releases, not pre-releases like v0.2.0-beta. To stay on one version,
change the tag in the compose file, for example
ghcr.io/lusan-sapkota/flint:0.1 (patch releases of 0.1) or :0.1.0
(exactly that one). Nothing updates automatically.Requires Go (see backend/go.mod) and a running Ollama.
ollama serve # or the system service
cd backend
go run . # must run from backend/: assets resolve via ../frontend
Open http://localhost:8080, sign up, and pick a model.
To build a static binary (no cgo, any OS):
cd backend && CGO_ENABLED=0 go build -o flint .
| Variable | Default | |
|---|---|---|
HOST |
127.0.0.1 |
address to listen on; localhost only by default, since commands run on this machine and signup is open |
PORT |
8080 |
|
DB_PATH |
data/chat.db |
SQLite file, relative to backend/ |
ATTACHMENTS_DIR |
data/attachments |
uploaded files |
OLLAMA_BASE_URL |
http://localhost:11434 |
server default; each user can override it in Settings |
FLINT_ABLATE |
empty | benchmark only: switches scaffolding off, see benchmark.md. Leave unset. |
A new image is published for every release, for linux/amd64 and
linux/arm64:
| Tag | Follows |
|---|---|
latest |
the newest normal release (never a pre-release like v0.2.0-beta) |
0.1 |
the newest 0.1.x patch release |
0.1.4 |
exactly that release |
The compose files use latest. To stay on one version, change the tag
in the compose file. A published version always means the same code: a
broken release is fixed by the next version, never by republishing one.
How a release is made (for maintainers) is in
CONTRIBUTING.md.
GET /healthz checks the database and Ollama’s /api/version. It returns
200 with {"db":"ok","ollama":"ok"}, or 503 naming what failed.
SIGINT and SIGTERM stop accepting requests and give in-flight ones up to 10 seconds to finish. A background summarization cut short by shutdown is just redone later.
Anything Ollama serves works for chat. What Flint uses:
tools
capability, such as qwen2.5-3b-instruct or qwen3.5-4b.vision (qwen3.5-4b).thinking (qwen3.5-4b).@web re-ranking uses nomic-embed-text, and it’s optional, not a
dependency. Without it @web still works, using Brave’s own ranking.
With it, the model only loads for the moment a search runs: Flint asks
Ollama to unload it as soon as the results are ranked, not after
Ollama’s default 5 minutes. Flint never pulls it on its
own: Settings → Connection offers a Pull button when a Brave key is set
and the model is missing, and the Installed list marks it.By default a plain chat runs with a 4096-token window, a folder chat with
8192, and a chat with an Ollama cloud model with 32768. Each account can
set its own window for local and for cloud models in Settings →
Connection, and no model is given more than the context_length it
reports; see context-management.md.