-
Notifications
You must be signed in to change notification settings - Fork 64
Container Lifecycle and Sessions
Understanding how containers and sessions work in Coi.
-
Containers are always launched as non-ephemeral (persistent in Incus terms)
- This allows saving session data even if the container is stopped from within (e.g.,
sudo shutdown 0) - Session data can be pulled from stopped containers, but not from deleted ones
- This allows saving session data even if the container is stopped from within (e.g.,
-
Inside the container:
tmux→bash→<ai-tool>- When the AI tool exits, you are dropped to bash
- From bash you can: type
exit, pressCtrl+b dto detach, or runsudo shutdown 0
-
On cleanup (when you exit/detach):
- Session data (tool config directory) is always saved to
~/.coi/sessions-<tool>/ - If persistent mode is NOT enabled: container is deleted after saving
- If persistent mode is enabled (
[container] persistent = truein config or profile, as of v0.10.0 — previously the--persistentflag): container is kept for reuse - Cleanup is protected by
sync.Onceto prevent race conditions between signal handlers and deferred cleanup
- Session data (tool config directory) is always saved to
-
Docker/Compose support: Session containers automatically get Docker support flags (
security.nesting,security.syscalls.intercept.mknod/setxattr) applied before the container starts, so Docker and Docker Compose work out of the box inside sessions.
| Mode | Workspace Files | AI Tool Session | Container State |
|---|---|---|---|
| Default (ephemeral) | Always saved | Always saved | Deleted |
Persistent (persistent = true) |
Always saved | Always saved | Kept |
Restores the AI tool conversation in a fresh container:
- Use when you want to continue a conversation but do not need installed packages
- Container is recreated, only tool session data is restored
-
Profile auto-restore: The profile used when the session was originally created is automatically restored - no need to pass
--profileagain. Explicitly passing--profileon resume overrides the saved profile. -
Workspace-scoped: Only finds sessions from the current workspace directory (security feature) — unless
session_nameis set: named sessions find their saved sessions by NAME from any workspace location (see Named Sessions)
Keeps the entire container with all modifications:
- Use when you have installed tools, built artifacts, or modified the environment
-
coi attachreconnects to the same container with everything intact - Set it in the project's
./.coi/config.toml, your user config, or a profile — there is no CLI flag (as of v0.10.0) - On
--resume, an explicitly configuredpersistentwins over the resumed session's saved mode, so config can convert a session's persistence; when unset, the saved mode is inherited
Converts one or more ephemeral containers to persistent mode:
# Convert a specific container to persistent (keeps it on exit)
coi persist <container-name>
# Convert all containers (with confirmation)
coi persist --allUse coi list to see active containers and their persistence mode.
This is useful when you started an ephemeral session but later decide you want to keep the container (e.g., after installing tools or setting up the environment).
Forward your host's SSH agent into the container so git-over-SSH works without copying private keys:
# ~/.coi/config.toml
[ssh]
forward_agent = trueThe host's SSH_AUTH_SOCK is bridged into the container at /tmp/ssh-agent.sock via an Incus proxy device. Coi automatically sets SSH_AUTH_SOCK inside the container and includes retry logic to handle an Incus race condition where proxy devices on freshly-launched containers may not create the listen socket immediately.
Key points:
- Disabled by default (opt-in for security)
- Gracefully skips if no SSH agent is running on the host
- Works with both ephemeral and persistent containers
- Device is replaced on persistent container re-entry
Selectively forward host environment variables into the container by name:
# ~/.coi/config.toml
[defaults]
forward_env = ["ANTHROPIC_API_KEY", "GITHUB_TOKEN", "AWS_ACCESS_KEY_ID"]
# Static environment variables (always set)
[defaults.environment]
RUST_BACKTRACE = "1"
NODE_ENV = "development"Key points:
- Values are read from the host at session start - never stored in config files
- Forwarded variables are passed securely via
tmux new-session -eandtmux set-environmentinstead of being inlined asexport KEY=VALin the command string - secrets do not appear inpsoutput and propagate to new tmux windows/panes - Missing variables produce a warning but do not fail the session
- Config values from different levels are merged (deduplicated)
- Profile-level
environmentvars are also applied
-
exitin bash → exits bash but keeps container running (use for temporary shell exit) -
Ctrl+b d→ detaches from tmux, container stays running -
closeorsudo poweroff→ stops container, session is saved, then container is deleted (or kept in persistent mode). Theclosecommand is a safe alias forpoweroffthat only exists inside Coi containers, preventing accidental host shutdowns if typed outside the container.
-
coi shutdown <name>→ graceful stop with session save, then delete (60s grace window by default) - The grace window is config, not a flag (as of v0.10.0):
[container] shutdown_timeout = 30 -
coi shutdown --all→ graceful stop all containers (with confirmation) -
coi shutdown --all --force→ graceful stop all without confirmation -
coi close→ accepted alias forcoi shutdown(as of v0.11.0), identical flags and all (e.g.coi close --all). It echoes the in-containercloseverb: for the usual ephemeral container the two match (both end with the container gone), but for a persistent container they differ — the in-containerclosekeeps it (stopped, reused next session) whereascoi shutdown/coi closedeletes it. Shells will not tab-suggestclose, since completion covers command names only, not aliases. -
coi kill <name>→ force stop and delete immediately -
coi kill --all→ force stop and delete all containers (with confirmation) -
coi kill --all --force→ force stop all without confirmation -
coi unfreeze→ unfreeze a paused container (e.g., after security monitor auto-pause)
A slot is a numbered container instance tied to the same workspace. Slots let you run multiple independent AI sessions against the same project directory in parallel, each with its own isolated home directory, installed packages, and conversation history.
Coi derives a short hash from your workspace path (or from [container] session_name, when set) and uses it in the container name:
coi-abc12345-1 # first slot
coi-abc12345-2 # second slot
coi-abc12345-3 # third slot
The hash is stable — the same workspace always gets the same prefix.
Slots are allocated automatically when you run coi shell:
- If no container exists for this workspace, slot 1 is created
- If slot 1 is already running, slot 2 is created
- If slots 1 and 2 are running, slot 3 is created
By default slots are allocated automatically — each coi shell in a new terminal picks the next available number. You can also pin a specific slot with --slot N (0 means auto-allocate).
Each slot gets its own:
- Home directory (
/home/code) - Installed packages and system state
- Running processes
- AI tool conversation history
All slots share the same /workspace mount — they read and write the same project files.
When a container alias is configured, additional slots are named with a numeric suffix:
# Config: alias = "myproject"
coi shell # → myproject (slot 1)
coi shell # → myproject-2 (slot 2)
coi shell # → myproject-3 (slot 3)
# Attach by alias
coi attach myproject # slot 1
coi attach myproject-2 # slot 2coi list # shows all slots with their names and status
coi list --running # only slots whose container is Running (as of v0.10.0;
# also --stopped, or --status <any Incus state>)
coi shutdown --all # gracefully shut down all running slots
coi kill myproject-2 # force-stop a specific slot by aliascoi shell # Start session with default AI tool
# ... work with AI assistant ...
sudo poweroff # Shutdown container → session saved, container deleted
coi shell --resume # Continue conversation in fresh containerNote: exit in bash keeps the container running - use sudo poweroff or sudo shutdown 0 to properly end the session. Both require sudo but no password.
# ./.coi/config.toml
[container]
persistent = truecoi shell # Start persistent session (per config above)
# ... install tools, build things ...
# Press Ctrl+b d to detach
coi attach # Reconnect to same container with all tools
sudo poweroff # When done, shutdown and save
coi shell --resume # Resume with all installed tools intact# Terminal 1: Start first session (auto-allocates slot 1)
coi shell
# ... working on feature A ...
# Press Ctrl+b d to detach (container stays running)
# Terminal 2: Start second session (auto-allocates slot 2)
coi shell
# ... working on feature B in parallel ...
# Both sessions share the same workspace but have isolated:
# - Home directories (~/slot1_file won't appear in slot 2)
# - Installed packages
# - Running processes
# - AI tool conversation history
# List both running sessions
coi list
# coi-abc12345-1 (ephemeral)
# coi-abc12345-2 (ephemeral)
# When done, shutdown all sessions
coi shutdown --allAssign human-friendly names to your containers for easy management from any directory:
# .coi/config.toml
[container]
alias = "myproject"coi shell myproject # Launch session using alias (from any directory)
coi attach myproject # Attach to running aliased container
coi kill myproject --force # Kill by alias
coi attach myproject-2 # Attach to slot 2 by aliasAliases are registered in ~/.coi/aliases.json on first use and stored as user.coi.alias metadata on each container. coi list shows aliases next to container names.
By default a session's identity — its container name, slot and port allocation, and the saved-session store --resume/--continue searches — is keyed on a hash of the workspace's absolute path. Setting [container] session_name (typically in a profile, paired with persistent = true) keys all of that on the name instead, so the same session continues from any workspace location: a moved checkout, or several checkouts sharing one session.
# ~/.coi/profiles/myproj/config.toml
[container]
persistent = true
session_name = "myproj"Notes:
- On reuse from a new location the workspace mount is reconciled automatically (the container's workspace device is remounted from the current path before protections are re-applied). A running named session still mounting a different checkout is refused — stop it first.
- The name is honored from trusted scope only (
~/.coi/COI_CONFIG, and profiles under them): it selects which persistent container and saved state a launch attaches to, so a cloned repo's.coicannot attach itself to your session. - Launching a named session while it is already active on another slot creates a fork (a fresh container without the session's state) — coi warns loudly and names the slot to reuse instead.
- Adopting a name over an existing path-keyed workspace starts a fresh container lineage but carries the saved conversation history forward.
- If the name-carrying profile is selected via
--profileor an alias (rather than[defaults] profile), repeat that flag on operational commands (coi attach/monitor/snapshot) so they resolve the same identity. - An explicit
coi shell --container <name>bypasses both the running-workspace refusal and the workspace remount: naming a container means "enter it as it is", with its existing mounts.
Because a named session's identity is a hash of workspace + session_name — not the tool — two profiles that share one session_name (with persistent = true) resolve to the same container. Each profile sets its own [tool] name, so you can re-enter one persistent box under a different assistant while keeping its code, installed packages, and running services:
# ~/.coi/profiles/box-claude/config.toml
[container]
persistent = true
session_name = "box"
[tool]
name = "claude"# ~/.coi/profiles/box-codex/config.toml
[container]
persistent = true
session_name = "box"
[tool]
name = "codex"coi shell --profile box-claude # creates/enters "box", running Claude Code
# ... install tools, build things, then exit (the container is kept) ...
coi shell --profile box-codex # re-enters the SAME box, now running CodexThere is no --tool flag — the tool is chosen entirely by which profile you launch. Both profiles must set the same session_name with persistent = true, and both must live in trusted scope (see the trusted-scope note above).
Credentials are seeded on first switch (#708). The first time a newly-selected tool runs in a reused container, coi seeds that tool's CLI config and credentials into it, so the tool you just switched to is authenticated even though it was never used in this container before. coi does not re-copy the original tool's config, and it never touches conversation history — history is per-tool, so each assistant keeps its own transcripts across switches.
Limitations (by design in v0.11.1):
- Two truly concurrent launches of one name from different workspaces can race the workspace remount.
- Two profiles sharing a
session_nameshare one container regardless of their images — nothing registers a name's "owner". -
[[mount]]sources that lived under a moved workspace keep their old host paths (use absolute, workspace-independent mount paths with named sessions). - With
preserve_workspace_paththe in-container path changes across checkouts, so cwd-keyed tool history (e.g. Claude's per-project store) does not follow; the default/workspacemount keeps history continuous.
- Container Operations - Commands for managing running containers
- Snapshot Management - Checkpointing and restoring container state
- Tmux Automation - Interacting with AI sessions programmatically
- File Transfer - Moving files between host and container
- Configuration - Persistence, ephemeral mode, and slot settings
Home · Getting Started · Configuration · Migration Guide · GitHub · Issues
Getting Started
Setup
Configuration & Usage
- Best Practices
- Configuration
- Profiles
- Supported Tools
- Container Lifecycle & Sessions
- Container Operations
- Snapshot Management
- File Transfer
- Port Publishing
- Tmux Automation
- Headless Orchestration
- Image Management
- Resource & Time Limits
- Resource Usage (coi top)
Security
- Threat Model: Containment Limits
- Security Monitoring
- Audit Log
- Session Logs
- Security Best Practices
- Network Isolation
Maintenance
Help & Reference