SSH keys saved inside project containers were being deleted or overwritten. When a project has an SSH key path (per-project or global default), entrypoint.sh ran rm -rf /home/claude/.ssh and copied the host dir over it on every start, so anything created in the container was lost on the next start.
Fix
New sync_host_ssh in container/entrypoint.sh merges the host dir into ~/.ssh instead of replacing it:
Container-created files are never touched; a same-named host file is skipped with a warning.
Host-copied files are refreshed when the host changes and removed when the host drops them — only while still unedited in the container. Tracked in ~/.ssh/.triple-c-host-files (sha256 + path).
known_hosts is unioned, not replaced.
First start without a manifest (upgrade from the old entrypoint): differing files are backed up to <name>.triple-c-backup before being replaced.
Tests
6 unit tests in docker/image.rs extract the function from entrypoint.sh and run it against temp dirs (all pass). Not tested in a live container.
Note
Existing projects pick this up via base-image migration (Update); a plain recreate reuses the old snapshot's entrypoint.
## Problem
SSH keys saved inside project containers were being deleted or overwritten. When a project has an SSH key path (per-project or global default), `entrypoint.sh` ran `rm -rf /home/claude/.ssh` and copied the host dir over it on every start, so anything created in the container was lost on the next start.
## Fix
New `sync_host_ssh` in `container/entrypoint.sh` merges the host dir into `~/.ssh` instead of replacing it:
- Container-created files are never touched; a same-named host file is skipped with a warning.
- Host-copied files are refreshed when the host changes and removed when the host drops them — only while still unedited in the container. Tracked in `~/.ssh/.triple-c-host-files` (sha256 + path).
- `known_hosts` is unioned, not replaced.
- First start without a manifest (upgrade from the old entrypoint): differing files are backed up to `<name>.triple-c-backup` before being replaced.
## Tests
6 unit tests in `docker/image.rs` extract the function from `entrypoint.sh` and run it against temp dirs (all pass). Not tested in a live container.
## Note
Existing projects pick this up via base-image migration (Update); a plain recreate reuses the old snapshot's entrypoint.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
The entrypoint ran `rm -rf ~/.ssh` and copied the host SSH dir over it on
every start, deleting any key generated or saved inside the container and
overwriting same-named files. Replace it with sync_host_ssh, which merges:
container-created files are never touched, host-copied files are refreshed
or removed only while unedited (tracked in ~/.ssh/.triple-c-host-files),
and known_hosts is unioned. On first start without a manifest, differing
files are backed up to <name>.triple-c-backup before being replaced.
Unit tests run the function extracted from entrypoint.sh against temp dirs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jknapp
merged commit 412abd9348 into main2026-10-16 19:46:23 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Problem
SSH keys saved inside project containers were being deleted or overwritten. When a project has an SSH key path (per-project or global default),
entrypoint.shranrm -rf /home/claude/.sshand copied the host dir over it on every start, so anything created in the container was lost on the next start.Fix
New
sync_host_sshincontainer/entrypoint.shmerges the host dir into~/.sshinstead of replacing it:~/.ssh/.triple-c-host-files(sha256 + path).known_hostsis unioned, not replaced.<name>.triple-c-backupbefore being replaced.Tests
6 unit tests in
docker/image.rsextract the function fromentrypoint.shand run it against temp dirs (all pass). Not tested in a live container.Note
Existing projects pick this up via base-image migration (Update); a plain recreate reuses the old snapshot's entrypoint.
🤖 Generated with Claude Code