Using the Command Processor service

The Command Processor service provides a command-line interface (CLI) for interacting with the Kanzi Engine at runtime. You can enter commands from a local console (stdin/stdout), send them remotely over a TCP socket connection, or send them over a serial port (UART) connection. The service includes built-in commands for inspecting and controlling the Kanzi Engine, and you can register custom commands through the API.

To connect to the remote or the serial console, use the console clients that ship with Kanzi Monitor, the RemoteConsoleClient and the SerialConsoleClient. See Using the console clients.

Platform support

The Command Processor service builds from sources on all known Kanzi target platforms.

  • The local console requires stdin/stdout access.

  • The remote console uses the Windows Sockets API on Windows and POSIX sockets on Android, Linux, and QNX.

  • The serial console uses the Windows COM port API on Windows and POSIX termios on Android, Linux, and QNX.

How the Command Processor service works

The Command Processor service operates as a pipeline:

  1. Input – A console (local or remote) reads a command string from the user.

  2. Parse – The first word is the command name, the rest is passed as arguments.

  3. Lookup – The command registry is searched for a matching command.

  4. Execute – The command handler runs and writes output to the console.

  5. Response – The console delivers the output back to the user, followed by execution time.

The service supports three console types that can run simultaneously:

  • Local console – Uses stdin and stdout for interactive terminal use. Suitable for development and testing on desktop platforms.

  • Remote console – A TCP socket server that accepts connections from the RemoteConsoleClient or any TCP client. Suitable for deployed applications, headless targets, and Android devices.

  • Serial console – A serial port (UART) connection that accepts commands from the SerialConsoleClient or any serial terminal. Suitable for embedded targets where TCP is not available, such as QNX boards, Android hardware, and Linux embedded systems.

All consoles share the same command registry. Commands registered by any service or by application code are available from all consoles.

Using the local console

The local console provides an interactive command prompt on stdin/stdout. When enabled, the console displays a welcome message and the prompt Enter Command >.

The local console is automatically disabled when Kanzi Monitor is running in Kanzi Studio Preview, because Kanzi Studio Preview does not provide stdin/stdout to plugins. The remote console remains available in Kanzi Studio Preview.

Using the remote console

The remote console is a TCP socket server that listens for incoming connections.

It serves several clients at the same time, up to RemoteConsoleMaxConnections (four by default). Running the Web UI and the MCP server against one application is an ordinary setup, and so is leaving a console open while a script runs.

Each connection is independent: every response goes back to the client that sent the command, and one client’s traffic never appears on another’s connection.

Commands themselves still run one at a time on the Kanzi main thread — never concurrently — so two clients interleave rather than race. Within one connection, commands run in the order that connection sent them.

Between connections the order is not defined. Each connection has its own reader thread, and two commands sent at the same moment reach the task dispatcher in whichever order those threads happen to be scheduled, which is not necessarily the order the bytes arrived. Two clients writing the same state will therefore overwrite each other in an order you cannot predict or rely on. If a sequence matters, send it from one connection.

What does hold across connections is cause and effect. A response’s terminator is sent only after its command’s handler has returned, so a command that one client sends after another client has received its complete response runs after that command. Waiting for the other client’s response is the way to order commands across two connections, when sending them from one connection is not an option.

A client that connects when every slot is taken is told so and disconnected:

ERROR: remote console is at its connection limit; try again when a client disconnects.

It is refused rather than queued, so a tool can report the problem instead of appearing to hang. overwatch.status reports remoteConsoleConnections and remoteConsoleMaxConnections, which is the way to check before blaming the application.

A client must keep reading its responses. Each connection has its own writer thread, so a client that stops reading — a suspended browser tab behind the Web UI, a paused debugger — does not hold up the application or the other clients: commands keep running on the Kanzi main thread, and other clients are answered as usual. While a client has more than about 1 MB of output it has not read, Monitor stops running that client’s further commands until it catches up. When a response makes no progress for 10 seconds, Monitor gives up on that connection and closes it. A slow client that is still reading is not affected. A client disconnected this way sees the connection close partway through a response, never the rest of that response followed by the next one.

Note

Before Kanzi Monitor 1.41.3 the server accepted one client at a time. A second client’s connect() still succeeded — the operating system completes the handshake — but nothing ever answered it, with no refusal and no log line. A busy console was indistinguishable from a dead application (KZMON-592).

