Model or dataset
lynaghk/vibe avatar
lynaghk/vibe

vibe pins every Objective-C crate to a wildcard and serves its installer from a moving tag

Easy Linux virtual machine on MacOS to sandbox LLM agents.

957 stars53 forksRustMIT

At a glance

What is it?
A small Rust program that boots a Debian virtual machine on an Apple Silicon Mac, shares your project directory into it and hands you the terminal, so a coding agent can install whatever it wants. Two thousand lines, one binary, and a networking helper written in a second language.
Who is it for?
Use Vibe if you want an agent to have a machine of its own and you are on an Apple Silicon Mac, because the whole thing is a disposable Debian image plus a directory share. Four things to know first.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 32 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Releases are date-and-commit tags plus one that moves

There is no version scheme here, and the author says so: no formal releases, no change log, and a recommendation to read the commit history and pin to a specific version. The tags follow that. The two most recent are named for their date and a short commit, and then there is a third tag literally called latest, which is the one the install instructions point at:

code
curl -LO https://github.com/lynaghk/vibe/releases/download/latest/vibe-macos-arm64.zip
unzip vibe-macos-arm64.zip
mkdir -p ~/.local/bin
mv vibe ~/.local/bin
export PATH="$HOME/.local/bin:$PATH"

That URL resolves to whatever the last build was, so two people running the same four lines on different days get different binaries under the same command. The program compensates by printing a commit hash and a build date for its version flag, which is the only mechanism offered for telling builds apart.

The manifest calls itself 0.1.0 and every interop crate is a wildcard

The build manifest names the package, gives it the version 0.1.0 and the 2024 edition, and then lists its dependencies. Almost all of them are a wildcard. The Objective-C bridge crates, the foundation crate with a hand-picked list of enabled classes, the virtualization crate, the block and dispatch companions, and the C standard library are all requested at any version. Only the argument parser is pinned, to a specific minor. Two consequences. The claim in the documentation that the only dependencies are the interop crates and the argument parser is missing the C library entry, which is not part of that family. And a build from a manifest alone is not reproducible, because a wildcard can resolve to a newer interop crate than the one this was written against. The lockfile is committed, so a checkout is pinned, and the manifest is where the intent is not.

The network is a second program in a second language

The virtual machine cannot use either of Apple's obvious networking interfaces, and the README explains why in detail, which is the most useful paragraph in it. The user-mode attachment lost packets and left the guest broken whenever the host changed networks, so switching between wifi, ethernet and a VPN connection was enough to kill a running machine. The bridged attachment would work but requires an Apple entitlement that is restricted to approved applicants, and the author is explicit that he is not interested in requesting it. So the answer was to bundle a user-mode network helper in the same style as the gVisor and Lima projects, written in Go, which the program spawns automatically. The result is a deliberately asymmetric network: guests reach the host at a fixed address, the host cannot reach the guests, and guests cannot reach each other. Name resolution is forwarded to the host resolver, which is what makes VPN and split-DNS setups work unchanged inside the guest.

The image flag is ignored once an instance exists, and says so twice

The tool has exactly two verbs: run a machine from a raw disk image, and provision a machine by booting a base image, running scripts inside it and saving the result as a template. Everything else follows from that. Run it in a project directory and the default template is copied to an instance file inside a hidden directory, booted, and your terminal is attached to it; leave the shell and the machine shuts down, while its disk stays until you delete it. The template flag selects a different image, and the documentation states in two separate places that it is ignored if the instance file already exists. That is a sensible guard against silently replacing a machine you have been working in, and it is also a trap for anyone who changes their template configuration and cannot work out why nothing changed.

The base provisioning script always runs, and you cannot opt out of it

When the default template is built, a set of scripts is applied to a downloaded Debian base image, and one of them is unconditional. The base script installs basic tools, naming a compiler, a version manager and a search tool among them, and it runs on every provision. The documentation does not offer a flag to skip it. The escape hatch is to build your own raw image and drop it into the cache directory to be used as a template, which means you lose the automation entirely. For everything else, the provision command takes an ordered list of scripts, and the example builds a personal image with two built-in scripts resolved by prefix plus a shell script of your own, executed in the order given. That is where keybindings and shell customisations belong, not in the image you share.

The hundred-gigabyte disk is mostly not there

The default guest disk is a hundred gibibytes, which sounds alarming until you look at how the host filesystem behaves. It is copy-on-write and does not count unwritten blocks, so the file listing shows the full size while the actual usage is a small fraction. The README shows both numbers side by side for a real instance, a hundred gibibytes from the directory listing and two and a half gibibytes from the usage command, and suggests running the usage command yourself to see the truth for your own machine. Growing it is deliberately a two-sided operation: the sparse file is extended from the Mac with a truncation command, and the partition and filesystem are grown from inside the guest, so you have to remember to do both halves.

Why a machine rather than a container

The choice of virtual machine over a container is argued in two sentences and both are load-bearing. Virtualization is treated as more secure against a malicious escape than either containers or the host's own sandbox framework, which matters precisely because the threat model here is an agent running downloaded code. And containers on this operating system require a virtual machine underneath anyway, so the lighter option does not actually avoid the thing being avoided. What the guest is for is spelled out in the same section: an agent can install and remove tools freely, and the author can decide exactly what gets shared in, which also bounds what the upstream model provider ever sees. The stated inspiration was running a command line agent without its approval flag and watching it read files outside the directory it was started in.

The last note on entitlements stops mid-word

The final section of the documentation begins to explain that the operating system only lets binaries carrying a particular virtualization entitlement run at all, and stops partway through the word for virtualization. What follows that sentence is not on the page. The same thing happens in the options list, where the last entry visible is the flag that disables all default mounts, described as including the git directory and a project subfolder, and the description ends partway through a word. Both cutoffs are in the places a reader needs most: what the signed binary is required to carry, and exactly which host directories are shared into the guest by default. The default mount list is the one to go and verify on your own machine before you run an agent in it with anything you care about on disk.

Editorial conclusion

Use Vibe if you want an agent to have a machine of its own and you are on an Apple Silicon Mac, because the whole thing is a disposable Debian image plus a directory share. Four things to know first. There are no formal releases, only date-and-commit tags and a moving latest tag, so the download URL changes under you and the only way to identify your build is the version flag that prints a commit and a build date. Every Objective-C interop crate is a wildcard, so pin by lockfile and not by manifest. The template image always has a base script applied, so a custom image means building your own. And the host is reachable from the guest at a fixed address while the host cannot reach the guest at all, which is the tradeoff for not taking a restricted entitlement.

Frequently asked questions

What does vibe require before it will run?

An ARM-based Mac on macOS 13 or newer, and a network connection on the first run, which is when the Debian base image is downloaded and provisioned. The author reports roughly ten seconds to boot on an M1 MacBook Air.

How are vibe releases named?

There are no formal releases or change log. Tags are named for the date and a short commit, plus one tag called latest that the install instructions download from, so the same command can fetch a different binary on different days.

What Rust dependencies does vibe have?

The Objective-C interop crates, the block and dispatch companions, the C standard library, and the argument parser. Every one is a wildcard version except the parser, which is pinned to a specific minor, while the lockfile is committed to pin actual builds.

How does a vibe VM reach the network?

Through a bundled user-mode network helper written in Go, spawned automatically, in the style of the gVisor and Lima projects. Guests reach the host at a fixed address, the host cannot reach guests, guests cannot reach each other, and DNS goes to the host resolver.

What happens to the template flag if the instance already exists?

It is ignored, which the documentation states twice. The instance file in the project directory is what gets booted, so changing the template you provision has no effect until you delete that file.

Can I stop the base provisioning script from running?

There is no flag for it. The base script always installs basic tools during provisioning, so the only way to avoid it is to build your own raw image and copy it into the cache directory to use as a template.

Official sources

  1. Issues
  2. License: MIT
  3. lynaghk/vibe on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/lynaghk-vibe.svg)](https://hysenlabs.com/projects/lynaghk-vibe)