Skip to main content

L O C K I

All-in-one sandboxed worktrees for you and your AIs

 

With Locki, every AI conversation (Claude Code, Codex, etc.) receives its own Git worktree and VM sandbox -- zero interference between agents, zero interference with the host machine. Locki uses a unique sandboxing solution based on Lima and Incus, combining the power of real VMs with the speed of containers. Unlike most sandboxing solutions, Locki can run mostly anything -- from simple Python and Node.js apps to systemd services, containerized applications and full Kuberentes clusters!

 

https://github.com/user-attachments/assets/27c0aeb2-c5ef-4e7f-a293-519499215cc8

 

  • AI-agnostic: Supports Claude Code, Codex, Gemini, Pi, Copilot, OpenCode and more.
  • Fast: After the initial VM setup, spawning a new sandbox takes seconds.
  • Worktree-backed: Code lives in a git worktree on disk, fully under your control.
  • No compromises: Each agent gets a brand new, full-featured machine to develop in.
  • Aggresively cached: PyPI, NPM, Docker Hub and more are cached to ensure fast builds in a fresh sandbox.
  • Safe Git: Agents are only able to modify namespaced branches. Stash is scoped. Hooks are redirected.
  • Agent-friendly: Bundled hand-picked tools and sandbox-specific instructions for best behavior.

Real-world projects are using Locki, including Agent Stack, Kagenti ADK, and DAM.

 

