Skip to content

shell: Add sync-exclude flag and .limasyncignore file#4917

Open
peschmae wants to merge 2 commits into
lima-vm:masterfrom
peschmae:feat/sync-exclude-flags
Open

shell: Add sync-exclude flag and .limasyncignore file#4917
peschmae wants to merge 2 commits into
lima-vm:masterfrom
peschmae:feat/sync-exclude-flags

Conversation

@peschmae
Copy link
Copy Markdown

@peschmae peschmae commented May 1, 2026

Fix #4887

To avoid syncing generated or sensitive data into a vm, a new sync-exclude flag is added, to be used in conjunction with --sync. This allows to specify rsync excludes which are then not synced.

Additionally a .limasyncignore file can be created, which also considered and passed to rsync as the exclude-from flag.

@peschmae peschmae force-pushed the feat/sync-exclude-flags branch from 844ed46 to 5785cfc Compare May 1, 2026 08:33
@peschmae
Copy link
Copy Markdown
Author

peschmae commented May 1, 2026

@liketosweep You mentioned that you would be able to help with windows verification of this PR.

I only have a linux and mac machine that I was able to test it on, and there everything worked fine and I was successfully able to build and use the binary. As I don't have a windows machine available to me, could you help me with the windows part?

@liketosweep
Copy link
Copy Markdown

@peschmae on it

@peschmae peschmae force-pushed the feat/sync-exclude-flags branch from 5785cfc to 7b8be1e Compare May 1, 2026 08:40
@peschmae
Copy link
Copy Markdown
Author

peschmae commented May 1, 2026

Just updated the PR once more, after running the linting tools.

@liketosweep
Copy link
Copy Markdown

Windows Verification Report — PR #4917

Environment: Windows 11 host · wsl2 driver · manually compiled limactl.exe · Git Bash terminal


✅ What Was Tested

  • --sync-exclude flag (single and repeated invocations)
  • .limasyncignore file placement and parsing
  • Combined use of --sync + --sync-exclude
  • rsyncBack and getRsyncStats code paths (indirectly, via sync lifecycle)

❌ Blockers Found

1. Missing rsync Dependency — No Graceful Error

On a standard Windows host (including Git Bash / MSYS2 without extras), rsync is not present in %PATH%. The feature fails immediately with:

exec: "rsync": executable file not found in %PATH%

There is currently no user-friendly check or diagnostic message before this crash. Since one of lima's stated goals is reducing POSIX toolchain friction for Windows users, this needs either a preflight check with a clear message (e.g., "rsync is required for --sync on Windows. Install via Scoop: scoop install rsync"), or explicit documentation in the --sync flag help text.

Note: With the wsl2 driver, rsync runs on the host side to push files into the guest. If the intent is to shell out to rsync from within WSL2 instead, that assumption should be clarified in the implementation, as it changes the dependency story significantly.


2. Flag Value Concatenated Into Host Path

When passing --sync-exclude alongside --sync, the flag value is incorrectly appended to the resolved host working directory string rather than being treated as a separate rsync argument:

