{"id":16444921,"url":"https://github.com/jaymon/captain","last_synced_at":"2025-08-09T21:19:43.529Z","repository":{"id":13906872,"uuid":"16605660","full_name":"Jaymon/captain","owner":"Jaymon","description":"command line python scripts for humans","archived":false,"fork":false,"pushed_at":"2024-02-24T00:26:52.000Z","size":245,"stargazers_count":13,"open_issues_count":10,"forks_count":1,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-04-24T20:03:03.056Z","etag":null,"topics":["cli","cli-app","cli-command","cli-script","cli-utilities","cli-utility","python","python-script"],"latest_commit_sha":null,"homepage":null,"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/Jaymon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","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}},"created_at":"2014-02-07T05:48:27.000Z","updated_at":"2024-03-12T11:35:13.000Z","dependencies_parsed_at":"2023-01-13T17:40:51.902Z","dependency_job_id":"253e2c2e-fbc8-477d-b087-c3aa27ab001e","html_url":"https://github.com/Jaymon/captain","commit_stats":{"total_commits":107,"total_committers":1,"mean_commits":107.0,"dds":0.0,"last_synced_commit":"f37bae5339f5d323832ad27042577929da59c602"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jaymon%2Fcaptain","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jaymon%2Fcaptain/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jaymon%2Fcaptain/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jaymon%2Fcaptain/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Jaymon","download_url":"https://codeload.github.com/Jaymon/captain/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244114683,"owners_count":20400404,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["cli","cli-app","cli-command","cli-script","cli-utilities","cli-utility","python","python-script"],"created_at":"2024-10-11T09:42:37.609Z","updated_at":"2025-03-21T05:30:33.708Z","avatar_url":"https://github.com/Jaymon.png","language":"Python","readme":"# Captain\n\nEasy python cli scripts for people that just want get things done.\n\n\n## Usage\n\nA valid `captain` cli script needs just two things:\n\n1. A `Default` class that extends `captain.Command` and has a `handle()` method (can be async):\n\n    ```python\n    from captain import Command\n    \n    class Default(Command):\n        async def handle(self, foo, bar):\n            return 0\n    ```\n\n2. Calling `captain.application()` at the end of your script:\n\n    ```python\n    from captain import Command, application\n    \n    class Default(Command):\n        async def handle(self, foo, bar):\n            return 0\n\n    if __name__ == \"__main__\":\n        application()\n    ```\n\nThat's it! Whatever arguments you define in your class's `Default.handle()` method will be options on the command line. A captain script is called just like any other python command line script, so to run the above example you could do:\n\n    $ python path/to/script.py --foo=1 --bar=2\n\n\n## Argument Decorator\n\nThe `captain.arg()` decorator provides a nice passthrough api to the full [argparse.ArgumentParser.add_argument() method](https://docs.python.org/3/library/argparse.html#the-add-argument-method) if you want to fine tune how arguments are passed into your script:\n\n```python\nfrom captain import Command, application, arg\n\nclass Default(Command):\n    @arg('--foo', '-f', action=\"store_true\")\n    @arg('arg', metavar='ARG')\n    async def handle(self, *args, **kwargs):\n        '''this is the help description'''\n        self.output.out(args)\n        self.output.out(kwargs)\n\nif __name__ == \"__main__\":\n    application()\n```\n\nWould print a help string like this:\n\n    usage: script.py [-h] [--foo FOO] ARG\n\n    this is the help description\n\n    positional arguments:\n      ARG\n\n    optional arguments:\n      -h, --help         show this help message and exit\n      --foo FOO, -f FOO\n\n\n## Command Output\n\nThe `captain.io.Output` class makes it easy to print stuff in your script while still giving you full control by being able to configure the logger if you need to. It also will obey the global `--quiet` flag that Captain adds to every script. \n\nIt's available in the `handle()` method by using `self.output`:\n\n```python\nfrom captain import Command\n\nclass Default(Command):\n    async def handle(self, *args, **kwargs):\n        var1 = \"print\"\n\n        var2 = \"stdout\"\n        self.output.out(\"this will {} to {}\", var1, var2)\n\n        var2 = \"stderr\"\n        self.output.err(\"this will {} to {}\", var1, var2)\n\n        e = ValueError(\"this will print with stacktrace and everything\")\n        self.output.exception(e)\n```\n\nThe `captain.io.Output` class has a lot of nice little helper methods but Captain can also work with modules like [clint](https://github.com/kennethreitz/clint) if you need to do more advanced cli output.\n\n\n## Examples\n\nA typical python cli script\n\n```python\nimport argparse\n\nif __name__ == '__main__':\n    parser = argparse.ArgumentParser(description='fancy script description')\n    parser.add_argument(\"--foo\", action='store_true')\n    parser.add_argument(\"--bar\", default=0, type=int)\n    parser.add_argument(\"args\", nargs='*')\n    args = parser.parse_args()\n    sys.exit(0)\n```\n\nwould become:\n\n```python\nimport captain\n\nclass Default(captain.Command):\n    async def handle(foo=False, bar=0, *args):\n        '''fancy script description'''\n        return 0\n\nif __name__ == '__main__':\n    captain.application()\n```\n\n\n### Subcommands\n\nCaptain supports multiple subcommands defined in the script by naming your `captain.Command` child classes something other than `Default`:\n\n```python\n# cli.py\n\nimport captain\n\nclass Foo(captain.Command):\n    async def handle(self):\n        pass\n\nclass Bar(captain.Command):\n    async def handle(self):\n        pass\n\nif __name__ == '__main__':\n    captain.application()\n```\n\nSo `foo` could be called using:\n\n    $ python cli.py foo\n\nAnd `bar` could be called using:\n\n    $ python cli.py bar\n\n\n### Embedding captain in another package\n\nIf you want a script from you package to be usable using both `python -m example` and maybe a `console_scripts` entry point defined in `setup.py`, you can set up your package's `__main__.py` module like this:\n\n\n```python\n# example/__main__.py\n\nfrom captain import Command, application\n\nclass Default(captain.Command):\n    async def handle(self):\n        pass\n        \nif __name__ == \"__main__\":\n    application()\n```\n\nAnd then in your `setup.py` script you can add:\n\n\n```python\nentry_points = {\n    'console_scripts': [\n        'example = example.__main__:application'\n    ],\n}\n```\n\nThat's all there is to it.\n\n\n## Install\n\nUse pip:\n\n    $ pip install captain\n\nFor latest and greatest:\n\n    $ pip install -U \"git+https://github.com/Jaymon/captain#egg=captain\"\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaymon%2Fcaptain","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjaymon%2Fcaptain","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaymon%2Fcaptain/lists"}