Skip to content

Local-First AI

chris-os runs its AI infrastructure on local hardware. The database is on a Pi 5 in a network closet. Embeddings are generated on an M4 Pro Mac in the same room. Voice processing happens on local GPUs. The data never leaves the local network unless the owner explicitly sends it somewhere.

This is a deliberate architectural decision, not a cost optimization.

Privacy is structural, not promissory. Cloud services promise not to misuse your data. Local infrastructure makes misuse physically impossible. When your therapy notes, health records, and private messages live on hardware you control, the attack surface is “someone breaks into your house,” not “a vendor changes their terms of service.”

Latency disappears. A database query over a local Docker bridge network takes single-digit milliseconds. The same query through a cloud API, even with connection pooling, takes 50-200ms. When an AI assistant issues 10-20 tool calls in a single conversation, those milliseconds compound. Local MCP endpoints respond fast enough that tool calls feel instant.

You own the uptime. Cloud outages are someone else’s problem that becomes your problem. Local infrastructure fails for local reasons (power, hardware, misconfiguration), and you can fix all of those yourself. A Pi 5 with an NVMe drive and a UPS is more reliable for a single-user system than most managed services.

The data stays unified. One PostgreSQL instance holds everything: 210 tables across 5 schemas. Messages, health records, calendar events, financial transactions, semantic memories, automation state, and Home Assistant history all live in the same database. Queries that join across data types (for example, correlating health patterns with calendar events) are single-database queries, not cross-service API calls.

Running locally does not mean running in isolation. The Model Context Protocol (MCP) bridges local infrastructure and remote AI assistants.

chris-os exposes four MCP endpoints:

EndpointWhat It ExposesUsed By
mcp-dbPostgreSQL (read-write, scoped role)Claude Desktop, Claude Code, claude.ai
mcp-n8nn8n workflow APIClaude Desktop, Claude Code
mcp-memorySemantic memory (vector search + full-text)Claude Desktop, Claude Code, claude.ai
mcp-haHome Assistant (89 tools)Claude Desktop, claude.ai

Each endpoint follows a three-tier pattern: a proxy that wraps the service as MCP-over-HTTP, an auth layer that validates credentials (Cloudflare Access JWT or API key), and Caddy for TLS termination.

The result: Claude can query the database, trigger workflows, search memories, and control the home. But all the data and compute stay local. Claude sees the MCP tool results. It never sees the raw database, the filesystem, or the network.

Local-first AI is not free. Here is what it costs:

Complexity. 37 containers need configuration, monitoring, and maintenance. A cloud-hosted equivalent might be 3-5 managed services. The Docker Compose files, Caddy routing rules, network isolation, and auth middleware all exist because the infrastructure is self-hosted.

Hardware constraints. A Pi 5 with 16GB of RAM cannot run large language models locally. Embedding generation runs on a separate machine (Atlas, M4 Pro with 24GB). The voice pipeline needs a GPU node (Nightwatch). A cloud deployment could scale elastically; local hardware has fixed capacity.

Operational burden. There is no on-call team. If PostgreSQL runs out of disk space at 3 AM, it waits until morning. The monitoring stack (Grafana, Prometheus, Loki, alerting via Pushover) mitigates this, but it does not eliminate it.

No geographic redundancy. The primary copy of everything is on a single Pi in a single location. Offsite backups go to Cloudflare R2, but recovery from a total loss requires restoring to new hardware.

These tradeoffs are acceptable for a personal system with a single user. They would not be acceptable for a multi-user production service. chris-os optimizes for privacy, control, and integration density at the cost of operational simplicity and redundancy.

Local-first does not mean local-only. chris-os uses cloud services where they make sense:

Cloud ServiceWhat It ProvidesWhy Not Local
CloudflareDNS, CDN, tunnel, R2 backupsRequires a global network
Anthropic APIClaude language modelRequires datacenter-scale compute
GitHubSource control, CI runners, project managementCollaboration tooling
Google APIsGmail, Calendar push notificationsIntegration with existing services

The principle is: data and infrastructure stay local; external services provide connectivity and compute that local hardware cannot. The AI models run remotely, but the context they operate on (the database, the memories, the tools) is controlled locally. MCP is the interface that enforces this boundary.