Installation
With cargo (recommended):
cargo install jake
With npm:
npm install -g @cle-does-things/jake@latest
Initialization
You can create a boilerplate jakefile.toml with the --init option:
jake --init "task1,task2" # tasks need to be provided as a comma-separated list
This will write a jakefile.toml in the current working directory, which will look like this:
task1 = "echo 'No task yet for task1'"
task2 = "echo 'No task yet for task2'"
You can then customize the file as needed.
Task Definition
Tasks are defined in a file called jakefile.toml placed either in the working directory where jake is executed, or anywhere up the directory tree. Each entry in the file represents a task, mapping a task name to either a plain string command or an object with additional configuration.
A task can be defined in two ways:
As a plain string: use this when the task has no dependencies:
say-hello = "echo 'hello'"
list = "ls"
As an object: use this when you need to specify dependencies:
say-hello-back = { command = "echo 'hello back'" }
say-bye = { command = "echo 'bye'", depends_on = ["say-hello", "say-hello-back"] }
The anatomy of an object task is as follows:
say-bye = { command = "echo 'bye'", depends_on = ["say-hello", "say-hello-back"] }
| | |
Task name Command to execute Array of tasks to be executed before
the task itself
command is required when using the object syntax, unless you use script instead (see below). depends_on is optional: if omitted, the task runs with no prerequisites.
Inline Scripts
Instead of command, you can use script to write code directly in jakefile.toml. The first line of the script must be the language identifier, followed by the code:
[python]
script = """py
def sum_ints(x: int, y: int) -> int:
return x + y
print(sum_ints(1, 2))
"""
[javascript]
script = """javascript
function main() {
console.log('hello world')
}
main()
"""
[typescript]
script = """ts
console.log('hey there, great to run TS!')
"""
Supported language identifiers:
| Language | Identifiers |
|---|---|
| Python | py, python |
| JavaScript | js, javascript |
| TypeScript | ts, typescript |
| Ruby | rb, ruby |
| PHP | php |
| Lua | lua |
| Perl | perl |
Scripts are executed by invoking the appropriate interpreter (e.g. python3 -c, node -e, npx tsx -e).
The Default Task
You can designate a task to run when no task name is passed to jake by naming it default:
default = { command = "cat README.md" }
If no default task is explicitly defined, jake will fall back to the first task in the file.
Tasks Referencing Environment Variables
You can use environment variables inside any task command:
env_var = "echo $HELLO"
jake resolves environment variables from export statements or a .env file, either in the working directory where jake is executed, or anywhere up the directory tree.
To enable loading .env files, you need to provide the --env flag to the jake command.
Full Example
default = { command = "cat README.md" }
say-hello = "echo 'hello'"
say-hello-back = { command = "echo 'hello back'" }
say-bye = { command = "echo 'bye'", depends_on = ["say-hello", "say-hello-back"] }
list = "ls"
Running Tasks
jake can be invoked from any subdirectory of the project: it will walk up the directory tree to locate the nearest jakefile.toml.
List all available tasks
jake --list
Execute the default task
jake
Execute a specific task
jake say-hello
'hello'
Execute a task with dependencies
When a task declares depends_on, all listed tasks are executed first, in order, before the task itself runs:
jake say-bye
'hello'
'hello back'
'bye'
Dry-run (print commands without running them)
Use --dry-run to print each command that would be run, in order, without executing anything. Useful for debugging or auditing task graphs.
jake say-bye --dry-run
echo 'hello'
echo 'hello back'
echo 'bye'
Pass additional options to a task
You can forward extra flags to the underlying command using --options:
jake list --options "-la"
This will output:
total 48
drwxr-xr-x@ 10 user staff 320 Feb 13 11:14 .
drwxr-xr-x@ 125 user staff 4000 Feb 13 10:20 ..
drwxr-xr-x@ 9 user staff 288 Feb 13 10:20 .git
-rw-r--r--@ 1 user staff 8 Feb 13 10:20 .gitignore
-rw-r--r--@ 1 user staff 7656 Feb 13 11:13 Cargo.lock
-rw-r--r--@ 1 user staff 162 Feb 13 11:13 Cargo.toml
-rw-r--r--@ 1 user staff 332 Feb 13 11:21 jakefile.toml
-rw-r--r--@ 1 user staff 152 Feb 13 11:16 README.md
drwxr-xr-x@ 4 user staff 128 Feb 13 10:22 src
drwxr-xr-x@ 6 user staff 192 Feb 13 10:22 target
The value passed to --options is appended to the task’s command at execution time, so jake list --options "-la" effectively runs ls -la.
Load a .env file and execute a task
If a task requires an environment variable, e.g.:
env_var = "echo $HELLO"
You can either provide it with an export statement or define it within a .env file:
HELLO="hello"
Now run jake with --env:
jake env_var --env
Output:
hello
Running scripts defined in a package.json
In environments such as JavaScript or TypeScript codebases, jake can execute scripts contained in package.json.
With scripts defined like this in package.json:
{
"scripts": {
"build": "bun build src/index.ts --outdir ./dist --target node"
}
}
jake can execute the build script as its own task by using the --js flag:
jake build --js
Which would output:
Bundled 1 module in 20ms
index.js 0.66 KB (entry point)
package.json can be placed either in the working directory where jake is executed, or anywhere up the directory tree.