leash: eBPF tracing, Cedar policies and a control UI, with release binaries built for one platform
Leash by StrongDM - take your AI agents for a walk
At a glance
- What is it?
- StrongDM's container wrapper for coding agents, which watches what the agent does at the system-call level and enforces policies written in Cedar. What the telemetry design, the credential forwarding and the build setup commit you to.
- Who is it for?
- Leash fits a team that needs to know what an autonomous coding process is allowed to touch, and the design decisions that matter are the ones about telemetry rather than the ones about blocking. Capturing every filesystem access and network connection means a policy can be written after the fact and an audit trail is complete, and correlating MCP tool calls into the same stream means a tool invocation is visible next to the file it opened.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 180 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 3, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Two named dependencies do the work, eBPF and Cedar
The mechanism is visible in the module file rather than described. Two direct dependencies carry the design: cilium/ebpf at v0.19.0, which is how the Leash container watches system calls, and cedar-policy/cedar-go at v1.2.6, which evaluates the policies you write. Everything else in the dependency list is plumbing by comparison, from the websocket library behind the control UI to the TOML parser and the terminal UI toolkit. The monitoring claim is stated as full monitoring: every filesystem access and network connection initiated by the agent is captured, and the reason given is that Cedar policies and audit trails need complete telemetry to be meaningful. That is a different design from sampling or logging at the agent's own API boundary, and it is what lets a policy be written about a file path or a destination host rather than about a tool call.
An MCP observer puts tool calls in the same stream as file and network activity
Most agent sandboxes stop at the runtime layer and treat tool use as invisible. Leash adds an observer for the Model Context Protocol, which inspects, records and enforces MCP tool calls, and the part that makes it useful is the correlation. Requests flowing through supported MCP transports are matched against the filesystem and network telemetry, so a policy can govern tool use alongside core runtime activity rather than as a separate silo. In practice that means an action can be expressed either way, as a tool the agent is not allowed to call, or as a file path the syscall tracer is not allowed to touch, and both land in the same audit trail. The project points to a design document for the Cedar side with ready-to-adapt snippets and to a telemetry document for what is captured, which are the two files to read before writing a policy of your own.
Host credentials are forwarded, and the decision can be remembered globally
Two separate mechanisms move secrets into the container, and they behave differently. Environment forwarding is automatic and maps the common API keys by agent: ANTHROPIC_API_KEY for claude, OPENAI_API_KEY for codex, GEMINI_API_KEY for gemini, and DASHSCOPE_API_KEY for qwen, which is the provider key rather than a key named after the agent. Mount prompts are a decision, not a default. On first use Leash asks whether to mount the host coder-agent config directory, for example ~/.claude, into the container, and the answer can be remembered globally, for the current project, or only for that once. Persistent choices are stored in a TOML file at ~/.config/leash/config.toml. The distinction matters for a policy story: a globally remembered mount means every future project on that machine forwards those credentials unless you reset it, and the documentation has a reset path for exactly that.
Multi-architecture release binaries are switched off behind a temporary note
The build file contains a line that is easy to skim past. A multi-platform list for darwin and linux on both amd64 and arm64 is present but commented out, and what follows is a temporary note that disables multi-architecture builds, with the surviving definition resolving the platform from uname of the build machine instead. That means a release binary is built for whatever system produced it, and the matrix across the four platform and architecture combinations is not currently produced. Three install routes are documented, and two of them hand you a binary: a pre-built release from the releases page, and on macOS a Homebrew cask named leash-app. Image names are split across two registries as well, with the Makefile defaulting to ghcr.io paths while the documentation points the target image at a public ECR path. Anyone planning a rollout across a mixed fleet should check what is actually published before assuming a cask or release asset exists for their platform.
A Go binary that builds a Node control UI and a terminal interface
The repository is Go at its core, with the module declaring go 1.23.0, and the toolchain shows in the dependencies. The terminal interface comes from the bubbletea and lipgloss pair, and the control UI is a separate build: the Makefile defines cache volumes for pnpm, corepack and Next.js caches and a UI cache directory under the home directory, and the tree carries a controlui/ directory alongside cmd/, internal/ and e2e/. Telemetry uses OpenTelemetry across its trace, metric, SDK and stdout exporter packages, so traces can be written to standard output rather than to a collector. Two build scripts in the build/ directory do version work, one resolving the binary version and another producing Docker tags, and the Makefile treats an empty result as a hard error rather than building something unversioned. It is a larger system than the one-line description suggests, with a Go daemon, a web UI and per-agent images.
The Control UI is on port 18080 and its bind address is one flag
The Leash container is the one that watches, and it also serves the interface you use to look at what it saw. The control UI is at http://localhost:18080, and passing --open on any Leash command launches it in a browser automatically, which is how the first-launch examples work. The bind address is configurable through --listen or the LEASH_LISTEN variable, and the configuration table spells out the default: a blank value binds to 127.0.0.1:18080. That is the safe reading for a UI that shows an agent's file and network activity. Anything else has to be set deliberately, and nothing on the page describes authentication for the UI, so the sensible assumption is that it stays on loopback and is reached through a tunnel if you need it elsewhere.
Two containers, the working directory bind-mounted, volumes repeatable
The topology is two containers. The agent container runs your command with the current directory bind-mounted, so the tools see the same file tree they would on the host rather than a copy. The Leash container monitors system calls, applies the policies and exposes the UI. Configuration has more entry points than most projects of this kind, which is convenient and worth mapping before you rely on it: target image via config.toml or LEASH_TARGET_IMAGE or --image, target container base through TARGET_CONTAINER which is auto-sanitized from the current directory when unset, the manager image through --leash-image or LEASH_IMAGE, and the policy file through --policy or LEASH_POLICY_FILE. Extra mounts use a repeatable -v src:dst[:ro] flag and -e KEY=value forwards variables into both containers. The project section of the config file is keyed by absolute path.
[leash]
codex = true
[projects."/absolute/path/to/project"]
target_image = "ghcr.io/example/dev:latest"
[projects."/absolute/path/to/project".volumes]
"~/devtools" = "/workspace/devtools:rw"To use your own image, extend Dockerfile.coder with your project packages, or reuse an existing image by adding ca-certificates and telling Leash to launch it.
Three install routes, one of which needs a quarantine removal
Installation is a choice of how much you want a native helper. The recommended route is a global npm install of @strongdm/leash, which is unusual for a Go project and tells you the binary is distributed to Node users as well. The alternative is a pre-built binary from the releases page. On macOS there is a third route, a Homebrew cask named leash-app, and it installs two things: a helper app that enables experimental native mode on macOS, and the leash formula itself. The two macOS notes are practical rather than optional. A binary downloaded from the releases page needs a quarantine attribute removed by hand after extraction, and the native capabilities, which are documented separately in MACOS.md, come from the helper app rather than from the CLI. The runtime requirements are a container engine, Docker, Podman or OrbStack, on macOS or Linux including WSL.
Editorial conclusion
Leash fits a team that needs to know what an autonomous coding process is allowed to touch, and the design decisions that matter are the ones about telemetry rather than the ones about blocking. Capturing every filesystem access and network connection means a policy can be written after the fact and an audit trail is complete, and correlating MCP tool calls into the same stream means a tool invocation is visible next to the file it opened. Two things to weigh first. Host credentials and API keys are forwarded into the agent container, with the mount decision remembered at a global level if you choose that, so the blast radius of a policy mistake includes the keys. And the build configuration has multi-architecture releases disabled behind a temporary note, so check that a binary exists for your platform before planning around it. Cedar itself is the part to read before writing policy, and the project ships ready-to-adapt snippets for it.
Frequently asked questions
What does Leash from StrongDM do?
It wraps AI coding agents in containers and monitors their activity, and you define policies in Cedar which Leash enforces. Monitoring captures every filesystem access and network connection the agent initiates, so policies and audit trails run on complete telemetry, and an MCP observer correlates tool calls with the same stream.
Which coding agents does Leash support?
The default coder image ships claude, codex, gemini, qwen and opencode. Environment forwarding maps ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY and DASHSCOPE_API_KEY automatically, and the control UI is served at http://localhost:18080, launched by the browser with --open.
How do I install Leash?
The recommended route is `npm install -g @strongdm/leash`, with a pre-built binary from the releases page as the alternative. On macOS a cask installs a helper app for experimental native mode plus the leash formula, and a binary downloaded from the releases page needs `xattr -d com.apple.quarantine leash` after extraction. Docker, Podman or OrbStack is required.
How do I run my own container image under Leash?
Set target_image in config.toml, or use LEASH_TARGET_IMAGE, or pass --image, which defaults to the public ECR coder image. You can extend Dockerfile.coder with project packages, or reuse an existing image by adding ca-certificates, and add mounts with a repeatable -v src:dst[:ro] flag.
How does Leash decide whether to forward my agent credentials?
On first use it prompts to mount the host coder-agent config directory, for example ~/.claude, into the container, and you choose whether to remember that globally, for the current project, or just this once. Persistent choices are stored at ~/.config/leash/config.toml.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/strongdm-leash)