CLI-Anything Software-Specific Backends: Blender, OBS-WebSocket, Python, and QGIS

CLI-Anything supports four software-specific backends—Blender (bpy), OBS-WebSocket (obs-websocket), generic Python (py), and QGIS—that translate uniform CLI commands into native API calls for each target application.

CLI-Anything, developed by HKUDS, is an open-source framework that exposes complex desktop and server applications through a standardized command-line interface. The project achieves this abstraction through software-specific backends, which are Python modules that handle process spawning, IPC channel management, and API translation. Each backend implements a consistent protocol in the HKUDS/CLI-Anything repository, allowing AI agents and users to interact with diverse software without learning individual native APIs.

Overview of Supported Software-Specific Backends

CLI-Anything currently ships with four dedicated backends, each targeting a specific software ecosystem. The following table summarizes how each backend connects to its target application and where the implementation resides in the source tree.

Backend Target Application Implementation File Selection Method
Blender (bpy) Blender's embedded Python interpreter cli_anything/blender/utils/blender_backend.py --backend bpy or auto-detection
OBS-WebSocket OBS Studio via obs-websocket plugin (v5) cli_anything/obs_studio/utils/obs_backend.py --backend obs-websocket
Python (py) Arbitrary Python scripts and libraries cli_anything/python/utils/python_backend.py --backend py (default)
QGIS QGIS Python API (qgis.core, qgis.gui) cli_anything/qgis/utils/qgis_backend.py --backend qgis

