- Add clone_mode and branch fields to tool_instances - Add ssh_key_id to git_repositories for per-repo SSH key assignment - Implement host-side git cloning with branch selection (default: main) - Mount SSH keys into containers for git operations in clone mode - Add dirty state check on clone-mode instance deletion with confirmation - Update SessionsPage with mount/clone selector, branch input, SSH key display - Add SSH key selector to repository creation form - Add dirty delete confirmation modal with changed files list - Update API schemas and endpoints for new fields - Sync delta specs to main specs (git-repo, tool-instances, repo-clone-mode) - Archive completed OpenSpec change: repo-clone-mode-with-ssh - Document git requirement for custom tool types Quality gates: Frontend typecheck and build passed OpenSpec: repo-clone-mode-with-ssh archived with all tasks complete
4.3 KiB
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:
- Mount (current): Live sync with working copy on host
- 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
- Run Alembic migrations to add new columns
- Existing instances default to
clone_mode='mount'(no behavior change) - Existing repositories have
ssh_key_id=null(no behavior change until assigned) - No data migration needed
Open Questions
- Should the
.sshmount 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?