npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

pve-client

v1.2.0

Published

Proxmox Typescript API Client

Downloads

151

Readme

pve-client

Full-coverage TypeScript client for the Proxmox VE REST API

npm version JSR License codecov Node.js

Docs · npm · JSR · Issues · Discussions


pve-client is a TypeScript-first API client covering all 675 endpoints of the official Proxmox VE REST API — typed end-to-end so your editor knows every path, parameter, and return shape. No hand-rolled fetch calls, no guessing field names.

import { Client } from "pve-client";

const client = new Client({ baseUrl: "https://pve.example.com:8006", apiToken: "..." });

const nodes = await client.api.nodes.list();
//    ^? { node: string; status: "online" | "offline" | ...; ... }[]

Contents


Features

| | | |---|---| | 675 typed endpoints | Every Proxmox VE API path — GET, POST, PUT, DELETE — is typed with parameter and return types generated from the official spec | | Two auth methods | API token (recommended) or username/password ticket flow | | Autocomplete everywhere | Path params, query strings, body fields, and return shapes all resolve in your IDE | | Response unwrapping | Proxmox wraps responses in { data: ... } — this client strips it automatically | | Task polling | Built-in client.task.listen() and client.task.wait() for async Proxmox tasks | | Live resource events | Subscribe to cluster resource and task streams via client.events | | ESM + CJS | Dual-format build works in any modern Node.js project | | Node.js ≥ 18 | Uses native fetch; bring your own HTTPS agent for self-signed certs |


Installation

# npm
npm install pve-client

# yarn
yarn add pve-client

# pnpm
pnpm add pve-client

JSR (Deno / JSR-compatible runtimes):

deno add @sourceregistry/proxmox
# or
npx jsr add @sourceregistry/proxmox

Quick Start

import { Client } from "pve-client";
import { Agent } from "node:https";

const client = new Client({
  baseUrl: "https://pve.example.com:8006",
  apiToken: "PVEAPIToken=root@pam!mytoken=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",

  // required only for self-signed certificates
  agent: new Agent({ rejectUnauthorized: false }),
});

// list nodes
const nodes = await client.api.nodes.list();

// get cluster status
const status = await client.api.cluster.status();

// get VMs on a node
const vms = await client.api.nodes.get("pve").qemu.list();

Authentication

API Token (recommended)

Create a token in the Proxmox web UI under Datacenter → Permissions → API Tokens, then:

const client = new Client({
  baseUrl: "https://pve.example.com:8006",
  apiToken: "PVEAPIToken=root@pam!mytoken=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  // shorthand also works:
  // apiToken: "root@pam!mytoken=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
});

Username / Password

const client = new Client({
  baseUrl: "https://pve.example.com:8006",
  username: "root",
  password: "your-password",
  realm: "pam", // defaults to "pam"
});

await client.login(); // exchanges credentials for a ticket + CSRF token

Note: Some Proxmox operations (VM console, terminal access) require ticket-based auth and are unavailable to API tokens regardless of permissions.

Using .env

PVE_BASE_URL=https://pve.example.com:8006
PVE_API_TOKEN=PVEAPIToken=root@pam!mytoken=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
import "dotenv/config";
import { Client } from "pve-client";

const client = new Client({
  baseUrl: process.env.PVE_BASE_URL!,
  apiToken: process.env.PVE_API_TOKEN!,
});

API Modules

The client exposes all 675 Proxmox endpoints through six typed modules:

| Module | Path prefix | Covers | |---|---|---| | client.api.access | /access | Users, groups, roles, ACLs, domains, TFA, tickets | | client.api.cluster | /cluster | Cluster config, HA, replication, firewall, SDN, backup, ACME, resources | | client.api.nodes | /nodes | Node management, VMs (QEMU), containers (LXC), storage, networking, tasks | | client.api.pools | /pools | Resource pool management | | client.api.storage | /storage | Storage configuration | | client.api.version | /version | API version info |

Request argument shape

Every method accepts an object with the following optional keys:

| Key | Used for | |---|---| | $path | URL path parameters — usually pre-bound by helper methods like .get("node") | | $query | Query string parameters (GET / DELETE) | | $body | Request body (POST / PUT — sent as application/x-www-form-urlencoded) | | $headers | Extra request headers |

// explicit path/query/body example
await client.api.access.permissions({
  $query: { path: "/vms/100", userid: "root@pam" },
});

await client.request("/nodes/{node}/qemu", "POST", {
  $path: { node: "pve" },
  $body: { vmid: 101, memory: 2048, cores: 2, name: "my-vm" },
});

