Sandboxed AI agent workspace with MCP bridge
Project description
kennelbox
A local sandboxed AI agent workspace CLI. Agents like OpenClaw and Hermes Agent connect to a project directory via MCP (Model Context Protocol) — with hard restrictions on filesystem scope, command execution, and network access.
╔══════════════════════════════╗
║ ██╗ ██╗██████╗ ║
║ ██║ ██╔╝██╔══██╗ ║
║ █████╔╝ ██████╔╝ ║
║ ██╔═██╗ ██╔══██╗ ║
║ ██║ ██╗██████╔╝ ║
║ ╚═╝ ╚═╝╚═════╝ ║
╠══════════════════════════════╣
║ KENNELBOX // v0.1.0 ║
║ agent sandbox + MCP bridge ║
╠══════════════════════════════╣
║ $ kennelbox run --agent <x> ║
╚══════════════════════════════╝
Features
- CWD lock — agents can only read/write inside the directory where
kennelbox initwas run - Auto-venv — detects Python, Node, or generic projects and sets up an isolated environment
- Firejail sandbox (required) — every tool call (commands and file I/O) runs inside firejail with filesystem whitelisting, network blocking, and seccomp filtering
- Command allowlist — explicit per-project command rules; unknown = blocked. Inline code-execution flags (
-c,-e,--eval, …) are blocked even for allowed interpreters - Resource caps — configurable limits on file read/write sizes and command output
- MCP bridge — stdio JSON-RPC 2.0 server compatible with any MCP-capable agent
Requirements
- Python 3.10+
- Linux (Ubuntu / Zorin OS or compatible)
firejail— required; kennelbox refuses to start without it
Install firejail
sudo apt install firejail
firejail provides the kernel-level isolation boundary. There is no software-only fallback — without firejail,
kennelbox runexits with an error.
Installation
One-line installer (recommended)
git clone https://github.com/datacarismo/kennelbox.git
cd kennelbox
bash install.sh
The installer checks your Python version, installs firejail via apt (required), installs the package via pipx (preferred) or pip (fallback), and verifies kennelbox is on your PATH.
Options:
--yes accept all prompts non-interactively
--no-firejail skip the firejail apt step (kennelbox will not run until it's installed)
Manual install
git clone https://github.com/datacarismo/kennelbox.git
cd kennelbox
pipx install --editable . # or: pip install -e .
pipxis recommended — it installs into an isolated venv and avoids PEP 668 "externally managed environment" errors on modern Debian/Ubuntu.
Via pip (once published)
pip install kennelbox
Quick Start
cd /path/to/your/project
# 1. Initialize the sandbox
kennelbox init
# 2. Check the rules
kennelbox rules
# 3. Start a sandboxed agent session (stdio MCP)
kennelbox run --agent openclaw
# 4. Check status
kennelbox status
# 5. Tear down when done
kennelbox release
CLI Reference
| Command | Description |
|---|---|
kennelbox init |
Initialize .kennelbox/ in the current directory |
kennelbox run --agent <name> |
Start sandboxed MCP session for the named agent |
kennelbox rules |
Show allow/blocklist tables |
kennelbox status |
Show sandbox state (agent, network, firejail) |
kennelbox release |
Delete .kennelbox/ and tear down the sandbox |
All commands accept --cwd <path> to target a different directory.
Configuration
On init, kennelbox creates a .kennelbox/ directory with two config files:
.kennelbox/allowlist.toml
Controls which commands and file extensions agents may access.
[commands]
allowed = ["ls", "cat", "grep", "python3", "pip", "node", "npm", "git status", "git log", "git diff"]
# Flags enabling inline code execution — blocked regardless of base command
blocked_args = ["-c", "-e", "--eval", "--exec", "-x", "--command"]
# Advisory only: matches are logged as warnings but NOT blocked
warn_patterns = ["rm -rf", "sudo", "curl", "wget", "nc", "chmod 777", "mkfs", "dd", "shutdown", "reboot"]
[limits]
max_read_bytes = 10485760 # 10 MB
max_write_bytes = 10485760 # 10 MB
max_output_bytes = 1048576 # 1 MB — command output truncated beyond this
[files]
allowed_extensions = [".py", ".js", ".ts", ".json", ".toml", ".yaml", ".md", ".txt"]
Unknown commands default to BLOCKED. Dotfiles and sensitive filenames (.env, .pem, .key, etc.) are always denied regardless of the extension allowlist.
.kennelbox/sandbox.toml
Firejail profile options.
[firejail]
network = false # block outbound network
read_only_home = true # no writes outside CWD
restrict_above_cwd = true
seccomp = true # drop dangerous syscalls
MCP Bridge
kennelbox exposes a JSON-RPC 2.0 server (MCP-compatible) over two transports:
stdio (default) — the server starts on stdin/stdout and a local agent connects to it.
HTTP (--http) — for remote agents (e.g. an agent on a VPS reaching your machine over Tailscale):
kennelbox run --agent hermes --http --host 100.x.x.x --port 7333
- A bearer token is required — auto-generated and printed if you don't pass
--token - Binds
127.0.0.1by default; pass--host(e.g. your Tailscale IP) to accept remote connections - Optional
--allowed-ip(repeatable) restricts clients by source IP on top of the token GET /healthfor liveness;POST /for JSON-RPC- Every HTTP request goes through the same allowlist + firejail pipeline as stdio
Available MCP Tools
| Tool | Description |
|---|---|
read_file |
Read a file relative to the project root |
write_file |
Write a file relative to the project root |
edit_file |
Replace an exact, unique string in a file (fails on zero or multiple matches) |
list_directory |
List directory contents |
run_command |
Run an allowlisted shell command |
All calls are validated against the allowlist before execution. Path traversal above the project root is always blocked.
Connecting OpenClaw
Configure OpenClaw to use kennelbox as its MCP server:
{
"mcpServers": {
"kennelbox": {
"command": "kennelbox",
"args": ["run", "--agent", "openclaw"],
"transport": "stdio"
}
}
}
Connecting Hermes Agent
Add to your Hermes Agent config:
{
"mcp": {
"transport": "stdio",
"command": "kennelbox run --agent hermes"
}
}
Project Structure
kennelbox/
├── kennelbox.py # CLI entrypoint (typer)
├── config/
│ ├── allowlist.toml # default permitted commands (copied to .kennelbox/ on init)
│ └── sandbox.toml # default firejail profile options
├── sandbox/
│ ├── jail.py # firejail wrapper logic
│ └── venv_mgr.py # auto-venv setup (Python / Node / generic)
├── agent_bridge/
│ └── server.py # MCP stdio JSON-RPC 2.0 server
├── pyproject.toml
└── README.md
Security Model
The firejail sandbox is the security boundary. The allowlist is policy/UX guidance layered on top — it shapes what a well-behaved agent can request, but kernel-level isolation is what actually contains a misbehaving one. firejail is therefore required; kennelbox refuses to start without it.
- Filesystem — firejail whitelists only
$CWDwithin the home tree. Credential directories (~/.ssh,~/.gnupg,~/.aws,~/.config/gcloud, etc.) are explicitly blacklisted./tmpand/devare replaced with private views (--private-tmp,--private-dev). - All tool I/O is sandboxed — not just
run_command:read_file,write_file, andlist_directoryalso execute inside firejail. - Network — disabled by default (
net=none). Setnetwork = trueinsandbox.tomlto enable.Note: this applies to the firejail subprocesses. The kennelbox process itself and the agent connecting over stdio are outside the sandbox — LLM API calls (to Anthropic, OpenAI, etc.) are unaffected.
- Commands — only commands in
allowedrun. Argument flags enabling inline code execution (-c,-e,--eval,--exec,-x,--command) are rejected even for allowed interpreters.warn_patternsare advisory only — logged, never enforced. - Files — extension allowlist plus unconditional denial of dotfiles and sensitive filenames (
.env,.pem,.key,.cert,.pfx,.p12). Writes to.kennelbox/(the config directory) are always blocked. - Path escape — every path is resolved and containment-checked against the project root (
Path.relative_to, not string prefix) before any I/O. - Resource caps — file reads/writes and command output are size-limited (configurable in
[limits]). - Syscalls — firejail's default
--seccompfilter (maintained upstream, more complete than any hand-rolled list).
kennelbox does not require root. firejail handles privilege separation at the kernel level via user namespaces.
License
MIT — see LICENSE
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file kennelbox-0.1.1.tar.gz.
File metadata
- Download URL: kennelbox-0.1.1.tar.gz
- Upload date:
- Size: 21.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1e6d5f344c6917aee4ddc0d1efa68617b56f6e44b41fe2ce39d39a2f0f65bd22
|
|
| MD5 |
86fab5ee2988fa027fd27210fa82deb9
|
|
| BLAKE2b-256 |
dbf40544cf6025c03788a8c76267d6abbcf6627ef9c6dce94e4dd9a7961311d9
|
Provenance
The following attestation bundles were made for kennelbox-0.1.1.tar.gz:
Publisher:
publish.yml on datacarismo/kennelbox
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kennelbox-0.1.1.tar.gz -
Subject digest:
1e6d5f344c6917aee4ddc0d1efa68617b56f6e44b41fe2ce39d39a2f0f65bd22 - Sigstore transparency entry: 2148272591
- Sigstore integration time:
-
Permalink:
datacarismo/kennelbox@e8eea7c75a74975a230687ad86539faff3fbd061 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/datacarismo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e8eea7c75a74975a230687ad86539faff3fbd061 -
Trigger Event:
release
-
Statement type:
File details
Details for the file kennelbox-0.1.1-py3-none-any.whl.
File metadata
- Download URL: kennelbox-0.1.1-py3-none-any.whl
- Upload date:
- Size: 20.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
425c8f33843495899c92506fdefacfe06ac74a696030ebb7f5310625b78a323f
|
|
| MD5 |
776efcb8751596275892e51ef6a6b93d
|
|
| BLAKE2b-256 |
139c8cb4f5d740ff91ab15144223925bf013aa04c6417a305ef397526604f116
|
Provenance
The following attestation bundles were made for kennelbox-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on datacarismo/kennelbox
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kennelbox-0.1.1-py3-none-any.whl -
Subject digest:
425c8f33843495899c92506fdefacfe06ac74a696030ebb7f5310625b78a323f - Sigstore transparency entry: 2148272601
- Sigstore integration time:
-
Permalink:
datacarismo/kennelbox@e8eea7c75a74975a230687ad86539faff3fbd061 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/datacarismo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e8eea7c75a74975a230687ad86539faff3fbd061 -
Trigger Event:
release
-
Statement type: