Mitchell: First allow me to apologize for the tone of my comment. Re-reading it now, I realize that I glossed over a key point: I used Vagrant every day for a team of 5 people. In general, it worked very well, rarely broke in any way, saved us a whole bunch of time getting up and running. So thank you for your small, but real, contribution to my startup.

> middleware was so _painfully_ the RIGHT way to do things

I did see how you were composing the operations and I'm familiar with the middleware pattern; thanks for sharing your talk. However, I think this is one of those cases where OOP has a name for something that FP just takes for granted: function composition. Regardless, Clojure's Rack equivilant does provide middleware as functions of request -> response maps. It's much nicer to work with, but that might be a result of Clojure's design vs Ruby's and unrelated to Vagrant: https://github.com/ring-clojure/ring/wiki/Concepts

> Write a shell script that does the following

I don't have any of those requirements. I only need to support OSX as the host OS. The team's MacBook Airs don't have enough resources to run more than one VM, so I don't ever worry about port collisions. I need to configure my network adapters anyway for my production deployment, so I just need an if statement or two in that config file template. Hell, I don't even need the ability to turn off a VM gracefully, since kill -9 seemed like a decent way to test crash recovery.

Even thought I don't have those requirements: I used Vagrant. It saved me some time up front.

But that complexity has a cost. Running `vagrant ssh`, for example, took 3ish seconds on my machine. Again, this is probably due to RubyGems, which is painfully slow. I had to explain to the team to run `vagrant ssh-config >> ~/.ssh/config`, then to go tweak that a bit, so that they could write `ssh dev` and have it be instantaneous.

Worth noting however, is that I already needed a way to generate local ssh config for each production box to be able to talk to specific other production boxes, and for client machines to talk to our cluster. Vagrant's ssh-config command was just one more extra moving part to concern myself with, so I manually put the correct config into a cat script along with the production needs, and added it to the build process.

There was one or two more of these little things that escape my memory now.

> make all of that REUSABLE and EXTENSIBLE

I think my main complaint about Vagrant is one which you seem to be fixing, starting with the very commit that this HN thread is attached to: You're pulling out the REUSABLE bit of abstracting away various virtualization platforms across a variety of host and guest operating systems.

However, I'm a big believer that EXTENSIBLE does not belong in library code. Extensibility belongs at user layers. Furthermore, extensibility is really fucking hard. 99% of the time, I'd rather the core be more reusable and allow me to bypass extensibility.

I think that Git is a perfect example of this design. They call it plumbing and porcelain. The plumbing commands offer zero extensibility. They don't have any creature comforts, as their output is tuned for parsing. The goal of these commands is to manipulate the abstractions of the underlying system. The porcelain, by contrast, does offer extensibility via git-foo.sh scripts on your path, aliases and configuration, commit hooks, etc. I'd see a lot of value in something like this for virtual machine management.

Another example would be Chef & Puppet's facts systems. I forgot what they are called. Ohai? Something like that. They provide OS-independent interfaces for gathering facts about machines. Those components should be hoisted to first class project status!

Unfortunately, Vagrant does not, yet, provide a plumbing vs porcelain split. In many ways, I view Vagrant like SVN: It's a damn solid piece of software. Lot's of people get a ton of milage out of it. However, it's underlying concepts are slightly muddled together and there are huge gains to be reaped from deep thought and careful modularization. When those big gains do come, they will only work on a single platform, maybe one or two guest operating systems, people will bitch about it's low ease of use, despite it's inherent simplicity, but the people who deeply understand machine provisioning and management will adopt it in droves, until eventually Windows support doesn't suck too bad, all the various use cases are more or less covered, and people are wondering "How can you possibly still use that old thing?"

I think you've got a good start towards that goal in Vagrant, but my complexity sense is tingling.

> I'd say Vagrant's 3000 line of code count is pretty spot on

I just ran cloc on the master branch locally; I see 12355 lines of Ruby ;-)