Architecture

ArchitectureπŸ”—

LocalGPT is one Cargo workspace: the assistant, the world apps (the desktop app, Gen, MD, Verse, previs) and the world-format crates they all share. MD and Verse used to be repositories of their own and were folded in so the format could not drift between apps; the format itself then moved out to the Open World Format, whose Rust reference this workspace consumes as the openworldformat crate.

Workspace StructureπŸ”—

crates/
β”œβ”€β”€ core/         # localgpt-core β€” the shared library: agent, memory, config, security, MCP, cron, hooks
β”œβ”€β”€ cli/          # localgpt β€” the main binary: clap CLI, TUI, desktop GUI, daemon, `localgpt world`
β”œβ”€β”€ cli-tools/    # localgpt-cli-tools β€” the dangerous tools: bash, read/write/edit_file, browser
β”œβ”€β”€ server/       # localgpt-server β€” HTTP/WS API, OpenAI-compatible API, TLS, BridgeManager
β”œβ”€β”€ sandbox/      # localgpt-sandbox β€” Landlock/Seatbelt kernel-enforced shell isolation
β”œβ”€β”€ mobile-ffi/   # localgpt-mobile-ffi β€” UniFFI bindings for iOS/Android
β”œβ”€β”€ gen/          # localgpt-gen β€” the world builder (Bevy): interactive, MCP server, headless, sessions, live canvas
β”œβ”€β”€ app/          # localgpt-app β€” the one desktop app: Gen's shell with documents, songs and packages as modes
β”œβ”€β”€ md/           # localgpt-md β€” a Markdown file as a walkable world (pure lib + Bevy bin)
β”œβ”€β”€ verse/        # localgpt-verse β€” a 3D world for every song (lib + Bevy bin)
β”œβ”€β”€ previs/       # localgpt-previs β€” screenplay β†’ per-scene .world with set/cast/coverage, a board, a shot list
β”œβ”€β”€ previs-web/   # localgpt-previs-web β€” previs's draft as WASM, for the localgpt.md page
β”œβ”€β”€ world-types/  # localgpt-world-types β€” the world data model (serde only; the format's types re-exported)
β”œβ”€β”€ world-bevy/   # localgpt-world-bevy β€” the one Bevy mapping of the format (Gen, MD, Verse, the app)
β”œβ”€β”€ world-audio/  # localgpt-world-audio β€” the one mapping of the format's audio (kira + FunDSP)
β”œβ”€β”€ world-export/ # localgpt-world-export β€” the three.js viewer and HTML export, no Bevy
β”œβ”€β”€ world-sync/   # localgpt-world-sync β€” collaborative rooms: shared document, ops, wire protocol, authority
β”œβ”€β”€ world-editor/ # localgpt-world-editor β€” the non-linear editing model: tips, forks, folds, deltas
β”œβ”€β”€ world-agent/  # localgpt-world-agent β€” the live authority, packages, headless commands, the tool-call protocol
β”œβ”€β”€ relay/        # localgpt-relay β€” internet reach for collaborative rooms
β”œβ”€β”€ bridge/       # localgpt-bridge β€” secure IPC protocol for bridge daemons
└── spacetime/    # localgpt-spacetime β€” SpacetimeDB multiplayer module (standalone; wasm toolchain)

bridges/
└── cli/          # localgpt-bridge-cli β€” a terminal that connects to a running daemon over the IPC socket

apps/
β”œβ”€β”€ apple/        # iOS/macOS (Swift, UniFFI)
β”œβ”€β”€ android/      # Android (Kotlin, UniFFI)
β”œβ”€β”€ app-desktop/  # the LocalGPT.app bundler (Developer ID + notarization when given)
└── web/          # web client

website*/         # one Cloudflare Worker each: localgpt.app (this site), gen., verse., localgpt.md, localgpt.world
scripts/          # fetch-model.sh and fetch-assets.sh β€” the two downloads every app shares

Dependency GraphπŸ”—

                        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                        β”‚ localgpt-core   β”‚  (no internal deps; compiles for iOS and Android)
                        β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
         β–Ό               β–Ό       β–Ό        β–Ό              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ localgpt-    β”‚ β”‚ localgpt-  β”‚ β”‚ gen  β”‚ β”‚ mobile β”‚ β”‚ world-types  β”‚
β”‚ bridge       β”‚ β”‚ sandbox    β”‚ β”‚      β”‚ β”‚ -ffi   β”‚ β”‚ (serde only) β”‚
β”‚ (no internal)β”‚ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚                                   β”‚
       β”‚               β–Ό                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
       β”‚     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β–Ό                 β–Ό              β–Ό           β–Ό
       β”‚     β”‚ localgpt-cli-    β”‚   world-bevy        world-export    world-sync   world-agent
       β”‚     β”‚ tools (core+     β”‚   world-audio       (three.js)      world-editor (the authority)
       β”‚     β”‚  sandbox)        β”‚   (Bevy, kira)                      previs
       β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚                 β”‚              β”‚           β”‚
       β–Ό              β”‚                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚                           β–Ό
