Repository: lima-vm/lima

Issue:
`make check-generated` should check reproducibility of `*.pb.go`, not just `*.pb.desc`
https://github.com/lima-vm/lima/blob/dc733cf1cad7210ab0ede06846bdb1b99108d031/.github/workflows/test.yml#L38-L39

https://github.com/lima-vm/lima/blob/dc733cf1cad7210ab0ede06846bdb1b99108d031/Makefile#L502-L506


`make check-generated` should check reproducibility of `*.pb.go` too, as such machine-generated codes are well-known hot spots to hide malicious contribution.

Our repo does **not** seem compromised so far, so I'm not treating this issue as a vulnerability.
- https://github.com/lima-vm/lima/commits/master/pkg/guestagent/api/guestservice.pb.go
- https://github.com/lima-vm/lima/commits/master/pkg/guestagent/api/guestservice_grpc.pb.go
- https://github.com/lima-vm/lima/commits/master/pkg/driver/external/driver.pb.go
- https://github.com/lima-vm/lima/commits/master/pkg/driver/external/driver_grpc.pb.go


Hints from issue comments:

Solution patch:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index a303db15..c9ebd98c 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -36,7 +36,7 @@ jobs:
         # macOS SDK version
         xcrun --show-sdk-version || true
     - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8  # v5.0.0
-    - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5  # v5.5.0
+    - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00  # v6.0.0
       with:
         go-version: 1.25.x
     - name: Make darwin artifacts
@@ -63,7 +63,7 @@ jobs:
       with:
         name: artifacts-darwin
         path: _artifacts/
-    - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5  # v5.5.0
+    - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00  # v6.0.0
       with:
         go-version: 1.25.x
     - name: Install gcc
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index b39384d8..6611b084 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -27,7 +27,7 @@ jobs:
     timeout-minutes: 30
     steps:
     - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8  # v5.0.0
-    - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5  # v5.5.0
+    - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00  # v6.0.0
       with:
         go-version: 1.25.x
     - name: Install protoc and Go plugins
@@ -80,7 +80,7 @@ jobs:
         git config --global core.autocrlf false
         git config --global core.eol lf
     - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8  # v5.0.0
-    - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5  # v5.5.0
+    - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00  # v6.0.0
       with:
         go-version: 1.25.x
     - id: golangci-lint-version
@@ -128,7 +128,7 @@ jobs:
         sudo apt-get update
         sudo apt-get install -y --no-install-recommends qemu-utils
     - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8  # v5.0.0
-    - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5  # v5.5.0
+    - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00  # v6.0.0
       with:
         go-version: ${{ matrix.go-version }}
     - name: Unit tests
@@ -179,7 +179,7 @@ jobs:
         git config --global core.autocrlf false
         git config --global core.eol lf
     - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8  # v5.0.0
-    - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5  # v5.5.0
+    - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00  # v6.0.0
       with:
         go-version: 1.25.x
     - name: Unit tests
@@ -207,7 +207,7 @@ jobs:
         git config --global core.autocrlf false
         git config --global core.eol lf
     - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8  # v5.0.0
-    - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5  # v5.5.0
+    - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00  # v6.0.0
       with:
         go-version: 1.25.x
     - name: Make
@@ -232,7 +232,7 @@ jobs:
     timeout-minutes: 120
     steps:
     - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8  # v5.0.0
-    - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5  # v5.5.0
+    - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00  # v6.0.0
       with:
         go-version: 1.25.x
     - name: Unit tests
@@ -301,7 +301,7 @@ jobs:
         - ../hack/test-templates/test-misc.yaml  # TODO: merge net-user-v2 into test-misc
     steps:
     - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8  # v5.0.0
-    - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5  # v5.5.0
+    - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00  # v6.0.0
       with:
         go-version: 1.25.x
     - name: Make
@@ -354,7 +354,7 @@ jobs:
         # checks Lima's version and requires proper semantic version format
         fetch-depth: 0
         ref: ${{ github.event.pull_request.head.sha }}
-    - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5  # v5.5.0
+    - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00  # v6.0.0
       with:
         go-version: 1.25.x
     - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809  # v4.2.4
@@ -397,7 +397,7 @@ jobs:
     timeout-minutes: 120
     steps:
     - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8  # v5.0.0
-    - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5  # v5.5.0
+    - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00  # v6.0.0
       with:
         go-version: 1.25.x
     - name: Make
@@ -458,7 +458,7 @@ jobs:
         path: homebrew-core
         fetch-depth: 0
         filter: tree:0
-    - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5  # v5.5.0
+    - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00  # v6.0.0
       with:
         go-version: 1.25.x
     - name: Cache image used by ${{ matrix.oldver }}/examples/ubuntu-lts.yaml
@@ -494,7 +494,7 @@ jobs:
         - default.yaml
     steps:
     - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8  # v5.0.0
-    - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5  # v5.5.0
+    - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00  # v6.0.0
       with:
         go-version: 1.25.x
     - name: Make
@@ -527,7 +527,7 @@ jobs:
     timeout-minutes: 30
     steps:
     - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8  # v5.0.0
-    - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5  # v5.5.0
+    - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00  # v6.0.0
       with:
         go-version: 1.25.x
     - name: Install gomodjail
@@ -552,7 +552,7 @@ jobs:
     timeout-minutes: 30
     steps:
     - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8  # v5.0.0
-    - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5  # v5.5.0
+    - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00  # v6.0.0
       with:
         go-version: 1.25.x
     - run: GOOS=netbsd go build ./...
@@ -564,7 +564,7 @@ jobs:
     timeout-minutes: 30
     steps:
     - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8  # v5.0.0
-    - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5  # v5.5.0
+    - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00  # v6.0.0
       with:
         go-version: 1.25.x
     - name: Make
