Driver development today is a round trip. Change code, build a .c4z, import it into Composer, deploy it to the controller, trigger the event you want to test, dig through logs, repeat. Each cycle is minutes of waiting for feedback before you find out whether your change worked — and most changes are small. Live debugging collapses that loop to seconds. Your driver code runs on your own machine, a real Control4 controller drives it with real events and real API calls, and your usual Lua debugger attaches to the running code the same way it would to any other Lua process. Breakpoints hit inside your callbacks. Variables inspect. Step over, step into, step out — all of it — inside the handlers the controller is actually calling into. The way it works is that your real driver isn't on the controller at all during a debug session. When you run anvil debug , Anvil temporarily swaps your driver for a small shim driver that ships with the CLI. The shim contains no business logic — it exists to be a bridge. The controller itself doesn't know anything has changed: it still calls OnDriverInit , ReceivedFromProxy , OnPropertyChanged and every other callback exactly as it always does. The shim intercepts each call, captures the arguments, and forwards it over a messaging channel to your machine, where your actual driver code is running in a local Lua process. Your code executes, hits any breakpoints you've set, and returns a response. The shim passes that response back to the controller as if nothing unusual happened. The messaging goes both directions, which is what makes it feel like you're actually on the controller. Callbacks come down from the controller to your machine as above. API calls go up from your machine to the controller: when your code calls C4:SendToDevice or C4:GetDeviceVariable or any other C4: function, the call doesn't execute locally — it's sent across the same channel to the shim, which runs it on the real controller (against real devices, real properties, real state) and returns the result back to your code. So C4:SendToDevice actually sends. C4:GetDeviceVariable actually reads the current value. Your code behaves the same way it would if it were running on the controller itself, because as far as the controller is concerned, it is. Because your code lives on your machine for the whole session, there's nothing to push up when you make a change. Save a file and the next callback the controller fires runs the new version — no rebuild, no repackaging, no redeploy, no hot-reload protocol to think about. The local Lua process just picks up what's on disk. That means the inner loop of driver development — tweak, trigger, observe, repeat — takes as long as it takes the controller to fire the event again, which is usually a fraction of a second. Both the shim and the CLI connect outbound to Anvil's messaging broker, so a direct network path between your laptop and the controller isn't needed. This works when the controller is behind a customer's firewall, on a VLAN you can't reach, or otherwise isolated from where you're sitting. When you're done, Ctrl+C ends the session and anvil deploy puts your real driver back on the controller exactly as it was before. What we're thinking anvil debug to start a session, anvil deploy to end it and restore your real driver The shim driver is part of the CLI — no manual stub deployment, no code changes to your driver Your usual Lua debugger (VS Code, ZeroBrane, etc.) attaches to the local process Bidirectional messaging: controller callbacks come down to your machine, C4 API calls go back up to the controller Real API calls execute on the real controller against real devices and real state Save a file to update — no rebuild, no redeploy, no hot-reload protocol Both sides connect outbound to Anvil's broker — works across VLANs and firewalls Logs and events from the session still flow to Anvil UI as normal Help us shape this: Which IDE or debugger do you use for Lua today — VS Code, ZeroBrane, something else? Of the three things this unlocks — breakpoints and variable inspection, save-to-update with no rebuilds, and remote reachability across VLANs/firewalls — which would change your workflow most? Any controller setups where network access between your machine and the controller is blocked today, making the outbound-only design important for you?