β”‚ localgpt-server β”‚   β”‚                 gen ─► app (md + verse as libs)
β”‚ (core + bridge) β”‚   β”‚                 md, verse, previs-web
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
         β–Ό            β–Ό
      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
      β”‚ localgpt (CLI)           β”‚
      β”‚ core + server + sandbox  β”‚
      β”‚ + cli-tools + world-agentβ”‚
      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Bridge daemons depend on core + bridge. Mobile depends on core with default-features = false plus local embeddings and sqlite-vec.

Crate SummaryπŸ”—

CrateTypePurpose
localgpt-corelibAgent, providers, memory, config, security, MCP client and server, cron, hooks. Zero platform-specific dependencies
localgptbinThe assistant’s CLI, TUI, desktop GUI and daemon, and localgpt world
localgpt-cli-toolslibThe dangerous tools (shell, files, browser) the CLI and daemon inject; never in core
localgpt-serverlibHTTP/WebSocket API, OpenAI-compatible surface, embedded web UI, TLS, BridgeManager
localgpt-sandboxlibLandlock/seccomp, Seatbelt and container sandboxing for shell commands
localgpt-bridgelibIPC protocol for bridge daemons
localgpt-bridge-clibinTerminal chat over the daemon’s bridge socket
localgpt-mobile-ffilib+binUniFFI bindings; LocalGPTClient owns a tokio runtime and an AgentHandle
localgpt-genlib+binThe world builder: Bevy viewport, the agent loop, 77 tools, MCP server and relay, headless, sessions, the live canvas
localgpt-appbinThe one desktop app, assembled from the gen library with MD and Verse as libraries (not published)
localgpt-mdlib+binMarkdown β†’ sections β†’ a world; the pure library is what the app compiles documents with
localgpt-verselib+binSong analysis β†’ mood β†’ a furnished, performing world; song_world is what the app calls
localgpt-previslib+binScreenplay β†’ per-scene .world, board and shot list; deterministic, no model, no network
localgpt-previs-weblibThe same draft as WASM for localgpt.md (not published)
localgpt-world-typeslibThe data model: the format’s types re-exported, plus NPCs, behavior libraries, regions, sync drift. schema writes world.schema.json
localgpt-world-bevylibThe only place a shape, material, light or environment becomes Bevy components
localgpt-world-audiolibOne kira AudioManager; FunDSP graphs as sources; ambience, spatial emitters, soundtracks
localgpt-world-exportlibThe three.js viewer (vendored from the format’s npm package) and generate_html; no Bevy
localgpt-world-synclibShared world document, validated EditOps, the wire protocol, the room authority; no Bevy, no I/O
localgpt-world-editorlibHistory as a tree: a branch index, a fold cache fast enough to scrub, deltas between tips
localgpt-world-agentlibLiveWorld (the live authority), packages, the headless commands behind localgpt world, the tool-call protocol, the shared download paths
localgpt-relaybinForwards WebSocket frames between a host and its guests by room code; never holds world state (not published)
localgpt-spacetimemoduleSpacetimeDB rooms: the same ops and validation as a LAN host, in the cloud (standalone workspace)

The world format is sharedπŸ”—

Every app reads and writes one format. localgpt-world-types is the source: the Open World Format’s document, session and state types come from the openworldformat crate and are re-exported unchanged, and the crate adds LocalGPT’s own surface on top. localgpt-world-bevy is the only place those types become Bevy components, so Gen, MD, Verse and the app render identically; localgpt-world-audio is the one mapping of the format’s audio; localgpt-world-export holds the only web renderer, the same three.js viewer localgpt.world serves and every exported HTML page embeds.

Reference scenes live in crates/world-types/conformance/ and are rendered by both renderers; the web viewer’s headless render check runs in CI. The rule inside the workspace: add fields to world-types, never a parallel format β€” proposals that change what the format means belong in the format’s own repository.

A .world package is a folder: manifest.json (the head), ops.jsonl (the log), assets/ (content-addressed), AGENTS.md. LiveWorld in world-agent is the one authority that commits to it β€” from the window (live canvas) or from localgpt world β€” and world-editor is the view that follows: tips, forks, folds and deltas, which the history rail and panel draw.

Core LibrariesπŸ”—

localgpt-coreπŸ”—

Foundation library with zero platform-specific dependencies, compiled for aarch64-apple-ios and aarch64-linux-android as well as the desktop:

  • Agent: the LLMProvider trait and its implementations (Anthropic, OpenAI and OpenAI-compatible, xAI, Gemini, Vertex AI, GLM, Ollama, Claude/Gemini/Codex CLIs), model aliases, failover, compaction, checkpoints, tool filters, approval
  • Memory: SQLite FTS5 + sqlite-vec with local embeddings, Markdown and no-op backends, active recall, dreaming (background consolidation), the wiki
  • Config: TOML with XDG path resolution, migration and hot reload
  • Security: POLICY.md injection and sanitization, protected files, SSRF guards, the hardcoded security suffix
  • Heartbeat and cron: autonomous runs, each job in a fresh session, with a durable outbox
  • MCP: a client for external servers (stdio, HTTP/SSE) and a server exposing memory tools
  • Session: conversation management with automatic compaction and branching

