Hippo

License: MIT macOS Rust Python

Local-first knowledge capture daemon for macOS. Hippo watches your shell activity, Claude Code sessions, and Firefox browsing, redacts known secret formats, enriches events with a local LLM, and builds a searchable second brain — all without sending data to third-party services. LLM inference runs against any OpenAI-compatible local server on your machine — defaults target oMLX ↗ (continuous batching + tiered KV cache for Apple Silicon), and LM Studio ↗ works as a drop-in alternative. Telemetry is off by default and points at localhost when on. See Privacy and Security for the full data-flow story.

Why hippo

Hippo solves a problem that shell history (~/.zsh_history, fish history, Atuin) and consumer “memory” tools (Rewind, Apple Continuity) don’t:

If you want a faster ^R, use Atuin. If you want hippo’s setup, keep reading.

Quick Install (Apple Silicon)

curl -fsSL https://github.com/stevencarpenter/hippo/releases/latest/download/install.sh | bash

The release binaries are arm64-only. Intel Macs need to build from source — see Manual Installation.

The installer downloads the daemon and brain with checksum verification, writes LaunchAgent plists, and prints a hippo doctor summary on completion. See the install script source at the link above for what it touches.

Verify it’s working

After install, generate ~5 minutes of shell + browser activity, then:

hippo doctor                                # green across the board?
hippo events --since 30m                    # are events landing?
hippo ask "what have I been working on"     # synthesized answer + cited sources

If hippo events returns nothing, see Troubleshooting below — the most common cause is the shell hook not being sourced.

Architecture

+-----------+                  +--------------+                +--------------+
|  zsh      |  Unix socket     |              |  SQLite (WAL)  |              |
|  shell    | ---------------> |              | <------------> | hippo-brain  |
+-----------+                  |              |                | (Python)     |
+-----------+  FSEvents        | hippo-daemon |                +------+-------+
|  Claude   |  watcher         | (Rust)       |                       |
|  Code     | ---------------> |              |                +------+-------+
+-----------+                  |              |                |  hippo-mcp   |
+-----------+  Native Msg      |              |                | (MCP server) |
|  Firefox  | ---------------> |              |                +--------------+
|  ext.     |                  |              |                  ^         |
+-----------+                  +--------------+           stdio  |  SQLite |
                                                        (JSONL) | sqlite-vec |
                                                                |  LM API |
                                                          Claude Code / Desktop
ComponentLanguageRole
hippo-daemonRustCaptures events via Unix socket and Native Messaging. Applies secret redaction, stores to SQLite, serves CLI queries.
hippo-brainPythonPolls enrichment queues, calls the local inference server for summarization, correlates browser research with shell activity, writes knowledge nodes + vector embeddings to SQLite via sqlite-vec.
hippo-mcpPythonMCP server exposing the knowledge base over stdio. Claude Code queries your personal knowledge base mid-conversation.

Five core LaunchAgents run under gui/$(id -u):

AgentRole
com.hippo.daemonLong-lived Rust daemon (KeepAlive)
com.hippo.brainLong-lived Python brain server (KeepAlive)
com.hippo.claude-session-watcherFSEvents watcher on ~/.claude/projects/**/*.jsonl (KeepAlive); ingests Claude Code sessions
com.hippo.watchdogCapture-reliability monitor; runs every 60 s, asserts I-1..I-12 invariants, writes capture_alarms rows
com.hippo.probeSynthetic canary probes; runs every 5 min, round-trips a real event through each capture path and records latency in source_health

hippo daemon install --force writes the plists and bootstraps all five. The capture-reliability stack (source health, invariants, watchdog, probes, alarms) is documented in docs/capture/ — start with architecture.md. For an end-to-end trace of how a shell command, Claude session segment, or browser visit becomes a knowledge node, see docs/lifecycle.md. Review-blocker rules every contributor must follow live in docs/capture/anti-patterns.md.

If Hippo is configured to use oMLX, mise run install:omlx installs an optional com.hippo.omlx LaunchAgent. It starts /opt/homebrew/opt/omlx/bin/omlx serve on 127.0.0.1:8000 at login and keeps it in Hippo’s service lifecycle, so no terminal session has to stay open.

Prerequisites

