Coding agents are security black holes. They read and write your filesystem. They run local shell commands. They send everything they read and everything you say to a datacenter you cannot audit.
LLMs are are trained to compensate for stupidity with persistence, making them naturally adversarial:
Clank is a coding agent for Linux and MacOS, built on the belief that:
Asking for permission on every command trains the user to say “yes.”
Sanitising shell commands with tree-sitter and regex
is not a safeguard.
Adding load-bearing emoji to your 🚨CRITICAL🚨 instructions is just thoughts and prayers.
Safety is feature zero for an agent harness.
Development containers are the last line of defense, not the first.
Clank is designed from first principles for safety:
Local-first. No remote LLM connection by
default. First-class compatibility with local servers like
llama-server and vLLM.
Sandbox-always. All LLM tool calls route through a restricted process using native OS sandboxing primitives.
Deny-all baseline. A sandbox defaults to the
minimum permissions required to launch a sh process. Add
more permissions with allow-lists, then refine further
with deny-lists.
Subagent capabilities are monotonic. The sandbox process tree mirrors the agent dispatch tree. Permissions are inherited structurally. A subagent can do nothing its parent can’t.
Zero permission prompts. The only good check is an automated check. Decision fatigue kills.
Zero telemetry. Nothing leaves your machine without your explicit permission.
(Link to GitHub etc)
Clank has a minimal, safe core, written in Rust.
The clank-sandbox binary implements Clank’s process
sandbox. The sandbox itself is a minimal self-contained program, so its
interfaces and safety properties are easy to reason about.
clank-sandbox irreversibly self-restricts on startup,
according to permissions passed on the command line. It then accepts
RPCs on stdio to perform file access and run shell
commands. The Clank backend holds stdio file descriptors
for all top-level clank-sandbox processes.
The RPC interface also supports spawning and killing child sandboxes.
clank-sandbox passes the child’s permission list straight
from the RPC to the child’s startup arguments; monotonicity of
permissions is enforced structurally, by the operating system
restricting the child according to the parent process’s permissions.
RPCs have a hierarchical destination (pid1.pid2…) to
route RPCs down to child processes, with responses bubbling back up.
clank-sandbox uses the following OS-level sandboxing
primitives to restrict itself:
| OS | Filesystem | Networking |
|---|---|---|
| MacOS | Seatbelt | Seatbelt |
| Linux | Landlock | unshare() |
The clank-core crate implements all backend logic:
spawning and managing sandbox processes, parsing and applying
configuration, communicating with the LLM server, implementing the
tool-call loop, maintaining session state, and persisting sessions to
disk. All communication between frontend and backend is through a pair
of MPSC event queues (one up, one down).
The following frontend binaries statically link with the
clank-core crate to provide a user interface:
clank-tui: Text-mode interface, using
ratatui + crossterm.clank-gui: Graphical interface, using Tauri v2.0.clank-server: Bridges backend MPSCs to TCP, for remote
use from clank-tui or clank-gui.The clank-test crate is a fourth, dummy frontend which
drives the backend MPSCs and implements a dummy LLM HTTP server for
end-to-end testing. The testcases are Rhai scripts, running in the
clank-test embedded Rhai interpreter.
Clank uses the Rhai scripting language for extensions. Don’t know how to write Rhai? That’s fine, your agent does. Clank ships with extensive scripting API documentation and examples built into the binary, so agents have all the information they need without internet access.
Each chat session is stored as a JSONL file under
.clank/sessions in your project tree. The session tree is
stored as a parent pointer within each file – there’s no top-level
index. New messages added to a session are appended to existing session
files. This format is designed to:
If you check your .clank/sessions directory into Git,
every commit now has a plain-text audit trail of all the commands an
agent ran to produce it. If you don’t want that, just add
.clank/sessions to your .gitignore.
If you delete your .clank/sessions, the conversation
record is wiped for good. There’s nothing left hanging around in system
directories.
Clank does not support MCP servers. The most important reason is they break Clank’s process sandboxing model. There are also some philosophical reasons.
MCP is fundamentally a way of passing text commands to an external
process. Clank already provides a tool for this: bash. Your
agent is already trained to use it.
Install the command-line tools your agent needs, and document them in
AGENTS.md. This improves things for both human and robot
developers. If your agent has trouble with a tool, you can run the same
tool to figure out the problem. When your agent runs the tool, it’s
inside its sandbox, so your system is naturally protected from it.
You can use Docker if you want. Clank runs fine inside a Docker container, Bubblewrap, or a full Linux VM.
Clank offers more fine-grained permission control than Docker. Want
to stop your agent from trashing the local Git history? Just add
-w $PWD/.git to your permissions to make .git
read-only for agents. Now you can make commits, but agents can’t.
Good defense comes in layers. Use Docker to enclose your development
environment, if you choose. Use Clank to establish ground rules for what
your agent can do to your development environment, or restrict it to a
single project in a multi-project container. Docker itself has known
gotchas like its tendency to poke holes in ufw firewalls;
building safety into the harness means Docker is not your last line of
defense.