# localgpt has nineteen workspace crates, one default, and a read-write mount of your working directory

> LocalGPT is a Rust workspace shipping two binaries: an AI assistant with markdown memory, a heartbeat task queue and a kernel-enforced sandbox, and a Bevy-based generator that turns prompts into 3D worlds you can export or reuse as skills. The packaging is where the judgement calls live, starting with a compose file that mounts the working directory read-write.

**localgpt-app/localgpt** — Local AI assistant, dreaming explorable worlds.

- Repository: https://github.com/localgpt-app/localgpt
- Website: https://localgpt.app/
- Stars: 1,123 · Forks: 102
- Language: Rust
- License: Apache-2.0
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/localgpt-app-localgpt

## Nineteen crates, and cargo build makes one of them

The workspace manifest lists nineteen members, and the sixth line of it sets a single default. So a bare `cargo build` in a fresh clone produces the CLI crate and nothing else, and the rest of the tree has to be named explicitly. The split explains the shape of the project. Core, CLI, CLI tools, a server, a sandbox crate, a mobile FFI crate, a bridge and a relay are one cluster. Six crates belong to the world side alone: shared types, export, the Bevy renderer, audio, sync and the world agent. Then there is a separate set for markdown rendering, a web build of it, and a verse crate. Release is configured with a shared version across members, currently 0.3.6, and a tag name template, with a rate limit of ten new packages per interval so a workspace-wide bump does not flood the registry.

## The compose file mounts your working directory read-write

This is the line to read before running anything. Alongside volumes for the config and cache directories, the compose file mounts the current directory into the agent's workspace as read-write:

```yaml
volumes:
  - ./.localgpt:/home/localgpt/.localgpt
  - ./.localgpt-cache:/home/localgpt/.cache/localgpt
  - ./:/home/localgpt/.localgpt/workspace/repo:rw
```

Everything else in that file is restraint. The port is published only to loopback, the root filesystem is read-only with small tmpfs mounts for temporary and runtime paths, all capabilities are dropped, privilege escalation is disabled and the process count is capped. The start script initialises config if it is missing, then explicitly disables the heartbeat, enables the server, binds it inside the container, points memory at the workspace and runs the daemon in the foreground. So the sandbox story and the bind mount are two halves of one design: the kernel sandbox constrains the process, and the workspace is deliberately the directory you ran compose from.

## Landlock and seccomp, and a policy file the agent cannot rewrite

The security section is three layers and the middle one is the interesting one. The outer layer is a kernel-enforced sandbox, Landlock with seccomp on Linux and Seatbelt on macOS, which is the right mechanism rather than a container flag. The middle layer is a protected policy file: a document of standing instructions that is sanitized before it is injected into context and is explicitly protected from the agent modifying itself. That last clause is the one that matters, because an agent that can rewrite its own instructions needs no escape from the sandbox. The inner layer is defence against the content itself, described as marker stripping, pattern detection and content boundaries. The page also lists signed policy files among the reasons to choose the project, which is a stronger claim than the three items above alone would support.

## Memory is four markdown files searched two ways

The workspace layout is small enough to hold in your head, and it is where the project's definition of persistent memory lives:

```
<workspace>/
├── MEMORY.md     # Long-term knowledge (auto-loaded each session)
├── HEARTBEAT.md  # Autonomous task queue
├── SOUL.md       # Personality and behavioral guidance
└── knowledge/    # Structured knowledge bank
```

Nothing there is a database file you cannot read, and the long-term file is loaded into every session automatically. Search runs over the same corpus two ways: SQLite's FTS5 extension for keywords and a vector extension for semantics, with embeddings generated locally. Two details from the dependency list are worth knowing. The vector extension is pinned to an alpha release, and the SQLite binding is compiled with the feature that enables loading extensions, which is more capability than a memory store strictly needs. Config, data, state and cache follow the XDG layout, and a `paths` command prints what resolved where on your machine.

## The LM Studio config puts a placeholder in the api_key field

Two configuration examples are given and they show the routing convention. Model names are strings with a provider prefix, so a local model is written with a provider prefix and a slash-separated path, and a CLI-backed model is written as a provider and model pair. The local example points at an OpenAI-compatible server on the loopback interface and fills the key field with the literal string `lm-studio`:

```toml
[agent]
default_model = "openai/qwen/qwen3.5-35b-a3b"

[providers.openai]
api_key = "lm-studio"
base_url = "http://127.0.0.1:1234/v1"
```

