## Context Currently, all tool instances bind-mount the host repository path via `{{REPO_PATH}}` substitution in compose templates. The repository model (`GitRepository`) has no SSH key association. The instance model (`ToolInstance`) has no concept of repository access mode. Users want two modes: 1. **Mount** (current): Live sync with working copy on host 2. **Clone** (new): Fresh isolated copy with full git history inside the container The SSH key system already exists with encrypted private keys in the database. Keys can be project-scoped or user-scoped. ## Goals / Non-Goals **Goals:** - Allow per-instance choice between mount and clone mode - Support branch selection for clone mode (default: main) - Enable git operations inside containers via SSH key mounting - Protect against accidental data loss with dirty check on clone deletion - Allow SSH key assignment at repository creation and later modification **Non-Goals:** - Modifying existing tool type compose templates - Installing git in containers (assumes tool images have git or install it) - Multiple SSH keys per container - Automatic push/pull/sync between host and container - Shallow clones (full history only) ## Decisions ### 1. Host-Side Clone (not in-container) **Decision**: Clone happens on the host before container start, not inside the container. **Rationale**: - No changes to compose templates required - Works with all existing tool types immediately - No need for git/SSH inside every container image - Host has direct filesystem access to the clone - Easier error handling and rollback **Alternative considered**: In-container clone via command override. Rejected because it requires git in every image, SSH auth setup inside containers, and makes error handling fragile. ### 2. SSH Key Mounting via `_modify_compose_file` **Decision**: Inject SSH key volume dynamically at container start time using the existing `_modify_compose_file` helper. **Rationale**: - Zero changes to tool type definitions - Consistent with how other runtime overrides work (port, command, working_dir, extra_volumes) - Mounts the `.ssh/` directory with key + config into container **Implementation**: ``` instance_dir/.ssh/ id_ed25519 (decrypted private key, mode 600) id_ed25519.pub (public key) config (StrictHostKeyChecking no) ``` Mounted as: `instance_dir/.ssh:/root/.ssh:ro` (or appropriate home dir) ### 3. Single SSH Key per Repository **Decision**: The SSH key is stored on `GitRepository` and used for both clone and container access. **Rationale**: - Natural association: a repository's clone URL determines which SSH key is needed - Simpler UX: one key per repo, not per session - Session creation can override (future enhancement) but defaults to repo key ### 4. Dirty Check via `git status --short` **Decision**: Check for uncommitted changes using `git status --short` before allowing deletion of clone-mode instances. **Rationale**: - Simple and reliable - Catches staged, unstaged, and untracked files - Fast (local filesystem operation) ## Risks / Trade-offs **[Risk] Disk space usage** → Each clone-mode instance duplicates the full repository. Mitigation: Instance deletion removes the clone directory. **[Risk] Clone time for large repos** → Synchronous clone during instance creation may timeout. Mitigation: No timeout on clone operation; consider async clone in future. **[Risk] SSH key permissions in containers** → Some containers run as non-root users. The `.ssh` directory mount needs correct ownership. Mitigation: Mount as read-only; container's entrypoint may need to copy to writable location if needed. **[Risk] Git not installed in custom tool images** → User-defined tool types may not have git. Mitigation: Document requirement; built-in types already have or install git. **[Risk] SSH host key checking** → Cloning from new hosts may fail. Mitigation: SSH config sets `StrictHostKeyChecking no` for clone operations. ## Migration Plan 1. Run Alembic migrations to add new columns 2. Existing instances default to `clone_mode='mount'` (no behavior change) 3. Existing repositories have `ssh_key_id=null` (no behavior change until assigned) 4. No data migration needed ## Open Questions - Should the `.ssh` mount be read-only or writable? (Writable needed if container generates new keys, but we don't support that) - Should we support submodules in cloned repos?