<p align="center">
<img src="https://github.com/kaliv0/koi_fish/blob/main/assets/koi-fish.jpg?raw=true" width="450" alt="Koi fish">
</p>
# Koi fish

[](https://pypi.org/project/koi-fish/)
[](https://pepy.tech/projects/koi-fish)
<br>Command line task runner & automation tool
---------------------------
### How to use
- Describe tasks as tables/dictionaries in a config file called <i>'koi.toml'</i>.
```toml
[test]
description = "run tests"
pre_run = "uv sync --all-extras --dev"
commands = "uv run pytest -v ."
post_run = "rm -rf .pytest_cache/"
```
- <i>description</i>, <i>pre_run</i> and <i>post_run</i> could be optional but not <i>commands</i>
```toml
[no-deps]
commands = "echo 'Hello world'"
```
- they can have long (full) or short names
```toml
[test]
info = "run tests"
pre = "uv sync --all-extras --dev"
cmd = "uv run pytest -v ."
post = "rm -rf .pytest_cache/"
```
- <i>pre_run</i>, <i>commands</i> and <i>post_run</i> could be strings or (in case of more than one) a list of strings
```toml
commands = ["uv run ruff check", "uv run ruff format"]
```
- You could provide an optional [run] table inside the config file with a <i>'main'</i> flow - list of selected tasks to run, alongside with other flows
<br>(In this case the 'main' table is mandatory and will be executed by default unless explicitly specified otherwise)
```toml
[run]
main = ["lint", "format", "test"]
full = ["install", "lint", "format", "test", "teardown"]
```
---------------------------
Example <i>koi.toml</i> (used as a main automation tool during the development of this project)
```toml
[install]
description = "setup .venv and install dependencies"
commands = "uv sync --all-extras --dev"
[format]
description = "format code"
commands = ["uv run ruff check", "uv run ruff format"]
[lint]
description = "run mypy"
commands = "uv run mypy ."
[teardown]
description = "remove venv and cache"
commands = "rm -rf .venv/ .ruff_cache/ .mypy_cache/"
[run]
description = "tasks pipeline"
main = ["install", "format", "lint"]
```
---------------------------
- Run the tool in the terminal with a simple <b>'koi'</b> command and pass the directory path where the koi.toml file resides
<br>(if it is the current directory the path argument can be omitted)
```shell
$ koi ~/pyproj/foo
```
```shell
(logs omitted...)
$ All tasks succeeded! ['lint', 'format', 'test']
Detoxing took: 14.088007061000098
```
- In case of failing tasks you get general stats
```shell
(logs omitted...)
$ Unsuccessful detoxing took: 13.532951637999759
Failed tasks: ['format']
Successful tasks: ['lint', 'test']
```
or
```shell
$ Unsuccessful detoxing took: 8.48367640699962
Failed tasks: ['format']
Successful tasks: ['lint']
Skipped tasks: ['test']
```
Running <i>'koi \<path>'</i> executes the <i>'main'</i> flow from the [run] table.
<br>If no such table is present, <i>koi_fish</i> will execute all tasks specified in the config file
---------------------------
- You could run specific tasks in the command line
```shell
$ koi --task format
```
or a list of tasks
```shell
$ koi -t format test
```
<b>NB:</b> If there is a <i>'run'</i> table in the config file tasks specified in the command line take precedence
- other available options
```shell
# run all tasks from the config file
$ koi --run-all # short form: -r
```
```shell
# hide output logs from running commands
$ koi --silent # -s
```
```shell
# don't print shell commands - similar to @<command> in Makefile
$ koi --mute-commands # -m
```
```shell
# skip task(s) from config file - can be combined e.g. with --run-all
$ koi -r --skip test # -S
```
```shell
# cancel flow if a task fails
$ koi --fail-fast # -F
```
```shell
# task(s) to run at the end if the flow fails
$ koi -rF --finally teardown
```
```shell
# allow duplicate tasks in flow
$ koi --allow-duplicates # -A
```
```shell
# disable colored output in logs
$ koi --no-color # -n
```
```shell
# run task(s) from given 'flow' table
$ koi --flow bar # -f
```
- commands showing data
```shell
# display all tasks from the config file
$ koi --all # -a
# ['install', 'format', 'test', 'teardown', 'run']
```
```shell
# display 'run' table
$ koi --config # -c
```
```shell
# display all tasks from a flow inside 'run' table
$ koi --describe-flow main # -D
# ['install', 'format', 'test']
```
```shell
# display config for given task(s)
$ koi --describe format # -d
# FORMAT
# description: format code
# commands: uv run ruff check
# uv run ruff format
```
Raw data
{
"_id": null,
"home_page": null,
"name": "koi-fish",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.12",
"maintainer_email": null,
"keywords": "task automation, cli tool, command line runner, task runner",
"author": null,
"author_email": "kaliv0 <kaloyan.ivanov88@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/27/13/7a42432c526c4a4d6f2943db246542f7ae198b4745b60afc962f6280b000/koi_fish-2.0.0.tar.gz",
"platform": null,
"description": "<p align=\"center\">\n <img src=\"https://github.com/kaliv0/koi_fish/blob/main/assets/koi-fish.jpg?raw=true\" width=\"450\" alt=\"Koi fish\">\n</p>\n\n# Koi fish\n\n\n[](https://pypi.org/project/koi-fish/)\n[](https://pepy.tech/projects/koi-fish)\n\n<br>Command line task runner & automation tool\n\n---------------------------\n### How to use\n- Describe tasks as tables/dictionaries in a config file called <i>'koi.toml'</i>.\n```toml\n[test]\ndescription = \"run tests\"\npre_run = \"uv sync --all-extras --dev\"\ncommands = \"uv run pytest -v .\"\npost_run = \"rm -rf .pytest_cache/\"\n```\n- <i>description</i>, <i>pre_run</i> and <i>post_run</i> could be optional but not <i>commands</i>\n```toml\n[no-deps]\ncommands = \"echo 'Hello world'\"\n```\n- they can have long (full) or short names\n```toml\n[test]\ninfo = \"run tests\"\npre = \"uv sync --all-extras --dev\"\ncmd = \"uv run pytest -v .\"\npost = \"rm -rf .pytest_cache/\"\n```\n- <i>pre_run</i>, <i>commands</i> and <i>post_run</i> could be strings or (in case of more than one) a list of strings\n```toml\ncommands = [\"uv run ruff check\", \"uv run ruff format\"]\n```\n\n- You could provide an optional [run] table inside the config file with a <i>'main'</i> flow - list of selected tasks to run, alongside with other flows\n<br>(In this case the 'main' table is mandatory and will be executed by default unless explicitly specified otherwise)\n```toml\n[run]\nmain = [\"lint\", \"format\", \"test\"]\nfull = [\"install\", \"lint\", \"format\", \"test\", \"teardown\"]\n```\n---------------------------\nExample <i>koi.toml</i> (used as a main automation tool during the development of this project)\n```toml\n[install]\ndescription = \"setup .venv and install dependencies\"\ncommands = \"uv sync --all-extras --dev\"\n\n[format]\ndescription = \"format code\"\ncommands = [\"uv run ruff check\", \"uv run ruff format\"]\n\n[lint]\ndescription = \"run mypy\"\ncommands = \"uv run mypy .\"\n\n[teardown]\ndescription = \"remove venv and cache\"\ncommands = \"rm -rf .venv/ .ruff_cache/ .mypy_cache/\"\n\n[run]\ndescription = \"tasks pipeline\"\nmain = [\"install\", \"format\", \"lint\"]\n```\n---------------------------\n- Run the tool in the terminal with a simple <b>'koi'</b> command and pass the directory path where the koi.toml file resides\n<br>(if it is the current directory the path argument can be omitted)\n```shell\n$ koi ~/pyproj/foo\n```\n```shell\n(logs omitted...)\n$ All tasks succeeded! ['lint', 'format', 'test']\nDetoxing took: 14.088007061000098\n```\n- In case of failing tasks you get general stats\n```shell\n(logs omitted...)\n$ Unsuccessful detoxing took: 13.532951637999759\nFailed tasks: ['format']\nSuccessful tasks: ['lint', 'test']\n```\nor\n```shell\n$ Unsuccessful detoxing took: 8.48367640699962\nFailed tasks: ['format']\nSuccessful tasks: ['lint']\nSkipped tasks: ['test']\n```\nRunning <i>'koi \\<path>'</i> executes the <i>'main'</i> flow from the [run] table.\n<br>If no such table is present, <i>koi_fish</i> will execute all tasks specified in the config file\n\n---------------------------\n- You could run specific tasks in the command line\n```shell\n$ koi --task format\n```\nor a list of tasks\n```shell\n$ koi -t format test\n```\n<b>NB:</b> If there is a <i>'run'</i> table in the config file tasks specified in the command line take precedence\n\n- other available options\n```shell\n# run all tasks from the config file \n$ koi --run-all # short form: -r\n```\n```shell\n# hide output logs from running commands\n$ koi --silent # -s\n```\n```shell\n# don't print shell commands - similar to @<command> in Makefile\n$ koi --mute-commands # -m\n```\n```shell\n# skip task(s) from config file - can be combined e.g. with --run-all\n$ koi -r --skip test # -S\n```\n```shell\n# cancel flow if a task fails\n$ koi --fail-fast # -F\n```\n```shell\n# task(s) to run at the end if the flow fails\n$ koi -rF --finally teardown\n```\n```shell\n# allow duplicate tasks in flow\n$ koi --allow-duplicates # -A\n```\n```shell\n# disable colored output in logs\n$ koi --no-color # -n\n```\n```shell\n# run task(s) from given 'flow' table\n$ koi --flow bar # -f\n```\n- commands showing data\n```shell\n# display all tasks from the config file\n$ koi --all # -a\n# ['install', 'format', 'test', 'teardown', 'run']\n```\n```shell\n# display 'run' table\n$ koi --config # -c\n```\n```shell\n# display all tasks from a flow inside 'run' table\n$ koi --describe-flow main # -D\n# ['install', 'format', 'test']\n```\n```shell\n# display config for given task(s)\n$ koi --describe format # -d\n# FORMAT\n# description: format code\n# commands: uv run ruff check\n# uv run ruff format\n```",
"bugtrack_url": null,
"license": null,
"summary": "CLI task runner & automation tool",
"version": "2.0.0",
"project_urls": {
"repository": "https://github.com/kaliv0/koi_fish.git"
},
"split_keywords": [
"task automation",
" cli tool",
" command line runner",
" task runner"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "c05212678dc3778e9a77c61289a2e8f5c481aeb11dfd52d7e8983331a85814b5",
"md5": "768c120d4ddc15695cbaeeb486f5e9df",
"sha256": "8eec04d5cba84fab8d0e8fc22ed3e7c5bde9f0a2bbd6f89246c4777376004783"
},
"downloads": -1,
"filename": "koi_fish-2.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "768c120d4ddc15695cbaeeb486f5e9df",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.12",
"size": 11186,
"upload_time": "2025-07-20T06:53:09",
"upload_time_iso_8601": "2025-07-20T06:53:09.388192Z",
"url": "https://files.pythonhosted.org/packages/c0/52/12678dc3778e9a77c61289a2e8f5c481aeb11dfd52d7e8983331a85814b5/koi_fish-2.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "27137a42432c526c4a4d6f2943db246542f7ae198b4745b60afc962f6280b000",
"md5": "2a74690fcca6fc7c622cc193aa6a6bfa",
"sha256": "c37d77bb2573517b9a56616b6d1ea62e6e81a96a4e5f04b1dad13baf0eb9f37a"
},
"downloads": -1,
"filename": "koi_fish-2.0.0.tar.gz",
"has_sig": false,
"md5_digest": "2a74690fcca6fc7c622cc193aa6a6bfa",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.12",
"size": 11111,
"upload_time": "2025-07-20T06:53:10",
"upload_time_iso_8601": "2025-07-20T06:53:10.411002Z",
"url": "https://files.pythonhosted.org/packages/27/13/7a42432c526c4a4d6f2943db246542f7ae198b4745b60afc962f6280b000/koi_fish-2.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-20 06:53:10",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "kaliv0",
"github_project": "koi_fish",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "koi-fish"
}