Documentation
Everything you need to install PMClient, connect to a cluster, and get the most out of consoles, clipboard, terminals and migration. Downloads are on the product page.
Getting started
Windows
Grab the win-x64 executable — or win-arm64 on a Snapdragon-class
device — and run it. The application is that one file: no installer, no runtime to add.
macOS
Two builds, and they are not interchangeable: osx-arm64 for Apple silicon
(M-series) and osx-x64 for Intel. Check under Apple menu → About This
Mac if unsure — "Chip: Apple M…" means Apple silicon. Unzip, open the app bundle
— named PMClient-x64.app in the Intel download — and drag it to Applications
if you want it to stay. macOS 11 or newer.
Taking the wrong build is not subtle: the Apple silicon build will not start on an Intel Mac at all, and the Intel build on Apple silicon runs through Rosetta — slower than the native one for no benefit.
Linux — Debian and Ubuntu
sudo apt install ./wickasoft-pmclient_<version>_amd64.deb
Use the arm64 package on ARM hardware. The package adds PMClient to the
applications menu, puts wickasoft-pmclient on your PATH, and pulls in what it
needs — including WebKitGTK for browser sign-in. Remove it with
sudo apt remove wickasoft-pmclient.
./ in that command — it is what makes apt treat
the file as a local package and resolve its dependencies. dpkg -i does not,
and will simply complain.Linux — other distributions
tar xzf WickaSoft-PMClient-<version>-linux-x64.tar.gz ./WickaSoft-PMClient-<version>-linux-x64
The tarball preserves the executable bit; a bare binary copied from elsewhere does not,
so chmod +x it first in that case. Browser sign-in needs the WebKitGTK
runtime (libwebkit2gtk-4.1-0 on Debian-family systems) — password and
API-token logins work without it.
Connecting
Everything lives on the bar at the top, left to right:
- Host — the cluster or node address. The port in use is shown faintly
inside the box; a non-standard one goes on the end:
pve.example.com:8007. After the first successful login the box remembers and offers previous hosts. - Realm — populated from the server once it answers, with the cluster's default preselected.
- User / Password — for password realms.
user@realmworks too. For an API token, the user isuser@realm!tokenidand the password is the token secret. - TOTP — enabled only when the account actually has a second factor.
Single sign-on (OpenID / OIDC)
If the cluster has an OpenID realm — Microsoft Entra, Okta, Keycloak, Authentik or any other OIDC provider — pick it and the user and password boxes gray out: sign-in happens in a browser instead. On Windows and macOS that browser is embedded in the window; on Linux it opens as its own window. The embedded browser keeps its session, so later sign-ins are usually silent. To sign in as a different account, tick Choose account before logging in — the provider shows its account chooser instead of reusing the cached session.
PMClient fronts the cluster's own OpenID flow, using the PVE origin as the redirect —
the same one the Proxmox web UI already uses — so nothing needs to change in your
provider's app registration. The flow never names a provider — any realm whose type is
openid qualifies — though Entra is the provider it has been exercised
against most.
The certificate question
Most Proxmox installations run on a self-signed certificate, so your first connection asks you to confirm a fingerprint. Read it rather than clicking through: compare it with what Proxmox shows under Node → System → Certificates.
You are asked once per cluster, not once per node — after you accept, PMClient learns the cluster's own certificate authority over that trusted connection, so other nodes (including ones added later) are recognized automatically. A certificate that stops matching what you approved is refused outright, and there is deliberately no button to override it.
Save stores the host, user, realm and the accepted certificate under a profile name; passwords go to the operating system's own secret store, never to a file.
VM consoles
Open a QEMU guest from the tree and you get a real VNC console — PMClient speaks RFB directly to the cluster. Containers and node shells get a text console instead, and selecting the Datacenter row opens the Proxmox web UI itself, already signed in (in the pane on Windows and macOS; in its own window on Linux).
- Encoding — the login-bar box. The default favors fast local networks (ZRLE); switch to Tight when working over a slow link.
- Fullscreen — the button, F11, or Ctrl+Alt+Enter. The tree becomes a fly-out tab on the left edge.
- Ctrl+Alt+Del — the console-bar button, or Ctrl+Alt+End; the real chord is caught by your own machine.
- View only — a switch on the bar that withholds keyboard, mouse and paste, for watching a guest without touching it.
- Powered-off guests — the console pane offers a Start button instead of failing, when your account may start the guest.
- Theme — follows the system by default; pin Light or Dark in About. Consoles and terminals stay dark regardless; that is deliberate.
Resizing the guest desktop
When the VM's display supports host-initiated resizing, a Resolution
button appears on the console bar with sizes from 1024×768 up to 4K, filtered by what
the display's memory allows (memory=, 16 MiB when unset — 4K
needs 32). The resize is sent over the console connection itself; nothing runs inside
the guest. In practice this is a Linux capability — Linux guests resize
this way even on the default std display.
Windows guests don't follow host-initiated resizes on any display
type — the virtio-win display driver is display-only and ignores the request. What the
console offers instead is a one-click switch of the VM's display to
virtio-gpu (needs VM.Config.HWType; the rest of the display
config, clipboard=vnc included, is preserved; takes effect after a full
stop and start — an in-guest reboot is not enough). That unlocks a much longer
resolution list inside Windows, under Settings → Display — and the
console follows whatever the guest picks.
PMClient reports honestly either way: QEMU can only confirm a resize request was forwarded to the guest, so when a guest ignores it, PMClient says so instead of pretending it worked.
Copy & paste
Copy inside the guest and the text is on your machine's clipboard; copy on your machine and paste inside the guest. Both directions, over the console connection itself. Two things make it work:
clipboard=vncon the VM's display (PVE 8.1 or later). The console offers a one-click Enable when it's off — flipping it needs theVM.Config.HWTypeprivilege and takes effect at the guest's next stop/start.- The SPICE agent inside the guest. On Windows guests it arrives with the virtio-win
guest tools, alongside the QEMU guest agent; on Linux guests it is the
spice-vdagentpackage, a small companion to the usualqemu-guest-agent. Despite the name, no SPICE connection is involved — QEMU reuses that in-guest channel for the VNC clipboard.
When paste doesn't work, PMClient says why rather than failing silently — it checks whether the guest's agent is actually running and reports what it found. One limit worth knowing: clipboard payloads are capped at 1 MiB.
Clipboard and live migration
A running VM with clipboard=vnc refuses to live-migrate unless two
version gates are both met: the cluster is on PVE 9.2 or later, and
the VM's QEMU machine version is 10.1 or newer. Everywhere older — all
of PVE 8.x, and 9.x before 9.2 — the migration is blocked outright, and a machine
version pinned below 10.1 keeps the block even on a current cluster. Migrating the guest
while it's stopped is never affected.
You won't discover this mid-transfer: PMClient's migrate menu shows the condition as Blocked before anything starts.
Text consoles
Containers, node shells and serial-only VMs get a genuine terminal, not a log view —
vim, htop, less and full-screen curses programs
render properly, in color.
- Copy is Ctrl+Shift+C (Cmd+C on a Mac). Plain Ctrl+C is left alone — it has to keep working as interrupt.
- Selection — select with the mouse; a double-click grabs a whole path rather than just a word, and a triple-click takes the line.
- Scrolling — the wheel moves through history, or pages through
lessandmanwhen one is running.
Terminal type
The terminal is an xterm-class emulator with the full 256-color palette. Shells opened
through PMClient normally arrive with a sane TERM already set, but if a
program renders wrong — serial consoles and minimal container images sometimes default to
vt220 or linux, and the value doesn't follow you through an
onward ssh — set it yourself:
export TERM=xterm-256color
On a rare guest whose terminfo database lacks that entry, plain xterm is the
fallback. Avoid vt100: it works, but it costs you color and the function
keys full-screen programs expect.
Migration
Right-click a guest and open Migrate to. Every viable target is listed
with its route and cost up front — bare name for shared storage,
(replicated) when replication already mirrors the guest there, or
(copies 12 GiB) when local disks would have to move. Nodes that cannot
take the guest stay visible, disabled, with the reason — an older PVE version, a QEMU too
old for the guest's machine type, a running cpu=host guest that cannot cross
CPU vendors. A guest that cannot move at all says Blocked and why, before
anything starts.
Before committing you're told what to expect: a running VM keeps running through a live migration with a brief pause, while a container is restarted — Proxmox cannot live-migrate containers. During the move, a chip on the guest's row tracks the phase that dominates (disk copy or RAM transfer, with a percentage), read from the cluster's own task log. An open console rides along: it waits for the guest to be running, re-resolves the new node and reconnects by itself.
Keeping nodes updated
Right-click a node and open Update. Both actions run in a node console
you can watch — real apt output, not a spinner — so they need Sys.Console
on the node.
- Update package database — runs
apt-get update; it installs nothing. Afterwards the status bar sums up what's pending by origin — r730: 21 packages pending (17 Debian, 4 Proxmox) — a distinction worth having, since Debian security updates are routine while a Proxmox kernel means a reboot. - Upgrade packages… — opens the real upgrade shell on the node, the
same one the Proxmox web UI uses, where apt lists exactly what would change and asks
before installing. Proxmox only permits this shell for
root@pam— its own restriction, not a grantable privilege — so for other accounts the item is grayed with that reason rather than hidden.
After a node session ends, PMClient compares the kernel the node booted with the newest one installed and says plainly when a reboot is due to start using the new kernel. When it can't determine the running kernel, it says nothing rather than guessing.
Permissions
PMClient reads your account's effective privileges — including grants inherited through pools, and privilege-separated API tokens — and shapes the UI to match. Power and migration actions you lack simply don't appear; anything the cluster still refuses is explained in plain language naming the privilege to request. What each privilege unlocks:
| Privilege | Unlocks |
|---|---|
VM.Console | Opening a VM or container console |
VM.PowerMgmt | Power actions, including the Start button on a powered-off guest |
VM.Config.Disk | Hibernate, on top of VM.PowerMgmt — it allocates a state volume |
VM.Migrate | The Migrate to menu |
VM.Config.HWType | The one-click clipboard Enable |
Sys.Console | Node shells, including the update and upgrade consoles |
Datastore.Audit | Listing a storage's contents |
Sys.Audit | The datacenter summary |
API tokens are privilege-separated by default in Proxmox: grant the ACL to
user@realm!tokenid itself, or disable privilege separation on the token.
Where it writes
| Windows | macOS | Linux | |
|---|---|---|---|
| Profiles, layout | %APPDATA%\PMClient\ |
~/Library/Application Support/PMClient/ |
~/.config/PMClient/ |
| Saved secrets | Windows DPAPI | login Keychain | Secret Service (GNOME Keyring / KWallet) |
| Sign-in browser data | %LOCALAPPDATA%\PMClient\WebView2 |
inside the app's container | ~/.local/share/PMClient/webkit/ |
Passwords and token secrets only ever live in the operating system's store. On a Linux machine without a running Secret Service — a minimal or server install — PMClient still works; it simply saves no secrets and asks again next launch, rather than writing them anywhere unprotected.
Troubleshooting
- It won't start, or something looks broken — run it from a terminal
with
--self-test. It opens the real windows, checks assets, theming and the password store, prints a line per check and exits with a pass/fail code. - It crashed — every crash is appended to
crash.login the settings folder (see Where it writes), with the version, OS and architecture. That file, plus what you were doing at the time, is the fastest route to a fix. - Single sign-on on an older Windows 10 — browser sign-in uses the WebView2 runtime, preinstalled on Windows 11 and most patched Windows 10. If it's missing, install Microsoft's free Evergreen Bootstrapper once. Password, TFA and API-token logins never need it.
- Blank sign-in or portal window on Linux — that window renders through
WebKitGTK and the system GPU stack; a fault there is outside the app, and PMClient
reloads once and then says so rather than leaving a white rectangle. Update
libwebkit2gtk-4.1-0and the Mesa packages first; failing that, setPMCLIENT_WEBKIT_SOFTWARE_GL=1to keep that window's page process off the GPU entirely (it only ever renders a login page or the PVE UI, so the cost is small). - First launch on a new machine — there's no installer, so the first run performs the one piece of setup an installer would have done: unpacking bundled libraries into a one-time cache. Two instances launched together on a machine that has never run PMClient — the same file twice, or two copies — will both attempt that unpack, and can trip over each other. Let the first launch finish before opening a second; every launch after that finds the cache in place, and multiple instances are no trouble.
- Paste stopped working — check the console's hint bar: PMClient
reports whether
clipboard=vncis off or the guest's agent is missing or stopped, and names what it found. See Copy & paste.