Support mounting host directories outside workspace - #83
Draft
janost wants to merge 1 commit into
Draft
Conversation
janost
marked this pull request as draft
March 5, 2026 17:45
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This is a PR for #82.
Add
--direct-mountflag to mount host directories at arbitrary guest paths, independent of--workspace. Also fix FUSE-mounted file ownership to reflect host UID/GID instead of always showingroot:root.Motivation
All VFS mounts currently must be subpaths of
--workspace. This makes it impossible to mount host credentials or config at locations tools expect them (e.g.,~/.ssh,~/.aws,~/.config/gh) without setting up a workspace that encompasses them. Direct mounts solve this by allowing workspace-independent host-to-guest directory mapping.Usage
:rwfor read-write--workspace— direct-mount-only sandboxes are validChanges
API layer (
pkg/api/)mount.go:DirectMountSpectype andParseDirectMountSpec()parser — handleshost:guest[:rw]format with host path validation, guest path safety checks, and absolute path resolutionerrors.go:ErrInvalidDirectMountFormatsentinel errorconfig.go:HasVFSMounts()now considers direct mounts;ValidateVFS()validates direct mount guest paths independently of workspace; interception check accepts direct mountsmount_test.go: 7 tests forParseDirectMountSpec(basic readonly, explicit rw, host not exist, relative guest, invalid format, unknown option, too many parts)config_test.go: 4 tests (direct mounts without workspace, mixed mounts, invalid path rejection,HasVFSMountswith direct mounts only)CLI (
cmd/matchlock/)cmd_run.go:--direct-mountrepeatable flag, viper binding, parsing intovfsConfig.DirectMounts— VFS config now created when direct mounts are present even without workspaceSandbox (
pkg/sandbox/)sandbox_common.go:buildVFSProviders()createsRealFSProvider/ReadonlyProviderfor each direct mount; newsortedDirectMountPaths()helper for deterministic kernel arg orderingsandbox_linux.go/sandbox_darwin.go: PasssortedDirectMountPaths(config)toVMConfigVM backends (
pkg/vm/)backend.go:DirectMountPaths []stringadded toVMConfiglinux/backend.go: Addsmatchlock.direct_mount=path1,path2kernel argdarwin/backend.go: Same kernel arg added to all 3 format string variants (no-network, interception, default)Guest FUSE daemon (
internal/guestruntime/fused/)main.go:getDirectMountsFromCmdline()parsesmatchlock.direct_mount=kernel arg;connectVFSClient()extracted as helper;Run()refactored to collect mount points from both workspace and direct mounts, create one VFSClient + FUSE server per mount, and usesync.WaitGroupfor concurrent serve/shutdownSDK (
pkg/sdk/)types.go:DirectMountConfigstruct;DirectMountsfield onCreateOptionsbuilder.go:MountDirect()andMountDirectReadonly()builder methodscreate.go: Serializesdirect_mountsin VFS params of create requestBug fix: VFS UID/GID propagation (
pkg/vfs/server.go+fused/main.go)VFSStatwire format now includesUID/GIDfieldsstatFromInfo()extracts UID/GID fromsyscall.Stat_ton the host sidefillAttr()passes UID/GID through to the kernel viafuse.Attrroot:root— affects workspace mounts too, not just direct mountsNotes