Security
Local-first. Plain text you own. Verifiable.
loci is built on a simple principle: your working memory with AI belongs to you. The substrate is a folder of markdown files on your machine. No cloud, no accounts, no lock-in.
Privacy model
loci ships in three forms. Each keeps its network surface as small as the job allows.
| Component | Network access |
|---|---|
| Plain markdown templates | None. Text files. There is nothing to run. |
CLI (loci-cli) | None. Read-only: no network, no inference, no daemons. |
| Desktop app (Tauri) | AI features: no external network by default, talk to a local Ollama instance. An external option exists and is explicit (see below). Separately, an explicit "check again" in Settings fetches the published methodology file from GitHub (see below). |
There is no telemetry, no analytics, no crash reporting in any of loci's shipped forms above: the templates, the CLI, or the desktop app.
This documentation site (docs.loci.garden) is a separate thing from the software: it runs self-hosted Umami for aggregate page-view counts, the same posture as loci.garden's own analytics. No cookies, no cross-site tracking. It records the page path, the referrer, the country (derived from IP, then discarded), browser family, and screen size. IP addresses are hashed in memory and never written to disk. No individual visitor is identifiable from the analytics database. Source: github.com/umami-software/umami. Full disclosure: loci.garden/privacy.
What data loci holds
Your palace is the data: markdown files in a folder you choose. You write them, or your AI writes them with your review. loci does not scrape browsers, index chat sites, or collect anything on its own.
The desktop app additionally keeps:
~/.loci/config.json: app settings, plain JSON
Everything is plain text. grep works. So does deleting the folder.
Desktop inference: local by default, external by choice
The desktop app's AI features call a local Ollama instance. Zero API keys. If Ollama is not running, the feature fails closed: it never silently calls an external API instead.
Every inference endpoint is validated before any HTTP call. Allowed hosts:
localhost,127.0.0.1,[::1]- a Tailscale address in the CGNAT range (
100.64.0.0/10), for palaces that span your own devices
Anything else is rejected. This is an SSRF gate on the inference path, not a preference.
An external brain option exists: it runs the Claude Code CLI already installed on your machine, and its spawns are scoped to the API host. Choosing it is explicit. If the CLI is not present, the call errors. There is no silent external fallback.
The one call to GitHub: checking for methodology updates
The inference allowlist above covers AI features. It does not cover one separate, narrow call: the desktop app can check whether a newer PALACE-METHODOLOGY.md has been published, so it can tell you what's changed.
- Fetches a single fixed URL: the
PALACE-METHODOLOGY.mdfile on themainbranch ofgithub.com/huximaxi/loci, over HTTPS. - Explicit-trigger only: it runs when you click "check again" on the methodology check in Settings. It does not fetch on app startup or on a timer.
- Read-only: the response is a published markdown file. Nothing from your palace is sent with the request.
- This call is outside the inference SSRF gate by design: it is not an inference endpoint, and its target is a single hardcoded GitHub URL rather than a user-configurable host.
The MCP server: shipped backend, no UI yet
The desktop app's Rust backend ships a real MCP server (JSON-RPC 2.0, 127.0.0.1:3456 only) in v0.6.0-beta: two write tools, three read resources, an expose_rooms allowlist, and the X-Loci-Content-Trust / X-Loci-Threat-Gate headers described in the MCP API reference. It is compiled into the release; nothing about it is deferred at the code level.
What is missing is a way to reach it: the shipped frontend never calls its start/stop commands, so today it only starts by invoking start_mcp_server directly, not by clicking anything in the app. Separately, the CLI's own loci serve command does not exist yet; that is a genuinely deferred, different surface. See Architecture and the FAQ for the current status.
The cockpit and instrument embedding
The desktop cockpit renders one tab per instrument your palace generates for itself (self-contained HTML pages). Before an instrument is embedded:
- the file path must be relative and resolve inside the palace root
- traversal and absolute paths are rejected before any read happens
- a canonical-root check catches symlink escapes
These checks are unit-tested. Instruments are embedded via iframe srcdoc after passing them.
Trust and governance
Security in loci is not only code. The substrate ships a governance layer as one of its seven feature sets:
| Mechanism | What it does |
|---|---|
| The Gate | A named human-review checkpoint ([username]GATE) before anything ships, sends, or becomes irreversible. |
| Foreign-process quarantine | Anything that did not originate inside the palace is untrusted. Read it as data before executing. Structure-only access by default; contents by explicit per-item approval. |
| Confirm against disk | The filesystem is ground truth. State is verified against disk before it is asserted. |
| Palace audit | A read-only structural audit across six dimensions (scored out of 30), including tracker integrity. |
| Tool shelf gate ledger | The desktop cockpit records a quarantine verdict per foreign tool: admitted, admitted-escorted, deferred, held-conditional, or rejected. The ledger lists tools; it never loads them. |
For the full boundary rules on external text, see the Quarantine Protocol.
Data at rest
Palace files and config are stored as plaintext. loci relies on OS-level disk encryption:
- macOS: FileVault
- Windows: BitLocker
- Linux: LUKS / dm-crypt
How code reaches the repo
Releases pass through ordered gates, documented in docs/RELEASING.md in the repo:
- Bleed Gate: an automated pre-commit scan of the staged diff for private markers
- Human read: a maintainer reads the full diff
- Commit gate: explicit maintainer approval; a passing scan is necessary, not sufficient
- Recon Gate: an adversarial reconstruction pass on the outbound range, pre-push
A failing check is never bypassed silently.
Open source verification
loci is open source (MIT). The substrate is markdown: read it directly, there is nothing to build.
git clone https://github.com/huximaxi/loci
cd loci
# The templates are the product. Read them.
ls templates/
# Build the CLI from source
cargo install --path loci-cliThe desktop app builds from desktop/ (Tauri). Same source, same behaviour.
Reporting security issues
Do not open a public GitHub issue for vulnerabilities. Use one of these channels:
- Preferred: GitHub Security Advisories. Open a private advisory at github.com/huximaxi/Loci/security/advisories/new.
- Encrypted email, once the project's PGP key is published (in progress).
- Machine-readable contact: loci.garden/.well-known/security.txt (RFC 9116).
What to expect:
- Acknowledgement within 72 hours; triage within one week
- Coordinated disclosure: 90 days by default, faster if a fix ships sooner
- Credit if you want it; pseudonymous credit is fully accepted
There is no monetary bounty programme. There is credit in release notes, and a first call to review related code paths.