bwg
BandwagonHost / KiwiVM fleet control for humans and AI agents.
CLI · Go SDK · MCP server · read-only enforced in the client, not by a prompt · MIT
$ bwg ls SERVER HOSTNAME PLAN LOCATION BANDWIDTH USED RESETS STATE osaka osaka.example.com speed-2g JP, Osaka █████████░ 94% 6d 3h attention tokyo tokyo.example.com micro128 JP, Tokyo █████░░░░░ 47% 6d 3h ok la la.example.com kvm-2g US, Los Angeles ██░░░░░░░░ 19% 6d 3h ok Total: 1.8 TiB of 3.9 TiB across 3 servers (45%) ! osaka: bandwidth at 94%
Real output, pinned by a test so it cannot drift from what the tool prints. KiwiVM shows you one VPS per page; this is the whole account in one sweep.
Install
curl -fsSL https://raw.githubusercontent.com/lroolle/bwg-cli/main/install.sh | bash
# or
go install github.com/lroolle/bwg-cli/cmd/bwg@latest
60 seconds
Two values per VPS, both from the KiwiVM panel: the VEID in the panel
URL after ?veid=, and the API key under the API tab.
export BWG_VEID=1347645 export BWG_API_KEY=private_xxxxxxxx bwg ls # the fleet bwg info # plan, addresses, quota bwg ssh # ssh in, port resolved from the API
A fleet lives in ~/.config/bwg/config.yaml (mode 0600):
bwg server add, or bwg server import keys.csv from the
billing portal's export, then bwg server check to verify every pair.
Why it exists
- KiwiVM authenticates per VPS — there is no account-level endpoint, so every fleet-wide question is N calls with N credential pairs. bwg sweeps them concurrently and prints one table.
- A KiwiVM API key can reinstall your server. Handing that to an agent needs a real answer, not a prompt.
Read-only is a capability, not a flag
c := kiwivm.New(veid, key, kiwivm.ReadOnly()) c.Restart(ctx) // *ReadOnlyError — no HTTP request is made c.ServiceInfo(ctx) // fine
Every endpoint is classified in one registry — 45 endpoints, 29 of them mutating — and the gate sits in the SDK in front of the HTTP client. The CLI, the MCP server and any Go program importing the package inherit it. A test reflects over every client method and asserts a read-only client refuses all 29 without touching the network, so a method added later is covered automatically.
bwg --read-only ls # or: export BWG_READ_ONLY=1 bwg api ops # how every endpoint is classified
For agents
Every command speaks --json and --jq. Data on stdout,
diagnostics on stderr. Exit codes carry the reason: 2 configuration,
3 refused, 4 credentials rejected. Errors name the
command that fixes them.
claude mcp add bwg -- bwg mcp --read-only
In read-only mode the mutating MCP tools are not advertised at all — an agent is never offered a tool that is certain to be refused. MCP has no confirmation channel, so serve read-only unless the host has an approval layer you trust.
When to skip it
- One VPS you already keep open in the panel — the panel is fine.
- Billing, renewals or buying capacity: KiwiVM's API has no billing endpoints, so neither does bwg.
- Anything inside the guest beyond a shell command — that is ssh's job, and
bwg sshhands you straight to it.