Understanding the protocol

The remote console uses a simple line-based text protocol:

  • The client sends a command followed by a newline character (\n).

  • The server responds with one or more lines of output, terminated by an empty line (\n\n).

  • The client reads response lines until it encounters the empty terminating line.

Do not send empty commands. The server silently drops empty commands without sending a response, which causes the client to wait indefinitely for a response that never arrives. The same happens to any line beginning with a space, because the line is split at the first space and the command name comes out empty.

Send \n. Both consoles strip a trailing carriage return from 1.41.3, so \r\n works too. On 1.41.2 and earlier the remote console kept it as part of the command name, which is matched exactly, so a CRLF client got Command kzinfo\r not found.

See also

Console protocol v1 is the full wire contract — framing, request grammar, the four response shapes, the connection model, and the known defects with numbers you can cite. Read it before writing a client; the summary above is not sufficient to implement one.

Connecting with the RemoteConsoleClient

The RemoteConsoleClient, shipped with Kanzi Monitor, is a command-line client for the remote console. See Using the console clients.

Connecting with other TCP clients

Any TCP client that supports the line-based protocol can connect to the remote console.

For example, using a raw TCP connection:

telnet 127.0.0.1 56000

Using the serial console

The serial console provides command access over a serial port (UART) connection. It is designed for embedded targets where TCP networking is not available, such as QNX boards, Android hardware, and Linux embedded systems.

The serial console is disabled by default. To enable it, set SerialConsoleEnabled = 1 in the configuration file and configure the port name and baud rate.

Unlike the remote console, the serial console does not use a listen/accept pattern. Serial is point-to-point: the plugin opens the configured port and immediately begins reading commands. When the remote end disconnects, the console continues to wait for new input on the same port.

Responses are sent by a thread of their own, so a large response over a slow link does not hold up the application or the remote console’s clients. A link that is not being read is waited out rather than given up: the response is sent whole once the other end reads again. While about 1 MB or more of output is waiting to be sent, the serial console runs no further command until it has gone.

Configuring the serial console

Set the serial port and baud rate in kanzimonitor.cfg:

SerialConsoleEnabled = 1
SerialConsolePort = COM7
SerialConsoleBaudRate = 115200

On Linux, QNX, and Android, use the device path:

SerialConsolePort = /dev/ttyUSB0

The supported baud rates are: 9600, 19200, 38400, 57600, 115200, 230400, 460800. If an unsupported baud rate is configured, the console defaults to 115200 with a warning.

If the configured serial port cannot be opened (for example, the device does not exist or is in use), the application logs a warning and continues without the serial console.

Connecting with the SerialConsoleClient

The SerialConsoleClient, shipped with Kanzi Monitor, is a command-line client for the serial console. See Using the console clients.

Testing with virtual serial ports

On Windows, use com0com to create a virtual COM port pair (for example, COM7 and COM8). Configure the plugin on one port and the client on the other.

On Linux, use socat to create a virtual serial port pair:

socat -d -d pty,raw,echo=0 pty,raw,echo=0

This creates two pseudo-terminal devices (for example, /dev/pts/3 and /dev/pts/4). Configure the plugin on one and the client on the other.

Connecting to Android Emulator

The Android Studio Emulator runs on its own network within the host PC. Applications running in the emulator do not share the same localhost (127.0.0.1) as the host PC.

To connect from the host PC to a socket in the emulator, use port forwarding:

adb forward tcp:56000 tcp:56000

This maps the port of the emulator to the port of the host PC, allowing the RemoteConsoleClient to connect to 127.0.0.1:56000.

Inspecting the runtime environment

The kzinfo command displays information about the Kanzi runtime environment:

kzinfo

Example output:

Kanzi version: 2026-06-22: 4.1.0
Monitor plugin version: 1.41.3
Platform OS: Windows
GraphicsOutput: 640x480
GraphicsOutput Type: WindowedGraphicsOutput
Window Size: 640x480
NativeWindowHandle: HWND
Graphics Backend: OpenGL
Graphics API Version: 4.6
Graphics Device: Intel(R) Arc(TM) 140V GPU (16GB)
Build configuration: Release

