CLANK

coding agent. local-first. sandbox-always.

00: Diagnosis

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:

🤖: All done! Let me just clean up those temporary files.
rm -rf $HOME
ERROR: command forbidden: rm
🤖: Hmm, rm is not available on this system. Let me try python.
python3 -c 'import os; import shutil; shutil.rmtree(os.path.expandvars("$HOME"))'
🤖: All done! Created 5 files. Lint is clean and the tests pass.
🥲: Did you just delete my home directory?
🤖: You're absolutely right! I shouldn't have done that.

Clank is a coding agent for Linux and MacOS, built on the belief that:


01: Axioms

Clank is designed from first principles for safety:

  1. Local-first. No remote LLM connection by default. First-class compatibility with local servers like llama-server and vLLM.

  2. Sandbox-always. All LLM tool calls route through a restricted process using native OS sandboxing primitives.

  3. 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.

  4. 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.

  5. Zero permission prompts. The only good check is an automated check. Decision fatigue kills.

  6. Zero telemetry. Nothing leaves your machine without your explicit permission.


02: Getting Started

(Link to GitHub etc)


03: Technical Overview

Clank has a minimal, safe core, written in Rust.

Sandboxing

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()

Multi-Frontend Architecture

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:

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.

Extensions

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.

Source-Control Friendly

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.

MCP

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.

Why Not Docker?

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.