fatal msg="expected the depth of the host working directory
(\"/mnt/c/Users/user/project/--sync-exclude=secret.txt\")
to be more than 4..."

This looks like the argument parser is consuming the flag as a positional token and folding it into the path-building logic, rather than extracting it before path resolution. The --exclude arguments passed to rsync need to be isolated from the directory argument earlier in the pipeline.

Reproduction:

limactl shell --sync . --sync-exclude=secret.txt default

3. Positional Argument Parsing Breaks in Presence of --sync

When --sync is present, the positional argument parser appears to shift, causing the instance name to be skipped entirely:

fatal msg="instance \"ls\" does not exist"

Here, ls is the command being run inside the VM — the parser has consumed the instance name (default) as something else and landed on ls as the instance. This is a separate issue from #2 and likely stems from how the boolean --sync flag interacts with the cobra/pflag positional argument handling on Windows.

Reproduction:

limactl shell --sync default ls

🔧 Recommendations

| Area | Suggestion

-- | -- | --
1 | Dependency check | Add a preflight exec.LookPath("rsync") check before the sync runs, and return a descriptive error pointing users to installation options (Scoop, MSYS2, cwrsync).
2 | Flag isolation | Ensure --sync-exclude values are extracted and stored before the host working directory is resolved; they should never enter the path-construction code path.
3 | Positional arg parsing | Audit the command parsing order for shell when --sync is passed — specifically verify that boolean flags don't shift the [instance] positional slot on Windows builds.
4 | .limasyncignore path | Confirm that the file lookup uses the resolved host directory root, not os.Getwd(), to avoid issues when limactl is called from a different working directory.


📝 Notes

AI assistance was used during testing and for drafting this report.

@liketosweep
Copy link
Copy Markdown

@peschmae I've published the results of all the test i have conducted above .
Note - AI was used in testing and drafting of report so there maybe minor errors .

@peschmae
Copy link
Copy Markdown
Author

peschmae commented May 1, 2026

Thanks for the review, I had a quick look at your findings.

  1. Missing rsync Dependency — No Graceful Error

I assume this is already the case with 2.1? I can investigate this, but I think this is unrelated to this PR.

  1. Flag Value Concatenated Into Host Path

I'm not able to reproduce this, with your reproduction sample, but if I don´t provide a path, it takes the --sync-exclude as the path to sync.

eg.

limactl shell --sync --sync-exclude='.git*' ai-box

But this would then be the same finding as 3, which also doesn´t provide a directory in the reproduction sample.

  1. Positional Argument Parsing Breaks in Presence of --sync
limactl shell --sync default ls

In this example, you provide the directory default to by synced, and ls as the instance name.

@liketosweep
Copy link
Copy Markdown

@peschmae, thanks for the feedback regarding positional argument order.

I re-tested natively on Windows using the explicit directory . as suggested, but the Path Concatenation Bug persists:

Updated Command: limactl shell --sync . default ls

Observed Behavior: The CLI still appends subsequent flags/arguments directly to the host path string (e.g., /mnt/c/Users/.../--sync-exclude=.git*) .

Finding: Even with the corrected syntax, the Windows parser fails to properly terminate the path string before moving to the next argument, causing the "directory depth" fatal error.

I've attached a fresh trace showing the result with the updated command structure. Regarding rsync , I agree it is likely an inherited issue, though I've noted it for the maintainers as a general Windows UX blocker .

image

The above image shows the commands executed .

Note: AI was utilized during the testing process and for the documentation of this report.

To avoid syncing generated or sensitive data into a vm, a new sync-exclude flag
is added, to be used in conjunction with --sync. This allows to specify rsync excludes
which are then not synced.

Additionally a .limasyncignore file can be created, which also considered and
passed to rsync as the exclude-from flag.

Signed-off-by: Mathias Petermann <mathias.petermann@gmail.com>
@peschmae peschmae force-pushed the feat/sync-exclude-flags branch from 7b8be1e to 6e86471 Compare May 1, 2026 19:30
limactl shell --sync . --sync-exclude .git default
```

Alternatively a `.limasyncignore` file can be created in the target directory, which contains a list of excludes.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if we want to have a .limasyncignore file, maybe we can have something like https://lima-vm.io/docs/config/environment-variables/#lima_shellenv_block but would love to know what other maintainers think of this.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another option would be, to implement a --sync-exclude-from flag, which the user can then point to a specific file. This would remove the magic where files aren't synced, since it would need a conscious decision by the user to set the flag.

Comment thread cmd/limactl/shell_test.go
@peschmae
Copy link
Copy Markdown
Author

peschmae commented May 1, 2026

I've rebased my feature branch to master, to get the latest changes.

Additionally I've implemented a better handling of the --sync flag if no directory is provided. If it's followed by another flag, a corresponding error is shown.

$ limactl shell --sync --sync-exclude=git ai-box ls
FATA[0000] --sync flag requires a directory path argument, got "--sync-exclude=git" instead
Usage: limactl shell --sync <DIR> [--sync-exclude <PATTERN>...] <INSTANCE> [COMMAND...]

$ limactl shell --sync . --sync-exclude=git ai-box ls
INFO[0000] Syncing host current directory(/home/peschmae/upstream/lima) to guest instance...
INFO[0000] Successfully synced host current directory to guest(/home/peschmae.guest/home/peschmae/upstream/lima) instance.
LICENSE  MAINTAINERS.md  Makefile  NOTICE  README.md  ROADMAP.md  _output  cmd	docs  go.mod  go.sum  hack  pkg  templates  vz.entitlements  website
INFO[0000] No changes detected

Regarding the error @liketosweep got in the shell on windows, this probably requires more indepth analysis, and I guess it also happens with the latest released version.

In the shell.go the depth of directory is determined by splitting on os.PathSeperator which on Windows would be \. But since the commands were run in a different shell (git bash or simliar), the path is split by / which then results in no os.PathSeperator being found to split on.

Signed-off-by: Mathias Petermann <mathias.petermann@gmail.com>
@peschmae peschmae force-pushed the feat/sync-exclude-flags branch from 4c25bd2 to 37bef33 Compare May 1, 2026 21:07
@unsuman unsuman added this to the v2.2.0 milestone May 1, 2026
@jandubois
Copy link
Copy Markdown
Member

I've generated a "deep" AI review using multiple agents: https://jandubois.github.io/lima/20260501-221035-pr-4917.html

I've not looked into the report myself, especially not into the Windows path findings, and how they would interact with the proposed changes to make Lima work on Windows without msys and git for Windows.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

shell --sync: Allow excluding files/folders from rsync

4 participants