pve-client
    Preparing search index...

    pve-client

    pve-client

    npm version GitHub repo License Tests Coverage codecov

    TypeScript-first API client for Proxmox VE.

    It provides a typed API surface generated from the Proxmox spec, so endpoint paths, query/body fields, and return types are available through autocomplete.

    • Typed endpoint methods for Proxmox VE APIs
    • Token auth and username/password login flow
    • Automatic path/query/body handling
    • Proxmox-style response unwrapping ({ data: ... } -> data)
    • Works with Node.js fetch and supports custom HTTPS agents
    npm install pve-client
    
    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",
    // only needed for self-signed certs
    agent: new Agent({ rejectUnauthorized: false }),
    });

    const nodes = await client.api.nodes.list();
    console.log(nodes);
    import { Client } from "pve-client";
    import { Agent } from "node:https";

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

    await client.login();
    const nodes = await client.api.nodes.list();
    console.log(nodes);
    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!,
    });

    const nodes = await client.api.nodes.list();
    console.log(nodes);
    const cluster = await client.api.cluster.index();
    const nodes = await client.api.nodes.list();
    const nodeStatus = await client.api.nodes.get("pve").status.get();
    
    // no params required
    const version = await client.api.version.version();

    // optional query/body can still be passed
    const pools = await client.api.pools.index({
    $query: { type: "qemu" },
    });

    Methods accept an object with optional special fields depending on endpoint:

    • $path: path parameters (usually handled by path helper methods like .get("node"))
    • $query: query string parameters
    • $body: request body (sent as application/x-www-form-urlencoded)
    • $headers: additional request headers

    Example:

    await client.api.access.permissions({
    $query: { path: "/", userid: "root@pam" },
    });
    • apiToken accepts either:
      • full: PVEAPIToken=user@realm!token=secret
      • shorthand: user@realm!token=secret
    • For username/password auth, call await client.login() before other API calls.
    • For self-signed certificates, pass a custom https.Agent with rejectUnauthorized: false.
    • Some Proxmox functionalities are only accessible with username/password ticket auth (session + CSRF) and are not available to API tokens, even if token permissions are broad.

    There is a runnable example that opens a VM terminal and binds it to your local terminal (stdin/stdout):

    npm run example/terminal -- 100
    

    Or set PVE_VMID in .env and run without CLI args:

    npm run example/terminal
    

    Example .env (username/password required for terminal helper):

    PVE_BASE_URL=https://pve.example.com:8006
    PVE_USERNAME=root
    PVE_PASSWORD=your-password
    PVE_REALM=pam
    PVE_VMID=100
    

    Controls:

    • Ctrl-] disconnects from the local bridge.
    • Terminal resize is forwarded automatically.

    There is also a terminal example that continuously displays cluster tasks:

    npm run example/tasks
    

    Optional .env values:

    # required
    PVE_BASE_URL=https://pve.example.com:8006
    
    # auth: use token OR username/password
    PVE_API_TOKEN=PVEAPIToken=root@pam!tokenid=secret
    # or:
    PVE_USERNAME=root
    PVE_PASSWORD=your-password
    PVE_REALM=pam
    
    # optional polling interval (default 2000)
    PVE_TASKS_POLL_INTERVAL_MS=2000
    

    Non-2xx responses throw an Error including status and response text:

    try {
    await client.api.nodes.list();
    } catch (error) {
    console.error(error);
    }
    npm run build
    npm test
    npm run test:coverage
    npm run example/auth
    npm run example/terminal -- 100
    npm run example/tasks

    This project uses Vitest in a Node environment.

    • npm test runs all tests
    • npm run test:coverage runs tests and generates coverage reports (text, json, html)

    Current high-value suites cover:

    • Client authentication, request handling, events, and task polling
    • native_fetch request construction, header/body behavior, and abort handling
    • TimerPulledEventEmitter polling, filtering, dedupe, and error flows

    Apache-2.0