Safe tools only (create_safe_tools): memory, web, documents, audio transcription, wiki, spawn_agent. The CLI and daemon inject the dangerous tools from localgpt-cli-tools; server agents and bridges never get them.

localgpt-bridgeπŸ”—

IPC protocol for daemon-to-bridge communication: tarpc-based async RPC, peer identity verification (Unix UID/GID), credential exchange, Unix sockets and Windows named pipes.

Desktop ComponentsπŸ”—

localgpt-serverπŸ”—

  • Axum HTTP: REST API, the OpenAI-compatible /v1/chat/completions and /v1/models, the embedded web UI (RustEmbed), the tool-approval endpoint
  • WebSocket: real-time chat streaming
  • BridgeManager: the socket server for bridge daemons
  • TLS and per-IP rate limiting

localgpt-sandboxπŸ”—

PlatformTechnology
LinuxLandlock + seccomp
macOSSeatbelt (sandbox-init)
AnyDocker / Podman as a backend
WindowsRestricted tokens

Falls back gracefully on unsupported systems.

BinariesπŸ”—

localgpt (CLI)πŸ”—

CommandPurpose
chat, tui, askconversation
daemonHTTP server + web UI + heartbeat + cron
worlda .world package’s command line: init, submit, undo, log, tips, verify, history, and mcp β€” the open canvas’s tools over stdio
mcp-servermemory and web tools over stdio for other agents
memory, config, policy, session, cron, hooks, toolthe workspace and the daemon’s services
sandbox, cert, doctor, paths, init, completionsetup and diagnostics
genlaunches localgpt-gen

localgpt-genπŸ”—

The world builder: a Bevy window with the agent loop and 77 gen_* tools in three profiles; mcp-server (stdio, --mcp-http, --connect to a running window’s relay); headless generation; --host/--join/--web/--relay collaborative sessions over world-sync; --live for the live canvas; --replay. See LocalGPT Gen.

localgpt-appπŸ”—

The desktop app: Gen’s shell plus --md, --song and --world. Thin by design β€” everything heavy comes from the gen library, MD’s pure library compiles documents, Verse’s library builds song worlds, and the prompt panel runs Gen’s own agent loop.

localgpt-previsπŸ”—

Script to board, deterministic: Fountain, Final Draft .fdx, PDF or Markdown pages in; per scene a .world with set, cast and coverage, plus board.html and shotlist.csv. The same draft function runs as WASM on localgpt.md. See Previs.

localgpt-relayπŸ”—

Internet reach for collaborative rooms: forwards frames between a NAT’d host and its guests by room code.

System PromptπŸ”—

Every agent in the family shares the base system prompt built by build_system_prompt() in localgpt-core: identity, safety guidelines, the registered tools’ documentation, the workspace and the current time, memory conventions, runtime info. On a new session the agent loads its workspace context (SOUL.md, MEMORY.md, daily logs, HEARTBEAT.md) and appends it.

CLIGen and the appServer / Mobile
Agent creationAgent::new() β€” async, connects MCP serversAgent::new_with_tools() β€” the gen toolbelt at the chosen profileAgent::new() β€” safe tools only
ToolsSafe tools + CLI tools (shell, files) + spawn_agentSafe tools + gen_* tools; interactive Gen adds the CLI tools at the full profileSafe tools only
Workspacethe assistant’s (main agent)Gen’s own (gen agent, gen-settings.json); no config.tomlthe assistant’s
Extra promptsNonecreative-memory guidance and the headless experiment prompt, injected as user messagesNone

The world modes keep their own settings and workspace so nothing from the assistant’s memory reaches a world or a shared session unless the user puts it there.

MobileπŸ”—

localgpt-mobile-ffi exposes LocalGPTClient (an Arc<Mutex<Agent>> with its own tokio runtime) through UniFFI proc-macros. Build outputs: liblocalgpt_mobile.a + Swift bindings β†’ an XCFramework for iOS/macOS; liblocalgpt_mobile.so + Kotlin bindings β†’ an AAR for Android. Core is built with embeddings-local + sqlite-vec and none of the subprocess providers or HTTP.

Bridge DaemonπŸ”—

A standalone binary that connects to the running daemon over the IPC protocol in localgpt-bridge; localgpt-bridge-cli is the terminal one (rustyline).

Design PrinciplesπŸ”—

  1. Core stays portable β€” localgpt-core compiles for iOS and Android with no desktop dependencies; clap, eframe, axum, landlock and the like live in cli, server, sandbox, cli-tools or gen.
  2. Dangerous tools live in cli-tools β€” never in core’s safe set; server agents and bridges never see them.
  3. One format, one mapping each β€” fields go into world-types; world-bevy, world-audio and world-export are the only places the format becomes pixels or sound.
  4. One authority per world β€” LiveWorld commits; the canvas, the editor model and localgpt world follow. A direct write to manifest.json is put back.
  5. Feature flags for the heavy tiers β€” the in-process LLM, the ML mood model, physics and multiplayer are opt-in, and each has a CI job so gated code cannot rot.
  6. Graceful degradation β€” the sandbox falls back on unsupported systems; a missing model leaves the rule-derived draft on screen.