kindly 💖
A nice little task runner

Hex Docs License Build  •  Hex Package npm Package JSR Package
Works With Gleam Works With TypeScript Works With JavaScript  •  Runs With Node.js Runs With Deno Runs With Bun
Kindly Made

Quickstart  •  API Reference  •  Examples

• • •

Table of Contents

  1. Features
  2. Example
  3. About
  4. Try It
  5. Installation
  6. Run It
  7. Completions
  8. Where Next?
  9. Support

Features

Example

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"]),
  )
}
TypeScript & JavaScript
// 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"),
  });

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:

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):

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.

Try It

Gleam
# 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
Bun
# Print help info
bunx --bun @tynanbe/kindly
# Run an example task
bunx --bun @tynanbe/kindly format-check
Deno
# Print help info
deno run --allow-all --reload jsr:@tynanbe/kindly
# Run an example task
deno run -Ar jsr:@tynanbe/kindly format-check
Node.js
# Print help info
npx @tynanbe/kindly
# Run an example task
npx @tynanbe/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 support.

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.

Bun
bun install --global @tynanbe/kindly
Deno
deno install --global --allow-all jsr:@tynanbe/kindly
Node.js
# Or similar for pnpm, yarn, etc.
npm install --global @tynanbe/kindly

Run It

# 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 support.

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.

Bash

Bash Completion Demo

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

Fish Completion Demo

# ~/.config/fish/config.fish
if type kindly >/dev/null 2>&1
    kindly --cue fish | source
end
PowerShell (pwsh)

Pwsh PowerShell Completion Demo

# ~/.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
Zsh

Zsh Completion Demo

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

Where Next?

Quickstart

API Reference

Examples

Support

Contributions are welcome. Feel free to open an issue 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.

Kindly Badge Markdown
[![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)

Kindly Made

Search Document