Each backend module is responsible for locating its target software, establishing the necessary communication channel (whether it is Blender's bpy module, a WebSocket connection, or a headless QGIS process), and mapping generic CLI verbs to native API operations.

How Backend Selection Works

Backend discovery and selection are centralized in cli_anything/common/runtime.py through the RuntimeContext class. When you invoke a CLI-Anything command, the system follows this resolution flow:

  1. Explicit selection: The --backend flag accepts auto, bpy, obs-websocket, py, or qgis
  2. Auto-detection: If set to auto, RuntimeContext.detect_backend() iterates through known backends and calls each module's is_available() method
  3. First match wins: The first backend returning True (indicating the target software is installed and reachable) becomes the active backend

The entry point in cli_anything/<software>/<software>_cli.py (e.g., blender_cli.py) exposes this flag:

@click.command()
@click.option(
    "--backend",
    type=click.Choice(["auto", "bpy", "obs-websocket", "py", "qgis"]),
    default="auto",
)
def cli(backend, ...):
    if backend == "auto":
        backend = RuntimeContext.detect_backend()
    ctx = RuntimeContext(backend=backend, ...)

Every backend implements a uniform protocol consisting of is_available(), run_command(), and cleanup() methods, allowing the generic harness to treat them interchangeably.

Blender (bpy) Backend

The Blender backend provides direct access to Blender's scene graph, objects, materials, and rendering capabilities through the embedded bpy Python module. When selected, cli_anything/blender/utils/blender_backend.py launches a headless Blender process and exposes operations like render, object list, and material create.

Key implementation details:

Usage example:


# Render a scene using the bpy backend

cli-anything ./blender --backend bpy render --output scene.png

What happens: The backend starts a headless Blender interpreter and executes bpy.ops.render.render(write_still=True, filepath="scene.png").

OBS-WebSocket Backend

The OBS-WebSocket backend controls OBS Studio remotely via the obs-websocket plugin (WebSocket v5 protocol). Implemented in cli_anything/obs_studio/utils/obs_backend.py, this backend manages scene switching, source manipulation, and streaming state by sending JSON requests to ws://localhost:4455.

Key implementation details:

Usage example:


# Switch to the "Gameplay" scene

cli-anything ./obs-studio --backend obs-websocket scene switch --name Gameplay

What happens: The backend opens a WebSocket connection and sends the JSON request { "request-type": "SetCurrentScene", "scene-name": "Gameplay" }.

Python (py) Backend

The Python backend serves as the generic fallback when no dedicated backend exists for a target application. Located in cli_anything/python/utils/python_backend.py, this backend loads user-provided Python modules and introspects public functions, generating thin wrapper commands that forward CLI arguments to Python function calls.

Key implementation details:

Usage example:


# Execute a function from a custom module

cli-anything ./my-tool --backend py --module ./my_tool.py add --a 5 --b 7

What happens: The backend imports my_tool.py, discovers the add function, and invokes add(a=5, b=7).

QGIS Backend

The QGIS backend enables scripting of geographic information systems through the QGIS Python API (qgis.core and qgis.gui). Implemented in cli_anything/qgis/utils/qgis_backend.py, it searches for QGIS installations via the QGIS_PREFIX_PATH environment variable or standard install locations, then spawns a headless QGIS process to handle layer management, processing algorithms, and map exports.

Key implementation details:

Usage example:


# Export the current project to PDF

cli-anything ./qgis --backend qgis project export --format pdf --output map.pdf

What happens: The backend spawns a headless QGIS instance, loads the active project, and executes QgsProject.instance().write() with the appropriate PDF driver.

Backend Architecture and Protocol

All software-specific backends in CLI-Anything conform to a lightweight protocol defined in the runtime system. This standardization ensures that the CLI harness in cli_anything/common/runtime.py can initialize and invoke any backend without software-specific logic.

The three required methods:

  1. is_available(): Returns True if the target software is installed and ready for communication
  2. run_command(command, **kwargs): Executes the native API call and returns standardized results
  3. cleanup(): Releases resources, closes sockets, and terminates spawned processes

This architecture allows CLI-Anything to treat Blender's bpy module, OBS Studio's WebSocket API, and QGIS's processing algorithms as interchangeable command targets, abstracting implementation differences behind a uniform command-line surface.

Summary

  • CLI-Anything provides software-specific backends for Blender, OBS-WebSocket, Python, and QGIS, located in cli_anything/<software>/utils/<software>_backend.py.
  • Backend selection uses the --backend flag or RuntimeContext.detect_backend() auto-detection logic in cli_anything/common/runtime.py.
  • Each backend implements is_available(), run_command(), and cleanup() to provide uniform interaction with native APIs.
  • Blender (bpy) offers direct scene manipulation via the embedded Python interpreter.
  • OBS-WebSocket controls streaming software via WebSocket v5 protocol on port 4455.
  • Python (py) serves as the generic backend for arbitrary Python modules and functions.
  • QGIS enables geospatial scripting through headless QGIS processes with full access to qgis.core.

Frequently Asked Questions

How does CLI-Anything automatically detect which backend to use?

When you run a command without specifying --backend, CLI-Anything invokes RuntimeContext.detect_backend() from cli_anything/common/runtime.py. This method iterates through the list of known backends (bpy, obs-websocket, py, qgis), imports each module, and calls its is_available() method. The first backend returning True is selected automatically, making the tool work out-of-the-box when target software is installed.

Can I use the Python backend to wrap any arbitrary Python library?

Yes. The Python backend (cli_anything/python/utils/python_backend.py) is designed as a generic fallback. Use --module <path> to specify your Python file, and CLI-Anything introspects all public functions, creating CLI commands that map directly to function signatures. This allows you to expose any Python API—whether standard library, third-party package, or custom code—through a uniform command-line interface without writing a dedicated backend.

What is required for the OBS-WebSocket backend to function?

The OBS-WebSocket backend requires OBS Studio with the obs-websocket plugin (version 5) installed and enabled. The backend attempts to connect to ws://localhost:4455 to verify availability. If OBS Studio is running and the WebSocket server is active on that port, the backend can switch scenes, control sources, and manage streaming state remotely.

How does the QGIS backend locate the QGIS installation?

The QGIS backend (cli_anything/qgis/utils/qgis_backend.py) checks the QGIS_PREFIX_PATH environment variable first. If not set, it probes standard installation locations for QGIS binaries and Python libraries. Once located, it launches a headless QGIS process that imports qgis.core and qgis.gui, enabling CLI commands to manipulate layers, run processing algorithms, and export maps without opening the QGIS GUI.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →