Skip to main content

cliss — A lightweight framework for building CLI applications on top of argparse

Project description

cliss — A lightweight framework for building CLI applications on top of argparse

Python PyPI License Platform Ruff

Write type-annotated Python functions, get a full CLI — automatic --help, validation, and async support with zero dependencies.

✨ Features

  • 🪶 Zero Dependencies — Pure stdlib: argparse, asyncio, inspect
  • 🏷️ Type-Driven — Automatic arguments from function signatures and type hints
  • 🧩 Flexible — Declarative Argument objects, type inference, or both
  • ⚡ Async-Nativeasync def handlers with automatic event loop management
  • 🌍 Global Args — Define flags shared across all commands
  • 🔧 argparse Access — Full access to underlying parsers for advanced use

🚀 Quick Start

Prerequisites

  • Python 3.9+

Installation

pip install cliss

Via uv

uv pip install cliss

Via pipx (isolated environment)

pipx install cliss

From source (development)

git clone https://github.com/yourusername/cliss.git && cd cliss

pip

pip install .

uv

uv pip install .

pipx

pipx install .

Usage

from cliss import CLI

cli = CLI(name="todo", description="Task manager", version="1.0.0")

@cli.command()
def add(task: str, priority: int = 1, done: bool = False):
    """Add a new task."""
    status = "✓" if done else "○"
    return f"[{status}] {task} (priority: {priority})"

if __name__ == "__main__":
    cli.run()
$ python todo.py add "Buy milk" --priority 2
[] Buy milk (priority: 2)
$ python todo.py add "Call mom" --done --priority 3
[] Call mom (priority: 3)

📋 Commands

CLI class

CLI(name="myapp", description="...", version="1.0.0", auto_help=True)
Parameter Type Default Description
name str Program name in help output
description str Description in help output
version str Adds --version flag
auto_help bool True Adds --help flag

Argument class

Argument("--output", "-o", type=str, default=None, help="...", required=False, choices=["a","b"], action="store_true")
Parameter Type Default Description
*flags str Argument flags (e.g., --output, -o)
type type str Value type for coercion
default Any None Default value
help str "" Help text
required bool False Make argument required
choices list Restrict allowed values
action str argparse action (store_true, etc.)

Type → CLI Mapping

Function Signature CLI Argument
name: str Positional name
count: int = 1 --count with type int, default 1
verbose: bool = False --verbose flag (store_true)
quiet: bool = True --quiet flag (store_false)

📖 Examples

CRUD Application

from cliss import CLI

cli = CLI(name="db", description="Key-value store")
db = {}

@cli.command()
def set(key: str, value: str):
    """Store a value."""
    db[key] = value
    return f"OK: {key} = {value}"

@cli.command()
def get(key: str):
    """Retrieve a value."""
    return db.get(key, "Not found")

@cli.command()
def delete(key: str, force: bool = False):
    """Delete a key."""
    if force or key in db:
        db.pop(key, None)
        return f"Deleted: {key}"
    return f"Not found: {key} (use --force)"

cli.run()

Explicit Arguments

from cliss import CLI, Argument

cli = CLI(name="convert")

@cli.command(arguments=[
    Argument("input", help="Input file"),
    Argument("--output", "-o", default="out.txt"),
    Argument("--format", "-f", choices=["json", "csv"], default="json")
])
def convert(input: str, output: str = "out.txt", format: str = "json"):
    """Convert file format."""
    return f"{input} -> {output} [{format}]"

Async Handler

@cli.command()
async def fetch(url: str, retries: int = 3):
    """Fetch data asynchronously."""
    return f"Fetched {url} (retries: {retries})"

Global Arguments

cli = CLI(name="myapp")
cli.add_global_argument("--verbose", "-v", action="store_true")

@cli.command()
def status(verbose: bool = False):
    return "Detailed status..." if verbose else "OK"
$ myapp --verbose status
Detailed status...

📁 Project Structure

cliss/
├── cliss/
│   └── __init__.py      # CLI, Argument classes
├── pyproject.toml       # Project metadata
├── README.md            # Documentation
└── LICENSE              # MIT License

🔧 Requirements

Dependency Purpose
Python 3.9+ Type hints, inspect.signature

No external dependencies — stdlib only.

❓ FAQ

Why cliss when argparse already works?

argparse is powerful but verbose. A simple app with 3 commands can easily require 100+ lines of parser setup. cliss reduces this to type-annotated functions — the boilerplate is inferred, not written.

What about Click/Typer/Fire?

Tool Dependencies Style
cliss 0 (stdlib) Decorators + type hints
Click Click Decorators
Typer Click, typing-extensions Type hints
Fire 0 (stdlib) Introspection

cliss sits between Fire (zero-config, no validation) and Typer (rich features, heavy deps). It gives you type-driven CLI generation with argparse-compatible control, all in ~200 lines.

Can I use argparse features directly?

Yes. cli.parser and cli.subparsers are standard argparse objects. Add custom actions, mutually exclusive groups, or parent parsers as needed.

Does it support nested commands?

For subcommand groups, access cli.subparsers directly or use dotted command names:

@cli.command(name="compute:start")
def start(instance: str):
    return f"Starting {instance}"

How does async work?

If the command handler is async def or returns a coroutine, cliss automatically runs it with asyncio.run(). No manual event loop setup needed.

🐛 Troubleshooting

Issue Solution
Arguments not appearing Check that explicit Argument objects' dest matches parameter names
Bool flag inverted bool = Falsestore_true, bool = Truestore_false
Type coercion fails argparse error message shown automatically
Subcommand not found Verify command name: func.__name__ with _- unless overridden

📄 License

MIT License — see LICENSE file.

🙏 Acknowledgments

  • argparse — The foundation this is built on

Author: Fkernel653 Repository: github.com/Fkernel653/cliss PyPI: pypi.org/project/cliss

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cliss-0.1.1.tar.gz (7.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cliss-0.1.1-py3-none-any.whl (7.4 kB view details)

Uploaded Python 3

File details

Details for the file cliss-0.1.1.tar.gz.

File metadata

  • Download URL: cliss-0.1.1.tar.gz
  • Upload date:
  • Size: 7.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for cliss-0.1.1.tar.gz
Algorithm Hash digest
SHA256 47198ed7a4b5bedbbda090fea38e646d140ff896477be3a7be271f580eed4436
MD5 e21e9a6ffa16c1df8d7aa29a0c0f47a3
BLAKE2b-256 415c2b2223910efe43f271612b536bc45a132148b33337248e88c9ed807ad4f6

See more details on using hashes here.

File details

Details for the file cliss-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: cliss-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 7.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for cliss-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f18579aed476be85d7671b866c76032f5d1ef57130ebd0759986cc07a3ecd14f
MD5 1135193bfb86377750734dcd7c702d1e
BLAKE2b-256 6b3712a1d21ccc523aa56b93e298e32d36adc5d54051cb00c2820bc1539f36e9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page