CLI‑Anything Mini Clone

A tiny Python CLI harness for running arbitrary commands

Welcome to another official UVF IT build series! In this guide we’ll craft a minimal command‑line tool inspired by the CLI‑Anything project, letting you invoke any shell command from a Python wrapper.

You’ll have a working prototype in under 45 minutes using only Python’s standard library—no external APIs or paid services required.

Before you start

Mini CLI‑Anything Architecture
LOCAL RUNTIME executes reads (optional) cli_mini.py Python entry point System Shell config.json optional defaults
1

Phase 1: Scaffold the project

First, spin up a clean folder for your clone so everything stays tidy. Inside that folder we’ll create a Python virtual environment – this isolates our dependencies and mirrors real‑world projects. With the environment active we install Click, the only third‑party library we need for parsing command‑line arguments.

Having a reproducible setup makes the later steps painless and ensures anyone can run your tool with the same versions you used.

mkdir cli_mini_clone && cd cli_mini_clone
python3 -m venv .venv
source .venv/bin/activate  # on Windows use `.venv\Scripts\activate`
pip install --upgrade pip
pip install click
2

Phase 2: Core – command execution model

Now we add the heart of the clone: a helper that runs an arbitrary shell command and returns its output. The function uses Python’s subprocess module, captures stdout and stderr, and raises a clear exception if the command fails – this mirrors how CLI‑Anything reports errors to the user.

We also expose a simple Click command that forwards whatever you type to this helper, making the tool usable from the terminal with a single entry point.

cli_mini.py

import subprocess
import click

def run_shell(command: str) -> str:
    """Execute *command* in the system shell.
    Returns stdout; on error raises ClickException with stderr.
    """
    try:
        result = subprocess.run(
            command,
            shell=True,
            check=True,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True,
        )
        return result.stdout.strip()
    except subprocess.CalledProcessError as e:
        raise click.ClickException(e.stderr.strip())

@click.command(context_settings={"ignore_unknown_options": True, "allow_extra_args": True})
@click.argument('cmd', nargs=-1, type=click.UNPROCESSED)
def cli(cmd):
    """Pass any command line to the system shell.
    Example: `python cli_mini.py ls -l /tmp`
    """
    command_str = " ".join(cmd)
    output = run_shell(command_str)
    click.echo(output)

if __name__ == "__main__":
    cli()
3

Phase 3: API – Click‑based CLI wrapper

In this step we expose the tiny runner we built earlier through a Click command line interface. Click will handle parsing, help text, and forwarding any extra arguments straight to the underlying shell runner. By keeping the wrapper thin we preserve the original project's simplicity while gaining a polished entry point.

We also add a small `if __name__ == '__main__' guard so the file can be executed directly. The @click.command decorator registers the function, and click.argument('cmd', nargs=-1)` captures an arbitrary number of arguments, which we join into a single shell command string.

cli_mini.py

import subprocess
import sys
import click

def run_command(command: str) -> int:
    """Execute *command* in the user's shell and stream output.
    Returns the exit code so Click can propagate it.
    """
    # Use shell=True to allow complex commands, pipelines, etc.
    process = subprocess.Popen(command, shell=True)
    process.communicate()
    return process.returncode

@click.command(context_settings={'ignore_unknown_options': True, 'allow_extra_args': True})
@click.argument('cmd', nargs=-1, type=click.UNPROCESSED)
def cli(cmd):
    """Mini CLI‑Anything wrapper.
    All arguments after the command name are passed directly to the shell.
    Example: ``./cli_mini.py echo hello`` prints ``hello``.
    """
    if not cmd:
        click.echo('No command provided. Use --help for usage.', err=True)
        sys.exit(1)
    command_str = ' '.join(cmd)
    exit_code = run_command(command_str)
    sys.exit(exit_code)

if __name__ == '__main__':
    cli()
4

Phase 4: Run locally

Now that the CLI entry point exists we make the file executable and give it a quick sanity test. On Unix‑like systems the shebang line is optional because we invoke the script with `python`; however adding execute permission lets us run it like any native command.

We’ll try a simple `echo` to verify that arguments are correctly forwarded and that the output appears on stdout without any extra noise.

chmod +x cli_mini.py
# Test with a basic echo command
./cli_mini.py echo Hello, UVF IT!
5

Phase 5: Verify & extend

Check the terminal output – you should see `Hello, UVF IT! printed exactly as passed to echo. If the output matches, the wrapper is correctly forwarding arguments and handling exit codes. From here you can start adding sub‑commands (e.g., config or run`) or enrich the runner with a JSON/YAML configuration file for reusable command templates.

Extending is straightforward: define additional `@click.command functions and register them with a Click Group. The core run_command` helper stays unchanged, keeping the implementation DRY and easy to maintain.

# Verify that a non‑trivial command works, e.g., list files
./cli_mini.py ls -1
# Example of adding a sub‑command later (just a placeholder comment)
# click.group()(cli)
# @cli.command()
# def config():
#     click.echo('Config sub‑command placeholder')

Verifying the Stack

CheckCommand / Why it matters
Virtual environment activatedPrompt shows (.venv) after source .venv/bin/activate
CLI prints expected output./cli_mini.py echo test outputs test
No traceback on valid command./cli_mini.py ls (or dir on Windows) lists directory without error

You did it!

Your mini CLI‑Anything clone is now ready. Feel free to package it, add more commands, or integrate it with the real CLI‑Hub. Happy hacking!