cmdo banner

cmdo

cmdo ("commando") is a command-line tool which runs multiple commands in parallel.

A common problem when working with microservices is the need to run multiple applications in unison when developing locally; often using different languages and frameworks.

Existing solutions like Docker Compose exist, however, come with the overhead of creating and using Docker containers. Additionally, local development features such as hot-reloading can prove hard to implement when relying on containerisation.

command view

Features

cmdo provides a simple configuration-driven approach to running services in parallel without the need for containerisation. The key features currently provided are:

  • Run multiple commands in different working directories in parallel
  • Stdout/stderr output view
  • Web output view (see below)
  • Easily include and exclude different commands at runtime using tags

Web view

The cmdo has an optional web view for displaying command stdout and stderr output. This web view provides the following additional capabilities:

  • Command grid view
  • Inline unified command view
  • Global log searching and command-specific log searching

terminal view

Usage

Supply a configuration file containing different commands you want to execute in parallel

Installation

The simplest way to use and stay up to date with the latest version of cmdo is to retrieve the latest version via a go installation.

This automatically adds it to your path for use:

go install github.com/ryanachten/cmdo@main # install latest from main branch
cmdo --config .\example-config.json # use cmdo!

Release builds

If you prefer using prebuilt executables, the latest release can be downloaded from GitHub.

You'll need to add this to your path yourself and download the latest release to receive updates.

unified view

Arguments

cmdo --config .\example-config.json --tags backend --exclusions EnsembleApi --web=false
commandrequiredtypedefaultdescription
--configtruestringpoints to a configuration file using the schema below
--tagsfalsestring[][]when defined, only commands with supplied tags in configuration will be run
--exclusionsfalsestring[][]when defined, only commands without supplied name will be run
--webfalsebooltrueopts out of web view and only outputs using stdout and stderror

Configuration

The configuration file must conform to the following API:

  commands: {
    name: string, // label to be presented in the UI
    executable: string, // command to to be executed
    arguments: string[], // arguments to be passed to the command
    workingDirectory: string, // working directory where the command should be executed
    tags?: string[] // (optional) tags used to include exclude commands
  }[],

Examples

Examples of different configuration can be found in the examples directory.

One example using the ensemble project is as follows:

{
  "commands": [
    {
      "name": "EnsembleFrontend",
      "executable": "yarn",
      "arguments": ["run", "dev"],
      "workingDirectory": "C:\\dev\\ensemble\\client",
      "tags": ["frontend"]
    },
    {
      "name": "EnsembleApi",
      "executable": "go",
      "arguments": ["run", "."],
      "workingDirectory": "C:\\dev\\ensemble\\api",
      "tags": ["backend"]
    }
  ]
}

Development

Architecture

cmdo model

cmdo is comprised of two main parts; a command runner (commander in the diagram above), which executes a terminal process for each command the configuration.

The command output is piped is broadcasted via the webserver using websockets and piped to stdout/stderr. Commands can be individually stopped or started via the web view and the REST API, the resulting state update is then broadcasted via websockets. The command state and log history is also stored and served via a REST API so it can be persisted on page refresh.

A web app listening to websocket and REST API endpoints is served by cmdo. This intentionally uses a no-build process to keep the dev experience simple. Preact, JS modules, JSDoc and CSS imports are used in favour of alternatives requiring a frontend build step. The web app provides different view and searching capabilities not found in the CLI tool alone.

Prerequisites

  • Go installed locally (>v1.21)

Running locally

# from project root directory
go run . --config .\examples\ensemble.cmdo.json