kapsl

The hallmark of kapsl is agentic coding. You run the agent through kapsl — kapsl claude — and the agent itself runs containerized: its own state directory mounted, and nothing else. Every tool it shells out to runs containerized too, with the project checkout mounted read-only and the tool's own declared boundary. The whole session's blast radius is the checkout. An agent that can read the repository cannot read your SSH keys.

The example agents on this site cycle claude, codex, and omp. All three are building now — claude is already declared in the signed catalogue; codex and omp are not in it yet. The session below is captured from the real agent once its image is published.

$ kapsl claude
▍  ■ PULLING    ghcr.io/kapsl-sh/claude:latest
▍  ■ PULLED     ghcr.io/kapsl-sh/claude:latest · 6.4s
▍  ■ SCANNING   claude · 4 images
▍  ■ READY      claude · rw ~/.claude net

  fix the failing test in auth/
  ▸ rg "TODO" src/               the agent's tools run containerized too
  ▸ python -m pytest tests/ -x   read-only checkout, each with its own boundary
  ✓ 3 passed

Underneath the agent, the whole product is one line:

Prepend kapsl to a command you already know — the agent included. It works, it is the current version, it has been scanned, and it can only see what you let it see.

No installing, no upgrading: a name without a version is implicitly @latest, and staying current is the security model, not a convenience. This one works today, on any machine with a container runtime:

$ echo '{"name":"kapsl"}' | kapsl jq .name
"kapsl"

The same pipeline for every tool, in every session: the name resolves against the signed catalogue, the image pulls once per machine and is scanned before it runs, the tool runs with no network and a read-only view of your current directory, and when it exits, the container is gone. The first run pays the pull and the scan (tens of seconds); every run after is sub-second, and nothing persists but the caches — and the decisions you made.

What that gives you

  • Current by default — how it stays that way. There is no upgrade command, by design. Floating tags re-pull on a freshness window, the catalogue re-checks in the background, and a failed scan on a floating tag re-pulls and re-scans once, because a rebuild may have fixed the finding.
  • Scanned before it runs — the scan gate. The composed set — the tool and the packages you asked for — is vulnerability-scanned in a container before first run. CRITICAL findings stop the run; a scan that cannot run fails it. That is how CVEs in transitive dependencies get caught, which no native package manager ever sees.
  • Sees only your directory — the security model. The only filesystem a tool ever gets is the directory you ran it in. Your SSH, GnuPG and cloud credentials exist inside the container as empty stand-ins; a tool that genuinely needs one opts in, per tool, in the signed catalogue.

The whole interface, one screen

$ kapsl -h
■ kapsl v0.1.0
run any CLI tool in a container

USAGE  kapsl [OPTIONS] [TOOL] [ARGS]...

ARGUMENTS
  [TOOL]  Tool name or container image to execute

OPTIONS
  -h                           Print help
      --help                   Print help, with the full detail behind each flag
  -s, --search <SEARCH>        Search for tools in the catalogue
      --info <TOOL>            Show details for a tool
  -l, --list                   List installed shims
      --clean [<TARGET>]       Reclaim disk used by kapsl
      --status                 Show what kapsl is storing on disk
      --dry-run                With --clean: show what would go, and stop
  -y, --yes                    Pre-answer the --clean confirmation
      --update                 Refresh the tool catalogue now
      --completions <SHELL>    Print a shell completion script
  -i, --install                Install a shim for the tool
      --pull                   Prepare a run without running it
      --watch                  Rebuild and restart when the env file changes
      --non-interactive        Disable TTY allocation, for CI
  -v, --verbose                Show the full transcript
  -q, --quiet                  Errors and decisions only
  -e, --env <ENV_FILE>         Build the environment, compose other tools
  -E <NAME[=VALUE]>            Pass one environment variable into the container, explicitly
      --cap <CAP>              Capabilities: net, rw, ro, gpu, nomount, …
      --privileged             Drop all sandbox restrictions
      --skip-scan              Skip the vulnerability scan for this run
      --force-scan             Rescan and re-ask, ignoring the cache
      --offline                Run fully offline, cached state only
  -p, --port <PORT>            Publish a container port, HOST:CONTAINER
      --platform <PLATFORM>    Force a platform, e.g. linux/amd64
      --runtime <RUNTIME>      Force the container runtime

TOPICS
  capabilities  what --cap grants, and what is denied by default
  environments  composing tools and packages with -e
  catalogue     where tool definitions come from, and how they update
  scanning      what kapsl scans, when it asks, and what it records
  output        what kapsl prints, and how to make it quieter

  kapsl -h <topic>

Where to go next

  • Quickstart — five minutes: install, first tool, the security model failing and granting.
  • Use cases — agentic coding first, then IDEs and linters, CI/CD, and the package-provider theme.
  • The index — every published tool: its declared boundary, its scan findings, its assessments. One page per project.

kapsl runs on Linux and macOS; Windows via WSL2 (Windows).