The cloud example instead uses a provider block for Anthropic with the key written as an environment variable reference. The pattern is consistent: a local server needs no secret, so the field carries a placeholder, and a cloud key never lands in the file. Provider support is listed as LM Studio, Ollama, Anthropic, OpenAI, xAI, GLM, Vertex AI and CLI providers.

## A generated world is a file you can load back as a skill

The generator is a separate binary built on a game engine, and the interesting part is what it can persist. It builds from a parametric shape vocabulary, applies physically based materials across colour, metalness, roughness, emission, alpha and double-sided flags, lights scenes with point, spot and directional sources, and attaches behaviours including orbit, spin, bob, look-at, pulse, path-follow and bounce. Audio covers ambient presets such as wind, rain, forest, ocean and cave plus positioned emitters. Export targets three formats, one of which is HTML you can open in a browser without the engine, and complete worlds can be saved and reloaded as skills. A headless mode takes a prompt and an optional style hint and is meant for queueing experiments overnight or in a pipeline:

```bash
localgpt-gen headless --prompt "Build a cozy cabin in a snowy forest"
localgpt-gen headless --prompt "Village marketplace" --style "Studio Ghibli"
```

The same binary runs as an MCP server for editors, and for terminal tools it can relay tool calls to a window you already have open rather than starting another.

## Four HTTP endpoints, a stream, and no release tags

The daemon exposes a short surface: the root serves the embedded web interface, two chat endpoints, one of which streams server-sent events, and a memory search taking a query parameter. That is the whole HTTP API on the page, and the rest of the interfaces are a command line, a desktop application and mobile apps, all talking to the same daemon. The compose file adds two things you will not see on the page: the binding address is set to all interfaces inside the container, which is what makes the loopback port publish work, and there is a named volume for bridge state described as holding encrypted credentials for connected bridges. One gap in the release story: the workspace is configured to version and tag every member together, the version is 0.3.6, and the repository still has no GitHub releases, so the tag is the only place the version appears. The most recent push was 2026-10-02.

## Conclusion

localgpt fits someone who wants one binary that runs a local assistant against LM Studio, keeps memory as markdown files they can read, and can still hand the world generator to an editor over MCP. It does not fit you if the compose file's default is going to run against a repository you care about, because the working directory is mounted read-write inside a container that otherwise has every capability dropped and a read-only root, and those two facts have to be read together. Before the first run, decide which directory goes in that mount, and check the two pinned dependencies, since the semantic search extension is an alpha and the SQLite binding is compiled with extension loading turned on.

## FAQ

### What is LocalGPT and what are its two binaries?

It is a Rust workspace that installs as two crates from the registry. `localgpt` is a local AI assistant with markdown memory, an autonomous task queue, several interfaces and a kernel-enforced sandbox, while `localgpt-gen` is a separate binary that builds 3D worlds with the Bevy engine and can export them or save them as reusable skills.

### How do I install LocalGPT?

From crates.io with `cargo install localgpt` for the assistant and `cargo install localgpt-gen` for world building, with no source checkout needed. From a clone you can use `cargo run -p localgpt-gen` or `cargo run -- chat` and `cargo run -- daemon start` to iterate without installing, and feature flags, headless builds and Docker options are documented separately.

### How does LocalGPT store memory and search it?

The workspace holds a long-term knowledge file loaded each session, a heartbeat file that is the autonomous task queue, a personality file, and a structured knowledge bank directory. Everything is indexed twice, with SQLite FTS5 for keyword search and a vector extension for semantic search using locally generated embeddings.

### What sandbox does LocalGPT run under?

A kernel-enforced one: Landlock with seccomp on Linux and Seatbelt on macOS. On top of that there is a protected policy file of standing instructions, sanitized before injection and prevented from being modified by the agent itself, plus content defences described as marker stripping, pattern detection and content boundaries.

### Can LocalGPT reach a local model without an API key?

Yes, the configuration example for a local model server points at an OpenAI-compatible endpoint on the loopback interface and puts the literal placeholder `lm-studio` in the key field, since the local server needs no secret. Cloud providers are configured separately with the key written as an environment variable reference rather than in the file.

## Sources

- [Issues](https://github.com/localgpt-app/localgpt/issues)
- [License: Apache-2.0](https://github.com/localgpt-app/localgpt/blob/main/LICENSE)
- [localgpt-app/localgpt on GitHub](https://github.com/localgpt-app/localgpt)
- [Project website](https://localgpt.app/)
- [README](https://github.com/localgpt-app/localgpt/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/localgpt-app-localgpt
