Configuration driven CLI builder with subcommands and script loading
Project description
Sigil
Declarative argparse, without the CLI boilerplate.
Sigil is a lightweight, declarative CLI framework for Python. Define your command tree in YAML (or any other format), and sigil builds the argparse parser on the fly. Complete with subcommands and dynamic script loading.
It plays nicely with argcomplete out of the box.
Features
- Declarative command hierarchies (parents, subparsers, defaults)
- Each command can point to a dynamically imported Python script
argcompleteintegration for tab‑completion- Pluggable data sources – YAML is the default, but JSON, TOML, or a dict are trivial to swap in
- No boilerplate argparse code in your main logic
The alternatives
There are plenty of established options out there. Click and Typer are great libraries with their own approaches.
Sigil takes a different path, focusing on reducing boilerplate while keeping your command structure modular and flexible.
Quick Start
Install
pip install sigil-cli
or include argcomplete
pip install sigil-cli[completion]
0. Recommended file structure
project_root/
├── mycli.py # drop‑in entry script (alias this)
├── manifest.yml # lists all YAML config files to load
├── yml/
│ ├── root.yml # root command definition
│ ├── root_run.yml # subcommand definition(s)
│ └── ...
└── scripts/
├── run.py # implements the 'run' command
└── ... # other scripts
1. Entry script
Create mycli.py:
#!/usr/bin/env python3
from pathlib import Path
from sigil import run_from_config
if __name__ == "__main__":
run_from_config(Path(__file__).parent)
2. Configuration files
List all your YAML definitions in manifest.yml:
- root.yml
- root_run.yml
Define the root command in root.yml:
root:
name: mycli
script_dir: scripts
Define a subcommand in root_run.yml:
root_run:
name: run
parent: root
help: command utility to run containers
script: run
args:
- help: port to run, autoincrements from 8080
name:
- -p
- --port
3. Write the script
Create scripts/run.py:
import argparse
from typing import Any
def run(args: argparse.Namespace, ctx: dict[str, Any]) -> None:
port = getattr(args, "port", 8080)
port = find_next_free_port_logic(port)
print(f"Running container on port {port}")
4. Run it
chmod +x mycli.py
./mycli.py run --port 9000
# Running container on port 9000
./mycli.py run
# Running container on port 8080
./mycli.py run
# Running container on port 8081
Configuration Reference
Root
| Field | Description |
|---|---|
name |
Program name (used as prog in argparse) |
script_dir |
Directory (relative to the config root) where command scripts are located |
Command
| Field | Description |
|---|---|
name |
Subcommand name |
parent |
Parent command (must exist elsewhere in a config) |
help |
Help text for this subcommand |
script |
Python module name (without .py) inside script_dir or as absolute path |
args |
List of argument definitions (see below) |
default |
If true, this subcommand is used when no subcommand is given |
| any other parser kwarg | except for dest and formatter_class they are all supported |
Note that parent does not refer to argparse's parent parameter but is only used to resolve the parser tree. Parser (multi-)inheritance isn't supported but can be emulated by adding arguments to this command's parents in the tree.
Argument
Each argument entry can be a plain dict which maps 1-to-1 with argparse add_argument, except name which maps it's *args
- name: ["-p", "--port"] # or a single string, e.g. "positional"
required: false
default: 8069
help: "port number"
Groups and mutex groups are also suppored via the "kind" parameter (defaults to argument)
# mutex group
- kind: mutex
args:
- <any recursive args/group/mutex construct here>
...
... # any valid mutex group arguments go here
- kind: group
... # same
The name field can be --flag for flags or a string for positional arguments.
Both literal string and list of strings are supported.
Tab‑Completion (argcomplete)
Sigil registers itself with argcomplete automatically if available on your system.
To enable completion, install argcomplete and activate it for your entry script:
pip install argcomplete
activate-global-python-argcomplete
Then run your script and hit Tab – subcommands and flags will complete.
Pluggable Backends
Sigil uses yaml by default, but you can supply any loader that returns a dict[str, ParserConfig]:
from sigil import run_from_config
# Use JSON instead:
class JsonReader:
@classmethod
def load(cls, config_root):
# read *.json, parse, convert to dict of ParserConfig
...
run_from_config("/path/to/config", loader_class=JsonReader)
You can also pass a pre‑loaded dictionary directly by wrapping it:
run_from_config(my_dict, loader_class=DictLoader)
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sigil_cli-1.1.1.tar.gz.
File metadata
- Download URL: sigil_cli-1.1.1.tar.gz
- Upload date:
- Size: 18.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0dbd0a8fc692171b061b8cabaf3c4dde6511cce9bbed7bb274f8100745be3d1e
|
|
| MD5 |
ea993157e2a4e8196edc0b8608e1ccd3
|
|
| BLAKE2b-256 |
d9f0a975b96a8d7bb665af6cdb042ee2fab8b445a89ffc8c66f196f85fe447eb
|
Provenance
The following attestation bundles were made for sigil_cli-1.1.1.tar.gz:
Publisher:
publish.yml on kenzo-staelens/sigil
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sigil_cli-1.1.1.tar.gz -
Subject digest:
0dbd0a8fc692171b061b8cabaf3c4dde6511cce9bbed7bb274f8100745be3d1e - Sigstore transparency entry: 2207313647
- Sigstore integration time:
-
Permalink:
kenzo-staelens/sigil@6720c32c404e0a0aa43d5798c8a24e801913cbce -
Branch / Tag:
refs/tags/v1.1.1 - Owner: https://github.com/kenzo-staelens
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6720c32c404e0a0aa43d5798c8a24e801913cbce -
Trigger Event:
release
-
Statement type:
File details
Details for the file sigil_cli-1.1.1-py3-none-any.whl.
File metadata
- Download URL: sigil_cli-1.1.1-py3-none-any.whl
- Upload date:
- Size: 15.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5a5e8ba4c27a71a12b84c75b5f57ea9d1cc6a444aceb17e5ad686cfc43c4ebbb
|
|
| MD5 |
e63474d803d907efc0d69e564473fad0
|
|
| BLAKE2b-256 |
97c9333ec795d1d0a0ba6c102299c3a936d4d1605a9f79afc89d02047d88c1f2
|
Provenance
The following attestation bundles were made for sigil_cli-1.1.1-py3-none-any.whl:
Publisher:
publish.yml on kenzo-staelens/sigil
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sigil_cli-1.1.1-py3-none-any.whl -
Subject digest:
5a5e8ba4c27a71a12b84c75b5f57ea9d1cc6a444aceb17e5ad686cfc43c4ebbb - Sigstore transparency entry: 2207313667
- Sigstore integration time:
-
Permalink:
kenzo-staelens/sigil@6720c32c404e0a0aa43d5798c8a24e801913cbce -
Branch / Tag:
refs/tags/v1.1.1 - Owner: https://github.com/kenzo-staelens
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6720c32c404e0a0aa43d5798c8a24e801913cbce -
Trigger Event:
release
-
Statement type: