# dosh - The Simplest Build Tool on Earth
dosh is a minimal task runner pattern for shell scripts. Each dosh script is a standalone bash file where functions become tasks you can run from the command line.
Based on [8gears/do](https://github.com/8gears/do).
## How It Works
A dosh script defines functions, then uses `“$@“` to execute whatever function name is passed as an argument:
```bash #!/usr/bin/env bash
build() {
echo "Building..."
}
test() {
echo "Testing..."
}
“$@” ```
Run it with: ```bash ./dosh build # runs build() ./dosh test # runs test() ```
## Sample Script
A complete sample dosh script is available: [dosh.sh](dosh.sh)
## Convention: Private Functions
Functions starting with `_` are considered private/helper functions and won't appear in usage output or tab completion:
```bash _helper() {
echo "I'm a helper"
}
build() {
_helper echo "Building..."
} ```
## Usage Output
Add this at the end of your dosh script to show available tasks when run without arguments:
```bash “$@” [ “$#” -gt 0 ] || printf “Usage:\n\t./${SCRIPTNAME} %s\n” ”($(compgen -A function | grep '^[^_]' | paste -sd '|' -))” ```
## Tab Completion
### Bash
Add the `–completions` handler to your dosh script, just before the `“$@“` line:
```bash if "$1" == "--completions"; then
compgen -A function | grep '^[^_]' exit 0
fi
“$@” ```
Then add this to your `~/.bashrc`:
```bash _dosh_complete() {
local cur="${COMP_WORDS[COMP_CWORD]}"
local script="${COMP_WORDS[0]}"
COMPREPLY=($(compgen -W "$($script --completions 2>/dev/null)" -- "$cur"))
} complete -F _dosh_complete dosh complete -F _dosh_complete ./dosh ```
After reloading your shell (`source ~/.bashrc`), tab completion will work: ```bash ./dosh bu<TAB> # completes to ./dosh build ```
### Zsh
The same `–completions` handler in your dosh script works for zsh. Add this to your `~/.zshrc`:
```zsh _dosh_complete() {
local completions
completions=(${(f)"$($words[1] --completions 2>/dev/null)"})
_describe 'tasks' completions
} compdef _dosh_complete dosh compdef _dosh_complete ./dosh ```
## direnv Integration
A common pattern is to put dosh in `bin/dosh` and add `bin` to your PATH using direnv. This lets you run `dosh build` instead of `./bin/dosh build` from anywhere in the project.
Example `.envrc`: ```bash PATH_add bin ```
See [envrc](https://code.librehq.com/james/envrc) for a more complete direnv setup.
With this pattern, add a completion registration for `dosh` (without the `./`):
```bash complete -F _dosh_complete dosh # bash compdef _dosh_complete dosh # zsh ```
## Tips
- Root access: Functions needing root should check for it and fail early - Working directory: Use `BASEDIR` to ensure consistent paths regardless of where the script is invoked from - Dependencies: Consider a `deps` or `setup-dev` task to install required tools
