{"id":50510973,"url":"https://github.com/elo-enterprises/shil","last_synced_at":"2026-06-02T20:06:54.113Z","repository":{"id":189829541,"uuid":"650808869","full_name":"elo-enterprises/shil","owner":"elo-enterprises","description":"Parser/formatter/pprinter for shell code","archived":false,"fork":false,"pushed_at":"2025-08-06T05:19:53.000Z","size":176,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-17T17:32:46.662Z","etag":null,"topics":["python","shell"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/elo-enterprises.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-06-07T21:20:27.000Z","updated_at":"2025-08-06T05:19:56.000Z","dependencies_parsed_at":"2025-08-06T07:07:26.897Z","dependency_job_id":"b3051d53-ed3f-45d5-94fe-88f43a8f4ebe","html_url":"https://github.com/elo-enterprises/shil","commit_stats":null,"previous_names":["elo-enterprises/shil","elo-enterprises/schelp"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/elo-enterprises/shil","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elo-enterprises%2Fshil","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elo-enterprises%2Fshil/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elo-enterprises%2Fshil/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elo-enterprises%2Fshil/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/elo-enterprises","download_url":"https://codeload.github.com/elo-enterprises/shil/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elo-enterprises%2Fshil/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33834049,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-02T02:00:07.132Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["python","shell"],"created_at":"2026-06-02T20:06:53.446Z","updated_at":"2026-06-02T20:06:54.098Z","avatar_url":"https://github.com/elo-enterprises.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd colspan=2\u003e\n      \u003cstrong\u003eshil\u003c/strong\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\n      \u003ca href=https://pypi.org/project/shil\u003e\u003cimg src=\"https://img.shields.io/pypi/l/shil.svg\"\u003e\u003c/a\u003e\n      \u003ca href=https://pypi.org/project/shil\u003e\u003cimg src=\"https://badge.fury.io/py/shil.svg\"\u003e\u003c/a\u003e\n      \u003ca href=\"https://github.com/elo-enterprises/shil/actions/workflows/python-publish.yml\"\u003e\u003cimg src=\"https://github.com/elo-enterprises/shil/actions/workflows/python-publish.yml/badge.svg\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/elo-enterprises/shil/actions/workflows/python-test.yml\"\u003e\u003cimg src=\"https://github.com/elo-enterprises/shil/actions/workflows/python-test.yml/badge.svg\"\u003e\u003c/a\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd width=15%\u003e\u003cimg src=https://raw.githubusercontent.com/elo-enterprises/shil/master/img/icon.png style=\"width:150px\"\u003e\u003c/td\u003e\n    \u003ctd\u003e\n      Shell-util library for python.  \u003cbr/\u003e\n      Includes helpers for subprocess invocation, shell-formatters / pretty-printers, and more.\n      \u003cbr/\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n---------------------------------------------------------------------------------\n\n\u003cdiv class=\"toc\"\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"#overview\"\u003eOverview\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#features\"\u003eFeatures\u003c/a\u003e\u003cul\u003e\n\u003cli\u003e\u003ca href=\"#shell-formatters-pretty-printers\"\u003eShell-formatters / pretty-printers\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#subprocess-invocation\"\u003eSubprocess Invocation\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#installation\"\u003eInstallation\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#usage-cli\"\u003eUsage (CLI)\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#usage-api\"\u003eUsage (API)\u003c/a\u003e\u003cul\u003e\n\u003cli\u003e\u003ca href=\"#oop-style-dispatch\"\u003eOOP-style Dispatch\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#functional-approach-to-dispatch\"\u003eFunctional approach to dispatch\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#loading-data-when-command-output-is-json\"\u003eLoading data when command-output is JSON\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#serialization-with-pydantic\"\u003eSerialization with Pydantic\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#caller-determines-logging\"\u003eCaller determines logging\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#rich-console-support\"\u003eRich-console Support\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#stay-dry-with-runners\"\u003eStay DRY with Runners\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\n\n---------------------------------------------------------------------------------\n\n## Overview\n\nThe `shil` library provides various shell-utilities for python.\n\n-------------------------------------------------------------------------------\n\n## Features\n\n### Shell-formatters / pretty-printers\n\n* A somewhat usable parser / grammar for bash\n* Console support for [rich](https://rich.readthedocs.io/en/stable/index.html) \u0026 [rich protocols](https://rich.readthedocs.io/en/stable/protocol.html)\n\n### Subprocess Invocation\n\nThere's a lot of shell-related libraries out there, especially for invocation (see for example [this list](https://www.pyinvoke.org/prior-art.html)).\nThe interface for `shil` is hopefully unsurprising, and something that's convenient but not fancy.  It's a utility, and not a huge framework.\n\nThe main goal is to provide an API that is simple and stable, without a ton of dependencies.\n\n```pycon\n\u003e\u003e\u003e import shil\n\u003e\u003e\u003e proc = shil.invoke('echo hello world')\n\u003e\u003e\u003e assert proc.succeeded\n\u003e\u003e\u003e assert proc.stdout.strip()=='hello world'\n\u003e\u003e\u003e\n```\n\nBeyond such basics, shil includes support for [rich output](#) and uses pydantic for datastructures.\n\nSee the [API docs](#usage-api) for more detailed information.\n\n\n---------------------------------------------------------------------------------\n\n## Installation\n\nSee [pypi](https://pypi.org/project/shil/) for available releases.\n\n```bash\n$ pip install shil\n```\n\n---------------------------------------------------------------------------------\n\n## Usage (CLI)\n\nThe shil library publishes a small CLI tool, mostly just for testing \u0026 demoing the API behaviour. See [the CLI docs](docs/cli/) for the latest (autogenerated) help.\n\n-------------------------------------------------------------------------------\n\n## Usage (API)\n\nSee also:\n\n* [the unit-tests](tests/units) for some examples of library usage\n* [the smoke-tests](tests/smoke/test.sh) for example usage of stand-alone scripts\n\n### OOP-style Dispatch\n\nThis uses `shil.Invocation` and returns `shil.InvocationResponse`.\n\n```pycon\n\u003e\u003e\u003e import shil\n\u003e\u003e\u003e req = cmd = shil.Invocation(command='printf hello-world\\n')\n\u003e\u003e\u003e resp = cmd()\n\u003e\u003e\u003e print(resp.stdout)\nhello-world\n\u003e\u003e\u003e\n```\n\n### Functional approach to dispatch\n\nUse `shil.invoke`, get back `shil.InvocationResponse`\n\n```pycon\n\u003e\u003e\u003e import shil\n\u003e\u003e\u003e resp = shil.invoke(command='printf hello-world\\n')\n\u003e\u003e\u003e print(resp.stdout)\nhello-world\n\u003e\u003e\u003e\n```\n\n### Loading data when command-output is JSON\n\n```pycon\n\u003e\u003e\u003e import shil\n\u003e\u003e\u003e cmd = shil.Invocation(command=\"\"\"echo '{\"foo\":\"bar\"}'\"\"\", load_json=True)\n\u003e\u003e\u003e resp = cmd()\n\u003e\u003e\u003e print(resp.data)\n{'foo': 'bar'}\n\u003e\u003e\u003e assert type(resp.data) == type({})\n\u003e\u003e\u003e assert resp.data['foo'] == 'bar'\n\u003e\u003e\u003e\n```\n\n### Serialization with Pydantic\n\n```pycon\n\u003e\u003e\u003e import json, shil\n\u003e\u003e\u003e req = cmd = shil.Invocation(command=\"\"\"echo pipes-are-allowed|grep allowed\"\"\")\n\u003e\u003e\u003e resp = cmd()\n\u003e\u003e\u003e keys = resp.dict().keys()\n\u003e\u003e\u003e expected = 'stdout stderr failed failure success succeeded data'.split()\n\u003e\u003e\u003e assert all([k in keys for k in expected])\n\u003e\u003e\u003e\n```\n\n### Caller determines logging\n\nWorks like this with basic logger:\n\n```pycon\n\u003e\u003e\u003e import logging, shil\n\u003e\u003e\u003e logger = logging.getLogger()\n\u003e\u003e\u003e resp = shil.invoke('ls /tmp', command_logger=logger.critical, output_logger=logger.warning)\n\u003e\u003e\u003e\n```\n\nSupports using [rich-logger](https://rich.readthedocs.io/en/stable/logging.html) too:\n\n```pycon\n\u003e\u003e\u003e import shil\n\u003e\u003e\u003e from rich.console import Console\n\u003e\u003e\u003e console = Console(stderr=True)\n\u003e\u003e\u003e resp = shil.invoke('ls /tmp', command_logger=console.log)\n\u003e\u003e\u003e\n```\n\n### Rich-console Support\n\nBesides using rich-logger as above, you can use the [rich-protocol](https://rich.readthedocs.io/en/stable/protocol.html) more directly.\n\nPrinting works the way you'd expect for `Invocation` and `InvocationResponse`.\n\n```pycon\n\u003e\u003e\u003e import shil, rich\n\u003e\u003e\u003e req = cmd = shil.Invocation(command='echo {\"foo\":\"bar\"}')\n\u003e\u003e\u003e resp = cmd()\n\u003e\u003e\u003e rich.print(req)\n\u003e\u003e\u003e rich.print(resp)\n```\nBy default, output looks roughly like this:\n\n![rich console](https://raw.githubusercontent.com/elo-enterprises/shil/master/img/rich-1.png)\n\u003cbr/\u003e\n![rich console](https://raw.githubusercontent.com/elo-enterprises/shil/master/img/rich-2.png)\n\n### Stay DRY with Runners\n\nRunner's are basically just [partials](https://en.wikipedia.org/wiki/Partial_application) on `shil.invoke`.  It's simple but this can help reduce copying around repetitive configuration.\n\n```pycon\n\u003e\u003e\u003e import shil\n\u003e\u003e\u003e from rich.console import Console\n\u003e\u003e\u003e console=Console(stderr=True)\n\u003e\u003e\u003e runner = shil.Runner(output_logger=console.log, command_logger=console.log)\n\u003e\u003e\u003e resp = runner('ls /tmp')\n\u003e\u003e\u003e assert isinstance(resp,(shil.InvocationResult,))\n\u003e\u003e\u003e\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felo-enterprises%2Fshil","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felo-enterprises%2Fshil","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felo-enterprises%2Fshil/lists"}