README.md

<div id="readme"></div>

<div id="top"></div>

<div align="center">

<h1>
  kindly 💖
  <br>
  <font size="4"><i>A nice little task runner</i></font>
</h1>

<font color="#848484" size="6">

[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3?label&labelColor=2f2f2f&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNiAyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsPSIjZmVmZWZjIiBkPSJNMjUuNjA5IDcuNDY5YzAuMzkxIDAuNTYyIDAuNSAxLjI5NyAwLjI4MSAyLjAxNmwtNC4yOTcgMTQuMTU2Yy0wLjM5MSAxLjMyOC0xLjc2NiAyLjM1OS0zLjEwOSAyLjM1OWgtMTQuNDIyYy0xLjU5NCAwLTMuMjk3LTEuMjY2LTMuODc1LTIuODkxLTAuMjUtMC43MDMtMC4yNS0xLjM5MS0wLjAzMS0xLjk4NCAwLjAzMS0wLjMxMyAwLjA5NC0wLjYyNSAwLjEwOS0xIDAuMDE2LTAuMjUtMC4xMjUtMC40NTMtMC4wOTQtMC42NDEgMC4wNjMtMC4zNzUgMC4zOTEtMC42NDEgMC42NDEtMS4wNjIgMC40NjktMC43ODEgMS0yLjA0NyAxLjE3Mi0yLjg1OSAwLjA3OC0wLjI5Ny0wLjA3OC0wLjY0MSAwLTAuOTA2IDAuMDc4LTAuMjk3IDAuMzc1LTAuNTE2IDAuNTMxLTAuNzk3IDAuNDIyLTAuNzE5IDAuOTY5LTIuMTA5IDEuMDQ3LTIuODQ0IDAuMDMxLTAuMzI4LTAuMTI1LTAuNjg4LTAuMDMxLTAuOTM4IDAuMTA5LTAuMzU5IDAuNDUzLTAuNTE2IDAuNjg4LTAuODI4IDAuMzc1LTAuNTE2IDEtMiAxLjA5NC0yLjgyOCAwLjAzMS0wLjI2Ni0wLjEyNS0wLjUzMS0wLjA3OC0wLjgxMiAwLjA2My0wLjI5NyAwLjQzOC0wLjYwOSAwLjY4OC0wLjk2OSAwLjY1Ni0wLjk2OSAwLjc4MS0zLjEwOSAyLjc2Ni0yLjU0N2wtMC4wMTYgMC4wNDdjMC4yNjYtMC4wNjMgMC41MzEtMC4xNDEgMC43OTctMC4xNDFoMTEuODkxYzAuNzM0IDAgMS4zOTEgMC4zMjggMS43ODEgMC44NzUgMC40MDYgMC41NjIgMC41IDEuMjk3IDAuMjgxIDIuMDMxbC00LjI4MSAxNC4xNTZjLTAuNzM0IDIuNDA2LTEuMTQxIDIuOTM4LTMuMTI1IDIuOTM4aC0xMy41NzhjLTAuMjAzIDAtMC40NTMgMC4wNDctMC41OTQgMC4yMzQtMC4xMjUgMC4xODctMC4xNDEgMC4zMjgtMC4wMTYgMC42NzIgMC4zMTMgMC45MDYgMS4zOTEgMS4wOTQgMi4yNSAxLjA5NGgxNC40MjJjMC41NzggMCAxLjI1LTAuMzI4IDEuNDIyLTAuODkxbDQuNjg4LTE1LjQyMmMwLjA5NC0wLjI5NyAwLjA5NC0wLjYwOSAwLjA3OC0wLjg5MSAwLjM1OSAwLjE0MSAwLjY4OCAwLjM1OSAwLjkyMiAwLjY3MnpNOC45ODQgNy41Yy0wLjA5NCAwLjI4MSAwLjA2MyAwLjUgMC4zNDQgMC41aDkuNWMwLjI2NiAwIDAuNTYyLTAuMjE5IDAuNjU2LTAuNWwwLjMyOC0xYzAuMDk0LTAuMjgxLTAuMDYzLTAuNS0wLjM0NC0wLjVoLTkuNWMtMC4yNjYgMC0wLjU2MiAwLjIxOS0wLjY1NiAwLjV6TTcuNjg4IDExLjVjLTAuMDk0IDAuMjgxIDAuMDYzIDAuNSAwLjM0NCAwLjVoOS41YzAuMjY2IDAgMC41NjItMC4yMTkgMC42NTYtMC41bDAuMzI4LTFjMC4wOTQtMC4yODEtMC4wNjMtMC41LTAuMzQ0LTAuNWgtOS41Yy0wLjI2NiAwLTAuNTYyIDAuMjE5LTAuNjU2IDAuNXoiPjwvcGF0aD48L3N2Zz4K)](https://hexdocs.pm/kindly/)
[![License](https://img.shields.io/hexpm/l/kindly?color=ffaff3&label&labelColor=2f2f2f&logo=data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjM0IiBoZWlnaHQ9IjI4IiB2aWV3Qm94PSIwIDAgMzQgMjgiPgo8cGF0aCBmaWxsPSIjZmVmZWZjIiBkPSJNMjcgN2wtNiAxMWgxMnpNNyA3bC02IDExaDEyek0xOS44MjggNGMtMC4yOTcgMC44NDQtMC45ODQgMS41MzEtMS44MjggMS44Mjh2MjAuMTcyaDkuNWMwLjI4MSAwIDAuNSAwLjIxOSAwLjUgMC41djFjMCAwLjI4MS0wLjIxOSAwLjUtMC41IDAuNWgtMjFjLTAuMjgxIDAtMC41LTAuMjE5LTAuNS0wLjV2LTFjMC0wLjI4MSAwLjIxOS0wLjUgMC41LTAuNWg5LjV2LTIwLjE3MmMtMC44NDQtMC4yOTctMS41MzEtMC45ODQtMS44MjgtMS44MjhoLTcuNjcyYy0wLjI4MSAwLTAuNS0wLjIxOS0wLjUtMC41di0xYzAtMC4yODEgMC4yMTktMC41IDAuNS0wLjVoNy42NzJjMC40MjItMS4xNzIgMS41MTYtMiAyLjgyOC0yczIuNDA2IDAuODI4IDIuODI4IDJoNy42NzJjMC4yODEgMCAwLjUgMC4yMTkgMC41IDAuNXYxYzAgMC4yODEtMC4yMTkgMC41LTAuNSAwLjVoLTcuNjcyek0xNyA0LjI1YzAuNjg4IDAgMS4yNS0wLjU2MiAxLjI1LTEuMjVzLTAuNTYyLTEuMjUtMS4yNS0xLjI1LTEuMjUgMC41NjItMS4yNSAxLjI1IDAuNTYyIDEuMjUgMS4yNSAxLjI1ek0zNCAxOGMwIDMuMjE5LTQuNDUzIDQuNS03IDQuNXMtNy0xLjI4MS03LTQuNXYwYzAtMC42MDkgNS40NTMtMTAuMjY2IDYuMTI1LTExLjQ4NCAwLjE3Mi0wLjMxMyAwLjUxNi0wLjUxNiAwLjg3NS0wLjUxNnMwLjcwMyAwLjIwMyAwLjg3NSAwLjUxNmMwLjY3MiAxLjIxOSA2LjEyNSAxMC44NzUgNi4xMjUgMTEuNDg0djB6TTE0IDE4YzAgMy4yMTktNC40NTMgNC41LTcgNC41cy03LTEuMjgxLTctNC41djBjMC0wLjYwOSA1LjQ1My0xMC4yNjYgNi4xMjUtMTEuNDg0IDAuMTcyLTAuMzEzIDAuNTE2LTAuNTE2IDAuODc1LTAuNTE2czAuNzAzIDAuMjAzIDAuODc1IDAuNTE2YzAuNjcyIDEuMjE5IDYuMTI1IDEwLjg3NSA2LjEyNSAxMS40ODR6Ij48L3BhdGg+Cjwvc3ZnPgo=)](https://github.com/tynanbe/kindly/blob/main/LICENSE)
[![Build](https://img.shields.io/github/actions/workflow/status/tynanbe/kindly/ci.yml?branch=main&color=ffaff3&label&labelColor=2f2f2f&logo=github-actions&logoColor=fefefc)](https://github.com/tynanbe/kindly/actions)
&nbsp;•&nbsp;
[![Hex Package](https://img.shields.io/hexpm/v/kindly?color=ffaff3&label&labelColor=2f2f2f&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsPSIjZmVmZWZjIiBkPSJNIDYuMjgzMiwxLjU5OTYgOS4yODMyLDYuNzk0OSBIIDE0LjcwNTEgTCAxNy43MDUxLDEuNTk5NiBaIE0gMTguMTQwNywxLjg0MzggbCAtMyw1LjE5NzMgMi43MTQ5LDQuNjk5MiBoIDYgeiBNIDUuODUzNSwxLjg1NTUgMC4xNDQ1LDExLjc0MDIgSCA2LjE0NDUgTCA4Ljg1MTYsNy4wNDg4IFogTSAwLjE0NDUsMTIuMjQwMiA1Ljg1MzUsMjIuMTI3IDguODUxNiwxNi45MzM2IDYuMTQ0NSwxMi4yNDAyIFogbSAxNy43MTEsMCAtMi43MTQ5LDQuNzAxMiAzLDUuMTk1MyA1LjcxNDksLTkuODk2NSB6IE0gOS4yODMyLDE3LjE4NzUgNi4yODUyLDIyLjM4MDkgSCAxNy43MDMyIEwgMTQuNzA1MSwxNy4xODc1IFoiLz48L3N2Zz4K)](https://hex.pm/packages/kindly)
[![npm Package](https://img.shields.io/npm/v/@tynanbe/kindly?color=ffaff3&label&labelColor=2f2f2f&logo=npm&logoColor=fefefc)](https://npmjs.com/package/@tynanbe/kindly)
[![JSR Package](https://img.shields.io/jsr/v/@tynanbe/kindly?color=ffaff3&label&labelColor=2f2f2f&logo=jsr&logoColor=fefefc)](https://jsr.io/@tynanbe/kindly)
<br>
[![Works With Gleam](https://img.shields.io/badge/-Gleam-ffaff3?labelColor=2f2f2f&logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTcuMzg0OCA5LjMwNDQ0QzcuMzg0OCA5LjMwNDQ0IDcuNTMyNTQgMTAuMjY0NiA4LjUzMjQ4IDEwLjA4ODJDOS41MzI0MiA5LjkxMTkzIDkuMzYzNzggOC45NTU0OSA5LjM2Mzc4IDguOTU1NDkiIHN0cm9rZT0iI2ZlZmVmYyIgc3Ryb2tlLXdpZHRoPSIxLjI1IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPHBhdGggZD0iTTUuNTQxNTUgNS41NDE1N0M2LjEyMzU1IDQuOTAxMDQgNi4wMTY4OCAyLjYyNTQxIDcuMjI4NzUgMi4zOTg1QzguNDQwNjMgMi4xNzE1OCA5LjE5MDk3IDQuMzMxNDggOS45MTk4MiA0LjY4MTRDMTAuNjQ4NyA1LjAzMTMzIDEyLjg1MTcgNC4zMDI4IDEzLjQzODEgNS4zODczNEMxNC4wMjQ0IDYuNDcxODggMTIuMTM5NSA3Ljk1OTczIDEyLjAyNiA4LjY0MDg4QzExLjkxMjYgOS4zMjIwMyAxMy4zNjE0IDExLjI0MTYgMTIuNDY3NSAxMi4xNzAxQzExLjU3MzYgMTMuMDk4NiA5LjczMDA1IDExLjc1NDUgOC45MDQ4NiAxMS44ODM0QzguMDc5NjYgMTIuMDEyMyA2Ljc5MjQ0IDEzLjkwOTUgNS42NzM2NyAxMy4zNTAyQzQuNTU0OTEgMTIuNzkwOSA1LjE2NzAyIDEwLjU0NTUgNC44MjQzNyA5Ljg3NjEyQzQuNDgxNzEgOS4yMDY3MyAyLjM0MDI4IDguNTQ5NzggMi40NTI1IDcuMzUwNDlDMi41NjQ3MSA2LjE1MTIxIDQuOTU5NTYgNi4xODIxIDUuNTQxNTUgNS41NDE1N1oiIHN0cm9rZT0iI0ZGNzY3NiIgc3Ryb2tlLW9wYWNpdHk9IjAuNTIiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPHBhdGggZD0iTTUuNTQxNTUgNS41NDE1N0M2LjEyMzU1IDQuOTAxMDQgNi4wMTY4OCAyLjYyNTQxIDcuMjI4NzUgMi4zOTg1QzguNDQwNjMgMi4xNzE1OCA5LjE5MDk3IDQuMzMxNDggOS45MTk4MiA0LjY4MTRDMTAuNjQ4NyA1LjAzMTMzIDEyLjg1MTcgNC4zMDI4IDEzLjQzODEgNS4zODczNEMxNC4wMjQ0IDYuNDcxODggMTIuMTM5NSA3Ljk1OTczIDEyLjAyNiA4LjY0MDg4QzExLjkxMjYgOS4zMjIwMyAxMy4zNjE0IDExLjI0MTYgMTIuNDY3NSAxMi4xNzAxQzExLjU3MzYgMTMuMDk4NiA5LjczMDA1IDExLjc1NDUgOC45MDQ4NiAxMS44ODM0QzguMDc5NjYgMTIuMDEyMyA2Ljc5MjQ0IDEzLjkwOTUgNS42NzM2NyAxMy4zNTAyQzQuNTU0OTEgMTIuNzkwOSA1LjE2NzAyIDEwLjU0NTUgNC44MjQzNyA5Ljg3NjEyQzQuNDgxNzEgOS4yMDY3MyAyLjM0MDI4IDguNTQ5NzggMi40NTI1IDcuMzUwNDlDMi41NjQ3MSA2LjE1MTIxIDQuOTU5NTYgNi4xODIxIDUuNTQxNTUgNS41NDE1N1oiIHN0cm9rZT0iI2ZlZmVmYyIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8Y2lyY2xlIGN4PSI2LjI1MDk4IiBjeT0iNy43NSIgcj0iMC43NSIgZmlsbD0iI2ZlZmVmYyIvPgo8Y2lyY2xlIGN4PSIxMC4xMDM1IiBjeT0iNy4yNSIgcj0iMC43NSIgZmlsbD0iI2ZlZmVmYyIvPgo8L3N2Zz4K)](https://gleam.run/)
[![Works With TypeScript](https://img.shields.io/badge/-TypeScript-ffaff3?labelColor=2f2f2f&logo=typescript&logoColor=fefefc)](https://www.typescriptlang.org/)
[![Works With JavaScript](https://img.shields.io/badge/-JavaScript-ffaff3?labelColor=2f2f2f&logo=javascript&logoColor=fefefc)](https://ecma-international.org/publications-and-standards/standards/ecma-262/)
&nbsp;•&nbsp;
[![Runs With Node.js](https://img.shields.io/badge/-Node.js-ffaff3?labelColor=2f2f2f&logo=nodedotjs&logoColor=fefefc)](https://nodejs.org/)
[![Runs With Deno](https://img.shields.io/badge/-Deno-ffaff3?labelColor=2f2f2f&logo=deno&logoColor=fefefc)](https://deno.com/)
[![Runs With Bun](https://img.shields.io/badge/-Bun-ffaff3?labelColor=2f2f2f&logo=bun&logoColor=fefefc)](https://bun.sh/)
<br>
[![Kindly Made](https://img.shields.io/badge/-kindly-ffaff3?labelColor=2f2f2f&logo=data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9Ijc2OCIgaGVpZ2h0PSI3NjgiIHZpZXdCb3g9IjcyIDcyIDYyNCA2MjQiPgo8ZGVmcz4KICA8cGF0aAogICAgaWQ9InNwYXJrbGUiCiAgICBkPSIKICAgICAgTSAzODQsMzg0CiAgICAgIEMgNDA0IDQ4NCwgMzg0IDQ2NCwgNDg0IDQ4NAogICAgICBDIDM4NCA1MDQsIDQwNCA0ODQsIDM4NCA1ODQKICAgICAgQyAzNjQgNDg0LCAzODQgNTA0LCAyODQgNDg0CiAgICAgIEMgMzg0IDQ2NCwgMzY0IDQ4NCwgMzg0IDM4NAogICAgIgogICAgZmlsbD0iI2ZlZmVmYyIKICAgIHN0cm9rZT0iI2ZlZmVmYyIKICAgIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIKICAgIHN0cm9rZS1saW5lam9pbj0icm91bmQiCiAgICBzdHJva2Utd2lkdGg9IjI0IgogIC8+CjwvZGVmcz4KPHBhdGgKICBpZD0iaGVhcnQiCiAgZD0iCiAgICBNIDQzNiA1NjUKICAgIEwgMzg0IDYwMAogICAgTCAyMTAgNDgwCiAgICBDIC01MCAzMDAsIDIxNCAxMCwgMzg0IDI1MAogICAgQyA1NDcgMjMsIDc3MiAyNzIsIDYxMyA0MzIKICAiCiAgZmlsbC1vcGFjaXR5PSIwIgogIHN0cm9rZT0iI2ZlZmVmYyIKICBzdHJva2UtbGluZWNhcD0icm91bmQiCiAgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIKICBzdHJva2Utd2lkdGg9IjQ1IgovPgo8dXNlIGhyZWY9IiNzcGFya2xlIiB0cmFuc2Zvcm09InNjYWxlKDEuMzUsIDEuMzUpIHRyYW5zbGF0ZSg1LCAtMTE1KSIgLz4KPHVzZSBocmVmPSIjc3BhcmtsZSIgdHJhbnNmb3JtPSJzY2FsZSgwLjYsIDAuNikgdHJhbnNsYXRlKDMwLCAxMCkiIC8+Cjwvc3ZnPgoK)](https://github.com/tynanbe/kindly)

</font>

<font color="#848484">

### [Quickstart](https://hexdocs.pm/kindly/quickstart.html) &nbsp;•&nbsp; [API Reference](https://hexdocs.pm/kindly/kindly.html) &nbsp;•&nbsp; [Examples](https://hexdocs.pm/kindly/examples.html)

</font>

[<font color="#848484" size="6">•&nbsp;•&nbsp;•</font>](https://youtu.be/aaj08tCfsVw)

</div>

<div id="table-of-contents"></div>

<div id="toc"></div>

## Table of Contents

1. [Features](#features)
1. [Example](#example)
1. [About](#about)
1. [Try It](#try-it)
1. [Installation](#installation)
1. [Run It](#run-it)
1. [Completions](#completions)
1. [Where Next?](#where-next)
1. [Support](#support)

<div id="features"></div>

## Features

- Simple CLI and API
- Shell completions
- Declarative and functional
- Works with Gleam, TypeScript, and JavaScript
- Runs with Node.js, Deno, or Bun

<div id="example"></div>

## Example

<details open>
<summary><strong>Gleam</strong></summary>

```gleam
// dev/handbook.gleam

import kindly.{type Handbook, task}

pub fn main() -> Handbook {
  kindly.handbook(for: "example")
  |> task(
    doc: "Format source code",
    tags: ["format"],
    action: kindly.just(run: "gleam", with: ["format"]),
  )
  |> task(
    doc: "Check source code formatting",
    tags: ["format-check", "check", "ci"],
    action: kindly.just(run: "gleam", with: ["format", "--check"]),
  )
}
```

</details>

<details>
<summary><strong>TypeScript &amp; JavaScript</strong></summary>

```typescript
// handbook.ts, handbook.mjs, or handbook.js

import kindly from "jsr:@tynanbe/kindly";

export default kindly.handbook({ for: "example" })
  .task({
    doc: "Format source code",
    tags: ["format"],
    action: kindly.just("deno", "fmt"),
  })
  .task({
    doc: "Check source code formatting",
    tags: ["format-check", "check", "ci"],
    action: kindly.just("deno", "fmt", "--check"),
  });
```

</details>

<div id="about"></div>

## About

Kindly provides a simple yet flexible way to reference and run one or more
user-defined tasks specific to your project.

By creating a project Handbook with minimal boilerplate, you can write your
tasks in Gleam, TypeScript, or JavaScript for a better developer experience that
can also make it easier to ensure your tasks will work in any environment with
your runtime of choice (Node.js, Deno, or Bun).

Kindly bases task selection on a flat system of tags, although you could use it
to emulate a command tree typical of other CLI tools. This allows you to group
multiple tasks in a way that fits your project's needs and run all of them
together or filter selected tasks for those in the group.

For example, suppose your Handbook has tasks with the following tags:

```txt
A. test, erlang
B. test, javascript
C. format-check, gleam
D. format-check, erlang
E. format-check, javascript
```

Invoking Kindly with different arguments would run various tasks as follows
(_Note: You can always include the `--help` flag to show which tasks Kindly
plans to run given your other arguments_):

```sh
kindly test erlang # A
kindly test # A, B
kindly javascript # B, E
kindly format-check --any gleam erlang # C, D
```

The first tag for each task should be the most specific way to reference that
task. It's given special consideration in Kindly's help output.

### When to consider Kindly

Kindly is for projects whose tasks are starting to outgrow a flat list of
scripts.

Some handbooks use mostly direct task names. Others use grouped tasks, where one
tag names the broader work and additional tags narrow it down. Kindly does not
force one style. It is meant to support whichever shape fits the project and the
way people actually use it.

It's an attractive option when tasks overlap, share helpers, or are easier to
generate than hand-write. In those cases, composable task selection can be more
useful than inventing a separate command name for every path through the task
menu.

If your project only needs a few isolated commands, scripts may be simpler. If
your tasks are related, grouped, or better expressed as code, Kindly may be a
nice fit.

<div id="try-it"></div>

## Try It

<details open>
<summary><strong>Gleam</strong></summary>

```sh
# Add kindly to your Gleam project’s dev dependencies
gleam add --dev kindly
# Print help info
gleam run --module kindly
# Run an example task
gleam run -m kindly -- format-check
```

</details>

<details>
<summary><strong>Bun</strong></summary>

```sh
# Print help info
bunx --bun @tynanbe/kindly
# Run an example task
bunx --bun @tynanbe/kindly format-check
```

</details>

<details>
<summary><strong>Deno</strong></summary>

```sh
# Print help info
deno run --allow-all --reload jsr:@tynanbe/kindly
# Run an example task
deno run -Ar jsr:@tynanbe/kindly format-check
```

</details>

<details>
<summary><strong>Node.js</strong></summary>

```sh
# Print help info
npx @tynanbe/kindly
# Run an example task
npx @tynanbe/kindly format-check
```

</details>

> **Note:** If your project uses a `handbook.gleam` or `handbook.ts` module and
> you want to run it with Node.js, it's recommended to run Node.js v24.0+, for
> [type stripping](https://nodejs.org/api/typescript.html#type-stripping)
> support.

<div id="installation"></div>

## Installation

It's recommended to install Kindly globally with Deno, Bun, or your Node.js
package manager of choice. This method is the simplest way to get shell
completions, and Kindly will still run your handbook using your project's local
Kindly dependency.

<details>
<summary><strong>Bun</strong></summary>

```sh
bun install --global @tynanbe/kindly
```

</details>

<details open>
<summary><strong>Deno</strong></summary>

```sh
deno install --global --allow-all jsr:@tynanbe/kindly
```

</details>

<details>
<summary><strong>Node.js</strong></summary>

```sh
# Or similar for pnpm, yarn, etc.
npm install --global @tynanbe/kindly
```

</details>

<div id="run-it"></div>

## Run It

```sh
# Print help info
kindly
# Run an example task
kindly format-check
```

> **Note:** If your project uses a `handbook.gleam` or `handbook.ts` module and
> you want to run it with Node.js, it's recommended to run Node.js v24.0+, for
> [type stripping](https://nodejs.org/api/typescript.html#type-stripping)
> support.

<div id="completions"></div>

## Completions

After you've installed Kindly globally or worked out some other way to get
`kindly` on your `$PATH`, you can set up shell completions and Kindly will
suggest the tags for your project as well as its own flags.

<details>
<summary><strong>Bash</strong></summary>

![Bash Completion Demo](https://github.com/tynanbe/kindly/raw/main/images/bash-completion.avif)

```sh
# ~/.bashrc
if type kindly >/dev/null 2>&1; then
  eval "$(kindly --cue bash)"
fi
```

</details>

<details open>
<summary><strong>Fish</strong></summary>

![Fish Completion Demo](https://github.com/tynanbe/kindly/raw/main/images/fish-completion.avif)

```sh
# ~/.config/fish/config.fish
if type kindly >/dev/null 2>&1
    kindly --cue fish | source
end
```

</details>

<details>
<summary><strong>PowerShell (pwsh)</strong></summary>

![Pwsh PowerShell Completion Demo](https://github.com/tynanbe/kindly/raw/main/images/pwsh-completion.avif)

```sh
# ~/.config/powershell/profile.ps1
# or $HOME\Documents\PowerShell\profile.ps1
if (Get-Command -Name kindly -ErrorAction Ignore) {
    kindly --cue pwsh | Out-String | Invoke-Expression
}

# -Function MenuComplete is recommended, but
# -Function Complete should also work
Set-PSReadlineKeyHandler -Key Tab -Function MenuComplete
```

</details>

<details>
<summary><strong>Zsh</strong></summary>

![Zsh Completion Demo](https://github.com/tynanbe/kindly/raw/main/images/zsh-completion.avif)

```sh
# ~/.zshrc
if type kindly >/dev/null 2>&1; then
  eval "$(kindly --cue zsh)"
fi
```

</details>

<div id="where-next"></div>

## Where Next?

[Quickstart](https://hexdocs.pm/kindly/quickstart.html)

[API Reference](https://hexdocs.pm/kindly/kindly.html)

[Examples](https://hexdocs.pm/kindly/examples.html)

<div id="support"></div>

## Support

Contributions are welcome. Feel free to
[open an issue](https://github.com/tynanbe/kindly/issues) on GitHub to suggest a
feature or report a bug.

If your project uses Kindly, you may wish to add a badge to your `README`.

<details>
<summary><strong>Kindly Badge Markdown</strong></summary>

```md
[![Kindly Made](https://img.shields.io/badge/-kindly-ffaff3?labelColor=2f2f2f&logo=data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9Ijc2OCIgaGVpZ2h0PSI3NjgiIHZpZXdCb3g9IjcyIDcyIDYyNCA2MjQiPgo8ZGVmcz4KICA8cGF0aAogICAgaWQ9InNwYXJrbGUiCiAgICBkPSIKICAgICAgTSAzODQsMzg0CiAgICAgIEMgNDA0IDQ4NCwgMzg0IDQ2NCwgNDg0IDQ4NAogICAgICBDIDM4NCA1MDQsIDQwNCA0ODQsIDM4NCA1ODQKICAgICAgQyAzNjQgNDg0LCAzODQgNTA0LCAyODQgNDg0CiAgICAgIEMgMzg0IDQ2NCwgMzY0IDQ4NCwgMzg0IDM4NAogICAgIgogICAgZmlsbD0iI2ZlZmVmYyIKICAgIHN0cm9rZT0iI2ZlZmVmYyIKICAgIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIKICAgIHN0cm9rZS1saW5lam9pbj0icm91bmQiCiAgICBzdHJva2Utd2lkdGg9IjI0IgogIC8+CjwvZGVmcz4KPHBhdGgKICBpZD0iaGVhcnQiCiAgZD0iCiAgICBNIDQzNiA1NjUKICAgIEwgMzg0IDYwMAogICAgTCAyMTAgNDgwCiAgICBDIC01MCAzMDAsIDIxNCAxMCwgMzg0IDI1MAogICAgQyA1NDcgMjMsIDc3MiAyNzIsIDYxMyA0MzIKICAiCiAgZmlsbC1vcGFjaXR5PSIwIgogIHN0cm9rZT0iI2ZlZmVmYyIKICBzdHJva2UtbGluZWNhcD0icm91bmQiCiAgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIKICBzdHJva2Utd2lkdGg9IjQ1IgovPgo8dXNlIGhyZWY9IiNzcGFya2xlIiB0cmFuc2Zvcm09InNjYWxlKDEuMzUsIDEuMzUpIHRyYW5zbGF0ZSg1LCAtMTE1KSIgLz4KPHVzZSBocmVmPSIjc3BhcmtsZSIgdHJhbnNmb3JtPSJzY2FsZSgwLjYsIDAuNikgdHJhbnNsYXRlKDMwLCAxMCkiIC8+Cjwvc3ZnPgoK)](https://github.com/tynanbe/kindly)
```

</details>

<div align="center">

[![Kindly Made](https://img.shields.io/badge/-kindly-ffaff3?labelColor=2f2f2f&logo=data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9Ijc2OCIgaGVpZ2h0PSI3NjgiIHZpZXdCb3g9IjcyIDcyIDYyNCA2MjQiPgo8ZGVmcz4KICA8cGF0aAogICAgaWQ9InNwYXJrbGUiCiAgICBkPSIKICAgICAgTSAzODQsMzg0CiAgICAgIEMgNDA0IDQ4NCwgMzg0IDQ2NCwgNDg0IDQ4NAogICAgICBDIDM4NCA1MDQsIDQwNCA0ODQsIDM4NCA1ODQKICAgICAgQyAzNjQgNDg0LCAzODQgNTA0LCAyODQgNDg0CiAgICAgIEMgMzg0IDQ2NCwgMzY0IDQ4NCwgMzg0IDM4NAogICAgIgogICAgZmlsbD0iI2ZlZmVmYyIKICAgIHN0cm9rZT0iI2ZlZmVmYyIKICAgIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIKICAgIHN0cm9rZS1saW5lam9pbj0icm91bmQiCiAgICBzdHJva2Utd2lkdGg9IjI0IgogIC8+CjwvZGVmcz4KPHBhdGgKICBpZD0iaGVhcnQiCiAgZD0iCiAgICBNIDQzNiA1NjUKICAgIEwgMzg0IDYwMAogICAgTCAyMTAgNDgwCiAgICBDIC01MCAzMDAsIDIxNCAxMCwgMzg0IDI1MAogICAgQyA1NDcgMjMsIDc3MiAyNzIsIDYxMyA0MzIKICAiCiAgZmlsbC1vcGFjaXR5PSIwIgogIHN0cm9rZT0iI2ZlZmVmYyIKICBzdHJva2UtbGluZWNhcD0icm91bmQiCiAgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIKICBzdHJva2Utd2lkdGg9IjQ1IgovPgo8dXNlIGhyZWY9IiNzcGFya2xlIiB0cmFuc2Zvcm09InNjYWxlKDEuMzUsIDEuMzUpIHRyYW5zbGF0ZSg1LCAtMTE1KSIgLz4KPHVzZSBocmVmPSIjc3BhcmtsZSIgdHJhbnNmb3JtPSJzY2FsZSgwLjYsIDAuNikgdHJhbnNsYXRlKDMwLCAxMCkiIC8+Cjwvc3ZnPgoK)](https://github.com/tynanbe/kindly)

</div>