Capability Matrix
This mirrors the provider.Table each backend actually returns from
Capabilities() (see internal/provider/{incus,lima,hyperv}/capability.go).
Incus and Lima are both real implementations; Hyper-V is still a
capability-table-driven stub, so almost everything on that row is a "not
wired up yet," not a platform limitation — see the notes below the table
for which cells are genuine platform gaps.
| Feature | Incus | Lima | Hyper-V |
|---|---|---|---|
| create / start / stop / delete / list / status | Supported | Supported | Under development |
| exec / shell | Supported | Supported | Under development |
| view (console) | Supported | Under development | Under development |
| snapshot create/list/restore/delete | Supported | Not available | Under development |
network.acl (--allow) |
Supported | Supported (macOS hosts) | Under development |
network.deny-lan (--deny-lan) |
Supported | Supported (macOS hosts) | Under development |
network.port-publish (--port) |
Supported | Supported | Manual workaround |
fs.mount (--mount) |
Supported | Supported | Manual workaround |
| fs.mount.readonly | Supported | Supported | Manual workaround |
| image.pull | Supported | Not available | Under development |
| image.build | Supported | Under development | Under development |
provision.packages (packages: / --package) |
Supported | Under development | Under development |
| logs.network / logs.exec | Under development | Under development | Under development |
Reading the "genuine platform gap" cells
These are the only entries where the gap is in the platform, not just in agentctl's own wiring:
- Lima: snapshot.* → Not available.
limactl snapshotis explicitly experimental/unstable upstream; agentctl won't build on it until it stabilizes. - Lima: image.pull → Not available. Lima has no local named image store
to pull into ahead of
create; a template's base image resolves lazily, per-instance, insidecreate/startitself — there's no daemon-side store to wire up to, unlike Incus'sincus image copy. - Lima: provision.packages → Under development (agentctl's wiring, not a
platform gap — listed here because the reason is unusual). Lima supports
this natively through a template's
provision:scripts, but that is a different mechanism from the one Incus uses, not the same one left unwired. Incus installs throughincus execagainst an instance itscreatealready starts and stops to provision the non-root user; Lima'screatedeliberately never starts anything, so there is no equivalent window to reuse. Until it's built, install by hand:limactl shell <name> -- sudo apt-get install -y <pkg>. - Hyper-V: network.port-publish → Manual workaround. Hyper-V has no
built-in "publish a port" primitive; agentctl prints a NAT-switch +
netsh interface portproxyprocedure. - Hyper-V: fs.mount / fs.mount.readonly → Manual workaround. Hyper-V has no
host-directory share primitive at all: no virtiofs, no 9p, and no
VMware-Tools-style shared folder. Enhanced Session Mode's drive redirection
is RDP-based and aimed at Windows guests. Sharing a folder with a Linux guest
therefore goes over SMB on the guest network, which agentctl prints as a
procedure. Two consequences worth understanding before relying on it: the
guest ends up holding host SMB credentials (a lateral-movement risk in its
own right — use a dedicated low-privilege account), and because the mount is
network traffic it needs a deliberate hole in
--deny-lanfor the host's vSwitch address. A native path — a host-side SFTP server serving only the named directories, which is what Lima does by default — is designed infilesystem-access.plan.mdbut not built: it needs agentctl to gain a host-side daemon, and the Hyper-V backend's own lifecycle is still a stub.
Lima's network.acl/network.deny-lan entries are Supported even though
Lima has no ACL object: agentctl enforces the same policy host-side by
confining Lima's own processes with a macOS sandbox profile and routing the
guest's egress through a per-instance filtering proxy — see
Lima setup for how,
and for the practical differences: clients must use the proxy, and a
profile's network.dns settings are refused, since a Lima guest's DNS
always goes through the Mac's own resolver. That
mechanism is macOS-specific, so on a Linux host the Lima backend reports
both as Not available (use Incus there). Lima's logs.network is Under
development rather than a gap: each instance's proxy already logs every
allowed and denied connection; agentctl logs just isn't wired to it yet.
Every other Under development cell reflects a backend that supports the
feature natively (New-VM/Start-VM, Extended Port ACLs, Standard/Production
checkpoints, VMConnect for Hyper-V) — agentctl just hasn't wired up the
integration yet. On Lima specifically, view stays Under development by
deliberate choice this milestone: a real GUI console needs a VNC bridge
that doesn't exist yet (Lima's default vz backend has no display concept
to attach to), which is a separately-scoped piece of work, not something
silently dropped.
--preview/--dry-run availability
--preview shows the backend command(s) an operation would run, built from
the exact same code path the real dispatch uses (see
Capability Model).
It only ever has something to show for an operation the active provider
actually supports — the capability gate above always runs first. Today
that means:
| Provider | --preview |
|---|---|
| Incus | Live — every command in the table above that's Supported |
| Lima | Live — every command in the table above that's Supported |
| Hyper-V | Nothing to preview yet (no operations are Supported yet) |
Where this comes from
Run any command against an unsupported feature and agentctl prints the same information live, plus (for manual-workaround cells) the actual copyable procedure:
$ agentctl --provider=lima image pull template://ubuntu-lts
agentctl: image.pull is not available on provider "lima": Lima has no local named image store to pull into ahead of create; a template's base image resolves lazily, per-instance, inside create/start itself.