acpmux: a chat sees the folders in its additionalDirectories, on every harness and start
Merged
TE
3d ago+430+430+012345678901234567890123456789-8-8-0123456789
Leo asked for chats that can see any folders and files, on any harness, with nothing required to start one:
"but like also being able to have chatgpt (and in this case, any harnesses) see whatever folders/files would be cool"
"and you can also just start with nothing"
This is the acpmux half for folders. A chat can now be started with ACP's additionalDirectories on session/new, and every start of its harness receives them.
- Validation. The folders are checked: absolute paths to existing directories, made canonical, each listed once, never the chat's own folder, at most 64. Anything else is refused with
-32602. WebSocket callers are still held to the web roots first byremote_guard.rs, which already checked this field. - Storage. They are kept in
SessionMeta::additional_directories, so a respawn, a restart and a daemon restart all keep them. A fork, a side chat and a handoff target carry them too. A fork's own folder is dropped from its list, and the agent'ssession/forkis asked with them. - Chats moved in from elsewhere. A guarded move (
transfer_guard.rs) checks each folder against the move's roots, the same way it checks the chat'scwd, and drops any folder outside them. A crafted bundle can never widen what the chat sees. - Claude Code. Gets
--add-dir DIRfor each folder, at every spawn. - ACP harnesses. OpenCode, pi, Gemini and the Codex bridge get the field in
session/newandsession/load(acp_params). The field is left out when the list is empty, so nothing changes for existing chats. - Session summary. Lists
additionalDirectoriesfor the pane. - Pool. A chat that has folders never takes a pooled (prewarmed) harness, because the pooled one started without them.
- No project required. A chat started with nothing still gets them. It runs in its empty agent-home folder, the folder the app gives a chat with no project.
Not in this PR (follow-ups):
- Adding folders to a running chat. A new
_acpmuxmethod, plus a respawn at the end of the turn throughprofile_respawn.rs. - The web side: the composer chip, and Sources + taking several folders and files on any machine.
- Codex
writableRootsin the cmux-codex-acp bridge. Codex can already read outside its workspace, but writing needs the bridge to map this field. - On a remote-origin (sandboxed) Claude chain, the folders are passed as
--add-dir, but the sandbox profile (Bound::for_session) only opens the chat's own folder. Inside the sandbox they are not reachable until the bounds include them. - A harness that ignores ACP
additionalDirectoriesgets no fallback yet. A context note listing the paths is a follow-up, as is sending the field only to harnesses that advertisesessionCapabilities.additionalDirectories. ACP agents ignore unknown params, so sending it today is harmless.
Changelog
none (no UI yet)
Tests
- Red first: e3a19633bf4 adds
tests/additional_directories.rs. It was not run on the fleet at that commit, because a lane VM'scmux-ciruns only at the PR head. Without the fix, the summary key and the--add-dirwords are absent, so its assertions fail. tests/remote_guard.rs: the unix socket now refuses a relativeadditionalDirectories. The test now expects that, as the review asked.cmux-ci test -- cargo test -p acpmux --test additional_directoriesand thehub::additional_dirsunit test: results in a comment below.
Observed / Not run
See the test comment. Not run: a live Claude Code or Codex run with real folders.
Agent session: agent session
š¤ Generated with Claude Code