DependencyRequiredNotes
macOS Apple Silicon (arm64)Yes for binariesIntel needs to build from source. Uses launchd for service management.
Rust ↗YesEdition 2024 via the shipped rust-toolchain.toml (1.95). mise.toml enables Rust idiomatic version-file management.
Python ↗Yes3.14+
uv ↗YesPython package manager
oMLX ↗ or LM Studio ↗YesLocal OpenAI-compatible LLM server. Default config targets oMLX on :8000 and the Qwen3.6-35B-A3B-UD-MLX-4bit chat model + nomicai-modernbert-embed-base-8bit embeddings (768d MLX). Plan on 32 GB+ unified memory for the default chat model; smaller models work with smaller machines — adjust the [models] section. LM Studio users: change [inference].base_url to http://localhost:1234/v1 and use LM Studio’s model IDs (e.g. qwen3.6-35b-a3b-ud-mlx, text-embedding-nomic-embed-text-v2-moe).
mise ↗RecommendedTask runner; all workflows are defined in mise.toml
glow ↗RecommendedRenders hippo ask markdown output in the terminal
Firefox Dev Edition ↗OptionalBrowser activity capture (allowlisted developer domains)

Manual Installation

# Clone hippo and enter the repo
git clone https://github.com/stevencarpenter/hippo.git
cd hippo

# Build and install everything (release binary, LaunchAgents, config, symlink)
mise run install

# Add shell hooks to your zsh config
echo "source $(pwd)/shell/hippo-env.zsh" >> ~/.zshenv
echo "source $(pwd)/shell/hippo.zsh"     >> ~/.zshrc
exec zsh  # reload

# Configure your inference server + models
hippo config edit

# Optional: make oMLX start through launchd for Hippo
mise run install:omlx

In the config editor, set the [models] section to match models loaded on your inference server. To list loaded models (default is omlx on :8000; LM Studio users use :1234):

curl -s http://localhost:8000/v1/models | python3 -m json.tool

Then edit:

[inference]
base_url = "http://localhost:8000/v1"   # omlx default; LM Studio uses :1234

[models]
enrichment = "your-chat-model"
enrichment_bulk = "your-chat-model"
query = "your-chat-model"
embedding = "your-embedding-model"      # 768d; e.g. nomicai-modernbert-embed-base-8bit (omlx) or text-embedding-nomic-embed-text-v2-moe (LM Studio)

Verify everything is wired up:

hippo doctor

If anything is red, run hippo doctor --explain for CAUSE / FIX / DOC per failure.

Usage

hippo status                            # Daemon status
hippo sessions --today                  # List today's sessions
hippo events --since 2h                 # Recent shell events
hippo ask "how did I fix that build error"  # RAG query (synthesized answer)
hippo query --raw "cargo build"         # Raw lexical search (no brain needed)
hippo entities                          # Known projects, tools, files, env vars
hippo export-training --since 30d --out ./export  # Export training data
hippo redact test "password=hunter2"    # Test redaction patterns

Operational:

hippo doctor                            # Run diagnostic checks; non-zero exit on any [!!]
hippo doctor --explain                  # Same, with CAUSE/FIX/DOC for each failure
hippo alarms list                       # Unacknowledged capture alarms (exit 1 if any)
hippo alarms ack <id> --note "..."      # Acknowledge an alarm
hippo probe --source claude-session     # Run a synthetic probe for one source
hippo ingest claude-session <path>      # Manual one-shot import of a JSONL (recovery)

Capture-reliability operator runbook (recipes for “I ran a command but it’s not in hippo events”, “doctor shows red”, “schema mismatch”, etc.): docs/capture/operator-runbook.md.

Troubleshooting

Common first-day failures, in rough order of frequency:

