Gibil v0.4.0: Your Own Machine, Wherever You Are
Vultr support lands alongside Hetzner. Tokyo, Seoul, Singapore, Sydney, Mumbai — five new APAC regions, one CLI. New Vultr accounts get $300 in free credits.
You're in Tokyo. Your agent is creating a server in Frankfurt because that's the only region gibil knew how to talk to. SSH lag is 250ms. Cloud-init clones your repo across half the planet. Tests that should take two minutes take six.
That's not a story we like telling. So we fixed it.
v0.4.0 ships multi-cloud. Vultr lands as a first-class provider next to Hetzner, and with it come five new regions: Tokyo, Seoul, Singapore, Sydney, Mumbai. Same CLI. Same flags. Same flow. Just closer to where you actually live.
Pick your cloud, pick your region
gibil create --name tokyo-test --provider vultr --location nrt --size small --ttl 30mThat's the whole story at the surface. --provider vultr says "use Vultr instead of the default." --location nrt is Tokyo. --size small is gibil's high-level sizing — the same word means a real server on either cloud, mapped to the right native SKU under the hood.
The full APAC lineup on Vultr today:
| Code | Region |
|---|---|
nrt | Tokyo |
icn | Seoul |
sgp | Singapore |
syd | Sydney |
bom | Mumbai |
Vultr covers the rest of the world too — North America, Europe, South America, Africa — but the APAC five are the ones that change what's possible. If you're an agent operator in Sydney, your SSH round-trip just dropped from hundreds of milliseconds to a handful.
See what's available before you commit
gibil providersHetzner Cloud (hetzner) default region: fsn1
small 2 vCPU / 4 GB RAM / 40 GB disk (cax11)
medium 4 vCPU / 8 GB RAM / 80 GB disk (cax21)
large 8 vCPU / 16 GB RAM / 160 GB disk (cax31)
Vultr (vultr) default region: nrt
small 2 vCPU / 4 GB RAM / 80 GB disk (vc2-2c-4gb)
medium 4 vCPU / 8 GB RAM / 160 GB disk (vc2-4c-8gb)
large 6 vCPU / 16 GB RAM / 320 GB disk (vc2-6c-16gb)Two things worth being honest about. First, Vultr's nearest 16 GB SKU is six vCPUs, not eight, so large isn't identical across clouds. We could have hidden that with a fake mapping, but you'd find out the first time you ran a benchmark. Better to surface it. Second, Vultr's pricing is higher than Hetzner's — the value isn't cost, it's that you can run inside the same datacenter as your users.
gibil providers --json returns the same data structured for agents. No token required to call it — the catalog is static and lives in the binary, so you can shop for a region before you've configured anything.
Add a second cloud, keep the first
If you already have Hetzner set up:
gibil init --add vultrThis walks you through pasting a Vultr API key, runs a quick verify call, and writes the new provider into your config. Your Hetzner setup stays exactly as it was. The new shape of ~/.gibil/config.json:
{
"default_provider": "hetzner",
"providers": {
"hetzner": { "token": "...", "default_location": "fsn1" },
"vultr": { "token": "...", "default_location": "nrt" }
}
}Existing users get migrated automatically on first save after upgrade. The old top-level hetzner_token is moved under providers.hetzner.token and dropped from disk. You don't have to do anything — the next gibil create does it for you.
For non-interactive setups (CI, scripts, an agent bootstrapping itself):
gibil init --provider vultr --token $VULTR_API_KEYNew to Vultr? Start with $300 in credits
Vultr runs a referral program. New accounts signing up via this link get $300 in free credits — enough for weeks of Gibil usage on small VMs. We get a small kickback when an account converts, which helps fund development. (Referral link disclosure.)
The bigger win sits inside gibil init --add vultr. Vultr's API has a footgun: requests are blocked by default until you whitelist an IP under "Access Control," and the error message tells you nothing. So the new flow asks "Do you have a Vultr account?" If you answer no, it walks you through it:
- Open
console.vultr.com/user/apiaccess/— direct link, no hunting through Account menus. - Whitelist your IP — we detect it automatically so you don't have to leave the terminal.
- Copy the personal access token from the top of the page.
If you paste a token that comes back 401, the validator now tells you the most likely cause (IP not whitelisted) and links you back to the right page. The Vultr newcomers who used to lose 10 minutes to that error get an answer in seconds.
If you already have an account, say yes and skip the pitch — the flow fast-paths straight to "paste your token."
How it works under the hood
The interesting part for engineers is what didn't change.
Every command in gibil — create, destroy, run, ssh, list, the MCP server, the VS Code extension — routes through a single CloudProvider interface. Nothing outside src/providers/ knows whether it's talking to Hetzner or Vultr. Adding a provider is one new file plus one row in the catalog.
The piece that makes this stick is the ProviderRegistry. When you create a server, gibil writes the provider name into the instance metadata file. Months later, when you run gibil destroy old-app, the registry reads that file, resolves the right provider, and dispatches. You can't accidentally send a Hetzner API call to Vultr. Pre-multi-cloud instance files (no provider field) default to "hetzner" for back-compat — your existing servers keep working unchanged.
The other piece is the static catalog at src/providers/catalog.ts. Provider metadata — sizes, default region, label — lives in plain TypeScript, separate from the provider class itself. That's how gibil providers can describe a cloud without needing a token, and how the size abstraction stays consistent across clouds. small is a contract: 2 vCPU and 4 GB RAM. The native SKU is an implementation detail.
If you ever want to bypass the abstraction:
gibil create --name benchmark --server-type cax31--server-type takes a native SKU and overrides --size entirely. It's the escape hatch for anyone who knows exactly what they want.
What this means for agents
If you're orchestrating agents from Claude Code, Cursor, or any other client over MCP — the create_server tool gained provider and size parameters. An agent can now request a server in the right region for the workload:
{
"tool": "create_server",
"input": {
"name": "ap-southeast-test",
"provider": "vultr",
"size": "medium",
"ttl": "1h"
}
}Common pattern: a fleet of test runners scattered across regions, each closer to a different chunk of users. Or a single agent picking the cheapest cloud for a long-running build (Hetzner) and the closest cloud for a latency-sensitive integration test (Vultr in Mumbai). The CLI is the same. The agent doesn't need to learn two tools.
What's the same
A surprising amount, on purpose.
gibil run my-app "pnpm test" works identically. gibil ssh my-app works identically. gibil list gained a new PROVIDER column but otherwise looks the same. The cloud-init script is provider-agnostic. The SSH key flow, the readiness probing, the TTL handling — all unchanged. The only real difference is that the destroy path now calls Vultr's API instead of Hetzner's when the metadata says so.
That's the whole point of the abstraction. New cloud, no new mental model.
What's next
The shape that opened up here makes a few obvious next steps cheap. AWS, GCP, and DigitalOcean all fit the same CloudProvider interface. Per-instance region selection by latency (--nearest) becomes possible once we have real pricing data. And for teams that want to mix clouds inside a single fleet — running 10 servers, six on Hetzner for cost and four on Vultr for proximity — the registry already supports it. We just haven't put a flag on it yet.
We're not promising any of those by date. But the architecture stopped being the blocker.
Upgrading
Already on gibil:
npm update -g gibil
gibil init --add vultr # only if you want APACYour existing servers, config, and Hetzner setup are untouched. The migration runs the next time you save config.
Starting fresh:
npm install -g gibil
gibil initgibil init now asks which provider you want first. Pick whichever cloud you have a token for. Add the other one later with --add if you need it.
That's v0.4.0. Same fire, more places to light it.