Skip to main content

Installation

msgbrowse installs with a single go install. The SQLite driver is pure Go (with FTS5 built in), so CGO_ENABLED=0 is the normal build — there is no C toolchain, no build tag, and no shared library to set up.

Install the binary

Requires Go 1.25+ and nothing else:

go install github.com/joestump/msgbrowse/cmd/msgbrowse@latest

The binary lands in $(go env GOBIN) (or $(go env GOPATH)/bin) — make sure that directory is on your PATH:

export PATH="$PATH:$(go env GOPATH)/bin"
msgbrowse version

Install the exporters

msgbrowse reads archives produced by three upstream tools. Install whichever sources you have — any subset (Signal-only, iMessage-only, …) works fine.

Signalsignal-export, installed with pipx:

pipx install signal-export
tip

The pip package is signal-export, but the console command it installs is sigexport — that is the binary msgbrowse export looks up on your PATH.

iMessageimessage-exporter, installed with Homebrew on macOS:

brew install imessage-exporter

WhatsAppwhatsapp-chat-exporter, installed with pipx (the console command is wtsexporter):

pipx install whatsapp-chat-exporter

msgbrowse never auto-installs these tools and never touches the sensitive sources (the Signal database, the macOS Keychain, chat.db, ChatStorage.sqlite) itself — it only spawns your own, already-installed exporters at your explicit request.

Alternative: Docker

Prefer containers? The repo ships a Dockerfile and a compose stack — the image is a fully static binary on a distroless base, running non-root with a read-only root filesystem and all capabilities dropped.

git clone https://github.com/joestump/msgbrowse.git
cd msgbrowse
cp .env.example .env
# edit .env:
# MSGBROWSE_ARCHIVE_HOST → your archive's absolute path
# MSGBROWSE_LLM_BASE_URL → your LiteLLM proxy (…/v1), MSGBROWSE_LLM_API_KEY → its key

make up # build + start msgbrowse (points at your external LiteLLM)
make signal-import # import the signal-export archive into the local DB
make embed # compute embeddings for semantic search (optional)
# open http://127.0.0.1:8787

make logs tails the server; make down stops the stack. The archive is mounted read-only (:ro), app data lives in a named volume, and the UI is published to host loopback only.

tip

No LLM proxy yet? Run the bundled, fully local LiteLLM with make up-bundled and set MSGBROWSE_LLM_BASE_URL=http://litellm:4000/v1. Until an endpoint is reachable, embed and the journal fail — browsing and keyword search work without any LLM.

About the LLM endpoint

msgbrowse only ever talks to your own OpenAI-compatible endpoint — configure it with MSGBROWSE_LLM_BASE_URL (a …/v1 URL) and MSGBROWSE_LLM_API_KEY via env, config.yaml, or flags (see the configuration reference for all keys and their precedence). The default is a local proxy at http://127.0.0.1:4000/v1. This endpoint is the only network egress in the entire application, and it is optional: everything except embed, facts, semantic search, and the journal works without it. The security model documents exactly what is sent to it.

Next step

With the binary and exporters installed, produce your first archives: Exporting your archives.