Skip to content

Migration Guide

Maciej Mensfeld edited this page May 26, 2026 · 4 revisions

Migration Guide

This page documents breaking changes between COI versions and how to migrate. Check this page after a coi update if the release notes mention configuration or behavior changes.

Config File Location: .coi.toml.coi/config.toml

In earlier versions of COI, the project config file was .coi.toml at the project root. This has been replaced by .coi/config.toml in a directory.

Before:

your-project/
├── .coi.toml       ← old location
└── ...

After:

your-project/
├── .coi/
│   └── config.toml ← new location
└── ...

Migration Steps

  1. Create the .coi/ directory in your project root:
mkdir -p .coi
  1. Move the old config file:
mv .coi.toml .coi/config.toml
  1. Update your .gitignore if needed — the directory form is typically still excluded:
# If you were ignoring the old file, update to the directory
.coi/
  1. Profile directories also move: ~/.coi-profiles/~/.coi/profiles/ (user-level) and .coi-profiles/.coi/profiles/ (project-level). Move your profile directories accordingly.

COI will warn on startup if it detects a .coi.toml at the project root and no .coi/config.toml, so you will not silently lose configuration.

Mount Syntax: [[mounts]] vs [[mounts.default]]

The mount table key differs between the main config and profile configs:

Context Correct key
~/.coi/config.toml or .coi/config.toml [[mounts.default]]
.coi/profiles/NAME/config.toml [[mounts]]

Main config:

# .coi/config.toml
[[mounts.default]]
host = "~/.claude/skills"
container = "/home/code/.claude/skills"
readonly = true

Profile config:

# .coi/profiles/rust-dev/config.toml
[[mounts]]
host = "~/.cargo"
container = "/home/code/.cargo"

Using [[mounts]] in the main config or [[mounts.default]] in a profile config will result in the mounts being silently ignored. If extra files are not appearing in the container, check the mount key.

Checking Your Current Version

coi version

Compare against the releases page to identify which migrations apply to your upgrade path.

Boolean Config Fields Now Use Pointer Semantics

Affected versions: All versions before this fix was introduced.

Symptom: Security settings like block_private_networks, auto_pause_on_high, or auto_kill_on_critical appeared disabled even though they were set to true in a lower-priority config file.

Cause: The multi-layer config merge (global → project → profile → CLI) used plain bool fields. When a higher-priority config omitted a boolean field, it defaulted to false and silently overwrote the true value from a lower-priority file.

Fix: 13 boolean config fields were converted to pointer types (*bool). Omitted fields are now nil (no override) rather than false. Update COI and verify your security settings are applied:

coi update
coi health --verbose
# Check the Monitoring section for auto_pause=true and other security settings

No config changes needed — the fix is transparent once you update the binary.

Claude Settings.json Deep Merge

Symptom: ~/.claude/settings.json was overwritten with COI's sandbox/bypass settings after coi shell. Custom settings (AWS Bedrock credentials, env variables, allowedTools) were lost.

Fix: COI now performs a deep merge rather than replacing the file. Existing fields are preserved; COI only adds the sandbox permissions it needs. If your settings were already overwritten, recreate them — going forward the merge is safe.

Docker Compose Support: Three-Step Launch

Symptom: docker compose up failed inside containers started with coi shell. Docker itself worked but Compose errored out.

Cause: A race condition where incus launch started the container before Docker support flags (security.nesting, security.syscalls.intercept.mknod, security.syscalls.intercept.setxattr) were applied.

Fix: Container launch now uses a three-step sequence: incus init → apply flags → incus start. Update COI to get this fix; no config changes needed.

Session Save: Cross-Device Link (EXDEV) Error

Symptom: Session save failed with an EXDEV (cross-device link) error when /tmp and the session storage directory were on different filesystems.

Fix: COI now falls back to a recursive copy when os.Rename fails with EXDEV. Update COI to get this fix.

UID/GID Remapping for Non-Default code_uid

Symptom: I have no name! shell prompt, or Permission denied errors on /home/code files, when code_uid in config was set to a value other than 1000.

Fix: COI now automatically remaps the container user's UID/GID during session setup when code_uid differs from the image default. Update COI. If you have an existing persistent container with broken ownership, fix manually:

incus exec <container-name> -- usermod -u <your-uid> code
incus exec <container-name> -- groupmod -g <your-uid> code
incus exec <container-name> -- chown -R <your-uid>:<your-uid> /home/code

See Also

Clone this wiki locally