Common Patterns

List all nodes and their status

const nodes = await client.api.nodes.list();

for (const node of nodes) {
  console.log(`${node.node}: ${node.status} (${node.uptime}s uptime)`);
}

Work with VMs on a node

const node = client.api.nodes.get("pve");

// list VMs
const vms = await node.qemu.list();

// start a VM
await node.qemu.vmid(100).status.start();

// stop a VM
await node.qemu.vmid(100).status.stop();

// clone a VM
await node.qemu.vmid(100).clone({ $body: { newid: 200, name: "clone-vm" } });

Work with LXC containers

const node = client.api.nodes.get("pve");

const containers = await node.lxc.list();
await node.lxc.id(200).status.start();
await node.lxc.id(200).config.get();

Node storage and LXC templates

const storage = client.api.nodes.get("pve").storage;

// list available LXC templates
const templates = await storage.get("local").content.list({
  $query: { content: "vztmpl" },
});

Cluster resources

// all VMs across the cluster
const vms = await client.api.cluster.resources({
  $query: { type: "vm" },
});

Task Monitoring

Proxmox operations return a UPID (task ID). Use client.task to track completion:

Wait for a task to finish

const upid = await client.request("/nodes/{node}/qemu/{vmid}/status/start", "POST", {
  $path: { node: "pve", vmid: 100 },
});

const logs = await client.task.wait(upid, (update) => {
  console.log(`[${update.status}]`, update.logs.at(-1));
});

console.log("Task completed:", logs);

Subscribe to task updates

const sub = client.task.listen(upid, async (update) => {
  if (update.status === "stopped") console.log("Done:", update.logs);
  if (update.status === "failed")  console.error("Failed:", update.logs);
}, 1000 /* poll interval ms */);

// cancel early if needed
sub.stop();

Live Events

client.events provides live-polling streams for cluster state:

Watch cluster resources

const monitor = client.events.resources();

monitor.on("qemu/100", (resource) => {
  console.log("VM 100 updated:", resource.status);
});

monitor.start(5000); // poll every 5 seconds

Watch cluster tasks

const tasks = client.events.tasks();

tasks.on("task", (task) => {
  console.log("New task:", task.type, task.status);
});

tasks.start(3000);

Stop all monitors

client.events.stopListening();

Error Handling

Non-2xx responses throw an Error with the HTTP status and response body:

try {
  await client.api.nodes.list();
} catch (err) {
  // err.message: "HTTP 401 Unauthorized: ..."
  console.error(err);
}

Examples

Runnable examples live in the examples/ directory. Copy .env.example to .env and fill in your cluster details.

Auth check

npm run example/auth

Terminal — attach to a VM console

npm run example/terminal -- 100
# or set PVE_VMID in .env and omit the argument
npm run example/terminal

Requires username/password auth. Press Ctrl-] to disconnect.

Live task feed

npm run example/tasks

.env reference:

# required
PVE_BASE_URL=https://pve.example.com:8006

# token auth (recommended)
PVE_API_TOKEN=PVEAPIToken=root@pam!tokenid=secret

# OR username/password (required for terminal)
PVE_USERNAME=root
PVE_PASSWORD=your-password
PVE_REALM=pam

# optional
PVE_VMID=100
PVE_TASKS_POLL_INTERVAL_MS=2000

Development

git clone https://github.com/AlexanderSlaa/pve-client.git
cd pve-client
npm install

npm run build           # compile TypeScript + Vite bundle
npm test                # run tests (Vitest)
npm run test:coverage   # run tests with coverage report
npm run docs:build      # generate TypeDoc HTML docs

Test suites cover Client authentication, request handling, event polling, task monitoring, and TimerPulledEventEmitter internals.


Contributing

Contributions are welcome! Here is how you can help:

  • Bug reports — open an issue with a minimal reproduction
  • Feature requests — start a discussion before opening a PR
  • Pull requests — fork, branch off main, make your change, open a PR

Guidelines

  • Keep commits in Conventional Commits format (feat:, fix:, refactor:, etc.) — releases are automated via semantic-release
  • All new API surface needs a corresponding type in src/api/
  • Run npm test and npm run build before opening a PR
  • Factory files export a single export default function — one thing per file

Reporting Proxmox API gaps

The type definitions are generated from the official Proxmox spec in res/apidoc.js. If you find a missing or incorrect endpoint, open an issue referencing the Proxmox API path and the expected parameters/return shape.


License

Apache-2.0 © Alexander Slaa