Get Started

  1. Install: uv tool install locki. (Install uv first if you don't have it.)
  2. If on Linux, install QEMU. (Not needed on macOS.)
  3. cd to your Git repository, run: locki ai, follow interactive setup and choose to create a new sandbox. Wait a few minutes for the initial start.
  4. Follow prompts to log in to the AI CLI. Login will be persisted across sandboxes.
  5. Build! Your agent is already instructed on how to behave in the sandbox. Agent can create any branch with #locki-<worktree-id> suffix, and if gh is available on host, even create a pull request.
  6. After merging the branch, run locki rm to delete the worktree.

 

Quick Reference

Commands act on the current worktree if inside one, letting you select interactively otherwise.

Most important commands are:

locki ai   # open AI agent in sandbox (pick existing or new)
locki x    # open Bash in sandbox (pick existing or new)
locki rm   # remove sandbox

See the "pro-tips" section below for more advanced usage like IDE integration, port forwarding, working on multiple repos at once and more! You can also use locki --help anytime for a refresher.

 

Path mapping from host to sandbox

Each sandbox gets its own worktree (a full copy of your repo) and shares a common home folder with other sandboxes. The original repo and your actual home stay safely out of reach:

  • Your Git repo (~/myproject/) — ❌ Not visible from any sandbox. That means sandboxes can't reach the .git folder and mess it up -- all git calls go through a command bridge and get reviewed and filtered.
  • Each sandbox's worktree (~/.local/share/locki/worktrees/myproject-locki-.../) — Visible in corresponding sandbox, at the same path. All edits in the sandbox are instantly visible on host.
  • Shared sandbox home (~/.local/share/locki/home/) — Visible from every sandbox as ~. Save your agent configuration here to use it in sandboxes.
  • Your actual home (~) — ❌ Not visible from any sandbox. Sandboxes can't mess up your global config.

 

Pro-tips for power users

  • Launch an IDE in the worktree folder using locki ide. 30+ editors are recognized out of the box (VSCode, Cursor, Zed, the JetBrains suite, Neovim, Sublime Text, ...), and you can set any custom command via locki setup or ide_command.
    (The IDE runs on host: you still need to run locki ai / locki x -- <cmd> in the built-in terminal to run commands in the sandbox. This is intentional: running your IDE inside the sandbox (using "remote SSH" or similar features) is unsafe, since the agent could potentially access authentication tokens stored in the IDE's memory.)

  • When cd'd into a worktree folder (~/.local/share/locki/worktrees/.../), locki commands use it by default -- otherwise they show an interactive picker. Use --match/-m to select by sandbox id or branch substring. locki list (alias ls) shows every sandbox and its worktree path.

  • Editors like VSCode show worktrees in the sidebar, useful as a quick UI for reviewing and modifying changes.
    (⚠️ VSCode 1.115.0+ requires setting "git.detectWorktrees": true for this to work.)

  • Working on two repos at once? cd into your sandbox's primary repo and run locki include --repo ../other-repo to graft the other repo into the current sandbox at .locki/include/<repo-name>-locki-<sandbox-id>/. Or from the other repo: locki include --this -m <sandbox-id>.

  • While locki ai opens a coding agent, locki exec (or short locki x) is the low-level version which can run any command. Pass a command to run in a sandbox, use --match/-m to select by branch substring or sandbox id: locki exec -m big-refactor -- pytest.

  • The first locki ai run prompts you to pick a default harness and editor. Re-run locki setup to change them, or edit ~/.config/locki/config.toml directly — the keys are full command lines, e.g. ai_command = "gemini --yolo -r" and ide_command = "code .". A repo can override ai_command via a locki.toml in its root; ide_command is user-only (it launches on your host).

  • Ask your agent to forward ports, or use locki port-forward for more control.

  • Locki sandboxes provide Mise for tool version management -- replacing nvm, rbenv, brew etc. with a single tool. Adding mise.toml to your repo with tool versions and task definitions will help agents and humans alike: ask your agent to do it!

  • Want to use custom AI configuration in the VM -- instructions, skills, MCP servers, ...? Sandboxes share a home folder accessible at ~/.local/share/locki/home on host (or $XDG_DATA_HOME/locki/home). For example, you can edit ~/.local/share/locki/home/.claude/CLAUDE.md for sandbox-specific instructions.

  • Something is broken? Try locki vm delete -- it will preserve your worktrees and settings, but the VM and sandboxes will be recreated from scratch on next run.

  • Sandboxes run on Fedora 43. Want a different OS? Create a locki.toml file in repo root referencing either an available OS image, or a local Incus image archive by path. For the local archive format, see the Incus image format documentation. Example:

    # locki.toml
    incus_image = "images:ubuntu/questing"
    

    For local image archives, use a path (relative to repo root) or a glob pattern. When a glob matches multiple files, the right one is picked by architecture substring (e.g. arm64, x86_64):

    incus_image = "images/locki-*.tar.xz"
    

    (Since containers share a binary cache, it is not recommended to mix musl distros (like Alpine) with regular ones.)

 

Comparison

Most sandboxing solutions use one of these techniques:

  • Full VM per sandbox (Vagrant, Multipass): resource-heavy, slow to start
  • MicroVM per sandbox (Firecracker, Apple container): none or limited support for building, running and orchestrating containers
  • OCI container per sandbox (Devcontainers, Distrobox, container-use): none or limited support for building, running and orchestrating containers; potentially unsafe if running VM-less on Linux
  • OS-level jail (Landlock, Bubblewrap, sandbox-exec): just restriction, not isolation (ports collide, image tags get overwritten, etc.)

Locki instead runs one Lima VM hosting many lightweight Incus containers — one shared kernel boundary you can trust, cheap per-sandbox containers, and full support for building and orchestrating containers (even Kubernetes) inside.

 

Security

Locki uses a single Lima VM which can only access the ~/.local/share/locki/worktrees and ~/.local/share/locki/home folders (honoring $XDG_DATA_HOME), which forms the security boundary. The sandboxed programs can read and write to these folders, and also access anything on the internet and local network. Furthermore, a guest-to-host SSH server exposes a limited set of git and gh subcommands, with write access restricted to the sandbox's own namespaced branches and stashes (so an agent in one sandbox cannot alter another sandbox's branch, the main branch, or unrelated stashes). .git files are checked for tampering when hooks are executed against them.

Locki is designed to provide protection for the host operating system and files from being messed up by a malfunctioning AI agent. There is no exfiltration protection, so be aware that API keys exposed to the agents need to be treated as potentially exposed and disposable, with limited scope. (This is no different from running the agent locally, just specifying that Locki does not help here.)

Locki may not provide perfect security, however it is certainly much better than going full --yolo on your bare machine and hoping for the best.

 

How it works

  • Python CLI driving a single Lima VM (both limactl and Lima's guest agents are bundled in the platform wheels — no separate install) that hosts many lightweight Incus containers, one per sandbox. The VM is sized to your full host RAM and CPU count with a 200 GiB sparse disk.
  • A host daemon provides the git/gh/port-forward command bridge (over an SSH forced command bound to loopback) and idles containers and the VM back down when unused.
  • Shared caches across all sandboxes keep repeat work fast: a pull-through container-registry cache (nginx), a shared BuildKit daemon (Docker layers cached across sandboxes), package caches for Mise, cargo, npm/pnpm, pip/uv, go, and more, plus GitHub-release and k3s-installer caching.
  • btrfs with bees deduplication for the container pool, so many similar sandboxes cost little disk. node_modules and .venv are redirected to the shared cache via a per-sandbox symlink (so opening a worktree on the host shows a symlink, not a real directory).
  • Mise provides on-demand, version-managed tools inside each sandbox.

 

Uninstall

locki vm delete
uv tool uninstall locki
rm -rf ~/.local/share/locki ~/.config/locki

 

License

Copyright 2026 Jan Pokorný and contributors

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

locki-0.0.27.tar.gz (75.3 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

locki-0.0.27-py3-none-manylinux_2_34_x86_64.whl (20.9 MB view details)

Uploaded Python 3manylinux: glibc 2.34+ x86-64

locki-0.0.27-py3-none-manylinux_2_34_aarch64.whl (18.9 MB view details)

Uploaded Python 3manylinux: glibc 2.34+ ARM64

locki-0.0.27-py3-none-macosx_12_0_x86_64.whl (21.3 MB view details)

Uploaded Python 3macOS 12.0+ x86-64

locki-0.0.27-py3-none-macosx_12_0_arm64.whl (24.4 MB view details)

Uploaded Python 3macOS 12.0+ ARM64

locki-0.0.27-py3-none-any.whl (82.8 kB view details)

Uploaded Python 3

File details

Details for the file locki-0.0.27.tar.gz.

File metadata

  • Download URL: locki-0.0.27.tar.gz
  • Upload date:
  • Size: 75.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for locki-0.0.27.tar.gz
Algorithm Hash digest
SHA256 b9b64b3a5dc52d06f1f0857dbc5e9108f639ab1044e0d7ab4166df2c7209a8e0
MD5 e20f28f6c1b8046d5e378abdab0d49f8
BLAKE2b-256 4f8c007435efde2e20b8069db566429d96d334a1de251100cea73aec1fe08291

See more details on using hashes here.

File details

Details for the file locki-0.0.27-py3-none-manylinux_2_34_x86_64.whl.

File metadata

  • Download URL: locki-0.0.27-py3-none-manylinux_2_34_x86_64.whl
  • Upload date:
  • Size: 20.9 MB
  • Tags: Python 3, manylinux: glibc 2.34+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for locki-0.0.27-py3-none-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 ee8bc6b29383aa4f974e7220a13b727a28c576f744f936346e39d49770f6ce6f
MD5 3cafda17d850489189554de860eb53f2
BLAKE2b-256 fa7b7579e7d67851fdc1bd43fa866c77c6fb677448707e38df3c87317fe2e416

See more details on using hashes here.

File details

Details for the file locki-0.0.27-py3-none-manylinux_2_34_aarch64.whl.

File metadata

  • Download URL: locki-0.0.27-py3-none-manylinux_2_34_aarch64.whl
  • Upload date:
  • Size: 18.9 MB
  • Tags: Python 3, manylinux: glibc 2.34+ ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for locki-0.0.27-py3-none-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 b126f4dd55c6ceaa465e45ad64c101b5e5f28c9200737f3443dae1e9f7382754
MD5 b4efd86ac09e8a9cba95f4e0f0d95aaf
BLAKE2b-256 e5c9099a2acf22badc7710cf81b699d41df2d3917680aff6dee352c5cedd298d

See more details on using hashes here.

File details

Details for the file locki-0.0.27-py3-none-macosx_12_0_x86_64.whl.

File metadata

  • Download URL: locki-0.0.27-py3-none-macosx_12_0_x86_64.whl
  • Upload date:
  • Size: 21.3 MB
  • Tags: Python 3, macOS 12.0+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for locki-0.0.27-py3-none-macosx_12_0_x86_64.whl
Algorithm Hash digest
SHA256 69c305ec046b977c50485fc7db60c340b7fb4682d17129140fe2b46522100560
MD5 43eda8296afb54b7b4e380fd22b835ca
BLAKE2b-256 3e89d2f2ecfe2e350e9da8baa42e03edeba1b27124f421d94b8dfd2d2da87a36

See more details on using hashes here.

File details

Details for the file locki-0.0.27-py3-none-macosx_12_0_arm64.whl.

File metadata

  • Download URL: locki-0.0.27-py3-none-macosx_12_0_arm64.whl
  • Upload date:
  • Size: 24.4 MB
  • Tags: Python 3, macOS 12.0+ ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for locki-0.0.27-py3-none-macosx_12_0_arm64.whl
Algorithm Hash digest
SHA256 c228d79322de58352be77b18a26c5eef909e93299e17376cb0366c96b6276074
MD5 a9482d1f1e0f33f7f7bccf35456d494d
BLAKE2b-256 96ff6038db398331806d1c229e8ce18055b27814a778fc69e6e81ce9718da081

See more details on using hashes here.

File details

Details for the file locki-0.0.27-py3-none-any.whl.

File metadata

  • Download URL: locki-0.0.27-py3-none-any.whl
  • Upload date:
  • Size: 82.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for locki-0.0.27-py3-none-any.whl
Algorithm Hash digest
SHA256 4dcb6dbbcb0c4481660d7c88e123bed0955018f243f63d242c8920ab9281d227
MD5 835ee8f1a0e6fdb52f9186979d8ce8ff
BLAKE2b-256 4ed0aec72df21a34e9bdfe36eca030811d15e10f477ee7b891d6453e8c125808

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page