| name | vast-ai-perl |
| description | WWW::VastAI — Perl client for the Vast.ai GPU cloud API. Usage patterns, architecture, testing. |
| user-invocable | false |
| allowed-tools | Read, Grep, Glob |
| model | sonnet |
WWW::VastAI — Perl Client
Usage
use WWW::VastAI;
my $vast = WWW::VastAI->new(
api_key => $ENV{VAST_API_KEY},
);
my $offers = $vast->offers->search(
limit => 5,
verified => { eq => \1 },
rentable => { eq => \1 },
gpu_name => { in => ['RTX_4090', 'RTX_5090'] },
);
my $instance = $offers->[0]->create_instance(
image => 'pytorch/pytorch:latest',
disk => 32,
runtype => 'ssh',
);
$vast->instances->list;
$vast->instances->get($id);
$vast->instances->stop($id);
$vast->instances->start($id);
$vast->instances->destroy($id);
$vast->volumes->list;
$vast->volumes->create(name => 'data', disk_space => 50);
$vast->volumes->delete($id);
$vast->endpoints->list;
$vast->endpoints->create(%config);
$vast->workergroups->list;
$vast->templates->list;
$vast->ssh_keys->list;
$vast->api_keys->list;
$vast->user->current;
$vast->env_vars->list;
$vast->invoices->list;
Architecture
Same pattern as WWW::Hetzner — Moo, pluggable IO, operation map.
WWW::VastAI — Main client, lazy-builds API accessors
Role::HTTP — Bearer auth, JSON encode/decode, _build_request/_parse_response
Role::IO — IO backend interface (call($request) -> $response)
LWPIO — Default sync backend (LWP::UserAgent)
Role::OperationMap — Central route table: operation name → HTTP method + path
API::* — Resource controllers (Offers, Instances, Volumes, etc.)
*.pm entities — Object classes (Instance, Offer, Volume, etc.)
Operation Map
All API routes defined in Role::OperationMap::_build_operation_map. Three base URLs:
v0 → https://console.vast.ai/api/v0/
v1 → https://console.vast.ai/api/v1/
run → https://run.vast.ai/
Usage: $client->request_op('searchOffers', body => \%params)
Adding a New API Endpoint
- Add operation to
Role::OperationMap::_build_operation_map
- Create
API::NewResource with methods that call request_op
- Create entity class if needed (with
new from API response data)
- Add accessor to
WWW::VastAI main class
- Add tests
Testing
prove -l t/
VAST_LIVE_TEST=1 prove -lv t/90-*.t
VAST_LIVE_TEST=1 VAST_LIVE_ALLOW_COST=1 prove -lv t/91-*.t
Mock tests use WWW::VastAI::Role::IO — inject a mock IO backend via constructor:
my $vast = WWW::VastAI->new(api_key => 'test', io => $mock_io);
Tech
- Moo + namespace::clean
- JSON::MaybeXS for JSON
- Log::Any for logging
- LWP::UserAgent default IO (via LWPIO)
- Dist::Zilla with
[@Author::GETTY]