Cloud start: never copy a credential folder; a gone or home folder says why
Follow-up to #34969, which fixed the Cloud start Leo asked about ("what's this") when it refused with:
This folder isn't open in this tab; pick it to send it to Cloud.
Since #34969 the Send's gesture is the pick of the composer's folder. That review left three follow-ups, and this PR fixes all of them.
Fixes #35006: never copy a credential folder
A Cloud start is now refused when its folder, its Git working copy or any of that copy's git folders:
- is one of home's credential folders:
~/.ssh,~/.aws,~/.gnupg,~/.config/gcloud,~/.kube,~/.docker,~/.secrets,~/.azureor~/Library(which holds Keychains); - is inside one of them; or
- holds one of them (so
~/.configis refused because it holds gcloud's folder).
The match ignores case, because this Mac's disk does not tell ~/.SSH from ~/.ssh. The refusal names the folder: "Cloud never copies ~/.ssh, which holds keys or credentials; pick a project folder." There was no shared Rust or web helper on this path, so the rule is the same Swift check (AgentPaneCloudFolderRefusal). Its list matches cmux-tui's link/access_cli.rs SECRET_FOLDERS, which covers a different path (the files of a shared folder).
Fixes #35005: each refusal says why
These refusals used to share transport.path_outside_roots and its "isn't open in this tab" message. Each now has its own code and message:
| Folder | Code | Message |
|---|---|---|
| Missing, or not a folder | cloud_folder_missing | "This folder no longer exists; pick another one to send to Cloud." |
| Home or above it | cloud_folder_home | "Cloud doesn't copy your home folder or a folder above it; pick a project folder." |
| Credential folder | cloud_folder_secret | Names the folder, as above. |
The codes are in both refused-here lists (AgentPaneHandOff.refusedHereCodes in Swift, REFUSED_HERE on the page), so no checklist step is marked failed. The three new strings are in every locale of Localizable.xcstrings.
Fixes #35004: stale comments
The comments on gitFolders and CloudStartChat that still described the old roots check are fixed.
Tests
- Swift
AgentPaneCloudStartTests:aCredentialFolderOrOneHoldingItIsNeverCopiedAndTheRefusalNamesIt,aMissingFolderAndHomeOrAboveEachSayWhy. - Web
cloudStartProgress.test.ts: "a gone, home or credential folder each says why".
Commands:
- Swift:
cmux-ci run --class light --script scripts/ci/package-test-lane.sh --arg suite --arg Packages/macOS/CmuxNext --arg AgentPaneCloudStartTests, at c2adee3 (the tests alone, expected red) and at the head (expected green). - Web:
bun test src/agent-session/acpmux/cloudStartProgress.test.tsthroughcmux-ci test.
The results are posted in a comment.
Observed / Not run
- Observed:
prepush-gate.pyshows no new violations, and the xcstrings key check passes.scripts/web-lint.shfails only ontest/transcript-row-hover-scope.test.ts:82, which this PR doesn't touch and which is red on base c48f7b6d29a. - Not run: a nightly Cloud start.
Changelog
- Fixed: A Cloud start never copies a folder of keys or credentials (~/.ssh, ~/.aws and others), and says why when it refuses a missing folder, the home folder, or a credential folder.
Agent session: agent session
🤖 Generated with Claude Code
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Cloud starts now never copy a folder of keys or credentials, and each folder refusal says why instead of the generic "This folder isn't open in this tab."
Bug Fixes
- Refuses any folder that is, is inside, or holds one of home's credential folders (
~/.ssh,~/.aws,~/.gnupg,~/.config/gcloud,~/.kube,~/.docker,~/.secrets,~/.azure,~/Library/Keychains), matching case-insensitively and naming the folder in the refusal. Projects under~/Library(iCloud Drive, CloudStorage) still start, and a pane with no home folder checks this Mac's. - Gives missing, home-or-above, and credential folder refusals their own codes and messages (
cloud_folder_missing,cloud_folder_home,cloud_folder_secret) instead of the sharedtransport.path_outside_roots. - Keeps the new codes on the refused-here lists so no checklist step is marked failed, and fixes stale comments describing the old roots check.