diff --git a/Makefile b/Makefile
index 3b718ecd..e8d004ef 100644
--- a/Makefile
+++ b/Makefile
@@ -501,9 +501,8 @@ uninstall:
 
 .PHONY: check-generated
 check-generated:
-	@test -z "$$(git status --short | grep ".pb.desc" | tee /dev/stderr)" || \
-		((git diff $$(find . -name '*.pb.desc') | cat) && \
-		(echo "Please run 'make generate' when making changes to proto files and check-in the generated file changes" && false))
+	git diff --exit-code || \
+		(echo "Please run 'make generate' when making changes to proto files and check-in the generated file changes" && false)
 
 .PHONY: lint
 lint: check-generated
diff --git a/cmd/limactl/editflags/editflags.go b/cmd/limactl/editflags/editflags.go
index d6b87547..2a11e394 100644
--- a/cmd/limactl/editflags/editflags.go
+++ b/cmd/limactl/editflags/editflags.go
@@ -16,6 +16,7 @@ import (
 	"github.com/spf13/cobra"
 	flag "github.com/spf13/pflag"
 
+	"github.com/lima-vm/lima/v2/pkg/localpathutil"
 	"github.com/lima-vm/lima/v2/pkg/registry"
 )
 
@@ -174,6 +175,10 @@ func buildMountListExpression(ss []string) (string, error) {
 	for i, s := range ss {
 		writable := strings.HasSuffix(s, ":w")
 		loc := strings.TrimSuffix(s, ":w")
+		loc, err := localpathutil.Expand(loc)
+		if err != nil {
+			return "", err
+		}
 		expr += fmt.Sprintf(`{"location": %q, "writable": %v}`, loc, writable)
 		if i < len(ss)-1 {
 			expr += ","
diff --git a/hack/gogenerate/protoc.sh b/hack/gogenerate/protoc.sh
new file mode 100755
index 00000000..d9c5bd36
--- /dev/null
+++ b/hack/gogenerate/protoc.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+# SPDX-FileCopyrightText: Copyright The Lima Authors
+# SPDX-License-Identifier: Apache-2.0
+
+# Generate Go code from a .proto file.
+# Expected to be called from `//go:generate` directive.
+
+set -eu
+if [ "$#" -ne 1 ]; then
+	echo >&2 "Usage: $0 FILE"
+	exit 1
+fi
+
+PROTO="$1"                         ## a.proto
+BASE="$(basename "$PROTO" .proto)" ## a
+PB_DESC="${BASE}.pb.desc"          ## a.pb.desc
+PB_GO="${BASE}.pb.go"              ## a.pb.go
+GRPC_PB_GO="${BASE}_grpc.pb.go"    ## a_grpc.pb.go
+
+set -x
+
+protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative "$PROTO" --descriptor_set_out="$PB_DESC"
+
+# -// - protoc             v6.32.0
+# +// - protoc version [omitted for reproducibility]
+#
+# perl is used because `sed -i` is not portable across BSD (macOS) and GNU.
+perl -pi -E 's@(^//.*)protoc[[:blank:]]+v[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+@\1protoc version [omitted for reproducibility]@g' "$PB_GO" "$GRPC_PB_GO"
diff --git a/pkg/driver/external/driver.pb.go b/pkg/driver/external/driver.pb.go
index 361f8b74..99026734 100644
--- a/pkg/driver/external/driver.pb.go
+++ b/pkg/driver/external/driver.pb.go
@@ -1,7 +1,7 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
 // 	protoc-gen-go v1.36.8
-// 	protoc        v6.32.0
+// 	protoc version [omitted for reproducibility]
 // source: driver.proto
 
 package external
diff --git a/pkg/driver/external/driver_grpc.pb.go b/pkg/driver/external/driver_grpc.pb.go
index ee2b02c4..cc6e2b51 100644
--- a/pkg/driver/external/driver_grpc.pb.go
+++ b/pkg/driver/external/driver_grpc.pb.go
@@ -1,7 +1,7 @@
 // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
 // versions:
 // - protoc-gen-go-grpc v1.5.1
-// - protoc             v6.32.0
+// - protoc version [omitted for reproducibility]
 // source: driver.proto
 
 package external
diff --git a/pkg/driver/external/gen.go b/pkg/driver/external/gen.go
index 84b6f38a..56ec1ff1 100644
--- a/pkg/driver/external/gen.go
+++ b/pkg/driver/external/gen.go
@@ -1,4 +1,4 @@
-//go:generate protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative driver.proto --descriptor_set_out=driver.pb.desc
+//go:generate ../../../hack/gogenerate/protoc.sh driver.proto
 
 // SPDX-FileCopyrightText: Copyright The Lima Authors
 // SPDX-License-Identifier: Apache-2.0
diff --git a/pkg/driverutil/vm.go b/pkg/driverutil/vm.go
index f6b3fbf3..63358a90 100644
--- a/pkg/driverutil/vm.go
+++ b/pkg/driverutil/vm.go
@@ -90,7 +90,7 @@ func handlePreConfiguredDriverAction(ctx context.Context, y *limatype.LimaYAML,
 	}
 
 	if stderrBuf.Len() > 0 {
-		return fmt.Errorf("external driver stderr: %s", stderrBuf.String())
+		logrus.Debugf("external driver stderr: %s", stderrBuf.String())
 	}
 
 	*y = res
@@ -168,7 +168,7 @@ func handleInspectStatusAction(ctx context.Context, inst *limatype.Instance, ext
 	}
 
 	if stderrBuf.Len() > 0 {
-		return "", fmt.Errorf("external driver stderr: %s", stderrBuf.String())
+		logrus.Debugf("external driver stderr: %s", stderrBuf.String())
 	}
 
 	*inst = respInst
diff --git a/pkg/guestagent/api/gen.go b/pkg/guestagent/api/gen.go
index d0980afc..d2b94c93 100644
--- a/pkg/guestagent/api/gen.go
+++ b/pkg/guestagent/api/gen.go
@@ -1,4 +1,4 @@
-//go:generate protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative guestservice.proto --descriptor_set_out=guestservice.pb.desc
+//go:generate ../../../hack/gogenerate/protoc.sh guestservice.proto
 
 // SPDX-FileCopyrightText: Copyright The Lima Authors
 // SPDX-License-Identifier: Apache-2.0
diff --git a/pkg/guestagent/api/guestservice.pb.go b/pkg/guestagent/api/guestservice.pb.go
index 38bfc162..b17b7156 100644
--- a/pkg/guestagent/api/guestservice.pb.go
+++ b/pkg/guestagent/api/guestservice.pb.go
@@ -1,7 +1,7 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
 // 	protoc-gen-go v1.36.8
-// 	protoc        v6.32.0
+// 	protoc version [omitted for reproducibility]
 // source: guestservice.proto
 
 package api
diff --git a/pkg/guestagent/api/guestservice_grpc.pb.go b/pkg/guestagent/api/guestservice_grpc.pb.go
index 6c31e95b..65c6086c 100644
--- a/pkg/guestagent/api/guestservice_grpc.pb.go
+++ b/pkg/guestagent/api/guestservice_grpc.pb.go
@@ -1,7 +1,7 @@
 // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
 // versions:
 // - protoc-gen-go-grpc v1.5.1
-// - protoc             v6.32.0
+// - protoc version [omitted for reproducibility]
 // source: guestservice.proto
 
 package api
diff --git a/pkg/limayaml/containerd.yaml b/pkg/limayaml/containerd.yaml
index b78207d1..4f449c1e 100644
--- a/pkg/limayaml/containerd.yaml
+++ b/pkg/limayaml/containerd.yaml
@@ -1,9 +1,9 @@
 archives:
-- location: https://github.com/containerd/nerdctl/releases/download/v2.1.3/nerdctl-full-2.1.3-linux-amd64.tar.gz
+- location: https://github.com/containerd/nerdctl/releases/download/v2.1.4/nerdctl-full-2.1.4-linux-amd64.tar.gz
   arch: x86_64
-  digest: sha256:e4750ba025c1a9b3d365285f800e683287ee782f0a878bc8c395f28d7bc194ba
-- location: https://github.com/containerd/nerdctl/releases/download/v2.1.3/nerdctl-full-2.1.3-linux-arm64.tar.gz
+  digest: sha256:03c1a3194b6e5fec02d866a35d0029c694b4cedb865b28f931187aa0c85dd125
+- location: https://github.com/containerd/nerdctl/releases/download/v2.1.4/nerdctl-full-2.1.4-linux-arm64.tar.gz
   arch: aarch64
-  digest: sha256:544fa1e518155fcc01a117ea49819d12d96b4dacfb2b62922f9f7956dc9f6dc8
+  digest: sha256:124b171778f8cc9bb317e094e5a92de5faf6d1bb5f5c9ded4b82a55df2c3c295
 # No arm-v7
 # No riscv64
diff --git a/pkg/limayaml/defaults.go b/pkg/limayaml/defaults.go
index ae915b5b..1c96ff8e 100644
--- a/pkg/limayaml/defaults.go
+++ b/pkg/limayaml/defaults.go
@@ -713,10 +713,14 @@ func FillDefault(ctx context.Context, y, d, o *limatype.LimaYAML, filePath strin
 				mounts[i].NineP.Cache = ptr.Of(Default9pCacheForRO)
 			}
 		}
-		if location, err := localpathutil.Expand(mount.Location); err == nil {
-			mounts[i].Location = location
-		} else {
-			logrus.WithError(err).Warnf("Couldn't expand location %q", mount.Location)
+
+		// Expand a path that begins with `~`. Relative paths are not modified, and rejected by Validate() later.
+		if localpathutil.IsTildePath(mount.Location) {
+			if location, err := localpathutil.Expand(mount.Location); err == nil {
+				mounts[i].Location = location
+			} else {
+				logrus.WithError(err).Warnf("Couldn't expand location %q", mount.Location)
+			}
 		}
 		if mount.MountPoint == nil {
 			mountLocation := mounts[i].Location
diff --git a/website/content/en/docs/config/environment-variables.md b/website/content/en/docs/config/environment-variables.md
index 064917e9..69acb1e1 100644
--- a/website/content/en/docs/config/environment-variables.md
+++ b/website/content/en/docs/config/environment-variables.md
@@ -109,18 +109,18 @@ This page documents the environment variables used in Lima.
 ### `LIMA_SSH_PORT_FORWARDER`
 
 - **Description**: Specifies to use the SSH port forwarder (slow) instead of gRPC (fast, previously unstable)
-- **Default**: `false` (since v1.1.0-beta.0)
+- **Default**: `false` (since v1.1.0)
 - **Usage**: 
   ```sh
   export LIMA_SSH_PORT_FORWARDER=false
   ```
 - **The history of the default value**:
-  | Version       | Default value       |
-  |---------------|---------------------|
-  | v0.1.0        | `true`, effectively |
-  | v1.0.0        | `false`             |
-  | v1.0.1        | `true`              |
-  | v1.1.0-beta.0 | `false`             |
+  | Version | Default value       |
+  |---------|---------------------|
+  | v0.1.0  | `true`, effectively |
+  | v1.0.0  | `false`             |
+  | v1.0.1  | `true`              |
+  | v1.1.0  | `false`             |
 
 ### `LIMA_USERNET_RESOLVE_IP_ADDRESS_TIMEOUT`
 
diff --git a/website/content/en/docs/config/multi-arch.md b/website/content/en/docs/config/multi-arch.md
index bbe90ede..443eeea4 100644
--- a/website/content/en/docs/config/multi-arch.md
+++ b/website/content/en/docs/config/multi-arch.md
@@ -3,7 +3,7 @@ title: Intel-on-ARM and ARM-on-Intel
 weight: 20
 ---
 
-Lima supports two modes for running Intel-on-ARM and ARM-on-Intel:
+Lima supports several modes for running Intel-on-ARM and ARM-on-Intel:
 - [Slow mode](#slow-mode)
 - [Fast mode](#fast-mode)
 - [Fast mode 2](#fast-mode-2)
diff --git a/website/content/en/docs/config/plugin/_index.md b/website/content/en/docs/config/plugin/_index.md
new file mode 100644
index 00000000..850e58c3
--- /dev/null
+++ b/website/content/en/docs/config/plugin/_index.md
@@ -0,0 +1,4 @@
+---
+title: Plug-in
+weight: 90
+---
diff --git a/website/content/en/docs/config/plugin/cli.md b/website/content/en/docs/config/plugin/cli.md
new file mode 100644
index 00000000..78be0ef0
--- /dev/null
+++ b/website/content/en/docs/config/plugin/cli.md
@@ -0,0 +1,60 @@
+---
+title: CLI plugins
+weight: 2
+---
+
+ | ⚡ Requirement | Lima >= 2.0 |
+ |----------------|-------------|
+
+Lima supports a plugin-like command aliasing system similar to `git`, `kubectl`, and `docker`. When you run a `limactl` command that doesn't exist, Lima will automatically look for an external program named `limactl-<command>` in your system's PATH.
+
+## Creating Custom Aliases
+
+To create a custom alias, create an executable script with the name `limactl-<alias>` and place it somewhere in your PATH.
+
+**Example: Creating a `ps` alias for listing instances**
+
+1. Create a script called `limactl-ps`:
+   ```bash
+   #!/bin/sh
+   # Show instances in a compact format
+   limactl list --format table "$@"
+   ```
+
+2. Make it executable and place it in your PATH:
+   ```bash
+   chmod +x limactl-ps
+   sudo mv limactl-ps /usr/local/bin/
+   ```
+
+3. Now you can use it:
+   ```bash
+   limactl ps                    # Shows instances in table format
+   limactl ps --quiet            # Shows only instance names
+   ```
+
+**Example: Creating an `sh` alias**
+
+```bash
+#!/bin/sh
+# limactl-sh - Connect to an instance shell
+limactl shell "$@"
+```
+
+After creating this alias:
+```bash
+limactl sh default           # Equivalent to: limactl shell default
+limactl sh myinstance bash   # Equivalent to: limactl shell myinstance bash
+```
+
+## How It Works
+
+1. When you run `limactl <unknown-command>`, Lima first tries to find a built-in command
+2. If no built-in command is found, Lima searches for `limactl-<unknown-command>` in your PATH
+3. If found, Lima executes the external program and passes all remaining arguments to it
+4. If not found, Lima shows the standard "unknown command" error
+
+This system allows you to:
+- Create personal shortcuts and aliases
+- Extend Lima's functionality without modifying the core application
+- Share custom commands with your team by distributing scripts
\ No newline at end of file
diff --git a/website/content/en/docs/config/plugin/vm.md b/website/content/en/docs/config/plugin/vm.md
new file mode 100644
index 00000000..13779e3b
--- /dev/null
+++ b/website/content/en/docs/config/plugin/vm.md
@@ -0,0 +1,7 @@
+---
+title: VM driver plugins
+weight: 1
+---
+
+See [Virtual Machine Drivers](../../dev/drivers.md).
+<!-- TODO: migrate the most of the content from ../../dev/drivers.md to here -->
\ No newline at end of file
diff --git a/website/content/en/docs/config/port.md b/website/content/en/docs/config/port.md
index 5fd1edab..164e4b57 100644
--- a/website/content/en/docs/config/port.md
+++ b/website/content/en/docs/config/port.md
@@ -11,12 +11,12 @@ Lima supports two port forwarders: SSH and GRPC.
 
 The default port forwarder is shown in the following table.
 
-| Version       | Default |
-| ------------- | ------- |
-| v0.1.0        | SSH     |
-| v1.0.0        | GRPC    |
-| v1.0.1        | SSH     |
-| v1.1.0-beta.0 | GRPC    |
+| Version | Default |
+| --------| ------- |
+| v0.1.0  | SSH     |
+| v1.0.0  | GRPC    |
+| v1.0.1  | SSH     |
+| v1.1.0  | GRPC    |
 
 The default was once changed to GRPC in Lima v1.0, but it was reverted to SSH in v1.0.1 due to stability reasons.
 The default was further reverted to GRPC in Lima v1.1, as the stability issues were resolved.
diff --git a/website/content/en/docs/config/vmtype.md b/website/content/en/docs/config/vmtype.md
deleted file mode 100644
index 15d234e4..00000000
--- a/website/content/en/docs/config/vmtype.md
+++ /dev/null
@@ -1,120 +0,0 @@
----
-title: VM types
-weight: 10
----
-
-Lima supports two ways of running guest machines:
-- [qemu](#qemu)
-- [vz](#vz)
-
-The vmType can be specified only on creating the instance.
-The vmType of existing instances cannot be changed.
-
-> **💡 For developers**: See [Virtual Machine Drivers](../../dev/drivers) for technical details about driver architecture and creating custom drivers.
-
-
-See the following flowchart to choose the best vmType for you:
-```mermaid
-flowchart
-  host{"Host OS"} -- "Windows" --> wsl2["WSL2"]
-  host -- "Linux" --> qemu["QEMU"]
-  host -- "macOS" --> intel_on_arm{"Need to run <br> Intel binaries <br> on ARM?"}
-  intel_on_arm -- "Yes" --> just_elf{"Just need to <br> run Intel userspace (fast), <br> or entire Intel VM (slow)?"}
-  just_elf -- "Userspace (fast)" --> vz
-  just_elf -- "VM (slow)" --> qemu
-  intel_on_arm --  "No" --> vz["VZ"]
-```
-
-The default vmType is QEMU in Lima prior to v1.0.
-Starting with Lima v1.0, Lima will use VZ by default on macOS (>= 13.5) for new instances,
-unless the config is incompatible with VZ. (e.g., legacyBIOS or 9p is enabled)
-
-## QEMU
-"qemu" option makes use of QEMU to run guest operating system. 
-
-Recommended QEMU version:
-- v8.2.1 or later (macOS)
-- v6.2.0 or later (Linux)
-
-## VZ
-
-| ⚡ Requirement | Lima >= 0.14, macOS >= 13.0 |
-|-------------------|-----------------------------|
-
-"vz" option makes use of native virtualization support provided by macOS Virtualization.Framework.
-
-An example configuration:
-{{< tabpane text=true >}}
-{{% tab header="CLI" %}}
-```bash
-limactl start --vm-type=vz --mount-type=virtiofs
-```
-{{% /tab %}}
-{{% tab header="YAML" %}}
-```yaml
-# Example to run ubuntu using vmType: vz instead of qemu (Default)
-vmType: "vz"
-images:
-- location: "https://cloud-images.ubuntu.com/releases/24.04/release/ubuntu-24.04-server-cloudimg-amd64.img"
-  arch: "x86_64"
-- location: "https://cloud-images.ubuntu.com/releases/24.04/release/ubuntu-24.04-server-cloudimg-arm64.img"
-  arch: "aarch64"
-mounts:
-  - location: "~"
-mountType: "virtiofs"
-```
-{{% /tab %}}
-{{< /tabpane >}}
-### Caveats
-- "vz" option is only supported on macOS 13 or above
-- Virtualization.framework doesn't support running "intel guest on arm" and vice versa
-
-### Known Issues
-- "vz" doesn't support `legacyBIOS: true` option, so guest machine like centos-stream and oraclelinux will not work
-- When running lima using "vz", `${LIMA_HOME}/<INSTANCE>/serial.log` will not contain kernel boot logs
-- On Intel Mac with macOS prior to 13.5, Linux kernel v6.2 (used by Ubuntu 23.04, Fedora 38, etc.) is known to be unbootable on vz.
-  kernel v6.3 and later should boot, as long as it is booted via GRUB.
-  https://github.com/lima-vm/lima/issues/1577#issuecomment-1565625668
-  The issue is fixed in macOS 13.5.
-
-## WSL2
-> **Warning**
-> "wsl2" mode is experimental
-
-| ⚡ Requirement | Lima >= 0.18 + (Windows >= 10 Build 19041 OR Windows 11) |
-| ----------------- | -------------------------------------------------------- |
-
-"wsl2" option makes use of native virtualization support provided by Windows' `wsl.exe` ([more info](https://learn.microsoft.com/en-us/windows/wsl/about)).
-
-An example configuration:
-{{< tabpane text=true >}}
-{{% tab header="CLI" %}}
-```bash
-limactl start --vm-type=wsl2 --mount-type=wsl2 --containerd=system
-```
-{{% /tab %}}
-{{% tab header="YAML" %}}
-```yaml
-# Example to run Fedora using vmType: wsl2
-vmType: wsl2
-images:
-# Source: https://github.com/runfinch/finch-core/blob/main/Dockerfile
-- location: "https://deps.runfinch.com/common/x86-64/finch-rootfs-production-amd64-1690920103.tar.zst"
-  arch: "x86_64"
-  digest: "sha256:53f2e329b8da0f6a25e025d1f6cc262ae228402ba615ad095739b2f0ec6babc9"
-mountType: wsl2 
-containerd:
-  system: true
-  user: false
-```
-{{% /tab %}}
-{{< /tabpane >}}
-
-### Caveats
-- "wsl2" option is only supported on newer versions of Windows (roughly anything since 2019)
-
-### Known Issues
-- "wsl2" currently doesn't support many of Lima's options. See [this file](https://github.com/lima-vm/lima/blob/master/pkg/wsl2/wsl_driver_windows.go#L19) for the latest supported options.
-- When running lima using "wsl2", `${LIMA_HOME}/<INSTANCE>/serial.log` will not contain kernel boot logs
-- WSL2 requires a `tar` formatted rootfs archive instead of a VM image
-- Windows doesn't ship with ssh.exe, gzip.exe, etc. which are used by Lima at various points. The easiest way around this is to run `winget install -e --id Git.MinGit` (winget is now built in to Windows as well), and add the resulting `C:\Program Files\Git\usr\bin\` directory to your path.
diff --git a/website/content/en/docs/config/vmtype/_index.md b/website/content/en/docs/config/vmtype/_index.md
new file mode 100644
index 00000000..469e917b
--- /dev/null
+++ b/website/content/en/docs/config/vmtype/_index.md
@@ -0,0 +1,28 @@
+---
+title: VM types
+weight: 10
+---
+
+Lima supports several VM drivers for running guest machines:
+
+The vmType can be specified only on creating the instance.
+The vmType of existing instances cannot be changed.
+
+> **💡 For developers**: See [Virtual Machine Drivers](../../dev/drivers) for technical details about driver architecture and creating custom drivers.
+
+
+See the following flowchart to choose the best vmType for you:
+```mermaid
+flowchart
+  host{"Host OS"} -- "Windows" --> wsl2["WSL2"]
+  host -- "Linux" --> qemu["QEMU"]
+  host -- "macOS" --> intel_on_arm{"Need to run <br> Intel binaries <br> on ARM?"}
+  intel_on_arm -- "Yes" --> just_elf{"Just need to <br> run Intel userspace (fast), <br> or entire Intel VM (slow)?"}
+  just_elf -- "Userspace (fast)" --> vz
+  just_elf -- "VM (slow)" --> qemu
+  intel_on_arm --  "No" --> vz["VZ"]
+```
+
+The default vmType is QEMU in Lima prior to v1.0.
+Starting with Lima v1.0, Lima will use VZ by default on macOS (>= 13.5) for new instances,
+unless the config is incompatible with VZ. (e.g., legacyBIOS or 9p is enabled)
\ No newline at end of file
diff --git a/website/content/en/docs/config/vmtype/qemu.md b/website/content/en/docs/config/vmtype/qemu.md
new file mode 100644
index 00000000..8cb5e45b
--- /dev/null
+++ b/website/content/en/docs/config/vmtype/qemu.md
@@ -0,0 +1,10 @@
+---
+title: QEMU
+weight: 1
+---
+
+"qemu" option makes use of QEMU to run guest operating system.
+
+Recommended QEMU version:
+- v8.2.1 or later (macOS)
+- v6.2.0 or later (Linux)
\ No newline at end of file
diff --git a/website/content/en/docs/config/vmtype/vz.md b/website/content/en/docs/config/vmtype/vz.md
new file mode 100644
index 00000000..cc35d294
--- /dev/null
+++ b/website/content/en/docs/config/vmtype/vz.md
@@ -0,0 +1,42 @@
+---
+title: VZ
+weight: 2
+---
+
+| ⚡ Requirement | Lima >= 0.14, macOS >= 13.0 |
+|-------------------|-----------------------------|
+
+"vz" option makes use of native virtualization support provided by macOS Virtualization.Framework.
+
+An example configuration:
+{{< tabpane text=true >}}
+{{% tab header="CLI" %}}
+```bash
+limactl start --vm-type=vz
+```
+{{% /tab %}}
+{{% tab header="YAML" %}}
+```yaml
+# Example to run ubuntu using vmType: vz instead of qemu (Default)
+vmType: "vz"
+images:
+- location: "https://cloud-images.ubuntu.com/releases/24.04/release/ubuntu-24.04-server-cloudimg-amd64.img"
+  arch: "x86_64"
+- location: "https://cloud-images.ubuntu.com/releases/24.04/release/ubuntu-24.04-server-cloudimg-arm64.img"
+  arch: "aarch64"
+mounts:
+  - location: "~"
+```
+{{% /tab %}}
+{{< /tabpane >}}
+### Caveats
+- "vz" option is only supported on macOS 13 or above
+- Virtualization.framework doesn't support running "intel guest on arm" and vice versa
+
+### Known Issues
+- "vz" doesn't support `legacyBIOS: true` option, so guest machine like `centos-stream` and `oraclelinux-8` will not work on Intel Mac.
+- When running lima using "vz", `${LIMA_HOME}/<INSTANCE>/serial.log` will not contain kernel boot logs
+- On Intel Mac with macOS prior to 13.5, Linux kernel v6.2 (used by Ubuntu 23.04, Fedora 38, etc.) is known to be unbootable on vz.
+  kernel v6.3 and later should boot, as long as it is booted via GRUB.
+  https://github.com/lima-vm/lima/issues/1577#issuecomment-1565625668
+  The issue is fixed in macOS 13.5.
\ No newline at end of file
diff --git a/website/content/en/docs/config/vmtype/wsl2.md b/website/content/en/docs/config/vmtype/wsl2.md
new file mode 100644
index 00000000..b62117c2
--- /dev/null
+++ b/website/content/en/docs/config/vmtype/wsl2.md
@@ -0,0 +1,45 @@
+---
+title: WSL2
+weight: 3
+---
+
+> **Warning**
+> "wsl2" mode is experimental
+
+| ⚡ Requirement | Lima >= 0.18 + (Windows >= 10 Build 19041 OR Windows 11) |
+| ----------------- | -------------------------------------------------------- |
+
+"wsl2" option makes use of native virtualization support provided by Windows' `wsl.exe` ([more info](https://learn.microsoft.com/en-us/windows/wsl/about)).
+
+An example configuration:
+{{< tabpane text=true >}}
+{{% tab header="CLI" %}}
+```bash
+limactl start --vm-type=wsl2 --mount-type=wsl2 --containerd=system
+```
+{{% /tab %}}
+{{% tab header="YAML" %}}
+```yaml
+# Example to run Fedora using vmType: wsl2
+vmType: wsl2
+images:
+# Source: https://github.com/runfinch/finch-core/blob/main/Dockerfile
+- location: "https://deps.runfinch.com/common/x86-64/finch-rootfs-production-amd64-1690920103.tar.zst"
+  arch: "x86_64"
+  digest: "sha256:53f2e329b8da0f6a25e025d1f6cc262ae228402ba615ad095739b2f0ec6babc9"
+mountType: wsl2
+containerd:
+  system: true
+  user: false
+```
+{{% /tab %}}
+{{< /tabpane >}}
+
+### Caveats
+- "wsl2" option is only supported on newer versions of Windows (roughly anything since 2019)
+
+### Known Issues
+- "wsl2" currently doesn't support many of Lima's options. See [this file](https://github.com/lima-vm/lima/blob/master/pkg/wsl2/wsl_driver_windows.go#L19) for the latest supported options.
+- When running lima using "wsl2", `${LIMA_HOME}/<INSTANCE>/serial.log` will not contain kernel boot logs
+- WSL2 requires a `tar` formatted rootfs archive instead of a VM image
+- Windows doesn't ship with ssh.exe, gzip.exe, etc. which are used by Lima at various points. The easiest way around this is to run `winget install -e --id Git.MinGit` (winget is now built in to Windows as well), and add the resulting `C:\Program Files\Git\usr\bin\` directory to your path.
diff --git a/website/content/en/docs/examples/_index.md b/website/content/en/docs/examples/_index.md
index 6370ffa2..52a69605 100644
--- a/website/content/en/docs/examples/_index.md
+++ b/website/content/en/docs/examples/_index.md
@@ -14,12 +14,9 @@ By default, the VM has read-only accesses to `/Users/<USERNAME>`.
 
 To allow writing to `/Users/<USERNAME>`:
 ```bash
-limactl edit --mount-writable --mount-type=virtiofs
+limactl edit --mount-writable
 ```
 
-Specifying `--mount-type=virtiofs` is not necessary here, but it is highly recommended
-for the best performance and stability.
-
 {{% alert title="Hint" color=success %}}
 Lima prior to v2.0 mounts `/tmp/lima` too in read-write mode.
 
@@ -81,7 +78,6 @@ limactl start \
   --memory=8 \
   --vm-type=vz \
   --rosetta \
-  --mount-type=virtiofs \
   --mount-writable \
   --network=vzNAT \
   template://fedora
@@ -92,7 +88,6 @@ limactl start \
 - `--memory=8`: Set the amount of the memory to 8 GiB
 - `--vm-type=vz`: Use Apple's Virtualization.framework (vz) to enable Rosetta, virtiofs, and vzNAT
 - `--rosetta`: Allow running Intel (AMD) binaries on ARM
-- `--mount-type=virtiofs`: Use virtiofs for better performance
 - `--mount-writable`: Make the home mount (`/Users/<USERNAME>`) writable
 - `--network=vzNAT`: Make the VM reachable from the host by its IP address
 - `template://fedora`: Use Fedora
diff --git a/website/content/en/docs/installation/_index.md b/website/content/en/docs/installation/_index.md
index 40834393..42222c68 100644
--- a/website/content/en/docs/installation/_index.md
+++ b/website/content/en/docs/installation/_index.md
@@ -19,6 +19,9 @@ Prerequisite:
 brew install lima
 ```
 
+Hint: specify `--HEAD` to install the HEAD (master) version.
+The HEAD version provides early access to the latest features and improvements before they are officially released.
+
 Homebrew formula is available [here](https://github.com/Homebrew/homebrew-core/blob/master/Formula/l/lima.rb).
 Supports macOS and Linux.
 {{% /tab %}}
diff --git a/website/content/en/docs/reference/_index.md b/website/content/en/docs/reference/_index.md
index 0294f49b..802f1ddf 100644
--- a/website/content/en/docs/reference/_index.md
+++ b/website/content/en/docs/reference/_index.md
@@ -1,4 +1,4 @@
 ---
 title: Command Reference
-weight: 5
+weight: 999
 ---
\ No newline at end of file
diff --git a/website/content/en/docs/talks/_index.md b/website/content/en/docs/talks/_index.md
index 1f2775fb..032c7372 100644
--- a/website/content/en/docs/talks/_index.md
+++ b/website/content/en/docs/talks/_index.md
@@ -30,3 +30,33 @@ Watch the [video](https://www.youtube.com/watch?v=GDInFocQJTU).
 [Akihiro Suda](https://github.com/AkihiroSuda) presented Lima in the CNCF project pavilion.
 
 Read the [slides](https://www.slideshare.net/AkihiroSuda/kubeconeu2023-lima-pavilion).
+
+### KubeCon + CloudNativeCon North America 2023
+
+[Akihiro Suda](https://github.com/AkihiroSuda) presented Lima in the CNCF project pavilion.
+
+Read the [slides](https://github.com/AkihiroSuda/AkihiroSuda/blob/master/slides/2023/20231107%20%5BKubeCon%20NA%20Pavilion%5D%20Lima.pdf).
+
+## 2024
+### KubeCon + CloudNativeCon Europe 2024
+
+[Akihiro Suda](https://github.com/AkihiroSuda) presented Lima in the CNCF project pavilion.
+
+Read the [slides](https://github.com/AkihiroSuda/AkihiroSuda/blob/master/slides/2024/20240321%20%5BKubeCon%20EU%20Pavilion%5D%20Lima.pdf).
+
+### KubeCon + CloudNativeCon North America 2024
+
+[Akihiro Suda](https://github.com/AkihiroSuda) presented Lima in the CNCF project pavilion.
+
+Read the [slides](https://github.com/AkihiroSuda/AkihiroSuda/blob/master/slides/2024/20241115%20%5BKubeCon%20NA%20Pavilion%5D%20Lima.pdf).
+
+He also mentioned Lima in the presentation "What’s Going on in the Containerd Neighborhood?" in the context of case study of nerdctl.
+
+Read the [slides](https://static.sched.com/hosted_files/kccncna2024/74/KCCNC-SLC-24-Containerd-session.pdf)or watch the [video](https://www.youtube.com/watch?v=kCNhgNXVdxw).
+
+## 2025
+### KubeCon + CloudNativeCon Europe 2025
+
+[Akihiro Suda](https://github.com/AkihiroSuda) presented Lima in the CNCF project pavilion.
+
+Read the [slides](https://github.com/AkihiroSuda/AkihiroSuda/blob/master/slides/2025/20250402%20%5BKubeCon%20EU%20Pavilion%5D%20Lima.pdf).
\ No newline at end of file
diff --git a/website/content/en/docs/usage/_index.md b/website/content/en/docs/usage/_index.md
index 74ae09a8..7a77bb56 100644
--- a/website/content/en/docs/usage/_index.md
+++ b/website/content/en/docs/usage/_index.md
@@ -72,61 +72,6 @@ Then you can connect directly:
 ssh lima-default
 ```
 
-### Command Aliasing (Plugin System)
-
-Lima supports a plugin-like command aliasing system similar to `git`, `kubectl`, and `docker`. When you run a `limactl` command that doesn't exist, Lima will automatically look for an external program named `limactl-<command>` in your system's PATH.
-
-#### Creating Custom Aliases
-
-To create a custom alias, create an executable script with the name `limactl-<alias>` and place it somewhere in your PATH.
-
-**Example: Creating a `ps` alias for listing instances**
-
-1. Create a script called `limactl-ps`:
-   ```bash
-   #!/bin/sh
-   # Show instances in a compact format
-   limactl list --format table "$@"
-   ```
-
-2. Make it executable and place it in your PATH:
-   ```bash
-   chmod +x limactl-ps
-   sudo mv limactl-ps /usr/local/bin/
-   ```
-
-3. Now you can use it:
-   ```bash
-   limactl ps                    # Shows instances in table format
-   limactl ps --quiet            # Shows only instance names
-   ```
-
-**Example: Creating an `sh` alias**
-
-```bash
-#!/bin/sh
-# limactl-sh - Connect to an instance shell
-limactl shell "$@"
-```
-
-After creating this alias:
-```bash
-limactl sh default           # Equivalent to: limactl shell default
-limactl sh myinstance bash   # Equivalent to: limactl shell myinstance bash
-```
-
-#### How It Works
-
-1. When you run `limactl <unknown-command>`, Lima first tries to find a built-in command
-2. If no built-in command is found, Lima searches for `limactl-<unknown-command>` in your PATH
-3. If found, Lima executes the external program and passes all remaining arguments to it
-4. If not found, Lima shows the standard "unknown command" error
-
-This system allows you to:
-- Create personal shortcuts and aliases
-- Extend Lima's functionality without modifying the core application
-- Share custom commands with your team by distributing scripts
-
 ### Shell completion
 - To enable bash completion, add `source <(limactl completion bash)` to `~/.bash_profile`.
 - To enable zsh completion, see `limactl completion zsh --help`



Test patch:
diff --git a/cmd/limactl/editflags/editflags_test.go b/cmd/limactl/editflags/editflags_test.go
index 7c6c2908..ae9e178e 100644
--- a/cmd/limactl/editflags/editflags_test.go
+++ b/cmd/limactl/editflags/editflags_test.go
@@ -4,10 +4,13 @@
 package editflags
 
 import (
+	"strings"
 	"testing"
 
 	"github.com/spf13/cobra"
 	"gotest.tools/v3/assert"
+
+	"github.com/lima-vm/lima/v2/pkg/localpathutil"
 )
 
 func TestCompleteCPUs(t *testing.T) {
@@ -160,6 +163,13 @@ func TestParsePortForward(t *testing.T) {
 }
 
 func TestYQExpressions(t *testing.T) {
+	expand := func(s string) string {
+		s, err := localpathutil.Expand(s)
+		assert.NilError(t, err)
+		// `D:\foo` -> `D:\\foo` (appears in YAML)
+		s = strings.ReplaceAll(s, "\\", "\\\\")
+		return s
+	}
 	tests := []struct {
 		name        string
 		args        []string
@@ -169,15 +179,15 @@ func TestYQExpressions(t *testing.T) {
 	}{
 		{
 			name:        "mount",
-			args:        []string{"--mount", "/foo", "--mount", "/bar:w"},
+			args:        []string{"--mount", "/foo", "--mount", "./bar:w"},
 			newInstance: false,
-			expected:    []string{`.mounts += [{"location": "/foo", "writable": false},{"location": "/bar", "writable": true}] | .mounts |= unique_by(.location)`},
+			expected:    []string{`.mounts += [{"location": "` + expand("/foo") + `", "writable": false},{"location": "` + expand("./bar") + `", "writable": true}] | .mounts |= unique_by(.location)`},
 		},
 		{
 			name:        "mount-only",
 			args:        []string{"--mount-only", "/foo", "--mount-only", "/bar:w"},
 			newInstance: false,
-			expected:    []string{`.mounts = [{"location": "/foo", "writable": false},{"location": "/bar", "writable": true}]`},
+			expected:    []string{`.mounts = [{"location": "` + expand("/foo") + `", "writable": false},{"location": "` + expand("/bar") + `", "writable": true}]`},
 		},
 		{
 			name:        "mixture of mount and mount-only",
diff --git a/pkg/limayaml/validate_unix_test.go b/pkg/limayaml/validate_unix_test.go
new file mode 100644
index 00000000..97c8cff3
--- /dev/null
+++ b/pkg/limayaml/validate_unix_test.go
@@ -0,0 +1,48 @@
+//go:build !windows
+
+// SPDX-FileCopyrightText: Copyright The Lima Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package limayaml
+
+import (
+	"testing"
+
+	"gotest.tools/v3/assert"
+)
+
+func TestValidateMounts(t *testing.T) {
+	yBase := `images: [{"location": "/dummy"}]`
+	tests := []struct {
+		name          string
+		mounts        string
+		skipOnWindows bool
+		wantErr       string
+	}{
+		{
+			name:    "Valid",
+			mounts:  `mounts: [{location: "/foo", writable: false}, {location: "~/foo", writable: true}]`,
+			wantErr: "",
+		},
+		{
+			name:   "Invalid (relative)",
+			mounts: `mounts: [{location: ".", writable: false}]`,
+			wantErr: func() string {
+				return "must be an absolute path"
+			}(),
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			y, err := Load(t.Context(), []byte(yBase+"\n"+tt.mounts), "lima.yaml")
+			assert.NilError(t, err)
+			err = Validate(y, false)
+			if tt.wantErr != "" {
+				assert.ErrorContains(t, err, tt.wantErr)
+			} else {
+				assert.NilError(t, err)
+			}
+		})
+	}
+}