SymptomLikely causeFix
hippo events returns nothing after several minutes of shell activityShell hook not sourced — ~/.zshrc / ~/.zshenv weren’t reloaded after install.exec zsh or open a new terminal. Verify with grep -l 'hippo.zsh' ~/.zshrc ~/.zshenv ~/.config/zsh/*.zsh 2>/dev/null.
hippo ask returns “I don’t have enough information”Brain hasn’t enriched yet, or the configured chat model isn’t loaded.hippo doctor to confirm. Open omlx (or LM Studio) and load the model in [models].enrichment.
hippo doctor says inference server isn’t reachableomlx/LM Studio isn’t running, or it’s serving on a non-default port.Start the server. For oMLX, run mise run install:omlx; for LM Studio, start it manually. Check the API base URL in ~/.config/hippo/config.toml ([inference].base_url). The legacy [lmstudio] section is rejected with a migration error — rename it to [inference].
Daemon won’t start; hippo doctor says schema mismatchDaemon and brain have different EXPECTED_SCHEMA_VERSION constants — happens after partial upgrades.mise run install --clean brings everything to the same version.
Brain queue backs upConfigured chat model unloaded or swapped for one not in [models].enrichment.Load the configured model. The reaper handles transient locks; persistent backlog is operator-visible. See docs/brain-watchdog.md.
Firefox extension shows no recent visitsNative messaging manifest missing, or extension not loaded.hippo daemon install --force rewrites the manifest. Reload the extension in about:debugging. See extension/firefox/README.md.

For anything not in this table, run hippo doctor --explain and follow the DOC link in each failure block. The full operator runbook lives at docs/capture/operator-runbook.md.

MCP Server

The MCP server lets Claude Code (or any MCP client) query your knowledge base mid-conversation.

ToolDescription
askRAG query — synthesizes an answer from relevant knowledge nodes
search_knowledgeSemantic or lexical search over enriched knowledge nodes
search_hybridHybrid sqlite-vec + FTS5 search with score fusion
search_eventsSearch raw events (shell commands, Claude sessions, browser visits)
get_entitiesList extracted entities (projects, tools, files, env vars, concepts)
list_projects / get_context / get_ci_status / get_lessonsDiscovery + auxiliary lookups

Full reference with arguments, return shapes, examples, and selection guide: docs/mcp-reference.md.

Add to your Claude Code MCP config (e.g., ~/.claude/settings.json or your MCP config file):

{
  "mcpServers": {
    "hippo": {
      "type": "stdio",
      "command": "uv",
      "args": ["run", "--project", "/path/to/hippo/brain", "hippo-mcp"]
    }
  }
}

Replace /path/to/hippo with the absolute path to your clone.

The MCP server reads SQLite directly (vectors live in the same DB via sqlite-vec; no dependency on the brain HTTP server).

Trust boundary. Granting Claude Code MCP access to hippo gives the model — and any prompt injection that reaches it through code or documents you ask Claude to read — read access to your shell history, Claude transcripts, and browser data. Grant deliberately.

Firefox Extension (Optional)

# Build + install in one step (also called by `mise run install`)
mise run install:ext

This builds the extension and side-loads the .xpi into your Firefox Dev Edition dev-edition-default profile. For development / hot-reload, extension/firefox/README.md covers the manual about:debugging flow.

The native messaging host is installed by hippo daemon install --force (also called by mise run install).

Configuration

FilePurpose
~/.config/hippo/config.tomlRuntime config (models, ports, browser allowlist, telemetry, GitHub token)
~/.config/hippo/redact.tomlSecret redaction patterns (regex-based)

Created automatically by mise run install. Edit with hippo config edit. See config/config.default.toml and config/redact.default.toml for the templates and inline documentation of each key.

The [models] section must be configured for enrichment to work. Set the model name to whatever your inference server exposes — verify with curl -s http://localhost:8000/v1/models | python3 -m json.tool (or :1234 for LM Studio).

Privacy and Security

Hippo captures shell commands (including stdout/stderr), Claude Code session transcripts, and browser visits from allowlisted domains. All data is stored locally in ~/.local/share/hippo/hippo.db (SQLite, unencrypted — use macOS FileVault for full-disk encryption). No data is sent to Anthropic, OpenAI, or any cloud service.

LLM calls are local. Enrichment and RAG queries go to whichever local OpenAI-compatible server you configure ([inference].base_url, default http://localhost:8000/v1 for omlx). If you point that URL at a remote backend, your shell history and session transcripts travel that path.

Redaction is best-effort. Hippo redacts known secret formats (AWS keys, GitHub tokens, password= assignments, JWTs, PEM headers) before storage. Regex-based redaction cannot catch secrets in positional arguments, non-standard env-var names, or multi-line stdout payloads. Treat it as a noise filter, not a security guarantee. Test patterns with hippo redact test "your candidate string". Full reference (default rules, evaluation model, custom patterns, known false-negatives, browser URL redaction): docs/redaction.md.

The SQLite database is accessible to any process running as your user. Single-user assumption. Consider restricting ~/.local/share/hippo/ to 700 if you share the machine.

MCP access is broad. Adding hippo to Claude Code’s MCP config grants the model read access to your shell history, Claude transcripts, and browser history — including via prompt injection through code or documents you ask Claude to read.

Telemetry is off by default. The OTel stack (otel/) is optional, points at localhost:4317, and only emits when [telemetry] enabled = true. See otel/README.md.

Network exposure. The brain HTTP server binds 127.0.0.1:9175. The daemon’s Unix socket lives at ~/.local/share/hippo/daemon.sock.

Uninstall. Stop services with mise run stop, remove ~/.local/share/hippo/, ~/.config/hippo/, and unload the LaunchAgents (launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.hippo.*.plist, then delete the plists).

Development

mise run build              # Build Rust crates (debug)
mise run build:release      # Build Rust crates (release)
mise run build:brain        # Sync Python dependencies
mise run test               # Full test suite (Rust + Python + lint + format check)
mise run lint               # clippy + ruff check
mise run fmt                # Format all code
mise run doctor             # Diagnostic checks

Run mise tasks for the complete list.

Without mise

# Rust
cargo build                                      # default features include `otel`
cargo build --no-default-features                # build without OTel instrumentation
cargo test --workspace --locked --no-fail-fast   # matches CI
cargo clippy --all-targets --locked -- -D warnings
cargo fmt --check

# Python
uv sync --project brain
uv run --project brain pytest brain/tests -v
uv run --project brain ruff check brain/
uv run --project brain ruff format --check brain/

# MCP server
uv run --project brain hippo-mcp

HippoGUI (separate repository)

The native macOS GUI lives in its own repo: stevencarpenter/hippo-gui ↗. It’s a standalone Swift/Xcode app that talks to the daemon over the local socket and the brain over HTTP — build and release it from there.

Service management

mise run start              # Start daemon + brain via launchd
mise run stop               # Stop both services
mise run restart            # Stop + start
mise run nuke               # SIGKILL everything (preserves data)
mise run install:omlx       # Optional: install + start Hippo's oMLX LaunchAgent

Contributing

See CONTRIBUTING.md — setup, test strategy, dev loop, cross-language coupling, CI, PR conventions, and where to ask. Review blockers for the capture layer are codified in docs/capture/anti-patterns.md (AP-1 through AP-12); read them before your first capture-layer PR.

Project Structure

crates/
  hippo-core/              Shared library (types, config, storage, redaction; SQL schema in src/schema.sql)
  hippo-daemon/            Binary (daemon + CLI + native messaging host)
brain/                     Python enrichment, query server, and MCP server
extension/
  firefox/                 Firefox WebExtension for browser activity capture
shell/                     zsh hooks (preexec/precmd integration)
config/                    Default config templates
launchd/                   macOS LaunchAgent plist templates
scripts/                   Utility scripts (bulk enrich, re-embed, monitor, dedup-entities)
otel/                      OpenTelemetry observability stack (docker-compose)
docs/                      Live reference docs (capture/, release.md, eval-harness-design.md, brain-watchdog.md)
docs/superpowers/          In-flight feature plans + designs
docs/archive/              Historical plans, design records, post-mortems
tools/                     Developer utilities (SQL formatting)

Data Storage

All paths follow XDG defaults. Override with XDG_DATA_HOME / XDG_CONFIG_HOME.

StorePathPurpose
SQLite~/.local/share/hippo/hippo.dbEvents, sessions, browser visits, enrichment queue, knowledge nodes, entities, vector embeddings (sqlite-vec). Schema lives at crates/hippo-core/src/schema.sql.
Config~/.config/hippo/config.tomlUser configuration
Logs~/.local/share/hippo/*.logDaemon and brain logs
Fallback~/.local/share/hippo/*.fallback.jsonlLast-resort durability backstop when the daemon socket is unreachable; replayed on next daemon start

Schema uses PRAGMA user_version = N (current: v14). Daemon and brain handshake on this constant at startup. See docs/schema.md for the per-version changelog, table map, and version-mismatch recovery; see docs/release.md for the lockstep release workflow.

License

MIT ↗