The reported fields:

  • Kanzi Engine version – The version of the Kanzi Engine that the application is linked against.

  • Kanzi Monitor Plugin version – The version of the Kanzi Monitor that is loaded.

  • Platform OS – The detected operating system: Windows, Android, Linux, QNX, or Other.

  • GraphicsOutput – The layout area size in pixels.

  • GraphicsOutput Type – WindowedGraphicsOutput (windowed platforms) or Non-windowed (headless/offscreen). Reports “Not available” if no graphics output is present.

  • Window Size – The window size in platform-specific units (windowed outputs only).

  • NativeWindowHandle – The platform-specific window handle type: HWND (Windows), ANativeWindow* (Android), (X11) uint32_t, (Wayland), QNX screen_window_t, or Unknown.

  • Graphics Backend – The active graphics API: Vulkan, OpenGL, OpenGL ES, or Unknown.

  • Graphics API Version – The version of the active graphics API.

  • Graphics Device – The GPU device name reported by the graphics driver.

  • Build configuration – Debug, Profiling, or Release. Inferred from Kanzi build defines.

Adding custom commands

You can register custom commands through the Command Processor service API.

A command handler has this signature:

int myCommandHandler(CommandProcessingManager* commandProcessor,
                     Console* console,
                     const kanzi::string& args,
                     void* userData);

The handler receives the command processor, the console for writing output, the argument string, and optional user data. Return 0 for success.

To register a command:

KanziMonitorModule* module = getKanziMonitorModule(domain);
CommandProcessorService* service = module->getCommandProcessorService();
service->addCommand("mycommand", myCommandHandler, myUserData,
                    "Description of my command. Usage: mycommand [arg]");

For commands that accept arguments, include Usage: command [args] at the end of the help text. This convention is used by all built-in commands and helps users discover the expected arguments through the help command.

Note

A handler that throws cannot bring the application down. The command dispatch contains any exception that escapes a handler, returns a JSON error naming the command and the reason, logs a diagnostic, and still terminates the response properly. You do not have to wrap every handler in a try block to keep the host safe.

Do still validate your own input, because the contained error can only report what the exception itself said. std::stoi: invalid argument tells the caller far less than naming the argument that was rejected and what the command expected — the built-in commands report the second kind.

Prefer returning an error as data over throwing: a handler that writes its own JSON error and returns KZ_CMD_RESULT_HANDLED produces a better message than the generic one, and keeps the diagnostic out of the log.

Available commands

The built-in commands registered by the Command Processor service:

Command

Description

help

Shows available commands with their description. Usage: help [command]

kzinfo

Shows Kanzi Runtime information including engine version, platform, graphics output, GPU device, and build configuration.

perfinfo

Shows Performance information.

fpsinfo

Shows frames-per-second performance information.

meminfo

Shows Memory usage information.

resinfo

Shows Resource Manager information. Each texture is annotated with a compact descriptor showing its type, face count, dimensions, format, and mipmap levels (for example, [CubeMap 6f 512x512 R8G8B8A8_UNORM mips:10]).

graphicsinfo

Shows detailed graphics information: backend type, API version, device name, driver version, and max texture size.

purge

Purges Resources from the ResourceManager.

idlesuspend

Gets and sets MainLoop SuspendWhenIdle. Usage: idlesuspend [0|1]

fpslimit

Sets MainLoop framerate limit. Usage: fpslimit [fps]

profcats

Sets all Profiling Categories enabled state, or without an argument reports how many are enabled. Usage: profcats [0|1]

quit

Shuts down the Kanzi Engine. Not supported on Android – see the note below.

nodetreeinfo

Shows Node Tree information. Usage: nodetreeinfo [index]

fontinfo

Shows FontRuntime information for all active fonts, including font identity, style definition, glyph cache state, and node usage.

perfinfolevel

Gets and sets the PerformanceInfo level. Usage: perfinfolevel [0|1|2]

Note

On Android, the application process lifecycle is owned by the platform, not by Kanzi, so quit cannot terminate the application – ending the Kanzi main loop does not close the Android process, and leaves it running with a shut-down engine. On Android quit therefore takes no action and reports that it is not supported; the application keeps running. To exit on Android, use the platform lifecycle instead – finish the Activity, or detach all Kanzi views to release the runtime. On Windows and embedded Linux/QNX, quit shuts down the application normally.

See also

Using the Overwatch service

Using the Monitor Web UI

Configuring Kanzi Monitor