Safe, persistent workspaces for AI coding agents.
Don't be crabby -- pick up where you left off.
Kanibako gives AI coding agents a safe place to work -- real tools, real files, real network access -- without risking your host system. Each project gets its own isolated container with persistent state: shell config, credentials, and agent sessions that survive reboots and SSH disconnects.
CRAB: Contained Runtime Agent in a Box.
No Docker or Podman experience required. Just cd into a project and run
kanibako. Setup, rig pulls, credential syncing, and teardown are automatic.
Claude Code is supported via the built-in plugin; other agents (Aider, Codex,
Goose) are available as example plugins.
- Safe by default -- rootless containers with no host access; the sandbox is what makes it safe to give agents real autonomy
- Automatic sandboxing -- no Docker or Podman experience required; Kanibako manages all container operations for you
- Session continuity --
kanibako startdefaults to--continue, picking up where you left off; persistent tmux sessions survive SSH disconnects - Per-project isolation -- each project gets its own shell, config, and credentials (three modes: local, workset, standalone)
- Credential forwarding -- host credentials are synced into the container and written back after each session
- Setup wizard --
kanibako setupdetects installed agents and checks your container runtime; no manual configuration needed - Diagnostics --
kanibako system diagnosechecks runtime, images, agents, and storage;box diagnose,crab diagnose, andrig diagnosedrill into specific scopes - Vault snapshots -- per-project read-only and read-write shared directories with smart snapshot strategy detection (reflink, hardlink, or tar.xz depending on filesystem)
- Shell customization -- per-project environment variables (
box config env.*), drop-in init scripts (shell.d/), and layered home directory templates - Crab configuration -- per-agent TOML config with template variant,
default args, state knobs, env vars, and shared caches; per-project
setting overrides via
box config - Shared caches -- global download caches (pip, cargo, npm, etc.) shared across projects; agent-level caches via crab TOML
- Plugin system -- agent-agnostic core (
kanibako-base); Claude Code plugin (kanibako-agent-claude) ships by default; three-tier discovery (entry points, user directory, project directory) - Rig freshness checks -- non-blocking digest comparison against GHCR on startup (24h cache)
- Helper spawning -- spawn child agent instances for parallel workloads with budget-controlled depth and breadth
- Concurrency lock -- prevents two sessions from running in the same project simultaneously
- Python 3.11+
- Podman (recommended) or Docker -- just needs to be installed; Kanibako manages all container operations automatically
- An AI coding agent installed on the host (e.g. Claude Code)
# Standard install (base + Claude plugin)
uv tool install kanibako
# -- or --
pip install kanibako
# Base only (no agent plugins -- agent-agnostic shell mode)
pip install kanibako-base
# Development install
git clone https://github.com/doctorjei/kanibako.git
cd kanibako
pip install -e '.[dev]' -e packages/agent-claude/On first use, Kanibako automatically creates its config and data directories.
Run kanibako setup to verify your environment, or just dive in -- setup
runs automatically when needed.
# Start an agent session in the current directory
cd ~/my-project
kanibako
# Start with a specific rig
kanibako --image kanibako-min:latest
# Open a plain bash shell (no agent)
kanibako shell
# Run a one-shot command in the container
kanibako shell -- echo hello
# Start a new conversation
kanibako -N
# Resume with the conversation picker
kanibako -RThat's it -- no docker run, no volume flags, no Containerfile. On first run,
Kanibako automatically pulls the container rig, sets up the project
environment, and syncs your credentials. Subsequent runs pick up where you
left off.
The default kanibako-oci rig (based on droste-fiber) includes Python, git,
gh, nano, jq, ripgrep, tmux, Podman, and common dev tools. This is enough for
most Python, JavaScript, and general scripting work.
# 1. Install kanibako
pip install kanibako
# 2. Create or clone a project
mkdir ~/my-flask-app && cd ~/my-flask-app
git init
# (or: git clone https://github.com/you/my-flask-app.git && cd my-flask-app)
# 3. Launch -- that's it
kanibakoOn the first launch, Kanibako will:
- Pull the base container rig (once, cached afterwards)
- Create an isolated environment for this project
- Copy your agent credentials into the sandbox
- Drop you into an agent session inside the container
The agent sees your project files in ~/workspace/ and has full access to
Python, git, and the other base tools. When you exit, your project files
and agent state are preserved -- next time you run kanibako in the same
directory, it picks up where you left off.
# Later: come back to the same project
cd ~/my-flask-app
kanibako # resumes your previous session
kanibako -N # or start a fresh conversationFor projects that need compiled languages, create a custom rig with the toolchains you need:
# 1. Create a custom rig with C/C++ and Rust
kanibako rig create systems
# (inside: sudo apt install build-essential cmake gdb && curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh)
# exit when done
# 2. Use it for your project
cd ~/my-rust-project
kanibako --image kanibako-template-systemsAfter the first run, Kanibako remembers the rig choice for this project,
so you can just run kanibako next time.
See Container Rigs for the base rigs and custom rig creation.
Kanibako organizes commands into four management groups plus seven top-level shortcuts for common operations:
| Shortcut | Maps to | Description |
|---|---|---|
kanibako [start] [project] |
box start |
Launch agent session (default command) |
kanibako stop [project|--all] |
box stop |
Stop running container(s) |
kanibako shell [project] [-- cmd] |
box shell |
Open a bash shell or run a one-shot command |
kanibako list [-a] [-q] |
box list |
List all projects |
kanibako ps [-a] [-q] |
box ps |
List active (running) boxes |
kanibako create [path] |
box create |
Create a new project |
kanibako rm <project> |
box rm |
Remove a project |
| Command | Description |
|---|---|
box |
Project lifecycle (create, list, start, stop, shell, config, archive, ...) |
rig |
Rig management -- container images (create, list, info, rm, rebuild) |
workset |
Project grouping (create, list, connect, disconnect, config, ...) |
crab |
Crab (agent) management (list, config, reauth, helper, fork) |
system |
Global configuration, diagnostics, and self-update |
Aliases: agent -> crab, image -> rig, container -> box
Run cycle:
| Subcommand | Description |
|---|---|
box start [project] |
Launch agent session (agent flags + infra flags + -- args) |
box stop [project] |
Stop container (--all stops all, --force skips confirm) |
box shell [project] |
Open bash or run one-shot command (infra flags + -- cmd) |
box ps |
List active (running) boxes (--all includes stopped, -q names only) |
Standard lifecycle:
| Subcommand | Description |
|---|---|
box create [path] |
Create project (--name, --standalone, --image, --no-vault, --distinct-auth) |
box list / box ls |
List projects (--all, --orphan, -q) |
box info / box inspect |
Project details (mode, paths, lock, rig) |
box rm / box delete |
Remove project (--purge deletes metadata, --force skips confirm) |
box config |
View or modify project configuration |
box diagnose [project] |
Check project box health |
Relocation:
| Subcommand | Description |
|---|---|
box move [project] <dest> |
Relocate project workspace |
box duplicate <source> [dest] |
Copy project (--name, --bare, --force) |
box archive [project] |
Pack session data to .txz (--as-local, --as-standalone, --force) |
box extract <archive> [dest] |
Unpack from archive (--name, --force) |
Data:
| Subcommand | Description |
|---|---|
box vault snapshot |
Create a vault snapshot |
box vault list / vault ls |
List snapshots (-q) |
box vault restore <name> |
Restore from snapshot (--force) |
box vault prune |
Delete old snapshots (--keep N, --force) |
| Subcommand | Description |
|---|---|
rig create <name> |
Create rig interactively (--base, --always-commit, --no-commit-on-error) |
rig list / rig ls |
List available rigs (-q) |
rig info / rig inspect |
Rig details (source, size, recoverability) |
rig rm / rig delete |
Remove rig (--force) |
rig rebuild [rig] |
Rebuild from registry or stored Containerfile (--all) |
rig diagnose |
Check rig (image) status |
| Subcommand | Description |
|---|---|
workset create [path] |
Create working set (--name, --standalone, --image, --no-vault, --distinct-auth) |
workset list / workset ls |
List working sets (-q) |
workset info / workset inspect |
Working set details |
workset rm / workset delete |
Remove working set (--purge, --force) |
workset config |
View or modify workset configuration |
workset connect <workset> [source] |
Add project to working set (--name) |
workset disconnect <workset> <project> |
Remove project from working set (--force) |
| Subcommand | Description |
|---|---|
crab list / crab ls |
List configured crabs (-q) |
crab info / crab inspect |
Crab configuration details |
crab config |
View or modify crab configuration |
crab reauth [project] |
Refresh credentials |
crab helper spawn |
Spawn child instance (--depth, --breadth, --model, --image) |
crab helper list / helper ls |
List helpers (-q) |
crab helper stop <n> |
Stop a helper |
crab helper respawn <n> |
Respawn a stopped helper |
crab helper cleanup <n> |
Clean up helper (--cascade) |
crab helper send <n> <msg> |
Message a helper |
crab helper broadcast <msg> |
Message all helpers |
crab helper log |
View message log (-f, --from, --tail) |
crab fork <name> |
Fork project into a new directory |
crab diagnose |
Check agent status and configuration |
| Subcommand | Description |
|---|---|
system info / system inspect |
System details (version, runtime, paths) |
system config |
View or modify global configuration |
system upgrade |
Self-update (--check for dry run) |
system diagnose |
Check system health (runtime, images, agents, storage) |
| Flag | Description |
|---|---|
-N, --new |
Start a new conversation |
-C, --continue |
Continue the most recent conversation (default) |
-R, --resume |
Resume with conversation picker |
-A, --autonomous |
Run with full permissions (default) |
-S, --secure |
Run without --dangerously-skip-permissions |
-M, --model MODEL |
Override the agent model for this run |
-N, -C, -R are mutually exclusive. -A, -S are mutually exclusive.
| Flag | Description |
|---|---|
-e, --env KEY=VALUE |
Per-run environment variable (repeatable) |
--image IMAGE |
Container rig override |
--entrypoint CMD |
Override container entrypoint |
--persistent |
Use tmux session wrapper (default) |
--ephemeral |
No tmux, session dies with terminal |
--no-helpers |
Disable helper spawning |
--no-auto-auth |
Disable automated browser-based OAuth refresh |
--browser |
Launch a headless browser sidecar (BROWSER_WS_ENDPOINT injected) |
| Flag | Description |
|---|---|
-v, --verbose |
Show debug output (target detection, container command) |
Kanibako supports three ways to organize project state. The mode is inferred automatically from context.
Centralized store keyed by project name. Just cd into any directory and
run kanibako.
$XDG_DATA_HOME/kanibako/boxes/{name}/ metadata + shell
{project}/vault/share-ro/ read-only vault
{project}/vault/share-rw/ read-write vault
Group related projects under a named working set with human-readable paths.
Worksets are stable and supported but not actively receiving new features. For most use cases, local mode is simpler.
kanibako workset create ~/worksets/research --name my-research
kanibako workset connect my-research ~/repos/paper-a --name paper-a
cd ~/worksets/research/workspaces/paper-a
kanibako{workset}/boxes/{name}/ metadata + shell
{workset}/workspaces/{name}/ workspace
{workset}/vault/{name}/share-{ro,rw}/ vault
All state lives inside the project directory itself. Fully portable.
kanibako create --standalone # in the current directory
kanibako create --standalone ~/myproj # create and initialize a new directory{project}/.kanibako/ metadata + shell
{project}/vault/share-{ro,rw}/ vault
Find projects whose workspace directory no longer exists:
kanibako box list --orphanAll rigs are built on Droste tiers (Debian 13) with a thin Kanibako layer on top (agent user, gh, ripgrep, directory scaffolding). The AI agent binary is mounted from the host.
| Rig | Droste Base | Role |
|---|---|---|
kanibako-min |
droste-seed | Minimal agent container |
kanibako-oci |
droste-fiber | Agent container + nested OCI host |
kanibako-lxc |
droste-thread | LXC system container host (via Kento) |
kanibako-vm |
droste-hair | VM host (via Kento + Tenkei) |
kanibako-oci is the default. It includes Podman and rootless container
infrastructure, so it can both run agents directly and host nested Kanibako
containers.
Container rigs are built on Droste, a layered OCI image builder. Kento converts them to LXC/VM hosts.
Rigs are pulled automatically from GHCR on first use. If the pull fails, Kanibako falls back to a local build from the bundled Containerfiles.
kanibako rig list # show local rigs
kanibako rig rebuild # rebuild current project's rig
kanibako rig rebuild --all # rebuild all known rigsCreate custom rigs by installing tools interactively and committing the result:
kanibako rig create jvm # start from kanibako-oci, install tools
# (inside container: apt install openjdk-21-jdk maven, etc.)
# exit when done
kanibako rig list # show local rigs
kanibako rig rm jvm # remove a custom rigCustom rigs are standard OCI images -- push them to any registry for sharing:
podman push kanibako-template-jvm ghcr.io/myorg/kanibako-template-jvmFor always-on deployments using LXC, VMs, or nested OCI containers, see docs/host-deployment.md.
Inside the container, the agent sees:
/home/agent/ persistent shell (bind mount)
|- .bashrc shell config (with shell.d sourcing)
|- .profile login profile
|- .shell.d/ drop-in init scripts (*.sh)
|- .claude/ agent credentials
|- .claude.json agent settings
|- workspace/ project files (bind mount)
|- share-ro/ read-only vault (bind mount, optional)
'- share-rw/ read-write vault (bind mount, optional)
Set per-project or global environment variables that are passed to the container:
# Persistent (stored in project config)
kanibako box config env.EDITOR=vim # project-level
kanibako system config env.EDITOR=nano # global (all projects)
kanibako box config env.EDITOR # show one value
# Per-run (not persisted)
kanibako start -e EDITOR=vim -e DEBUG=1Project env vars override global ones.
The shell prompt is controlled by the KANIBAKO_PS1 environment variable:
kanibako box config env.KANIBAKO_PS1="(myproject) \u:\w\$ "Drop .sh files into the shell.d/ directory inside your project's shell
path. They are sourced by .bashrc on every interactive shell startup:
# Find your shell path
kanibako box info
# Add a custom init script
echo 'export PATH="$HOME/.local/bin:$PATH"' > /path/to/shell/.shell.d/path.sh
echo 'alias ll="ls -la"' > /path/to/shell/.shell.d/aliases.shExisting shells from older Kanibako versions are automatically upgraded to
support shell.d/ on the next launch.
Each crab (agent instance) gets a TOML configuration file at
$XDG_DATA_HOME/kanibako/agents/{id}.toml. The file is generated
automatically on first use (via the target plugin's generate_agent_config()
method) and can be edited afterwards.
[agent]
name = "Claude Code"
shell = "standard" # template variant (see Shell Templates)
default_args = [] # extra CLI args prepended on every launch
[state]
model = "opus" # target-specific knobs (e.g. --model for Claude)
access = "permissive"
[env]
# KEY = "value" # raw env vars injected into the container
[shared]
# plugins = ".claude/plugins" # agent-level shared cache paths
[tweakcc]
# enabled = false # enable tweakcc binary patching
# config = "~/.tweakcc/config.json" # external tweakcc config fileSections:
[agent]-- identity and defaults (name, shell template variant, default CLI args)[state]-- runtime behavior knobs translated by the target plugin into CLI args and env vars (e.g. Claude mapsmodel->--model)[env]-- environment variables injected into the container[shared]-- agent-level shared cache paths (mounted from the per-agent shared directory, independent of global shared caches)[tweakcc]-- optional tweakcc integration for binary patching (see docs/tweakcc.md)
Manage crab settings via the CLI:
kanibako crab list # list configured crabs
kanibako crab config model # show effective model
kanibako crab config model=sonnet # set crab-level defaultShell templates provide layered home directory initialization for new projects.
Templates live under $XDG_DATA_HOME/kanibako/templates/ and are applied
once during project init.
Resolution order (for template variant standard and agent claude):
templates/claude/standard/-- agent-specific templatetemplates/general/standard/-- general fallback- None -- no template files applied
The special variant "empty" always resolves to None (no files applied),
bypassing directory lookup entirely. Use shell = "empty" in the crab
TOML to skip template initialization.
Layering:
templates/general/base/is copied first (common skeleton)- The resolved template overlays on top
Example directory layout (for agent claude, variant standard):
templates/
|- general/
| |- base/ <- layer 1: always copied (common skeleton)
| | |- .bashrc
| | '- .profile
| '- standard/ <- layer 2 fallback (if no agent-specific dir)
'- claude/
'- standard/ <- layer 2 preferred (agent-specific)
|- .claude/
| '- settings.json
'- playbook/
'- ONBOARD.md
Important: files go inside claude/standard/, not directly in claude/.
Placing files in templates/claude/ (without the variant subdirectory) will
have no effect -- the resolver looks for templates/{agent}/{variant}/.
The template variant is controlled by the shell field in the crab TOML
(defaults to "standard"). To customize, create a directory under
templates/ matching the desired structure and set shell in the crab TOML.
Each project has optional read-only and read-write shared directories:
- share-ro/ -- files visible inside the container but not writable (documentation, reference data, prompt libraries)
- share-rw/ -- files that persist across sessions and can be modified (databases, build caches, generated artifacts)
In local mode, vault directories live under your project and are hidden inside the container via a read-only tmpfs overlay, so the agent cannot see or modify vault metadata.
Kanibako automatically creates a snapshot of share-rw/ before each
container launch. The snapshot strategy is detected per-project: reflink
(instant copy-on-write on Btrfs/XFS), hardlink (fast for unchanged files),
or tar.xz (universal fallback). Manage snapshots manually:
kanibako box vault snapshot # create a snapshot now
kanibako box vault list # show all snapshots
kanibako box vault restore <name> # restore from a snapshot
kanibako box vault prune --keep 5 # keep only 5 most recentkanibako create --standalone --no-vault # standalone project without vault
kanibako create --standalone ~/p --no-vault # new directory, no vaultKanibako is agent-agnostic. All agent-specific logic lives in target
plugins -- Python classes that implement the Target abstract base class.
Claude Code is supported via kanibako-agent-claude (installed by the
kanibako meta-package); other agents can be added as pip packages.
Install kanibako-base for agent-agnostic operation.
If no agent is detected, Kanibako falls back to no_agent -- a plain shell
with no agent binary or credentials.
Supported agents:
- Claude Code -- built-in via
kanibako-agent-claude - Aider, Codex CLI, Goose -- example plugins in examples/
A target handles:
- Detecting the agent binary on the host
- Mounting the binary/installation into the container
- Syncing credentials between host and container
- Building CLI arguments for the agent entrypoint
Kanibako discovers target plugins from three sources, checked in order. Later sources override earlier ones when two plugins register the same name.
| Tier | Location | Use case |
|---|---|---|
| 1. Entry points | kanibako.targets entry point group + kanibako.plugins.* namespace scan |
Pip-installed packages and bind-mounted plugins in nested containers |
| 2. User directory | ~/.local/share/kanibako/plugins/*.py |
Personal plugins shared across all projects |
| 3. Project directory | {project}/.kanibako/plugins/*.py |
Project-specific plugins |
Drop a .py file containing a Target subclass into the user or project
plugins directory and Kanibako picks it up automatically -- no packaging or
pip install needed. Files starting with _ are skipped.
Security note: file-drop plugins run with the same permissions as Kanibako itself. Only place files you trust in plugin directories.
See docs/writing-targets.md for the full developer guide, and examples/ for three graduated example plugins (Aider, Codex CLI, Goose).
# Install a third-party target
pip install kanibako-target-aider
# Use a specific target
kanibako box config target_name=aider
kanibako startPrecedence: CLI flag > project.toml > workset config > crab config > kanibako.toml > defaults
All configuration levels share a unified interface:
# Box (project) level
kanibako box config # show project overrides
kanibako box config --effective # show resolved values (inherited + overrides)
kanibako box config model # get one key
kanibako box config model=sonnet # set one key
kanibako box config --reset model # remove override, back to default
# Workset level (defaults for projects in this workset)
kanibako workset config <workset> model=opus
# Crab level (defaults for all projects using this crab)
kanibako crab config model=opus
# System level (global defaults)
kanibako system config model=opus
kanibako system config --reset --all # reset all global config- Global:
$XDG_CONFIG_HOME/kanibako.toml - Project:
boxes/{name}/project.toml - Crabs:
$XDG_DATA_HOME/kanibako/agents/{id}.toml - Templates:
$XDG_DATA_HOME/kanibako/templates/
| Key | Default | Description |
|---|---|---|
start_mode |
continue |
Default start mode (continue/new/resume) |
model |
platform default | Agent model name |
autonomous |
true |
Enable autonomy override |
persistence |
persistent |
Session type (persistent/ephemeral) |
image |
kanibako-oci:latest |
Container rig |
auth |
shared |
Credential mode (shared/distinct) |
vault.enabled |
true |
Enable vault directories |
env.* |
Persistent environment variables | |
resource.* |
Resource path overrides | |
target_name |
(auto-detect) | Agent target plugin |
The global config supports a [paths] section to override data directory
layout, and a [shared] section for globally shared cache mounts:
[paths]
data_path = "" # override XDG_DATA_HOME/kanibako
boxes = "boxes" # project state subdirectory
agents = "agents" # crab TOML subdirectory
shared = "shared" # shared caches subdirectory
templates = "templates"
[shared]
pip = ".cache/pip"
cargo = ".cargo/registry"
npm = ".npm"Shared caches are lazy -- they are only mounted if the host directory exists.
Kanibako containers can spawn child instances for parallel workloads. Each child gets its own directory tree, peer communication channels, and spawn budget. Helpers are enabled by default -- the host runs a Unix socket hub alongside the director container, and helpers connect to it for orchestration and messaging.
# Spawning and lifecycle
kanibako crab helper spawn # spawn a child with default budget
kanibako crab helper spawn --model sonnet # child uses a different model
kanibako crab helper spawn --depth 2 --breadth 3 # custom spawn limits
kanibako crab helper list # show all helpers with status
kanibako crab helper stop 1 # stop helper 1
kanibako crab helper respawn 1 # relaunch a stopped helper
kanibako crab helper cleanup 1 # stop and remove helper 1
kanibako crab helper cleanup 1 --cascade # also remove all descendants
# Messaging
kanibako crab helper send 1 "Analyze the auth module"
kanibako crab helper broadcast "Starting tests"
# Conversation log
kanibako crab helper log # display full message log
kanibako crab helper log --follow # tail log in real-time
kanibako crab helper log --from 1 # filter by helper number
kanibako crab helper log --tail 10 # show last 10 entries
# Opt out
kanibako start --no-helpers # launch without helper supportArchitecture: The Kanibako CLI is bind-mounted into every container
(director and helpers), so kanibako crab helper spawn/send/broadcast/log
works inside containers. Each helper launches with helper-init.sh as
its entrypoint -- the script registers with the hub, sources broadcast
startup scripts, then execs the agent command.
Two communication layers work together:
- Directories -- file sharing (workspace, vault, peers, broadcast). Persistent, async. Good for sharing code, configs, results.
- Socket -- control plane (spawn/stop) + real-time messaging (peer-to-peer, parent-child, broadcast). The host listener acts as a central message router.
Logging: All inter-agent messages are logged to a JSONL file on the
host. Each entry records sender, recipient(s), timestamp, and message
content. View the conversation in real-time with kanibako crab helper log --follow:
12:35:10 [0 -> 1] Analyze the auth module and report back.
12:36:45 [1 -> 0] Found 3 issues in the token refresh flow.
12:37:00 [0 -> *] Starting integration tests.
Spawn budget: Each helper gets a depth/breadth budget controlling
how many levels deep it can spawn and how many siblings are allowed.
Depth decrements with each level. The budget is written as a read-only
config (spawn.toml) inside the child, enforced at spawn time.
Peer channels: Helpers communicate through shared directories.
Each pair of siblings gets three channels (A-reads, B-reads, shared-rw).
A broadcast channel (all/) is available to all helpers.
Directory layout (inside a container):
~/helpers/
1/ # helper 1 root
workspace/ # helper's working directory
vault/share-ro/ # read-only vault share
vault/share-rw/ # read-write vault share
playbook/scripts/ # helper-init.sh (entrypoint wrapper)
peers/ # symlinks to peer channels
all -> ../all/ # broadcast channel
spawn.toml # RO spawn budget
state.json # status, model, depth, peers
all/ro/ # broadcast read-only
all/rw/ # broadcast read-write
channels/ # raw peer channel directories
~/.kanibako/
helper.sock # hub socket (mounted from host)
helper-messages.jsonl # message log (mounted read-only)
~/.local/bin/kanibako # kanibako CLI (bind-mounted from host, ro)
kanibako start runs agents in tmux by default (--persistent mode).
The container uses tmux as PID 1 -- detaching or losing the connection
leaves the agent running. Running kanibako start again reattaches to
the same session.
# Start a session (tmux by default)
kanibako start myproject
# Detach: Ctrl-B d (agent keeps running)
# Reattach later:
kanibako start myproject
# Start without tmux (session dies when terminal closes)
kanibako start --ephemeral myproject
# List running projects
kanibako psLifecycle:
- First
start-> creates a detached container with tmux, then attaches - Subsequent
start-> reattaches to the running container - SSH disconnect -> container keeps running; reconnect with
start kanibako stop-> stops and removes the container- Agent exits -> tmux session ends -> container stops
Set up SSH forced commands to map SSH keys directly to projects. Each key connects to a specific project -- no shell access needed.
Per-key routing in ~/.ssh/authorized_keys:
command="kanibako start myproject" ssh-ed25519 AAAA... user@laptop-myproject
command="kanibako start client/webapp" ssh-ed25519 AAAA... user@laptop-webapp
Dedicated SSH config on the client:
Host myproject
HostName remote-server.example.com
User kanibako
IdentityFile ~/.ssh/id_myproject
Then just ssh myproject to connect directly to the agent session.
With a jump host / bastion:
Host myproject
HostName internal-server
User kanibako
IdentityFile ~/.ssh/id_myproject
ProxyJump bastion.example.com
Tips:
- Use one SSH key per project for clean routing
- Set
PermitTTY yesandPermitOpen noneinsshd_configfor the kanibako user to restrict access to terminal-only - The kanibako user only needs access to
kanibako start-- no shell required (ForceCommandhandles routing) - Credentials are refreshed on every reattach; if tokens expire, the agent prompts for re-auth via URL
# Install dev dependencies
pip install -e ".[dev]" -e packages/agent-claude/
# Run tests
pytest tests/ -v # unit tests (1911)
pytest tests/ -v -m integration # integration tests (35)
# Lint
ruff check src/ tests/
# Type checking
mypy src/kanibako/
# Release
bump2version patch|minor|major # auto-commits and tags
git push && git push --tagsFor the full module-by-module breakdown, see docs/architecture.md.
Overview: Kanibako's core (kanibako-base) handles container lifecycle,
project state, configuration, and plugin discovery. Agent-specific logic
lives in target plugins (e.g. kanibako-agent-claude). The CLI is an
argparse tree in cli.py that delegates to command modules in commands/.
Configuration flows through a unified engine (config_interface.py) that
supports get/set/reset/show at every level (box, workset, crab, system).
See LICENSE for details.
LLMs were used as a tool in the development of this software.