Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Manual

First Taskfile

Create a taskfile:

cj --init

Add a task:

hello:
  @echo hello

Run it:

cj hello

Run cj without a task name to list visible tasks.

See CLI Reference and Taskfile Reference.

Descriptions And Help

Use @desc for the one-line summary shown by cj.

check:
  @desc run the test suite
  cargo test --locked

Use @help: for block-form help text shown by cj help and cj help <task>.

Tasks beginning with _ stay hidden from summary mode.

_clean-cache:
  rm -rf .cache

See @desc, @help:, and @selfhelp.

Commands

Ordinary commands run directly, without shell parsing.

check:
  cargo test --locked

Use @shell when you need redirection, pipes, glob expansion, or command chaining.

bundle:
  @shell mkdir -p dist && cat src/*.js > dist/app.js

See Taskfile Reference and @shell.

Nested Tasks

Nested tasks are addressed with colon-separated names. Tasks can only be nested one level.

build:
  @desc build commands

  cli:
    @desc build the CLI
    cargo build --release
cj build:cli

See Taskfile Reference.

Task Calls

Use @task when one task should run another task.

ci:
  @task fmt
  @task test

fmt:
  cargo fmt --check

test:
  cargo test --locked

See @task.

Arguments

Declare required arguments beside the task name.

greet (NAME):
  @echo hello $NAME
cj greet Ada

Arguments are required. Optional, default, and variadic arguments are not part of the format.

See Taskfile Reference.

Working directory

  • Always starts in the same directory of the taskfile, no matter where it is called from.
  • Directory changes via @cd persist for later lines in the same task context.
  • Called tasks receive the caller’s current directory as their baseline, but their directory changes reset when they return.

Variable definition

CJTaskrunner runs in an isolated snapshot of your environment which inherits all your environment variables. They can be used in your tasks by prefixing their name with a dollar sign ($) and CJTaskrunner will replace them with their value before doing anything else.

Define and set new variables using @set.

dev:
  @set foo BAR
  @echo foo $foo

Use its block form, @set VAR: to capture the output of commands:

branch:
  @set BRANCH:
    git rev-parse --abbrev-ref HEAD
  @echo $BRANCH

In order to persist the variable across taskrunner tasks and make it visible to child processes, use @export.

run:
  @export NODE_ENV production
  node server.js

@export can be used with the variable name and no value assignment and it will export whatever the existing value is.

Use @env: to set multiple taskfile-wide values. These are automatically exported. A ? means only set if not yet set.

@env:
  PORT?: 5173
  MYHOST?: http://localhost
  NODE_ENV?: production

dev:
  npm run dev -- --port $PORT --host $MYHOST

Variable usage

You can use variables by prefixing the name with a $. This is done before the task is parsed. You can substitute variable for a directive argument.

You can set a default for a variable or make a value mandatory when using them. Use ${NAME} when a value must exist, and ${NAME?fallback} for local fallback values.

You cannot use a variable as the name of a command in a task definition, nor can you substitute the name of a directive using a variable.

Directives that require the name of a variable (@if-set, @set, @export) expect a string value; if you include a $ in front of a variable name, it will resolve the value as the name.

  • Unexported variables set with @set are only accessible from the same task context. Subordinate tasks receive them as a snapshot, but changes do not propagate back.

  • Setting an environment variable using the @env: directive, or using @export on a variable will affect the taskfile execution context.

  • Pre-existing environment variables will be restored after the task runs. Variables and environment variable changes within the taskrunner context will be discarded after the task run.

See Variables Reference.

Parallel Tasks

Use @await when independent task branches can run at the same time.

dev:
  client:
    npm run dev
  server:
    node server.js

  @await dev:client dev:server
    @open http://localhost:5173
  @or
    @echo startup failed
    @stop

@await waits for all named tasks. Its block runs only when all awaited tasks succeed.

See @await.

Watch Tasks

Use @watch to restart one long-running line when files change.

docs:
  @watch docs
    mdbook serve

See @watch.

Conditional Logic

Use @if, @else, @and, and @or for status-based flow.

cond:
  @set MODE release
  @if $MODE == release
    cargo build --release
  @else
    cargo build

Use @if-in for list membership.

compile (TARGET):
  @if-in $TARGET linux macos windows
    @echo supported target

Every @if directive has a matching negative form such as @if-not or @if-not-in.

See Flow Control Directives.

Versions

Declare component versions with @version, then bump them with @patch, @minor, @major, @pre, or @release.

@version cli 0.1.0

bump:
  @patch cli
  @echo $VERSION_CLI

See SemVer Tools.