zplCloud CLI
api.zplcloud.com with an API key. Applies printer profiles, sends raw ZPL and print jobs in other printer languages (TCP 9100 / USB), provisions Weblink certificates, runs the outbound proxy agent and watch-folder printing.
Functions
- profiles apply - executes a saved printer profile (SGD/ZPL command sequence with variables) on a printer over TCP 9100 or USB.
- send - sends raw ZPL from an argument or file, and print jobs in other printer languages (TSPL, EPL2, DPL, SBPL, CPCL, ESC/POS, Brother raster, PCL, Easy Plug, TPCL, JScript) byte-exact - finished, or converted from ZPL with
--language. - weblink setup - generates the Weblink certificates server-side, uploads them, sets
weblink.ip.conn2.location, resets the printer. - proxy - remote agent: one outbound SignalR connection to
api.zplcloud.com; jobs from the "Remote Printers" tab are forwarded to LAN printers (TCP 9100) or USB printers. No inbound ports. - font - manage fonts and files in printer memory: list, upload (
~DY), delete and install the platform fontZPLCLOUD.TTF- straight at the printer or through a remote printer. - remote-printers list - list the account's remote printers with ID, target and agent status.
- USB - on Windows two built-in channels (WinUSB and the USBPRINT interface of
usbprint.sys, both bidirectional and without the spooler); on Linux/macOS the libusb printer class or a virtual COM port. - Watch folders - the agent prints every new
.zpl/.prnfile of configured folders, finished jobs such as.tsplbyte-exact, and converts ZPL for other printers on request (see below).
Installation
The installer detects OS and architecture and downloads the binary from https://zplcloud.com/downloads/.
macOS / Linux / Raspberry Pi
Targets: osx-x64, osx-arm64, linux-x64, linux-arm64 (64-bit Pi OS), linux-arm (32-bit Raspberry Pi).
Windows (PowerShell, no admin)
Installs to %LOCALAPPDATA%\zplcloud\zplcloud.exe and adds the directory to the user PATH (new terminals). Targets: win-x64, win-arm64.
Docker
Agent as a container for Raspberry Pi, Synology and any Docker host: CLI as Docker container.
API key
Created in the platform under API. Passed via environment variable or --api-key:
Commands
zplcloud profiles list
Lists the printer profiles of the account (ID, name, target configuration).
zplcloud profiles apply
Executes all commands of a profile in sequence on one printer; each command's response is printed live.
| Parameter | Meaning |
|---|---|
| <id-or-name> | Profile ID (number) or profile name (quoted). |
| --target <ip|hostname> | TCP target of the printer; default port 9100. |
| --port <n> | TCP port (default 9100). |
| --usb | Send over a USB virtual COM port instead of TCP. |
| --serial-port <name> | Explicit serial port (COM3, /dev/cu.usbmodem1101, …); empty = auto-detect Zebra printer. |
| --var name=value | Set a command variable (repeatable). |
| --vars-file file.json | JSON object with variable values. |
| --non-interactive | Fail instead of prompting for missing variables. |
| --timeout <ms> | Connect/read timeout (default 5000). |
zplcloud cookbook list
Lists the ZPL cookbook recipes (command snippets with variables).
zplcloud send
Sends raw ZPL. A missing line terminator is appended (\r\n), because the Zebra SGD parser does not process a command without CRLF. Print jobs in other printer languages are the exception: they go out byte-exact, without a line terminator (see Other printer languages).
The printer's answer is read automatically whenever the command produces one: SGD queries (! U1 …), JSON config ({}{"allconfig":null}), host status (~HS, ~HI, ~HQ…) and ZPL host commands (^HW directory, ^HH configuration). --read forces it. If a sleeping printer stays silent, it is woken with ~HS and the query is repeated once - queries only, a setvar is never sent twice. The proxy agent follows the same rule.
| Parameter | Meaning |
|---|---|
| --target <ip|hostname> | TCP target (required unless --usb). |
| --port <n> | TCP port (default 9100). |
| --zpl "<zpl>" | ZPL inline (either --zpl or --file). Use --file for SGD commands with quotes to avoid shell escaping. |
| --file <path> | Send a ZPL or SGD file (read as UTF-8 text, CRLF appended when missing). Files with a printer-language extension (.tspl, .bin …) go byte-exact. Firmware: zplcloud firmware. |
| --raw | Send --file byte-exact whatever its extension: no text decoding, no line terminator, no answer. |
| --language <id> | Convert the ZPL to another printer language through the API, then send the job byte-exact (API key required, see below). |
| --remote-printer <id|name> | Send through the cloud to the agent in the printer's LAN instead of directly: ZPL via /v1/remote-printers/{id}/send, print jobs via /v1/remote-printers/{id}/raw. API key required. |
| --usb / --serial-port | Send over USB instead of TCP (see profiles apply). |
Other printer languages (TSPL, DPL, Brother …)
The ZPL → printer language tools and POST /v1/tools/zpl-to-… turn a ZPL label into a finished job for TSC, Honeywell/Datamax, SATO, Brother, Toshiba, cab, Avery Dennison/Novexx, Epson or HP printers. Such a job contains binary image data, so it must reach the printer unchanged. The CLI does that in three ways:
| Way | Command | Needs |
|---|---|---|
| Finished job, directly | zplcloud send --target 10.0.0.7 --file label.tsplzplcloud send --usb --file label.bin | nothing - no API key |
| Convert ZPL, then send | zplcloud send --target 10.0.0.7 --file label.zpl --language tspl --dpi 300 --compress | API key (counts renders like the tool) |
| Through a remote printer | zplcloud send --remote-printer 4 --file label.dplzplcloud send --remote-printer Warehouse --file label.zpl --language brother --model td-4-300 | API key; agent v1.2.22+ for TCP printers, v1.2.26+ for USB printers |
Files with the extensions .tspl .epl .dpl .sbpl .cpcl .escpos .bin .pcl .ezp .tpcl .jscript - the names the tools give their downloads - are sent byte-exact automatically; --raw does the same for any other file. Up to v1.2.25 the CLI read every file as text and appended CRLF, which breaks binary jobs - update the CLI and the agent to v1.2.26.
| Option (with --language) | Meaning |
|---|---|
| --language <id> | tspl, epl2, dpl, sbpl, cpcl, escpos, brother, pcl, easyplug, tpcl or jscript. |
| --dpi <n> | Resolution of the target printer (allowed values per language as in the tool). Brother: comes from --model. |
| --width-mm / --height-mm | Label size; default from ^PW/^LL, otherwise 75 × 50 mm. |
| --compress | Compressed image format where the language has one (PCX, TIFF PackBits, TOPIX, #YIR). |
| --hex | SBPL and CPCL: image data as hex text. |
| --cut false | ESC/POS and Brother: do not cut after the job. |
| --paper a4|letter | PCL: paper size. |
| --model <id> / --media continuous|diecut | Brother: model family (e.g. ql-820, td-4-300, pt-p900) and media type. |
| --save <path> | Also keep the converted job as a file. |
zplcloud font
Manages fonts and files in printer memory - the same mechanics as the "Fonts/Files" dialog in the platform: list via ! U1 getvar "file.dir", delete via ^ID, upload as ~DY{drive}:{name},B,T,{size},, followed by the raw bytes. After the upload file.dir verifies that the file really is in flash (the printer needs a few seconds for that).
| Parameter | Meaning |
|---|---|
| list | install | upload | delete | List, install the platform font, upload any TTF, delete a file. |
| --target <ip> / --usb | Direct printer access (TCP 9100 or USB). |
| --remote-printer <id|name> | Through the cloud to the agent in the printer's LAN (/v1/remote-printers/{id}/file). Needs an API key and an agent from v1.2.22. |
| --drive <E|R> | Target drive: E: flash (default, survives a restart), R: RAM. |
| --file <ttf> | Local file. Optional for install - otherwise the font comes from the cloud. |
| --name <NAME> | Name in printer memory (default: the file name, or ZPLCLOUD.TTF). |
| --replace | Delete an existing file of that name first (install always does). |
ZPLCLOUD.TTF is about 10 MB - E: needs the space; the existing file is deleted first. Upload through a remote printer runs over TCP 9100 only, not USB.
zplcloud remote-printers list
Lists the account's remote printers with ID, target, assigned agent and its status. The IDs are what font --remote-printer and send --remote-printer expect.
zplcloud weblink setup
Generates the three NRD certificate files server-side (API key required), uploads them via ~DYE, sets weblink.ip.conn2.location and resets the printer. Reads the printer serial and registers owner + API key in the backend (also for replacement devices).
| Parameter | Meaning |
|---|---|
| --printer <hostname> | Printer name (certificate scope / NRD storage). |
| --endpoint <url> | Weblink URL: https://weblink.zplcloud.com (prod) or https://weblink.test.zplcloud.com (test). |
| --target / --port | TCP target + port (default 9100). |
| --api-key / --api-base | API key (required). Test stage: key + api-base of the test backend. |
Without CLI: Weblink certificate deployment (server-generated PowerShell/bash one-liner).
zplcloud proxy
Starts the remote agent. Outbound SignalR connection to api.zplcloud.com; jobs from the "Remote Printers" tab are forwarded to printers in the local LAN (TCP 9100) or USB.
| Parameter | Meaning |
|---|---|
| --agent <name> | Display name in the Remote Printers tab (required). |
| --timeout <ms> | Connect/read timeout (default 5000). |
| --verbose | --debug | SignalR negotiation/transport/handshake trace with timestamps. |
| --log | Write all console output to zplcloud-<yyyy-MM-dd>.log. |
| --log-dir <dir> | Log directory (default: current directory). |
| --service-install | Install as system service (systemd / launchd / scheduled task). Needs --agent + API key. |
| --service-uninstall | Remove the service (no API key needed). |
zplcloud proxy --service-install
Installs the agent as a service that starts at boot/login and reconnects automatically. API key, agent name, API base and timeout are written into the service definition.
| System | Mechanism | Start |
|---|---|---|
| Linux / Raspberry Pi | systemd unit zplcloud-agent.service (Restart=always, RestartSec=5) | at boot (sudo required, detected automatically) |
| macOS | launchd LaunchAgent ~/Library/LaunchAgents/com.zplcloud.agent.plist (KeepAlive=true) | at login, no admin |
| Windows | scheduled task zplcloud-agent (schtasks ONLOGON, /RL LIMITED) | at login, no admin |
Optional: --timeout <ms>, --log-dir <dir> (defaults: Linux /var/log/zplcloud, macOS /tmp, Windows %LOCALAPPDATA%\zplcloud\logs). In Docker, restart: unless-stopped replaces the service (see CLI as Docker container).
zplcloud usb list
Lists serial ports and the Zebra USB channels. On Windows there are two built-in paths, both bidirectional and without the spooler or a third-party driver:
| Channel | When it applies |
|---|---|
| WinUSB | The printer offers WinUSB natively (ZD421: usb.device.mode = composite) and Windows has registered the interface. |
| USBPRINT | Fallback through the device interface of usbprint.sys, opened directly with CreateFile. Needed when Windows registers no WinUSB interface for the printer - which happens even though winusb.sys is bound. |
The CLI tries WinUSB first, then USBPRINT, then the virtual COM port. On Linux/macOS it uses the libusb printer class.
zplcloud version / help
zplcloud version / --version prints the version, zplcloud help / --help the full help.
Data sources on the agent
Besides printers, the agent can also connect databases. The query then runs inside your network, the connection string stays local and only the result rows travel over the wire. Each engine has its own namespace; all three ways (option, environment variable, file) are equivalent. Details, query rules and the agentless cloud route are documented under Connectors.
| Engine | Option | Environment variable | File |
|---|---|---|---|
| SQL Server | --sql NAME=… | ZPLCLOUD_SQL_<NAME>_CONNECTION | sqlservers.json |
| MongoDB | --mongo NAME=… | ZPLCLOUD_MONGO_<NAME>_CONNECTION | mongoservers.json |
| PostgreSQL | --postgres NAME=… | ZPLCLOUD_PG_<NAME>_CONNECTION | pgservers.json |
| MySQL | --mysql NAME=… | ZPLCLOUD_MYSQL_<NAME>_CONNECTION | mysqlservers.json |
| MariaDB | --mariadb NAME=… | ZPLCLOUD_MARIADB_<NAME>_CONNECTION | mariadbservers.json |
| Kafka | --kafka NAME=… | ZPLCLOUD_KAFKA_<NAME>_CONNECTION | kafkabrokers.json |
Global options
| Option | Meaning |
|---|---|
| --api-key <key> | API key. |
| --api-base <url> | Backend base URL (default https://api.zplcloud.com). |
| --log / --log-dir | Logging (see proxy). |
Environment variables
| Variable | Meaning |
|---|---|
| ZPLCLOUD_API_KEY | API key (alternative to --api-key). |
| ZPLCLOUD_API_BASE | Base URL (alternative to --api-base). |
| ZPLCLOUD_AGENT | Agent name (same as --agent; used in Docker). |
| ZPLCLOUD_TIMEOUT | Connect/read timeout in ms. |
--help output
Watch-folder printing
The agent watches configured folders and sends every new .zpl/.prn file to a LAN printer (TCP 9100) or USB. Rules: oldest file first, one file at a time per folder; a file is printed only when its last write is older than stabilitySeconds; *.part/*.tmp are skipped; on success the file is deleted (deleteAfterOk) or kept; failures are moved to failedSubDir.
Configured per agent in the online agent config (GET/PUT /api/remote-printers/agents/{agent}/config); changes are pushed live (UpdateAgentConfig), no restart.
Folder targets appear in printer lists as wf:<agent>:<folder> ("Agent / 📁 folder"): the platform writes the ZPL as a file into the folder, the agent prints it. Endpoints: GET /api/remote-printers/agents/{agent}/folders, POST …/folders/send; public API GET /v1/agents/folders, POST /v1/print/folder with { "agent", "folder", "zpl" }.
Watch folders for other printer languages
From agent v1.2.26 a watch folder also serves printers that do not speak ZPL, in two ways:
- Finished jobs - files with the extensions
.tspl.epl.dpl.sbpl.cpcl.escpos.bin.pcl.ezp.tpcl.jscriptare sent byte-exact. Add the extension topattern, e.g."*.zpl;*.tspl". - Convert ZPL - with
convertthe agent turns every ZPL file into the printer's language before printing (POST /v1/tools/zpl-to-…with the agent's API key, counts renders like the tool). Your ERP or carrier software keeps writing ZPL; a TSC, Honeywell or Brother printer gets its own language. Options as in the tool:language,dpi,widthMm,heightMm,compress,hex,cut,paper,model,media.
The public API drops print jobs into such a folder as well: POST /v1/print/folder with { "agent", "folder", "zpl", "language": "tspl", "dpi": 300 } (the cloud converts) or { "agent", "folder", "base64", "fileName": "label.tspl" } (finished job). The file keeps the job's extension, so the folder's pattern must include it - otherwise the agent answers with an error instead of storing a file that would never print.