task Documentation

A fast, cross-platform build tool inspired by Make, designed for modern workflows.

16,249 stars Go Go 1 file Β· ~125,210 tokens #build-tool#devops#go#make#makefile#task#task-runner#taskfile
RAW Doc

Technical Documentation: go-task/task

ℹ️ Provenance: Multi-Tier Ingestion Β· CodeWiki Reference

Overview (`README.md`)


Website Src Latest Docs Getting Started (`website/src/latest/docs/getting-started.md`)


title: Quick Start section: Getting Started docType: guide outline: deep

Quick Start {#getting-started}

The following guide will help introduce you to the basics of Task. We'll cover
how to create a Taskfile, how to write a basic task and how to call it. If you
haven't installed Task yet, head over to our
installation guide.

Creating your first Taskfile

Once Task is installed, you can create your first Taskfile by running:

shell
task --init

This will create a file called Taskfile.yml in the current directory. If you
want to create the file in another directory, you can pass an absolute or
relative path to the directory into the command:

shell
task --init ./subdirectory

Or if you want the Taskfile to have a specific name, you can pass in the name of
the file:

shell
task --init Custom.yml

This will create a Taskfile that looks something like this:

yaml [taskfile.yml]
version: '3'

vars:
  GREETING: Hello, World!

tasks:
  default:
    desc: Print a greeting message
    cmds:
      - echo "{{.GREETING}}"
    silent: true

As you can see, all Taskfiles are written in YAML format.
The version attribute specifies the minimum version of Task that can be used
to run this file. The vars attribute is used to define variables that can be
used in tasks. In this case, we are creating a string variable called GREETING
with a value of Hello, World!.

Finally, the tasks attribute is used to define the tasks that can be run. In
this case, we have a task called default that echoes the value of the
GREETING variable. The silent attribute is set to true, which means that
the task metadata will not be printed when the task is run - only the output of
the commands.

Calling a task

To call the task, invoke task followed by the name of the task you want to
run. In this case, the name of the task is default, so you should run:

shell
task default

Note that we don't have to specify the name of the Taskfile. Task will
automatically look for a file called Taskfile.yml (or any of Task's
supported file names) in the
current directory. Additionally, tasks with the name default are special. They
can also be run without specifying the task name.

If you created a Taskfile in a different directory, you can run it by passing
the absolute or relative path to the directory as an argument using the --dir
flag:

shell
task --dir ./subdirectory

Or if you created a Taskfile with a different name, you can run it by passing
the name of the Taskfile as an argument using the --taskfile flag:

shell
task --taskfile Custom.yml

Adding a build task

Let's create a task to build a program in Go. Start by adding a new task called
build below the existing default task. We can then add a cmds attribute
with a single command to build the program.

Task uses mvdan/sh, a native Go sh interpreter.
So you can write sh/bash-like commands - even in environments where sh or
bash are usually not available (like Windows). Just remember any executables
called must be available as a built-in or in the system's PATH.

When you're done, it should look something like this:

yaml
version: '3'

vars:
  GREETING: Hello, World!

tasks:
  default:
    desc: Print a greeting message
    cmds:
      - echo "{{.GREETING}}"
    silent: true

  build:
    cmds:
      - go build ./cmd/main.go

Call the task by running:

shell
task build

That's about it for the basics, but there's so much more that you can do with
Task. Check out the rest of the documentation to learn more about all the
features Task has to offer! We recommend taking a look at the
usage guide next. Alternatively, you can check out our
reference docs for the Taskfile schema and
CLI.


Website Src Latest Docs Index (`website/src/latest/docs/index.md`)


title: Documentation Task is a task runner and build tool that aims to be simpler and easier to use than GNU Make. Start here to install it, learn it, or look something up. section: Overview docType: overview aside: false outline: false pageClass: docs-overview

Documentation

Install Task, learn the basics, or look up syntax for your Taskfile.yml.

Start with Task {#new-to-task}

Install Task and run your first Taskfile.

Use Task {#using-task}

Find a guide for your everyday workflows.

Reference {#looking-something-up}

Look up syntax, flags and functions.

For settings outside the Taskfile, see Configuration
and Environment.

Keeping up

Using an AI coding assistant

Task documentation for coding agents is a compact map of these
pages plus the semantics that are easiest to get wrong. Every page is also
available as raw Markdown by appending .md to its URL, and the whole corpus is
at /llms.txt.


Website Src Next Docs Getting Started (`website/src/next/docs/getting-started.md`)


title: Quick Start section: Getting Started docType: guide outline: deep

Quick Start {#getting-started}

The following guide will help introduce you to the basics of Task. We'll cover
how to create a Taskfile, how to write a basic task and how to call it. If you
haven't installed Task yet, head over to our
installation guide.

Creating your first Taskfile

Once Task is installed, you can create your first Taskfile by running:

shell
task --init

This will create a file called Taskfile.yml in the current directory. If you
want to create the file in another directory, you can pass an absolute or
relative path to the directory into the command:

shell
task --init ./subdirectory

Or if you want the Taskfile to have a specific name, you can pass in the name of
the file:

shell
task --init Custom.yml

This will create a Taskfile that looks something like this:

yaml [taskfile.yml]
version: '3'

vars:
  GREETING: Hello, World!

tasks:
  default:
    desc: Print a greeting message
    cmds:
      - echo "{{.GREETING}}"
    silent: true

As you can see, all Taskfiles are written in YAML format.
The version attribute specifies the minimum version of Task that can be used
to run this file. The vars attribute is used to define variables that can be
used in tasks. In this case, we are creating a string variable called GREETING
with a value of Hello, World!.

Finally, the tasks attribute is used to define the tasks that can be run. In
this case, we have a task called default that echoes the value of the
GREETING variable. The silent attribute is set to true, which means that
the task metadata will not be printed when the task is run - only the output of
the commands.

Calling a task

To call the task, invoke task followed by the name of the task you want to
run. In this case, the name of the task is default, so you should run:

shell
task default

Note that we don't have to specify the name of the Taskfile. Task will
automatically look for a file called Taskfile.yml (or any of Task's
supported file names) in the
current directory. Additionally, tasks with the name default are special. They
can also be run without specifying the task name.

If you created a Taskfile in a different directory, you can run it by passing
the absolute or relative path to the directory as an argument using the --dir
flag:

shell
task --dir ./subdirectory

Or if you created a Taskfile with a different name, you can run it by passing
the name of the Taskfile as an argument using the --taskfile flag:

shell
task --taskfile Custom.yml

Adding a build task

Let's create a task to build a program in Go. Start by adding a new task called
build below the existing default task. We can then add a cmds attribute
with a single command to build the program.

Task uses mvdan/sh, a native Go sh interpreter.
So you can write sh/bash-like commands - even in environments where sh or
bash are usually not available (like Windows). Just remember any executables
called must be available as a built-in or in the system's PATH.

When you're done, it should look something like this:

yaml
version: '3'

vars:
  GREETING: Hello, World!

tasks:
  default:
    desc: Print a greeting message
    cmds:
      - echo "{{.GREETING}}"
    silent: true

  build:
    cmds:
      - go build ./cmd/main.go

Call the task by running:

shell
task build

That's about it for the basics, but there's so much more that you can do with
Task. Check out the rest of the documentation to learn more about all the
features Task has to offer! We recommend taking a look at the
usage guide next. Alternatively, you can check out our
reference docs for the Taskfile schema and
CLI.


Website Src Next Docs Index (`website/src/next/docs/index.md`)


title: Documentation Task is a task runner and build tool that aims to be simpler and easier to use than GNU Make. Start here to install it, learn it, or look something up. section: Overview docType: overview aside: false outline: false pageClass: docs-overview

Documentation

Install Task, learn the basics, or look up syntax for your Taskfile.yml.

Start with Task {#new-to-task}

Install Task and run your first Taskfile.

Use Task {#using-task}

Find a guide for your everyday workflows.

Reference {#looking-something-up}

Look up syntax, flags and functions.

For settings outside the Taskfile, see Configuration
and Environment.

Keeping up

Using an AI coding assistant

Task documentation for coding agents is a compact map of these
pages plus the semantics that are easiest to get wrong. Every page is also
available as raw Markdown by appending .md to its URL, and the whole corpus is
at /llms.txt.


Website Src Latest Docs Deprecations Index (`website/src/latest/docs/deprecations/index.md`)


title: Deprecations Guide to deprecated features in Task and how to migrate to the new alternatives section: Project docType: project outline: deep

Deprecations

As Task evolves, it occasionally outgrows some of its functionality. This can be
because they are no longer useful, because another feature has replaced it or
because of a change in the way that Task works internally.

When this happens, we mark the functionality as deprecated. This means that it
will be removed in a future version of Task. This functionality will continue to
work until that time, but we strongly recommend that you do not implement this
functionality in new Taskfiles and make a plan to migrate away from it as soon
as possible.

You can view a full list of active deprecations in the "Deprecations" section of
the sidebar.


Website Src Latest Docs Experiments Index (`website/src/latest/docs/experiments/index.md`)


title: Experiments section: Project docType: project outline: deep

Experiments

::: warning

All experimental features are subject to breaking changes and/or removal at any
time
. We strongly recommend that you do not use these features in a production
environment. They are intended for testing and feedback only.

:::

In order to allow Task to evolve quickly, we sometimes roll out breaking changes
to minor versions behind experimental flags. This allows us to gather feedback
on breaking changes before committing to a major release. This process can also
be used to gather feedback on important non-breaking features before their
design is completed. This document describes the
experiment workflow and how you can get involved.

You can view the full list of active experiments in the sidebar submenu to the
left of the page and click on each one to find out more about it.

Enabling Experiments

Task uses environment variables to detect whether or not an experiment is
enabled. All of the experiment variables will begin with the same TASK_X_
prefix followed by the name of the experiment. You can find the exact name for
each experiment on their respective pages in the sidebar. If the variable is set
=1 then it will be enabled. Some experiments may have multiple proposals, in
which case, you will need to set the variable equal to the number of the
proposal that you want to enable (=2, =3 etc).

There are three main ways to set the environment variables for an experiment.
Which method you use depends on how you intend to use the experiment:

  1. Prefixing your task commands with the relevant environment variable(s). For
    example, TASK_X_{FEATURE}=1 task {my-task}. This is intended for one-off
    invocations of Task to test out experimental features.

  2. Adding the relevant environment variable(s) in your "dotfiles" (e.g.
    .bashrc, .zshrc etc.). This will permanently enable experimental features
    for your personal environment.

    shell
    # ~/.bashrc
    export TASK_X_FEATURE=1
  3. Creating a .env or a .taskrc.yml file in the same directory as your root
    Taskfile.
    The .env file should contain the relevant environment variable(s), while
    the .taskrc.yml file should use a YAML format where each experiment is
    defined as a key with a corresponding value.

    This allows you to enable an experimental feature at a project level. If you
    commit this file to source control, then other users of your project will
    also have these experiments enabled.

    If both files are present, the values in the .taskrc.yml file will take
    precedence.

::: code-group

yaml [.taskrc.yml]
experiments:
  FEATURE: 1
shell [.env]
TASK_X_FEATURE=1

:::

Workflow

Experiments are a way for us to test out new features in Task before committing
to them in a major release. Because this concept is built around the idea of
feedback from our community, we have built a workflow for the process of
introducing these changes. This ensures that experiments are given the attention
and time that they need and that we are getting the best possible results out of
them.

The sections below describe the various stages that an experiment must go
through from its proposal all the way to being released in a major version of
Task.

1. Proposal

All experimental features start with a proposal in the form of a GitHub issue.
If the maintainers decide that an issue has enough support and is a breaking
change or is complex/controversial enough to require user feedback, then the
issue's experiment status field will be set to proposed. At this point, the
issue becomes a proposal and a period of consultation begins. During this
period, we request that users provide feedback on the proposal and how it might
effect their use of Task. It is up to the discretion of the maintainers to
decide how long this period lasts.

2. Draft

Once a proposal's consultation ends, a contributor may pick up the work and
begin the initial implementation. Once a PR is opened, the maintainers will
ensure that it meets the requirements for an experimental feature (i.e. flags
are in the right format etc) and merge the feature. Once this code is released,
the experiment status field will be updated to draft. This indicates that an
implementation is now available for use in a release and the experiment is open
for feedback.

::: info

During the draft period, major changes to the implementation may be made based
on the feedback received from users. There are no stability guarantees and
experimental features may be abandoned at any time.

:::

3. Candidate

Once an acceptable level of consensus has been reached by the community and
feedback/changes are less frequent/significant, the experiment status field will
be updated to candidate. This indicates that a proposal is likely to
accepted and will enter a period for final comments and minor changes.

4. Stable

Once a suitable amount of time has passed with no changes or feedback, the
experiment status field will be updated to stable. At this point, the
functionality will be treated like any other feature in Task and any changes
must be backward compatible. This allows users to migrate to the new
functionality without having to worry about anything breaking in future
releases. This provides the best experience for users migrating to a new major
version.

5. Released

When an experiment moves to a released status, it becomes the default behavior
and flags or config are no longer required to enable the feature. For
non-breaking changes, this will happen in a minor release. For breaking changes,
this will happen in a major release.

Abandoned / Superseded

If an experiment is unsuccessful at any point then the experiment status field
will be updated to abandoned or superseded depending on which is more
suitable. These experiments will be removed from Task.


Website Src Latest Docs Guide Index (`website/src/latest/docs/guide/index.md`)


title: Guide Learn to define tasks, supply inputs, control execution, configure the environment and output, and include other Taskfiles. section: Guide docType: guide outline: deep

Guide

Use the guide to learn a feature or solve a specific problem. If you are new to
Task, start with the Quick Start. For accepted keys,
flags and functions, use the Taskfile Schema,
CLI and Templating
references.

Writing and running tasks {#writing-and-running-tasks}

  • Defining tasks: command lists, descriptions, aliases
    and display labels.
  • Running tasks: choosing a Taskfile, running from other
    directories, previewing commands and using interactive applications.

Variables and arguments {#variables-and-environment}

  • Variables: declaring values, computing them with shell
    commands, preserving types and understanding resolution order.
  • Command-line arguments: assigning variables, forwarding
    arguments with -- and capturing values from task names.
  • Validation and prompts: requiring inputs,
    restricting allowed values and asking for missing values.
  • Secret variables: loading sensitive values and
    masking them in Task's command logs.

Task execution {#controlling-what-runs}

  • Dependencies and task calls: running tasks concurrently
    or in sequence, limiting concurrency and controlling repeated calls.
  • Loops: repeating commands or task calls over values, files and
    matrices.
  • Conditional execution: skipping optional work
    with if, enforcing requirements with preconditions and asking for
    confirmation.
  • Errors and cleanup: continuing after selected
    failures and running cleanup with defer.
  • Up-to-date checks: skipping unchanged builds, checking for
    missing outputs and combining file checks with custom conditions.
  • Watch mode: rerunning tasks when source files change.

Environment and output {#execution-environment}

  • Environment variables: setting the environment for
    commands and loading .env files.
  • Platforms and shells: selecting platform-specific commands,
    understanding shell context and setting shell options.
  • Output and logging: streaming, grouping and prefixing output,
    hiding command echoes and displaying CI annotations.

Including Taskfiles {#composing-taskfiles}

  • Including Taskfiles: sharing tasks with namespaces,
    configuring includes and passing variables to them.
  • Remote Taskfiles: loading Taskfiles over HTTP or Git
    and managing trust, checksums and cached copies.

Website Src Latest Docs Security Index (`website/src/latest/docs/security/index.md`)


title: Security How to report Task security vulnerabilities and how the project responds to them section: Project docType: project outline: deep

Security

The Task team takes security seriously and we thank our community for disclosing
issues responsibly. To report security issues, please use GitHub's built-in
Private Vulnerability Reporting
or send an email to
[email protected]. Please include as much detail as
possible in your report.

A member of the team will investigate as soon as possible and we will keep you
updated throughout the process.

You can read more about how we handle security-related issues in our Incident
Response Plan
and Threat Model.


Website Src Next Docs Deprecations Index (`website/src/next/docs/deprecations/index.md`)


title: Deprecations Guide to deprecated features in Task and how to migrate to the new alternatives section: Project docType: project outline: deep

Deprecations

As Task evolves, it occasionally outgrows some of its functionality. This can be
because they are no longer useful, because another feature has replaced it or
because of a change in the way that Task works internally.

When this happens, we mark the functionality as deprecated. This means that it
will be removed in a future version of Task. This functionality will continue to
work until that time, but we strongly recommend that you do not implement this
functionality in new Taskfiles and make a plan to migrate away from it as soon
as possible.

You can view a full list of active deprecations in the "Deprecations" section of
the sidebar.


Website Src Next Docs Experiments Index (`website/src/next/docs/experiments/index.md`)


title: Experiments section: Project docType: project outline: deep

Experiments

::: warning

All experimental features are subject to breaking changes and/or removal at any
time
. We strongly recommend that you do not use these features in a production
environment. They are intended for testing and feedback only.

:::

In order to allow Task to evolve quickly, we sometimes roll out breaking changes
to minor versions behind experimental flags. This allows us to gather feedback
on breaking changes before committing to a major release. This process can also
be used to gather feedback on important non-breaking features before their
design is completed. This document describes the
experiment workflow and how you can get involved.

You can view the full list of active experiments in the sidebar submenu to the
left of the page and click on each one to find out more about it.

Enabling Experiments

Task uses environment variables to detect whether or not an experiment is
enabled. All of the experiment variables will begin with the same TASK_X_
prefix followed by the name of the experiment. You can find the exact name for
each experiment on their respective pages in the sidebar. If the variable is set
=1 then it will be enabled. Some experiments may have multiple proposals, in
which case, you will need to set the variable equal to the number of the
proposal that you want to enable (=2, =3 etc).

There are three main ways to set the environment variables for an experiment.
Which method you use depends on how you intend to use the experiment:

  1. Prefixing your task commands with the relevant environment variable(s). For
    example, TASK_X_{FEATURE}=1 task {my-task}. This is intended for one-off
    invocations of Task to test out experimental features.

  2. Adding the relevant environment variable(s) in your "dotfiles" (e.g.
    .bashrc, .zshrc etc.). This will permanently enable experimental features
    for your personal environment.

    shell
    # ~/.bashrc
    export TASK_X_FEATURE=1
  3. Creating a .env or a .taskrc.yml file in the same directory as your root
    Taskfile.
    The .env file should contain the relevant environment variable(s), while
    the .taskrc.yml file should use a YAML format where each experiment is
    defined as a key with a corresponding value.

    This allows you to enable an experimental feature at a project level. If you
    commit this file to source control, then other users of your project will
    also have these experiments enabled.

    If both files are present, the values in the .taskrc.yml file will take
    precedence.

::: code-group

yaml [.taskrc.yml]
experiments:
  FEATURE: 1
shell [.env]
TASK_X_FEATURE=1

:::

Workflow

Experiments are a way for us to test out new features in Task before committing
to them in a major release. Because this concept is built around the idea of
feedback from our community, we have built a workflow for the process of
introducing these changes. This ensures that experiments are given the attention
and time that they need and that we are getting the best possible results out of
them.

The sections below describe the various stages that an experiment must go
through from its proposal all the way to being released in a major version of
Task.

1. Proposal

All experimental features start with a proposal in the form of a GitHub issue.
If the maintainers decide that an issue has enough support and is a breaking
change or is complex/controversial enough to require user feedback, then the
issue's experiment status field will be set to proposed. At this point, the
issue becomes a proposal and a period of consultation begins. During this
period, we request that users provide feedback on the proposal and how it might
effect their use of Task. It is up to the discretion of the maintainers to
decide how long this period lasts.

2. Draft

Once a proposal's consultation ends, a contributor may pick up the work and
begin the initial implementation. Once a PR is opened, the maintainers will
ensure that it meets the requirements for an experimental feature (i.e. flags
are in the right format etc) and merge the feature. Once this code is released,
the experiment status field will be updated to draft. This indicates that an
implementation is now available for use in a release and the experiment is open
for feedback.

::: info

During the draft period, major changes to the implementation may be made based
on the feedback received from users. There are no stability guarantees and
experimental features may be abandoned at any time.

:::

3. Candidate

Once an acceptable level of consensus has been reached by the community and
feedback/changes are less frequent/significant, the experiment status field will
be updated to candidate. This indicates that a proposal is likely to
accepted and will enter a period for final comments and minor changes.

4. Stable

Once a suitable amount of time has passed with no changes or feedback, the
experiment status field will be updated to stable. At this point, the
functionality will be treated like any other feature in Task and any changes
must be backward compatible. This allows users to migrate to the new
functionality without having to worry about anything breaking in future
releases. This provides the best experience for users migrating to a new major
version.

5. Released

When an experiment moves to a released status, it becomes the default behavior
and flags or config are no longer required to enable the feature. For
non-breaking changes, this will happen in a minor release. For breaking changes,
this will happen in a major release.

Abandoned / Superseded

If an experiment is unsuccessful at any point then the experiment status field
will be updated to abandoned or superseded depending on which is more
suitable. These experiments will be removed from Task.


Website Src Next Docs Guide Index (`website/src/next/docs/guide/index.md`)


title: Guide Learn to define tasks, supply inputs, control execution, configure the environment and output, and include other Taskfiles. section: Guide docType: guide outline: deep

Guide

Use the guide to learn a feature or solve a specific problem. If you are new to
Task, start with the Quick Start. For accepted keys,
flags and functions, use the Taskfile Schema,
CLI and Templating
references.

Writing and running tasks {#writing-and-running-tasks}

  • Defining tasks: command lists, descriptions, aliases
    and display labels.
  • Running tasks: choosing a Taskfile, running from other
    directories, previewing commands and using interactive applications.

Variables and arguments {#variables-and-environment}

  • Variables: declaring values, computing them with shell
    commands, preserving types and understanding resolution order.
  • Command-line arguments: assigning variables, forwarding
    arguments with -- and capturing values from task names.
  • Validation and prompts: requiring inputs,
    restricting allowed values and asking for missing values.
  • Secret variables: loading sensitive values and
    masking them in Task's command logs.

Task execution {#controlling-what-runs}

  • Dependencies and task calls: running tasks concurrently
    or in sequence, limiting concurrency and controlling repeated calls.
  • Loops: repeating commands or task calls over values, files and
    matrices.
  • Conditional execution: skipping optional work
    with if, enforcing requirements with preconditions and asking for
    confirmation.
  • Errors and cleanup: continuing after selected
    failures and running cleanup with defer.
  • Up-to-date checks: skipping unchanged builds, checking for
    missing outputs and combining file checks with custom conditions.
  • Watch mode: rerunning tasks when source files change.

Environment and output {#execution-environment}

  • Environment variables: setting the environment for
    commands and loading .env files.
  • Platforms and shells: selecting platform-specific commands,
    understanding shell context and setting shell options.
  • Output and logging: streaming, grouping and prefixing output,
    hiding command echoes and displaying CI annotations.

Including Taskfiles {#composing-taskfiles}

  • Including Taskfiles: sharing tasks with namespaces,
    configuring includes and passing variables to them.
  • Remote Taskfiles: loading Taskfiles over HTTP or Git
    and managing trust, checksums and cached copies.

Website Src Next Docs Security Index (`website/src/next/docs/security/index.md`)


title: Security How to report Task security vulnerabilities and how the project responds to them section: Project docType: project outline: deep

Security

The Task team takes security seriously and we thank our community for disclosing
issues responsibly. To report security issues, please use GitHub's built-in
Private Vulnerability Reporting
or send an email to
[email protected]. Please include as much detail as
possible in your report.

A member of the team will investigate as soon as possible and we will keep you
updated throughout the process.

You can read more about how we handle security-related issues in our Incident
Response Plan
and Threat Model.


Website Src Latest Docs Changelog (`website/src/latest/docs/changelog.md`)


Changelog

::: v-pre

v3.54.0 - 2026-10-01

πŸš€ Features

  • Added versioned Homebrew casks (go-task@<major>.<minor>) to install a
    specific minor version of Task (#3023 by @vmaerten).
  • Added a remote.headers config option to send HTTP headers when downloading a
    remote Taskfile, configured per host. Header values support templating
    functions, e.g. {{env "GITLAB_TOKEN"}}. This keeps the credential out of the
    include URL, where it would leak into error messages and the confirmation
    prompt (#2329 by @vmaerten).

πŸ› Fixes

  • Fixed remote Git Taskfile cache poisoning on shared hosts (GHSA-679p-658w-m3wr,
    reported by @danielcadev, fixed by @vmaerten).

  • Fixed tasks cancelled by the user returning exit code 201 instead of 205
    (#3040, #3041 by @r3wretrhy).

  • Fixed a bug on Windows where watching source paths did not work as expected
    (#2863, #3028 by @pd93).

  • Fixed a remote Taskfile whose server refuses the credentials being reported as
    a missing Taskfile. A 401 now stops the search and reports the status code,
    instead of retrying every default Taskfile name and concluding that no
    Taskfile exists (#2329 by @vmaerten).

  • task --completion <shell> now serves a new completion engine that unifies
    Bash, Fish, Zsh, Nushell and PowerShell behind a single task __complete
    command, so every shell offers the same suggestions: task names, aliases,
    flags, flag values and per-task CLI variables. The Zsh show-aliases and
    verbose zstyles keep working, now backed by the --no-aliases and
    --no-descriptions completion flags (#2897 by @vmaerten).

πŸ“¦ Package API

  • Bumped the minimum Go version to 1.26. Task follows Go's two-latest support
    window, and is now tested against 1.26 and 1.27. This only affects projects
    importing Task as a Go module (#2920 by @vmaerten).

Other

  • Refactored some functional options to always return a concrete type instead of
    an interface and moved options into their own file (#3037 by @pd93).
  • Refactored the execext package to use mvdan/sh's new BashOpts API (#3035 by
    @pd93).

v3.53.1 - 2026-08-18

πŸš€ Features

  • Remote Taskfiles are now generally available! This has been an
    experimental feature for 3 years, but is now enabled by default. Massive
    thanks to all those that contributed and gave feedback (too many to list
    here). We've also given the
    Remote Taskfiles documentation a
    bit of a polish (#1317, #2906 by @pd93).
  • Added a per-command timeout that terminates a command once it exceeds the
    given duration (Go duration syntax). It covers shell commands, task calls,
    deferred commands, deps and the if condition, obeys ignore_error, and
    reports exit code 124. Callers that join a run: once or when_changed
    task already running now honor their own timeout, and inherit that task's
    failure instead of being told it succeeded (#1569, #2898 by @vmaerten).
  • Considerably improve performance of fingerprinting on large repositories
    (monorepos). Fingerprinting is up to 86% faster and make up to 70% fewer
    memory allocations on the more advanced scenarios. Benchmarks were added as
    well. We're basically skipping work when not needed. (#2853, #2883 by
    @Napolitain, #2884 by @Napolitain).
  • Further improved fingerprinting performance on large repositories: hashing
    source files now reuses a single buffer, reducing memory allocations by ~98%
    and wall-clock time by ~7% (#2925 by @vmaerten).
  • includes.excludes can now exclude a whole namespace: append :* to the
    namespace name, e.g. excludes: ['debug:*']. Bare entries still match a
    single task name exactly (#2300, #2959 by @xmxxc).
  • Added support for enum.ref in --interactive prompts. Required vars using
    enum.ref now show the selection list like static enums, instead of falling
    back to free-form input (#2817 by @vmaerten).
  • Added Nushell completions, available via task --completion nu. They complete
    task names and aliases, every flag with its description, and the values of
    --completion, --output and --sort (#2966 by @vmaerten).
  • Added a verbose log line for failed tasks. In --verbose mode, a task whose
    command exits non-zero now reports task: "<name>" failed: <error> instead of
    stopping without a trace (#2240 by @Drino).

πŸ› Fixes

  • Fixed a pinned checksum: not being verified when a remote Taskfile came from
    the cache (#2980 by @vmaerten).
  • Fixed the fingerprint variable ({{.CHECKSUM}}/{{.TIMESTAMP}}) ignoring a
    method: set at the Taskfile level: the variable now follows the same method
    resolution as the up-to-date check. Only the variable matching the effective
    method is injected, so a task inheriting a Taskfile-level method: timestamp
    gets {{.TIMESTAMP}} and no longer a {{.CHECKSUM}} (which now renders as an
    empty string), and neither variable is injected when the effective method is
    none (#2924 by @vmaerten).
  • Fixed ref: in for: matrix: and enum: only accepting literal lists. Refs
    computed with template functions like keys or splitList no longer fail
    with "must resolve to a list" (#2544, #2956 by @no-hup).
  • Fixed pressing Esc at an interactive variable prompt not cancelling the run
    (#2942 by @anilnatha).
  • Fixed joinUrl collapsing the // in a URL scheme (e.g. producing
    http:/localhost instead of http://localhost) (#2915 by @vsaraikin).
  • Fixed the JSON schema rejecting ignore_error on a command inside a for
    loop. Editors no longer flag a Taskfile that Task runs perfectly fine (#2044
    by @gokeefe-atb).
  • Fixed the JSON schema rejecting more keys the Taskfile parser accepts:
    ignore_error on a task: call, and if, set and shopt on a command
    inside a for loop (#2967 by @vmaerten).

πŸ“š Documentation & Website

  • Updated taskfile versions doc to mention when version checks were introduced
    (#2184 by @jubr).
  • Load the sidebar data and titles/excerpts from the blog post markdown document
    and its frontmatter on the website (#2981 by @pd93).

v3.53.0 - 2026-08-18

  • Failed due to an issue with our release process.

v3.52.0 - 2026-07-02

  • Fixed --interactive prompts for required vars sometimes appearing in a random
    order. Prompts now follow the order the vars are declared in the Taskfile.
    (#2871 by @caproven)
  • Fixed Fish completions not being picked up correctly by installing them to
    Fish's vendor_completions.d directory instead of completions (#2850, #2859
    by @Legimity).
  • PowerShell completions now work with aliases of the task command, not just
    the task binary itself (#2852 by @kojiishi).
  • Fixed task and namespace aliases not being completed by the Zsh completion. A
    show-aliases zstyle can turn this off (#2865, #2864 by @vmaerten).
  • Fixed task names containing certain characters (e.g. \, _, ^) leaking
    into checksum/timestamp filenames, breaking sources:/generates: up-to-date
    detection (#2886 by @s3onghyun).
  • Fixed for: matrix: loops using ref: rows producing wrong values when the
    same task was run concurrently (e.g. by parallel deps) with different vars
    (#2890, #2894 by @amitmishra11).
  • Added a secret: true flag for variables that masks their value in logs,
    task --summary, and command output (#2514 by @vmaerten).
  • Added the use_gitignore setting (global or per-task) to skip files matched
    by your .gitignore when fingerprinting sources/generates and when
    watching (#2773 by @vmaerten).
  • Added support for configuring output flags (--output,
    --output-group-begin, --output-group-end, --output-group-error-only) via
    the TASK_OUTPUT* environment variables (#2873 by @liiight).
  • Added a --temp-dir flag (with TASK_TEMP_DIR env var and temp-dir taskrc
    config) to customise the directory where Task stores temporary files such as
    checksums. Relative paths are resolved against the root Taskfile (#2891 by
    @kjasn).
  • Defined environment variable behavior for remote taskfiles (#2267, #2847 by
    @vmaerten).
  • Added support for remote Taskfiles hosted on Azure DevOps, whose git URLs use
    a /_git/ path segment rather than a .git suffix (#2904 by @pd93).
  • Re-added the example remote taskfile at
    taskfile.dev/Taskfile.yml (#2905 by
    @pd93).
  • Fixed malformed includes: entries (missing taskfile/dir) reporting a
    misleading "include cycle detected" error instead of a clear configuration
    error (#1881, #2892 by @Lewin671).

v3.51.1 - 2026-05-16

  • A significant performance boost was achieved for large Taskfiles (monorepos)
    by skipping templating altogether when the string is static (#2820 by @romnn).
  • Added absPath template function that resolves a path to its absolute form,
    cleaning .. and . components (#2681, #2788 by @mateenanjum).
  • Added joinEnv function to join paths based on your oprating system: ; for
    Windows and : elsewhere, and joinUrl to join URL paths. Also, added two
    new special variables: FILE_PATH_SEPARATOR which returns \ on Windows and
    / elsewhere, and PATH_LIST_SEPARATOR which returns ; on Windows and :
    elsewhere (#2406, #2408 by @solvingj).
  • Update the shell interpreter with a regression fix (#2812, #2832 by
    @andreynering).
  • Fix potential panic with the shell interpreter (#2810 by @trulede).

v3.50.0 - 2026-04-13

  • Added enum.ref support in requires: enum constraints can now reference
    variables or template pipelines (e.g., ref: .ALLOWED_ENVS) instead of
    duplicating static lists. Combined with sh: variables, this enables fully
    dynamic enum validation (#2678 by @vmaerten).
  • Fixed Fish completion using hardcoded task binary name instead of
    $GO_TASK_PROGNAME for experiments cache (#2730, #2727 by @SergioChan).
  • Fixed watch mode ignoring SIGHUP signal, causing the watcher to exit instead
    of restarting (#2764, #2642).
  • Fixed a long time bug where the task wouldn't re-run as it should when using
    method: timestamp and the files listed on generates: were deleted. This
    makes method: timestamp behaves the same as method: checksum (#1230, #2716
    by @drichardson).

v3.49.1 - 2026-03-08

  • Reverted #2632 for now, which caused some regressions. That change will be
    reworked (#2720, #2722, #2723).

v3.49.0 - 2026-03-07

  • Fixed included Taskfiles with watch: true not triggering watch mode when
    called from the root Taskfile (#2686, #1763 by @trulede).
  • Fixed Remote Git Taskfiles failing on Windows due to backslashes in URL paths
    (#2656 by @Trim21).
  • Fixed remote Git Taskfiles timing out when resolving includes after accepting
    the trust prompt (#2669, #2668 by @vmaerten).
  • Fixed unclear error message when Taskfile search stops at a directory
    ownership boundary (#2682, #1683 by @trulede).
  • Fixed global variables from imported Taskfiles not resolving ref: values
    correctly (#2632 by @trulede).
  • Every .taskrc.yml option can now be overridden with a TASK_-prefixed
    environment variable, making CI and container configuration easier (#2607,
    #1066 by @vmaerten).

v3.48.0 - 2026-01-26

  • Fixed if: conditions when using to check dynamic variables. Also, skip
    variable prompt if task would be skipped by if: (#2658, #2660 by @vmaerten).
  • Fixed ROOT_TASKFILE variable pointing to directory instead of the actual
    Taskfile path when no explicit -t flag is provided (#2635, #1706 by
    @trulede).
  • Included Taskfiles with silent: true now properly propagate silence to their
    tasks, while still allowing individual tasks to override with silent: false
    (#2640, #1319 by @trulede).
  • Added TLS certificate options for Remote Taskfiles: use --cacert for
    self-signed certificates and --cert/--cert-key for mTLS authentication
    (#2537, #2242 by @vmaerten).

v3.47.0 - 2026-01-24

  • Fixed remote git Taskfiles: cloning now works without explicit ref, and
    directory includes are properly resolved (#2602 by @vmaerten).
  • For output: prefixed, print prefix: if set instead of task name (#1566,
    #2633 by @trulede).
  • Ensure no ANSI sequences are printed for --color=false (#2560, #2584 by
    @trulede).
  • Task aliases can now contain wildcards and will match accordingly (e.g., s-*
    as alias for start-*) (#1900, #2234 by @vmaerten).
  • Added conditional execution with the if field: skip tasks, commands, or task
    calls based on shell exit codes or template expressions like
    {{ eq .ENV "prod" }} (#2564, #608 by @vmaerten).
  • Task can now interactively prompt for missing required variables when running
    in a TTY, with support for enum selection menus. Enable with --interactive
    flag or interactive: true in .taskrc.yml (#2579, #2079 by @vmaerten).

v3.46.4 - 2025-12-24

  • Fixed regressions in completion script for Fish (#2591, #2604, #2592 by
    @WinkelCode).

v3.46.3 - 2025-12-19

  • Fixed regression in completion script for zsh (#2593, #2594 by @vmaerten).

v3.46.2 - 2025-12-18

  • Fixed a regression on previous release that affected variables passed via
    command line (#2588, #2589 by @vmaerten).

v3.46.1 - 2025-12-18

✨ Features

  • A small behavior change was made to dependencies. Task will now wait for all
    dependencies to finish running before continuing, even if any of them fail. To
    opt for the previous behavior, set failfast: true either on your
    .taskrc.yml or per task, or use the --failfast flag, which will also work
    for --parallel (#1246, #2525 by @andreynering).
  • The --summary flag now displays vars: (both global and task-level),
    env:, and requires: sections. Dynamic variables show their shell command
    (e.g., sh: echo "hello") instead of the evaluated value (#2486 ,#2524 by
    @vmaerten).
  • Improved performance of fuzzy task name matching by implementing lazy
    initialization. Added --disable-fuzzy flag and disable-fuzzy taskrc option
    to allow disabling fuzzy matching entirely (#2521, #2523 by @vmaerten).
  • Added LLM-optimized documentation via VitePress plugin, generating llms.txt
    and llms-full.txt for AI-powered development tools (#2513 by @vmaerten).
  • Added --trusted-hosts CLI flag and remote.trusted-hosts config option to
    skip confirmation prompts for specified hosts when using Remote Taskfiles
    (#2491, #2473 by @maciejlech).
  • When running in GitHub Actions, Task now automatically emits error annotations
    on failure, improving visibility in workflow summaries (#2568 by @vmaerten).
  • The --yes flag is now accessible in templates via the new CLI_ASSUME_YES
    variable (#2577, #2479 by @semihbkgr).
  • Improved shell completion scripts (Zsh, Fish, PowerShell) by adding missing
    flags and dynamic experimental feature detection (#2532 by @vmaerten).
  • Remote Taskfiles now accept application/octet-stream Content-Type (#2536,
    #1944 by @vmaerten).
  • Shell completion now works when Task is installed or aliased under a different
    binary name via TASK_EXE environment variable (#2495, #2468 by @vmaerten).
  • Some small fixes and improvements were made to task --init and to the
    default Taskfile it generates (#2433 by @andreynering).
  • Added --remote-cache-dir flag and remote.cache-dir taskrc option to
    customize the cache directory for Remote Taskfiles (#2572 by @vmaerten).
  • Zsh completion now supports zstyle verbose option to show or hide task
    descriptions (#2571 by @vmaerten).
  • Task now automatically enables colored output in CI environments (GitHub
    Actions, GitLab CI, etc.) without requiring FORCE_COLOR=1 (#2569 by
    @vmaerten).
  • Added color taskrc option to explicitly enable or disable colored output
    globally (#2569 by @vmaerten).
  • Improved Git Remote Taskfiles by switching to go-getter: SSH authentication
    now works out of the box and applyOf is properly supported (#2512 by
    @vmaerten).

πŸ› Fixes

  • Fix RPM upload to Cloudsmith by including the version in the filename to
    ensure unique filenames (#2507 by @vmaerten).
  • Fix run: when_changed to work properly for Taskfiles included multiple times
    (#2508, #2511 by @trulede).
  • Fixed Zsh and Fish completions to stop suggesting task names after --
    separator, allowing proper CLI_ARGS completion (#1843, #1844 by
    @boiledfroginthewell).
  • Watch mode (--watch) now always runs the task, regardless of run: once or
    run: when_changed settings (#2566, #1388 by @trulede).
  • Fixed global variables (CLI_ARGS, CLI_FORCE, etc.) not being accessible in
    root-level vars section (#2403, #2397 by @trulede, @vmaerten).
  • Fixed a bug where ignore_error was ignored when using task: to call
    another task (#2552, #363 by @trulede).
  • Fixed Zsh completion not suggesting global tasks when using -g/--global
    flag (#1574, #2574 by @vmaerten).
  • Fixed Fish completion failing to parse task descriptions containing colons
    (e.g., URLs or namespaced functions) (#2101, #2573 by @vmaerten).
  • Fixed false positive "property 'for' is not allowed" warnings in IntelliJ when
    using for loops in Taskfiles (#2576 by @vmaerten).

v3.45.5 - 2025-11-11

  • Fixed bug that made a generic message, instead of an useful one, appear when a
    Taskfile could not be found (#2431 by @andreynering).
  • Fixed a bug that caused an error when including a Remote Git Taskfile (#2438
    by @twelvelabs).
  • Fixed issue where .taskrc.yml was not returned if reading it failed, and
    corrected handling of remote entrypoint Taskfiles (#2460, #2461 by @vmaerten).
  • Improved performance of --list and --list-all by introducing a faster
    compilation method that skips source globbing and checksum updates (#1322,
    #2053 by @vmaerten).
  • Fixed a concurrency bug with output: group. This ensures that begin/end
    parts won't be mixed up from different tasks (#1208, #2349, #2350 by
    @trulede).
  • Do not re-evaluate variables for defer: (#2244, #2418 by @trulede).
  • Improve error message when a Taskfile is not found (#2441, #2494 by
    @vmaerten).
  • Fixed generic error message exit status 1 when a dependency task failed
    (#2286 by @GrahamDennis).
  • Fixed YAML library from the unmaintained gopkg.in/yaml.v3 to the new fork
    maintained by the official YAML org (#2171, #2434 by @andreynering).
  • On Windows, the built-in version of the rm core utils contains a fix related
    to the -f flag (#2426,
    u-root/u-root#3464,
    mvdan/sh#1199, #2506 by
    @andreynering).

v3.45.4 - 2025-09-17

  • Fixed a bug where cache-expiry could not be defined in .taskrc.yml (#2423
    by @vmaerten).
  • Fixed a bug where .taskrc.yml files in parent folders were not read
    correctly (#2424 by @vmaerten).
  • Fixed a bug where autocomplete in subfolders did not work with zsh (#2425 by
    @vmaerten).

v3.45.3 - 2025-09-15

  • Task now includes built-in core utilities to greatly improve compatibility on
    Windows. This means that your commands that uses cp, mv, mkdir or any
    other common core utility will now work by default on Windows, without extra
    setup. This is something we wanted to address for many many years, and it's
    finally being shipped!
    Read our blog post this the topic.
    (#197, #2360 by @andreynering).
  • :sparkles: Built and deployed a brand new website
    using VitePress (#2359, #2369, #2371, #2375, #2378 by
    @vmaerten, @andreynering, @pd93).
  • Began releasing
    nightly builds. This
    will allow people to test our changes before they are fully released and
    without having to install Go to build them (#2358 by @vmaerten).
  • Added support for global config files in $XDG_CONFIG_HOME/task/taskrc.yml or
    $HOME/.taskrc.yml. Check out our new
    configuration guide for more
    details (#2247, #2380, #2390, #2391 by @vmaerten, @pd93).
  • Added experiments to the taskrc schema to clarify the expected keys and values
    (#2235 by @vmaerten).
  • Added support for new properties in .taskrc.yml: insecure, verbose,
    concurrency, remote offline, remote timeout, and remote expiry. :warning:
    Note: setting offline via environment variable is no longer supported. (#2389
    by @vmaerten)
  • Added a --nested flag when outputting tasks using --list --json. This will
    output tasks in a nested structure when tasks are namespaced (#2415 by @pd93).
  • Enhanced support for tasks with wildcards: they are now logged correctly, and
    wildcard parameters are fully considered during fingerprinting (#1808, #1795
    by @vmaerten).
  • Fixed panic when a variable was declared as an empty hash ({}) (#2416, #2417
    by @trulede).

Package API

  • Bumped the minimum version of Go to 1.24 (#2358 by @vmaerten).

Other news

We recently released our
official GitHub Action. This is based
on the fantastic work by the Arduino team who created and maintained the
community version. Now that this is officially adopted, fixes/updates should be
more timely. We have already merged a couple of longstanding PRs in our
first release (by
@pd93, @shrink, @trim21 and all the previous contributors to
arduino/setup-task).

v3.45.0-v3.45.2 - 2025-09-15

Failed due to an issue with our release process.

v3.44.1 - 2025-07-23

  • Internal tasks will no longer be shown as suggestions since they cannot be
    called (#2309, #2323 by @maxmzkrcensys)
  • Fixed install script for some ARM platforms (#1516, #2291 by @trulede).
  • Fixed a regression where fingerprinting was not working correctly if the path
    to you Taskfile contained a space (#2321, #2322 by @pd93).
  • Reverted a breaking change to randInt (#2312, #2316 by @pd93).
  • Made new variables TEST_NAME and TEST_DIR available in fixture tests
    (#2265 by @pd93).

v3.44.0 - 2025-06-08

  • Added uuid, randInt and randIntN template functions (#1346, #2225 by
    @pd93).
  • Added new CLI_ARGS_LIST array variable which contains the arguments passed
    to Task after the -- (the same as CLI_ARGS, but an array instead of a
    string). (#2138, #2139, #2140 by @pd93).
  • Added toYaml and fromYaml templating functions (#2217, #2219 by @pd93).
  • Added task field the --list --json output (#2256 by @aleksandersh).
  • Added the ability to
    pin included taskfiles
    by specifying a checksum. This works with both local and remote Taskfiles
    (#2222, #2223 by @pd93).
  • When using the
    Remote Taskfiles experiment,
    any credentials used in the URL will now be redacted in Task's output (#2100,
    #2220 by @pd93).
  • Fixed fuzzy suggestions not working when misspelling a task name (#2192, #2200
    by @vmaerten).
  • Fixed a bug where taskfiles in directories containing spaces created
    directories in the wrong location (#2208, #2216 by @pd93).
  • Added support for dual JSON schema files, allowing changes without affecting
    the current schema. The current schemas will only be updated during releases.
    (#2211 by @vmaerten).
  • Improved fingerprint documentation by specifying that the method can be set at
    the root level to apply to all tasks (#2233 by @vmaerten).
  • Fixed some watcher regressions after #2048 (#2199, #2202, #2241, #2196 by
    @wazazaby, #2271 by @andreynering).

v3.43.3 - 2025-04-27

Reverted the changes made in #2113 and #2186 that affected the
USER_WORKING_DIR and built-in variables. This fixes #2206, #2195, #2207 and
#2208.

v3.43.2 - 2025-04-21

  • Fixed regresion of CLI_ARGS being exposed as the wrong type (#2190, #2191 by
    @vmaerten).

v3.43.1 - 2025-04-21

  • Significant improvements were made to the watcher. We migrated from
    watcher to
    fsnotify. The former library used
    polling, which means Task had a high CPU usage when watching too many files.
    fsnotify uses proper the APIs from each operating system to watch files,
    which means a much better performance. The default interval changed from 5
    seconds to 100 milliseconds, because now it configures the wait time for
    duplicated events, instead of the polling time (#2048 by @andreynering, #1508,
    #985, #1179).
  • The Map Variables experiment
    was made generally available so you can now
    define map variables in your Taskfiles!
    (#1585, #1547, #2081 by @pd93).
  • Wildcards can now
    match multiple tasks (#2072,
    #2121 by @pd93).
  • Added the ability to
    loop over the files specified by the generates keyword.
    This works the same way as looping over sources (#2151 by @sedyh).
  • Added the ability to resolve variables when defining an include variable
    (#2108, #2113 by @pd93).
  • A few changes have been made to the
    Remote Taskfiles experiment
    (#1402, #2176 by @pd93):
    • Cached files are now prioritized over remote ones.
    • Added an --expiry flag which sets the TTL for a remote file cache. By
      default the value will be 0 (caching disabled). If Task is running in
      offline mode or fails to make a connection, it will fallback on the cache.
  • .taskrc files can now be used from subdirectories and will be searched for
    recursively up the file tree in the same way that Taskfiles are (#2159, #2166
    by @pd93).
  • The default taskfile (output when using the --init flag) is now an embedded
    file in the binary instead of being stored in the code (#2112 by @pd93).
  • Improved the way we report the Task version when using the --version flag or
    {{.TASK_VERSION}} variable. This should now be more consistent and easier
    for package maintainers to use (#2131 by @pd93).
  • Fixed a bug where globstar (**) matching in sources only resolved the
    first result (#2073, #2075 by @pd93).
  • Fixed a bug where sorting tasks by "none" would use the default sorting
    instead of leaving tasks in the order they were defined (#2124, #2125 by
    @trulede).
  • Fixed Fish completion on newer Fish versions (#2130 by @atusy).
  • Fixed a bug where undefined/null variables resolved to an empty string instead
    of nil (#1911, #2144 by @pd93).
  • The USER_WORKING_DIR special now will now properly account for the --dir
    (-d) flag, if given (#2102, #2103 by @jaynis, #2186 by @andreynering).
  • Fix Fish completions when --global (-g) is given (#2134 by @atusy).
  • Fixed variables not available when using defer: (#1909, #2173 by @vmaerten).

Package API

v3.42.1 - 2025-03-10

  • Fixed a bug where some special variables caused a type error when used global
    variables (#2106, #2107 by @pd93).

v3.42.0 - 2025-03-08

  • Made --init less verbose by default and respect --silent and --verbose
    flags (#2009, #2011 by @HeCorr).
  • --init now accepts a file name or directory as an argument (#2008, #2018 by
    @HeCorr).
  • Fix a bug where an HTTP node's location was being mutated incorrectly (#2007
    by @jeongukjae).
  • Fixed a bug where allowed values didn't work with dynamic var (#2032, #2033 by
    @vmaerten).
  • Use only the relevant checker (timestamp or checksum) to improve performance
    (#2029, #2031 by @vmaerten).
  • Print warnings when attempting to enable an inactive experiment or an active
    experiment with an invalid value (#1979, #2049 by @pd93).
  • Refactored the experiments package and added tests (#2049 by @pd93).
  • Show allowed values when a variable with an enum is missing (#2027, #2052 by
    @vmaerten).
  • Refactored how snippets in error work and added tests (#2068 by @pd93).
  • Fixed a bug where errors decoding commands were sometimes unhelpful (#2068 by
    @pd93).
  • Fixed a bug in the Taskfile schema where defer statements in the shorthand
    cmds syntax were not considered valid (#2068 by @pd93).
  • Refactored how task sorting functions work (#1798 by @pd93).
  • Added a new .taskrc.yml (or .taskrc.yaml) file to let users enable
    experiments (similar to .env) (#1982 by @vmaerten).
  • Added new Getting Started docs (#2086
    by @pd93).
  • Allow matrix to use references to other variables (#2065, #2069 by @pd93).
  • Fixed a bug where, when a dynamic variable is provided, even if it is not
    used, all other variables become unavailable in the templating system within
    the include (#2092 by @vmaerten).

Package API

Unlike our CLI tool,
Task's package API is not currently stable.
In an effort to ease the pain of breaking changes for our users, we will be
providing changelogs for our package API going forwards. The hope is that these
changes will provide a better long-term experience for our users and allow to
stabilize the API in the future. #121 now tracks this piece of work.

  • Bumped the minimum required Go version to 1.23 (#2059 by @pd93).
  • task.InitTaskfile
    (#2011, ff8c913 by @HeCorr and @pd93)
    • No longer accepts an io.Writer (output is now the caller's
      responsibility).
    • The path argument can now be a filename OR a directory.
    • The function now returns the full path of the generated file.
  • TaskfileDecodeError.WithFileInfo
    now accepts a string instead of the arguments required to generate a snippet
    (#2068 by @pd93).
    • The caller is now expected to create the snippet themselves (see below).
  • TaskfileSnippet
    and related code moved from the errors package to the taskfile package
    (#2068 by @pd93).
  • Renamed TaskMissingRequiredVars to
    TaskMissingRequiredVarsError
    (#2052 by @vmaerten).
  • Renamed TaskNotAllowedVars to
    TaskNotAllowedVarsError
    (#2052 by @vmaerten).
  • The
    taskfile.Reader
    is now constructed using the functional options pattern (#2082 by @pd93).
  • Removed our internal logger.Logger from the entire taskfile package (#2082
    by @pd93).
  • Remove Range functions in the taskfile/ast package in favour of new
    iterator functions (#1798 by @pd93).
  • ast.Call was moved from the taskfile/ast package to the main task
    package (#2084 by @pd93).
  • ast.Tasks.FindMatchingTasks was moved from the taskfile/ast package to the
    task.Executor.FindMatchingTasks in the main task package (#2084 by @pd93).
  • The Compiler and its GetVariables and FastGetVariables methods were
    moved from the internal/compiler package to the main task package (#2084
    by @pd93).

v3.41.0 - 2025-01-18

  • Fixed an issue where dynamic variables were not properly logged in verbose
    mode (#1920, #1921 by @mgbowman).
  • Support silent for defer statements (#1877, #1879 by @danilobuerger).
  • Added an option to exclude some tasks from being included (#1859 by
    @vmaerten).
  • Fixed an issue where a required variable was incorrectly handled in a template
    function (#1950, #1962 by @vmaerten).
  • Expose a new TASK_DIR special variable, which will contain the absolute path
    of task directory. (#1959, #1961 by @vmaerten).
  • Fixed fatal bugs that caused concurrent map writes (#1605, #1972, #1974 by
    @pd93, @GrahamDennis and @trim21).
  • Refactored internal ordered map implementation to use
    github.com/elliotchance/orderedmap
    (#1797 by @pd93).
  • Fixed a bug where variables defined at the task level were being ignored in
    the requires section. (#1960, #1955, #1768 by @vmaerten and @mokeko)
  • The CHECKSUM and TIMESTAMP variables are now accessible within cmds
    (#1872 by @niklasr22).
  • Updated installation docs and added pip
    installation method (#935, #1989 by @pd93).
  • Fixed a bug where dynamic variables could not access environment variables
    (#630, #1869 by @rohm1 and @pd93).
  • Disable version check for use as an external library (#1938 by @leaanthony).

v3.40.1 - 2024-12-06

  • Fixed a security issue in git-urls by switching to the maintained fork
    chainguard-dev/git-urls (#1917 by @AlekSi).
  • Added missing platforms property to cmds that use for (#1915 by
    @dkarter).
  • Added misspell linter to check for misspelled English words (#1883 by
    @christiandins).

v3.40.0 - 2024-11-05

  • Fixed output of some functions (e.g. splitArgs/splitLines) not working in
    for loops (#1822, #1823 by @stawii).
  • Added a new TASK_OFFLINE environment variable to configure the --offline
    flag and expose it as a special variable in the templating system (#1470,
    #1716 by @vmaerten and @pd93).
  • Fixed a bug where multiple remote includes caused all prompts to display
    without waiting for user input (#1832, #1833 by @vmaerten and @pd93).
  • When using the
    "Remote Taskfiles".
    experiment, you can now include Taskfiles from Git repositories (#1652 by
    @vmaerten).
  • Improved the error message when a dotenv file cannot be parsed (#1842 by
    @pbitty).
  • Fix issue with directory when using the remote experiment (#1757 by @pbitty).
  • Fixed an issue where a special variable was used in combination with a dotenv
    file (#1232, #1810 by @vmaerten).
  • Refactor the way Task reads Taskfiles to improve readability (#1771 by
    @pbitty).
  • Added a new option to ensure variable is within the list of values (#1827 by
    @vmaerten).
  • Allow multiple prompts to be specified for a task (#1861, #1866 by @mfbmina).
  • Added new template function: numCPU, which returns the number of logical
    CPUs usable (#1890, #1887 by @Amoghrd).
  • Fixed a bug where non-nil, empty dynamic variables are returned as an empty
    interface (#1903, #1904 by @pd93).

v3.39.2 - 2024-09-19

  • Fix dynamic variables not working properly for a defer: statement (#1803,
    #1818 by @vmaerten).

v3.39.1 - 2024-09-18

  • Added Renovate configuration to automatically create PRs to keep dependencies
    up to date (#1783 by @vmaerten).
  • Fixed a bug where the help was displayed twice (#1805, #1806 by @vmaerten).
  • Fixed a bug where ZSH and PowerShell completions did not work when using the
    recommended method. (#1813, #1809 by @vmaerten and @shirayu)
  • Fix variables not working properly for a defer: statement (#1803, #1814 by
    @vmaerten and @andreynering).

v3.39.0 - 2024-09-07

  • Added
    Env Precedence Experiment
    (#1038, #1633 by @vmaerten).
  • Added a CI lint job to ensure that the docs are updated correctly (#1719 by
    @vmaerten).
  • Updated minimum required Go version to 1.22 (#1758 by @pd93).
  • Expose a new EXIT_CODE special variable on defer: when a command finishes
    with a non-zero exit code (#1484, #1762 by @dorimon-1 and @andreynering).
  • Expose a new ALIAS special variable, which will contain the alias used to
    call the current task. Falls back to the task name. (#1764 by @DanStory).
  • Fixed TASK_REMOTE_DIR environment variable not working when the path was
    absolute. (#1715 by @vmaerten).
  • Added an option to declare an included Taskfile as flattened (#1704 by
    @vmaerten).
  • Added a new
    --completion flag to
    output completion scripts for various shells (#293, #1157 by @pd93).
    • This is now the preferred way to install completions.
    • The completion scripts in the completion directory
      are now deprecated.
  • Added the ability to
    loop over a matrix of values
    (#1766, #1767, #1784 by @pd93).
  • Fixed a bug in fish completion where aliases were not displayed (#1781, #1782
    by @vmaerten).
  • Fixed panic when having a flattened included Taskfile that contains a
    default task (#1777, #1778 by @vmaerten).
  • Optimized file existence checks for remote Taskfiles (#1713 by @vmaerten).

v3.38.0 - 2024-06-30

  • Added TASK_EXE special variable (#1616, #1624 by @pd93 and @andreynering).
  • Some YAML parsing errors will now show in a more user friendly way (#1619 by
    @pd93).
  • Prefixed outputs will now be colorized by default (#1572 by
    @AlexanderArvidsson)
  • References are now
    generally available (no experiments required) (#1654 by @pd93).
  • Templating functions can now be used in references (#1645, #1654 by @pd93).
  • Added a new
    templating reference page to the
    documentation (#1614, #1653 by @pd93).
  • If using the
    Map Variables experiment (1),
    references are available by
    prefixing a string with a #
    (#1654 by @pd93).
  • If using the
    Map Variables experiment (2),
    the yaml and json keys are no longer available (#1654 by @pd93).
  • Added a new TASK_REMOTE_DIR environment variable to configure where cached
    remote Taskfiles are stored (#1661 by @vmaerten).
  • Added a new --clear-cache flag to clear the cache of remote Taskfiles (#1639
    by @vmaerten).
  • Improved the readability of cached remote Taskfile filenames (#1636 by
    @vmaerten).
  • Starting releasing a binary for the riscv64 architecture on Linux (#1699 by
    @mengzhuo).
  • Added CLI_SILENT and CLI_VERBOSE variables (#1480, #1669 by @Vince-Smith).
  • Fixed a couple of bugs with the prompt: feature (#1657 by @pd93).
  • Fixed JSON Schema to disallow invalid properties (#1657 by @pd93).
  • Fixed version checks not working as intended (#872, #1663 by @vmaerten).
  • Fixed a bug where included tasks were run multiple times even if run: once
    was set (#852, #1655 by @pd93).
  • Fixed some bugs related to column formatting in the terminal (#1350, #1637,
    #1656 by @vmaerten).

v3.37.2 - 2024-05-12

  • Fixed a bug where an empty Taskfile would cause a panic (#1648 by @pd93).
  • Fixed a bug where includes Taskfile variable were not being merged correctly
    (#1643, #1649 by @pd93).

v3.37.1 - 2024-05-09

  • Fix bug where non-string values (numbers, bools) added to env: weren't been
    correctly exported (#1640, #1641 by @vmaerten and @andreynering).

v3.37.0 - 2024-05-08

  • Released the
    Any Variables experiment, but
    without support for maps
    (#1415, #1547 by @pd93).
  • Refactored how Task reads, parses and merges Taskfiles using a DAG (#1563,
    #1607 by @pd93).
  • Fix a bug which stopped tasks from using stdin as input (#1593, #1623 by
    @pd93).
  • Fix error when a file or directory in the project contained a special char
    like &, ( or ) (#1551, #1584 by @andreynering).
  • Added alias q for template function shellQuote (#1601, #1603 by @vergenzt)
  • Added support for ~ on ZSH completions (#1613 by @jwater7).
  • Added the ability to pass variables by reference using Go template syntax when
    the
    Map Variables experiment is
    enabled (#1612 by @pd93).
  • Added support for environment variables in the templating engine in includes
    (#1610 by @vmaerten).

v3.36.0 - 2024-04-08

  • Added support for
    looping over dependencies
    (#1299, #1541 by @pd93).
  • When using the
    "Remote Taskfiles"
    experiment, you are now able to use
    remote Taskfiles as your entrypoint.
    • includes in remote Taskfiles will now also resolve correctly (#1347 by
      @pd93).
  • When using the
    "Any Variables"
    experiments, templating is now supported in collection-type variables (#1477,
    #1511, #1526 by @pd93).
  • Fixed a bug where variables being passed to an included Taskfile were not
    available when defining global variables (#1503, #1533 by @pd93).
  • Improved support to customized colors by allowing 8-bit colors and multiple
    ANSI attributes (#1576 by @pd93).

v3.35.1 - 2024-03-04

  • Fixed a bug where the TASKFILE_DIR variable was sometimes incorrect (#1522,
    #1523 by @pd93).
  • Added a new TASKFILE special variable that holds the root Taskfile path
    (#1523 by @pd93).
  • Fixed various issues related to running a Taskfile from a subdirectory (#1529,
    #1530 by @pd93).

v3.35.0 - 2024-02-28

  • Added support for
    wildcards in task names
    (#836, #1489 by @pd93).
  • Added the ability to
    run Taskfiles via stdin
    (#655, #1483 by @pd93).
  • Bumped minimum Go version to 1.21 (#1500 by @pd93).
  • Fixed bug related to the --list flag (#1509, #1512 by @pd93, #1514, #1520 by
    @pd93).
  • Add mention on the documentation to the fact that the variable declaration
    order is respected (#1510 by @kirkrodrigues).
  • Improved style guide docs (#1495 by @iwittkau).
  • Removed duplicated entry for requires on the API docs (#1491 by
    @teatimeguest).

v3.34.1 - 2024-01-27

v3.34.0 - 2024-01-25

  • Removed support for version: 2 schemas. See the
    deprecation notice on our website
    (#1197, #1447 by @pd93).
  • Fixed a couple of issues in the JSON Schema + added a CI step to ensure it's
    correct (#1471, #1474, #1476 by @sirosen).
  • Added
    Any Variables experiment proposal 2
    (#1415, #1444 by @pd93).
  • Updated the experiments and deprecations documentation format (#1445 by
    @pd93).
  • Added new template function: spew, which can be used to print variables for
    debugging purposes (#1452 by @pd93).
  • Added new template function: merge, which can be used to merge any number of
    map variables (#1438, #1464 by @pd93).
  • Small change on the API when using as a library: call.Direct became
    call.Indirect (#1459 by @pd93).
  • Refactored the public read and taskfile packages and introduced
    taskfile/ast (#1450 by @pd93).
  • ast.IncludedTaskfiles renamed to ast.Includes and orderedmap package
    renamed to omap plus some internal refactor work (#1456 by @pd93).
  • Fix zsh completion script to allow lowercase taskfile file names (#1482 by
    @xontab).
  • Improvements on how we check the Taskfile version (#1465 by @pd93).
  • Added a new ROOT_TASKFILE special variable (#1468, #1469 by @pd93).
  • Fix experiment flags in .env when the --dir or --taskfile flags were
    used (#1478 by @pd93).

v3.33.1 - 2023-12-21

  • Added support for looping over map variables with the
    Any Variables experiment
    enabled (#1435, #1437 by @pd93).
  • Fixed a bug where dynamic variables were causing errors during fast
    compilation (#1435, #1437 by @pd93)

v3.33.0 - 2023-12-20

  • Added
    Any Variables experiment
    (#1415, #1421 by @pd93).
  • Updated Docusaurus to v3 (#1432 by @pd93).
  • Added aliases to --json flag output (#1430, #1431 by @pd93).
  • Added new CLI_FORCE special variable containing whether the --force or
    --force-all flags were set (#1412, #1434 by @pd93).

v3.32.0 - 2023-11-29

  • Added ability to exclude some files from sources: by using exclude: (#225,
    #1324 by @pd93 and @andreynering).
  • The
    Remote Taskfiles experiment
    now prefers remote files over cached ones by default (#1317, #1345 by @pd93).
  • Added --timeout flag to the
    Remote Taskfiles experiment
    (#1317, #1345 by @pd93).
  • Fix bug where dynamic vars: and env: were being executed when they should
    actually be skipped by platforms: (#1273, #1377 by @andreynering).
  • Fix schema.json to make silent valid in cmds that use for (#1385,
    #1386 by @iainvm).
  • Add new --no-status flag to skip expensive status checks when running
    task --list --json (#1348, #1368 by @amancevice).

v3.31.0 - 2023-10-07

  • Enabled the --yes flag for the
    Remote Taskfiles experiment
    (#1317, #1344 by @pd93).
  • Add ability to set watch: true in a task to automatically run it in watch
    mode (#231, #1361 by @andreynering).
  • Fixed a bug on the watch mode where paths that contained .git (like
    .github), for example, were also being ignored (#1356 by @butuzov).
  • Fixed a nil pointer error when running a Taskfile with no contents (#1341,
    #1342 by @pd93).
  • Added a new exit code (107) for when a
    Taskfile does not contain a schema version (#1342 by @pd93).
  • Increased limit of maximum task calls from 100 to 1000 for now, as some people
    have been reaching this limit organically now that we have loops. This check
    exists to detect recursive calls, but will be removed in favor of a better
    algorithm soon (#1321, #1332).
  • Fixed templating on descriptions on task --list (#1343 by @blackjid).
  • Fixed a bug where precondition errors were incorrectly being printed when task
    execution was aborted (#1337, #1338 by @sylv-io).

v3.30.1 - 2023-09-14

  • Fixed a regression where some special variables weren't being set correctly
    (#1331, #1334 by @pd93).

v3.30.0 - 2023-09-13

  • Prep work for Remote Taskfiles (#1316 by @pd93).
  • Added the
    Remote Taskfiles experiment
    as a draft (#1152, #1317 by @pd93).
  • Improve performance of content checksumming on sources: by replacing md5
    with XXH3 which is much faster. This is a soft breaking
    change because checksums will be invalidated when upgrading to this release
    (#1325 by @ReillyBrogan).

v3.29.1 - 2023-08-26

  • Update to Go 1.21 (bump minimum version to 1.20) (#1302 by @pd93)
  • Fix a missing a line break on log when using --watch mode (#1285, #1297 by
    @FilipSolich).
  • Fix defer on JSON Schema (#1288 by @calvinmclean and @andreynering).
  • Fix bug in usage of special variables like {{.USER_WORKING_DIR}} in
    combination with includes (#1046, #1205, #1250, #1293, #1312, #1274 by
    @andarto, #1309 by @andreynering).
  • Fix bug on --status flag. Running this flag should not have side-effects: it
    should not update the checksum on .task, only report its status (#1305,
    #1307 by @visciang, #1313 by @andreynering).

v3.28.0 - 2023-07-24

  • Added the ability to
    loop over commands and tasks
    using for (#82, #1220 by @pd93).
  • Fixed variable propagation in multi-level includes (#778, #996, #1256 by
    @hudclark).
  • Fixed a bug where the --exit-code code flag was not returning the correct
    exit code when calling commands indirectly (#1266, #1270 by @pd93).
  • Fixed a nil panic when a dependency was commented out or left empty (#1263
    by @neomantra).

v3.27.1 - 2023-06-30

  • Fix panic when a .env directory (not file) is present on current directory
    (#1244, #1245 by @pd93).

v3.27.0 - 2023-06-29

  • Allow Taskfiles starting with lowercase characters (#947, #1221 by @pd93).
    • e.g. taskfile.yml, taskfile.yaml, taskfile.dist.yml &
      taskfile.dist.yaml
  • Bug fixes were made to the
    npm installation method. (#1190, by
    @sounisi5011).
  • Added the
    gentle force experiment as a
    draft (#1200, #1216 by @pd93).
  • Added an --experiments flag to allow you to see which experiments are
    enabled (#1242 by @pd93).
  • Added ability to specify which variables are required in a task (#1203, #1204
    by @benc-uk).

v3.26.0 - 2023-06-10

  • Only rewrite checksum files in .task if the checksum has changed (#1185,
    #1194 by @deviantintegral).
  • Added experiments documentation to the
    website (#1198 by @pd93).
  • Deprecated version: 2 schema. This will be removed in the next major release
    (#1197, #1198, #1199 by @pd93).
  • Added a new prompt: prop to set a warning prompt to be shown before running
    a potential dangerous task (#100, #1163 by @MaxCheetham,
    Documentation).
  • Added support for single command task syntax. With this change, it's now
    possible to declare just cmd: in a task, avoiding the more complex
    cmds: [] when you have only a single command for that task (#1130, #1131 by
    @timdp).

v3.25.0 - 2023-05-22

  • Support silent: when calling another tasks (#680, #1142 by @danquah).
  • Improve PowerShell completion script (#1168 by @trim21).
  • Add more languages to the website menu and show translation progress
    percentage (#1173 by @misitebao).
  • Starting on this release, official binaries for FreeBSD will be available to
    download (#1068 by @andreynering).
  • Fix some errors being unintendedly suppressed (#1134 by @clintmod).
  • Fix a nil pointer error when version is omitted from a Taskfile (#1148,
    #1149 by @pd93).
  • Fix duplicate error message when a task does not exists (#1141, #1144 by
    @pd93).

v3.24.0 - 2023-04-15

  • Fix Fish shell completion for tasks with aliases (#1113 by @patricksjackson).
  • The default branch was renamed from master to main (#1049, #1048 by
    @pd93).
  • Fix bug where "up-to-date" logs were not being omitted for silent tasks (#546,
    #1107 by @danquah).
  • Add .hg (Mercurial) to the list of ignored directories when using --watch
    (#1098 by @misery).
  • More improvements to the release tool (#1096 by @pd93).
  • Enforce gofumpt linter (#1099 by @pd93)
  • Add --sort flag for use with --list and --list-all (#946, #1105 by
    @pd93).
  • Task now has custom exit codes
    depending on the error (#1114 by @pd93).

v3.23.0 - 2023-03-26

Task now has an
official extension for Visual Studio Code
contributed by @pd93! :tada: The extension is maintained in a
new repository under the go-task
organization. We're looking to gather feedback from the community so please give
it a go and let us know what you think via a
discussion,
issue or on our
Discord!

NOTE: The extension requires v3.23.0 to be installed in order to work.

  • The website was integrated with
    Crowdin to allow the community to
    contribute with translations! Chinese is the
    first language available (#1057, #1058 by @misitebao).
  • Added task location data to the --json flag output (#1056 by @pd93)
  • Change the name of the file generated by task --init from Taskfile.yaml to
    Taskfile.yml (#1062 by @misitebao).
  • Added new splitArgs template function
    ({{splitArgs "foo bar 'foo bar baz'"}}) to ensure string is split as
    arguments (#1040, #1059 by @dhanusaputra).
  • Fix the value of {{.CHECKSUM}} variable in status (#1076, #1080 by @pd93).
  • Fixed deep copy implementation (#1072 by @pd93)
  • Created a tool to assist with releases (#1086 by @pd93).

v3.22.0 - 2023-03-10

  • Add a brand new --global (-g) flag that will run a Taskfile from your
    $HOME directory. This is useful to have automation that you can run from
    anywhere in your system!
    (Documentation, #1029
    by @andreynering).
  • Add ability to set error_only: true on the group output mode. This will
    instruct Task to only print a command output if it returned with a non-zero
    exit code (#664, #1022 by @jaedle).
  • Fixed bug where .task/checksum file was sometimes not being created when
    task also declares a status: (#840, #1035 by @harelwa, #1037 by @pd93).
  • Refactored and decoupled fingerprinting from the main Task executor (#1039 by
    @pd93).
  • Fixed deadlock issue when using run: once (#715, #1025 by
    @theunrepentantgeek).

v3.21.0 - 2023-02-22

  • Added new TASK_VERSION special variable (#990, #1014 by @ja1code).
  • Fixed a bug where tasks were sometimes incorrectly marked as internal (#1007
    by @pd93).
  • Update to Go 1.20 (bump minimum version to 1.19) (#1010 by @pd93)
  • Added environment variable FORCE_COLOR support to force color output. Useful
    for environments without TTY (#1003 by @automation-stack)

v3.20.0 - 2023-01-14

  • Improve behavior and performance of status checking when using the timestamp
    mode (#976, #977 by @aminya).
  • Performance optimizations were made for large Taskfiles (#982 by @pd93).
  • Add ability to configure options for the
    set
    and
    shopt
    builtins (#908, #929 by @pd93,
    Documentation).
  • Add new platforms: attribute to task and cmd, so it's now possible to
    choose in which platforms that given task or command will be run on. Possible
    values are operating system (GOOS), architecture (GOARCH) or a combination of
    the two. Example: platforms: [linux], platforms: [amd64] or
    platforms: [linux/amd64]. Other platforms will be skipped (#978, #980 by
    @leaanthony).

v3.19.1 - 2022-12-31

  • Small bug fix: closing Taskfile.yml once we're done reading it (#963, #964
    by @HeCorr).
  • Fixes a bug in v2 that caused a panic when using a Taskfile_{{OS}}.yml file
    (#961, #971 by @pd93).
  • Fixed a bug where watch intervals set in the Taskfile were not being respected
    (#969, #970 by @pd93)
  • Add --json flag (alias -j) with the intent to improve support for code
    editors and add room to other possible integrations. This is basic for now,
    but we plan to add more info in the near future (#936 by @davidalpert, #764).

v3.19.0 - 2022-12-05

  • Installation via npm now supports pnpm as well
    (go-task/go-npm#2,
    go-task/go-npm#3).
  • It's now possible to run Taskfiles from subdirectories! A new
    USER_WORKING_DIR special variable was added to add even more flexibility for
    monorepos (#289, #920).
  • Add task-level dotenv support (#389, #904).
  • It's now possible to use global level variables on includes (#942, #943).
  • The website got a brand new
    translation to Chinese by
    @DeronW. Thanks!

v3.18.0 - 2022-11-12

  • Show aliases on task --list --silent (task --ls). This means that aliases
    will be completed by the completion scripts (#919).
  • Tasks in the root Taskfile will now be displayed first in
    --list/--list-all output (#806, #890).
  • It's now possible to call a default task in an included Taskfile by using
    just the namespace. For example: docs:default is now automatically aliased
    to docs (#661, #815).

v3.17.0 - 2022-10-14

  • Add a "Did you mean ...?" suggestion when a task does not exits another one
    with a similar name is found (#867, #880).
  • Now YAML parse errors will print which Taskfile failed to parse (#885, #887).
  • Add ability to set aliases for tasks and namespaces (#268, #340, #879).
  • Improvements to Fish shell completion (#897).
  • Added ability to set a different watch interval by setting interval: '500ms'
    or using the --interval=500ms flag (#813, #865).
  • Add colored output to --list, --list-all and --summary flags (#845,
    #874).
  • Fix unexpected behavior where label: was being shown instead of the task
    name on --list (#603, #877).

v3.16.0 - 2022-09-29

  • Add npm as new installation method: npm i @go-task/cli (#870, #871,
    npm package).
  • Add support to marking tasks and includes as internal, which will hide them
    from --list and --list-all (#818).

v3.15.2 - 2022-09-08

  • Fix error when using variable in env: introduced in the previous release
    (#858, #866).
  • Fix handling of CLI_ARGS (--) in Bash completion (#863).
  • On zsh completion, add ability to replace --list-all with --list as
    already possible on the Bash completion (#861).

v3.15.0 - 2022-09-03

  • Add new special variables ROOT_DIR and TASKFILE_DIR. This was a highly
    requested feature (#215, #857,
    Documentation).
  • Follow symlinks on sources (#826, #831).
  • Improvements and fixes to Bash completion (#835, #844).

v3.14.1 - 2022-08-03

  • Always resolve relative include paths relative to the including Taskfile
    (#822, #823).
  • Fix ZSH and PowerShell completions to consider all tasks instead of just the
    public ones (those with descriptions) (#803).

v3.14.0 - 2022-07-08

  • Add ability to override the .task directory location with the
    TASK_TEMP_DIR environment variable.
  • Allow to override Task colors using environment variables: TASK_COLOR_RESET,
    TASK_COLOR_BLUE, TASK_COLOR_GREEN, TASK_COLOR_CYAN, TASK_COLOR_YELLOW,
    TASK_COLOR_MAGENTA and TASK_COLOR_RED (#568, #792).
  • Fixed bug when using the output: group mode where STDOUT and STDERR were
    being print in separated blocks instead of in the right order (#779).
  • Starting on this release, ARM architecture binaries are been released to Snap
    as well (#795).
  • i386 binaries won't be available anymore on Snap because Ubuntu removed the
    support for this architecture.
  • Upgrade mvdan.cc/sh, which fixes a bug with associative arrays (#785,
    mvdan/sh#884,
    mvdan/sh#893).

v3.13.0 - 2022-06-13

  • Added -n as an alias to --dry (#776, #777).
  • Fix behavior of interrupt (SIGINT, SIGTERM) signals. Task will now give time
    for the processes running to do cleanup work (#458, #479, #728, #769).
  • Add new --exit-code (-x) flag that will pass-through the exit form the
    command being ran (#755).

v3.12.1 - 2022-05-10

  • Fixed bug where, on Windows, variables were ending with \r because we were
    only removing the final \n but not \r\n (#717).

v3.12.0 - 2022-03-31

  • The --list and --list-all flags can now be combined with the --silent
    flag to print the task names only, without their description (#691).
  • Added support for multi-level inclusion of Taskfiles. This means that included
    Taskfiles can also include other Taskfiles. Before this was limited to one
    level (#390, #623, #656).
  • Add ability to specify vars when including a Taskfile.
    Check out the documentation
    for more information (#677).

v3.11.0 - 2022-02-19

  • Task now supports printing begin and end messages when using the group
    output mode, useful for grouping tasks in CI systems.
    Check out the documentation
    for more information (#647, #651).
  • Add Taskfile.dist.yml and Taskfile.dist.yaml to the supported file name
    list.
    Check out the documentation
    for more information (#498, #666).

v3.10.0 - 2022-01-04

  • A new --list-all (alias -a) flag is now available. It's similar to the
    exiting --list (-l) but prints all tasks, even those without a description
    (#383, #401).
  • It's now possible to schedule cleanup commands to run once a task finishes
    with the defer: keyword
    (Documentation,
    #475, #626).
  • Remove long deprecated and undocumented $ variable prefix and ^ command
    prefix (#642, #644, #645).
  • Add support for .yaml extension (as an alternative to .yml). This was
    requested multiple times throughout the years. Enjoy! (#183, #184, #369, #584,
    #621).
  • Fixed error when computing a variable when the task directory do not exist yet
    (#481, #579).

v3.9.2 - 2021-12-02

v3.9.1 - 2021-11-28

  • Add logging in verbose mode for when a task starts and finishes (#533, #588).
  • Fix an issue with preconditions and context errors (#597, #598).
  • Quote each {{.CLI_ARGS}} argument to prevent one with spaces to become many
    (#613).
  • Fix nil pointer when cmd: was left empty (#612, #614).
  • Upgrade mvdan/sh which contains two relevant
    fixes:
    • Fix quote of empty strings in shellQuote (#609,
      mvdan/sh#763).
    • Fix issue of wrong environment variable being picked when there's another
      very similar one (#586,
      mvdan/sh#745).
  • Install shell completions automatically when installing via Homebrew (#264,
    #592,
    go-task/homebrew-tap#2).

v3.9.0 - 2021-10-02

v3.8.0 - 2021-09-26

  • Add interactive: true setting to improve support for interactive CLI apps
    (#217, #563).
  • Fix some nil errors (#534, #573).
  • Add ability to declare an included Taskfile as optional (#519, #552).
  • Add support for including Taskfiles in the home directory by using ~ (#539,
    #557).

v3.7.3 - 2021-09-04

  • Add official support to Apple M1 (#564, #567).
  • Our official Homebrew tap will
    support more platforms, including Apple M1

v3.7.0 - 2021-07-31

  • Add run: setting to control if tasks should run multiple times or not.
    Available options are always (the default), when_changed (if a variable
    modified the task) and once (run only once no matter what). This is a long
    time requested feature. Enjoy! (#53, #359).

v3.6.0 - 2021-07-10

  • Allow using both sources: and status: in the same task (#411, #427, #477).
  • Small optimization and bug fix: don't compute variables if not needed for
    dotenv: (#517).

v3.5.0 - 2021-07-04

  • Add support for interpolation in dotenv: (#433, #434, #453).

v3.4.3 - 2021-05-30

  • Add support for the NO_COLOR environment variable. (#459,
    fatih/color#137).
  • Fix bug where sources were not considering the right directory in --watch
    mode (#484, #485).

v3.4.2 - 2021-04-23

  • On watch, report which file failed to read (#472).
  • Do not try to catch SIGKILL signal, which are not actually possible (#476).
  • Improve version reporting when building Task from source using Go Modules
    (#462, #473).

v3.4.1 - 2021-04-17

  • Improve error reporting when parsing YAML: in some situations where you would
    just see an generic error, you'll now see the actual error with more detail:
    the YAML line the failed to parse, for example (#467).
  • A JSON Schema was published here
    and is automatically being used by some editors like Visual Studio Code
    (#135).
  • Print task name before the command in the log output (#398).

v3.3.0 - 2021-03-20

  • Add support for delegating CLI arguments to commands with -- and a special
    CLI_ARGS variable (#327).
  • Add a --concurrency (alias -C) flag, to limit the number of tasks that run
    concurrently. This is useful for heavy workloads. (#345).

v3.2.2 - 2021-01-12

  • Improve performance of --list and --summary by skipping running shell
    variables for these flags (#332).
  • Fixed a bug where an environment in a Taskfile was not always overridable by
    the system environment (#425).
  • Fixed environment from .env files not being available as variables (#379).
  • The install script is now working for ARM platforms (#428).

v3.2.1 - 2021-01-09

  • Fixed some bugs and regressions regarding dynamic variables and directories
    (#426).
  • The slim-sprig package was updated
    with the upstream sprig.

v3.2.0 - 2021-01-07

  • Fix the .task directory being created in the task directory instead of the
    Taskfile directory (#247).
  • Fix a bug where dynamic variables (those declared with sh:) were not running
    in the task directory when the task has a custom dir or it was in an included
    Taskfile (#384).
  • The watch feature (via the --watch flag) got a few different bug fixes and
    should be more stable now (#423, #365).

v3.1.0 - 2021-01-03

  • Fix a bug when the checksum up-to-date resolution is used by a task with a
    custom label: attribute (#412).
  • Starting from this release, we're releasing official ARMv6 and ARM64 binaries
    for Linux (#375, #418).
  • Task now respects the order of declaration of included Taskfiles when
    evaluating variables declaring by them (#393).
  • set -e is now automatically set on every command. This was done to fix an
    issue where multiline string commands wouldn't really fail unless the sentence
    was in the last line (#403).

v3.0.1 - 2020-12-26

  • Allow use as a library by moving the required packages out of the internal
    directory (#358).
  • Do not error if a specified dotenv file does not exist (#378, #385).
  • Fix panic when you have empty tasks in your Taskfile (#338, #362).

v3.0.0 - 2020-08-16

  • On v3, all CLI variables will be considered global variables (#336, #341)
  • Add support to .env like files (#324, #356).
  • Add label: to task so you can override the task name in the logs (#321,
    #337).
  • Refactor how variables work on version 3 (#311).
  • Disallow expansions on v3 since it has no effect.
  • Taskvars.yml is not automatically included anymore.
  • Taskfile_{{OS}}.yml is not automatically included anymore.
  • Allow interpolation on includes, so you can manually include a Taskfile
    based on operation system, for example.
  • Expose .TASK variable in templates with the task name (#252).
  • Implement short task syntax (#194, #240).
  • Added option to make included Taskfile run commands on its own directory
    (#260, #144)
  • Taskfiles in version 1 are not supported anymore (#237).
  • Added global method: option. With this option, you can set a default method
    to all tasks in a Taskfile (#246).
  • Changed default method from timestamp to checksum (#246).
  • New magic variables are now available when using status:: .TIMESTAMP which
    contains the greatest modification date from the files listed in sources:,
    and .CHECKSUM, which contains a checksum of all files listed in status:.
    This is useful for manual checking when using external, or even remote,
    artifacts when using status: (#216).
  • We're now using slim-sprig instead of
    sprig, which allowed a file size
    reduction of about 22% (#219).
  • We now use some colors on Task output to better distinguish message types -
    commands are green, errors are red, etc (#207).

v2.8.1 - 2020-05-20

  • Fix error code for the --help flag (#300, #330).
  • Print version to stdout instead of stderr (#299, #329).
  • Suppress context errors when using the --watch flag (#313, #317).
  • Support templating on description (#276, #283).

v2.8.0 - 2019-12-07

  • Add --parallel flag (alias -p) to run tasks given by the command line in
    parallel (#266).
  • Fixed bug where calling the task CLI only informing global vars would not
    execute the default task.
  • Add ability to silent all tasks by adding silent: true a the root of the
    Taskfile.

v2.7.1 - 2019-11-10

  • Fix error being raised when exit 0 was called (#251).

v2.7.0 - 2019-09-22

  • Fixed panic bug when assigning a global variable (#229, #243).
  • A task with method: checksum will now re-run if generated files are deleted
    (#228, #238).

v2.6.0 - 2019-07-21

  • Fixed some bugs regarding minor version checks on version:.
  • Add preconditions: to task (#205).
  • Create directory informed on dir: if it doesn't exist (#209, #211).
  • We now have a --taskfile flag (alias -t), which can be used to run another
    Taskfile (other than the default Taskfile.yml) (#221).
  • It's now possible to install Task using Homebrew on Linux
    (go-task/homebrew-tap#1).

v2.5.2 - 2019-05-11

  • Reverted YAML upgrade due issues with CRLF on Windows (#201,
    go-yaml/yaml#450).
  • Allow setting global variables through the CLI (#192).

2.5.1 - 2019-04-27

  • Fixed some issues with interactive command line tools, where sometimes the
    output were not being shown, and similar issues (#114, #190, #200).
  • Upgraded go-yaml/yaml from v2 to v3.

v2.5.0 - 2019-03-16

v2.4.0 - 2019-02-21

  • Allow calling a task of the root Taskfile from an included Taskfile by
    prefixing it with : (#161, #172).
  • Add flag to override the output option (#173).
  • Fix bug where Task was persisting the new checksum on the disk when the Dry
    Mode is enabled (#166).
  • Fix file timestamp issue when the file name has spaces (#176).
  • Mitigating path expanding issues on Windows (#170).

v2.3.0 - 2019-01-02

  • On Windows, Task can now be installed using Scoop (#152).
  • Fixed issue with file/directory globing (#153).
  • Added ability to globally set environment variables (#138, #159).

v2.2.1 - 2018-12-09

  • This repository now uses Go Modules (#143). We'll still keep the vendor
    directory in sync for some time, though;
  • Fixing a bug when the Taskfile has no tasks but includes another Taskfile
    (#150);
  • Fix a bug when calling another task or a dependency in an included Taskfile
    (#151).

v2.2.0 - 2018-10-25

  • Added support for
    including other Taskfiles
    (#98)
    • This should be considered experimental. For now, only including local files
      is supported, but support for including remote Taskfiles is being discussed.
      If you have any feedback, please comment on #98.
  • Task now have a dedicated documentation site: https://taskfile.org
    • Thanks to Docsify for making this pretty easy. To
      check the source code, just take a look at the
      docs directory of this
      repository. Contributions to the documentation is really appreciated.

v2.1.1 - 2018-09-17

  • Fix suggestion to use task --init not being shown anymore (when a
    Taskfile.yml is not found)
  • Fix error when using checksum method and no file exists for a source glob
    (#131)
  • Fix signal handling when the --watch flag is given (#132)

v2.1.0 - 2018-08-19

  • Add a ignore_error option to task and command (#123)
  • Add a dry run mode (--dry flag) (#126)

v2.0.3 - 2018-06-24

  • Expand environment variables on "dir", "sources" and "generates" (#116)
  • Fix YAML merging syntax (#112)
  • Add ZSH completion (#111)
  • Implement new output option. Please check out the
    documentation

v2.0.2 - 2018-05-01

  • Fix merging of YAML anchors (#112)

v2.0.1 - 2018-03-11

  • Fixes panic on task --list

v2.0.0 - 2018-03-08

Version 2.0.0 is here, with a new Taskfile format.

Please, make sure to read the
Taskfile versions
document, since it describes in depth what changed for this version.

  • New Taskfile version 2 (#77)
  • Possibility to have global variables in the Taskfile.yml instead of
    Taskvars.yml (#66)
  • Small improvements and fixes

v1.4.4 - 2017-11-19

  • Handle SIGINT and SIGTERM (#75);
  • List: print message with there's no task with description;
  • Expand home dir ("~" symbol) on paths (#74);
  • Add Snap as an installation method;
  • Move examples to its own repo;
  • Watch: also walk on tasks called on on "cmds", and not only on "deps";
  • Print logs to stderr instead of stdout (#68);
  • Remove deprecated set keyword;
  • Add checksum based status check, alternative to timestamp based.

v1.4.3 - 2017-09-07

  • Allow assigning variables to tasks at run time via CLI (#33)
  • Added support for multiline variables from sh (#64)
  • Fixes env: remove square braces and evaluate shell (#62)
  • Watch: change watch library and few fixes and improvements
  • When use watching, cancel and restart long running process on file change (#59
    and #60)

v1.4.2 - 2017-07-30

  • Flag to set directory of execution
  • Always echo command if is verbose mode
  • Add silent mode to disable echoing of commands
  • Fixes and improvements of variables (#56)

v1.4.1 - 2017-07-15

  • Allow use of YAML for dynamic variables instead of $ prefix
    • VAR: {sh: echo Hello} instead of VAR: $echo Hello
  • Add --list (or -l) flag to print existing tasks
  • OS specific Taskvars file (e.g. Taskvars_windows.yml, Taskvars_linux.yml,
    etc)
  • Consider task up-to-date on equal timestamps (#49)
  • Allow absolute path in generates section (#48)
  • Bugfix: allow templating when calling deps (#42)
  • Fix panic for invalid task in cyclic dep detection
  • Better error output for dynamic variables in Taskvars.yml (#41)
  • Allow template evaluation in parameters

v1.4.0 - 2017-07-06

  • Cache dynamic variables
  • Add verbose mode (-v flag)
  • Support to task parameters (overriding vars) (#31) (#32)
  • Print command, also when "set:" is specified (#35)
  • Improve task command help text (#35)

v1.3.1 - 2017-06-14

  • Fix glob not working on commands (#28)
  • Add ExeExt template function
  • Add --init flag to create a new Taskfile
  • Add status option to prevent task from running (#27)
  • Allow interpolation on generates and sources attributes (#26)

v1.3.0 - 2017-04-24

  • Migrate from os/exec.Cmd to a native Go sh/bash interpreter
    • This is a potentially breaking change if you use Windows.
    • Now, cmd is not used anymore on Windows. Always use Bash-like syntax for
      your commands, even on Windows.
  • Add "ToSlash" and "FromSlash" to template functions
  • Use functions defined on github.com/Masterminds/sprig
  • Do not redirect stdin while running variables commands
  • Using context and errgroup packages (this will make other tasks to be
    cancelled, if one returned an error)

v1.2.0 - 2017-04-02

  • More tests and Travis integration
  • Watch a task (experimental)
  • Possibility to call another task
  • Fix "=" not being recognized in variables/environment variables
  • Tasks can now have a description, and help will print them (#10)
  • Task dependencies now run concurrently
  • Support for a default task (#16)

v1.1.0 - 2017-03-08

  • Support for YAML, TOML and JSON (#1)
  • Support running command in another directory (#4)
  • --force or -f flag to force execution of task even when it's up-to-date
  • Detection of cyclic dependencies (#5)
  • Support for variables (#6, #9, #14)
  • Operation System specific commands and variables (#13)

v1.0.0 - 2017-02-28

  • Add LICENSE file

:::


Website Src Latest Docs Community (`website/src/latest/docs/community.md`)


title: Community Task community contributions, installation methods, and integrations maintained by third parties section: Project docType: project outline: deep

Community

Some of the work to improve the Task ecosystem is done by the community, be it
installation methods or integrations with code editor. I (the author) am
thankful for everyone that helps me to improve the overall experience.

Integrations

Many of our integrations are contributed and maintained by the community. You
can view the full list of community integrations
here.

Installation methods

Some installation methods are maintained by third party:

More

Also, thanks for all the
code contributors,
financial contributors, all those who
reported bugs and
answered questions.

If you know something that is missing in this document, please submit a pull
request.


Website Src Latest Docs Contributing (`website/src/latest/docs/contributing.md`)


title: Contributing Comprehensive guide for contributing to the Task project, including setup, development, testing, and submitting PRs section: Contributing docType: contributing outline: deep

Contributing

Thank you for your interest in contributing to Task! We welcome and appreciate
all forms of contributions, but we kindly ask that you read this document first.
If you have any questions that were not answered by this document, you can reach
out on our Discord or by opening a discussion
on GitHub. If you want to help, but you're not sure where to start, you can
check out our list of
good first issues.

::: info

This document applies to the core Task repository and Task for Visual
Studio Code
.

:::

AI Usage Policy

When using AI tools (including LLMs like ChatGPT, Claude, Copilot, etc.) to
contribute to Task:

  • Please disclose AI usage to reduce maintainer fatigue
  • You are responsible for all AI-generated issues or PRs you submit
  • Low-quality or unreviewed AI content will be closed immediately
  • Keep conversations human - PR descriptions, review comments, and issue
    discussions should be written in your own words, not generated by AI. Code
    review is a discussion between people, not bots.

We encourage the use of AI tools to assist with development, but all
contributions must be thoroughly reviewed and tested by the contributor before
submission. AI-generated code should be understood, validated, and adapted to
meet Task's standards.

Before you start

  • Check existing work - Is there an existing PR? Are there issues discussing
    the feature/change you want to make? Please make sure you consider/address
    these discussions in your work.
  • Backwards compatibility - Will your change break existing Taskfiles? It is
    much more likely that your change will merged if it backwards compatible. Is
    there an approach you can take that maintains this compatibility? If not,
    consider opening an issue first so that API changes can be discussed before
    you invest your time into a PR.
  • Experiments - If there is no way to make your change backward compatible
    then there is a procedure to introduce breaking changes into minor versions.
    We call these "experiments". If you're intending to work on an
    experiment, then please read the experiments workflow
    document carefully and submit a proposal first.

1. Setup

The easiest way to install everything you need to work on Task is mise.
From the repository root, run:

shell
mise install

This installs the pinned versions of Go, Node.js, pnpm and the dev tools
(golangci-lint, mockery, gotestsum, goreleaser and gorelease) declared
in the mise.toml file.

If you'd rather install things manually, you'll need:

  • Go - Task is written in Go. We always support the latest two major
    Go versions, so make sure your version is recent enough.
  • Node.js - Node.js is used to host Task's documentation server
    and is required if you want to run this server locally. It is also required if
    you want to contribute to the Visual Studio Code extension.
  • Pnpm - Pnpm is the Node.js package manager used by Task.

2. Making changes

  • Code style - Try to maintain the existing code style where possible. Go
    code should be formatted and linted by golangci-lint. This
    wraps the gofumpt and gci formatters and a number of
    linters. We recommend that you take a look at the golangci-lint
    docs
    for a guide on how to setup your editor to
    auto-format your code. Any Markdown or TypeScript files should be formatted
    and linted by Prettier. This style is enforced by our CI to ensure
    that we have a consistent style across the project. You can use the
    task lint command to lint the code locally and the task lint:fix command
    to try to automatically fix any issues that are found. You can also use the
    task fmt command to auto-format the files if your editor doesn't do it for
    you.
  • Documentation - Ensure that you add/update any relevant documentation. See
    the updating documentation section below.
  • Tests - Ensure that you add/update any relevant tests and that all tests
    are passing before submitting the PR. See the writing tests
    section below.

Running your changes

To run Task with working changes, you can use go run ./cmd/task. To run a
development build of task against a test Taskfile in testdata, you can use
go run ./cmd/task --dir ./testdata/<my_test_dir> <task_name>.

To run Task for Visual Studio Code, you can open the project in VSCode and hit
F5 (or whatever you debug keybind is set to). This will open a new VSCode window
with the extension running. Debugging this way is recommended as it will allow
you to set breakpoints and step through the code. Otherwise, you can run
task package which will generate a .vsix file that can be used to manually
install the extension.

Updating documentation

Task uses Vitepress to host a documentation server. The code for
this is located in the core Task repository. This can be setup and run locally
by using task website (requires nodejs & pnpm). All content is written in
Markdown and is located in the website/src directory. All Markdown documents
should have an 80 character line wrap limit (enforced by Prettier).

Search is provided by Algolia DocSearch. The crawler runs on Algolia's side and
is configured through their dashboard, but website/docsearch.config.js holds
the same configuration in the repository so it can be read and reviewed. If you
change one, change the other. A page's section: frontmatter is what the
crawler shows as the breadcrumb on a search result, while docType: powers its
search facet, so a new page needs both.

After building the site, run pnpm check:links from website/ to check links
in the generated Markdown pages and LLM indexes. The LLM plugin is patched in
website/patches/ to resolve links before it moves directory indexes such as
docs/guide/index.md to docs/guide.md. When upgrading the plugin, retain the
patch until upstream handles those links, and check both documentation channels.

When making a change, consider whether a change to the Usage
Guide
is necessary. This document contains descriptions and
examples of how to use Task features. If you're adding a new feature, try to
find an appropriate place to add a new section. If you're updating an existing
feature, ensure that the documentation and any examples are up-to-date. Ensure
that any examples follow the Taskfile Styleguide.

If you added a new command or flag, ensure that you add it to the CLI
Reference
. New fields also need to be added to the Schema
Reference
and JSON Schema. The descriptions
for fields in the docs and the schema should match.

Documentation channels

The docs, the blog and the coding-agent guide exist in two copies, so that
taskfile.dev never announces a feature that is not in the released binary yet:

Directory Channel Published on
website/src/next/{docs,blog} next next.taskfile.dev
website/src/latest/{docs,blog} latest taskfile.dev

The coding-agent guide follows the same channels as src/next/agents.md and
src/latest/agents.md, and is promoted at release time too.

Everything else - the homepage, the team, adopters, images - is shared by both
channels and goes live as soon as the site is deployed.

Write in website/src/next. It holds the upcoming release, and
cmd/release copies it over website/src/latest at every release. The same
split applies to the JSON schemas: edit next-schema.json and
next-schema-taskrc.json, never schema.json or schema-taskrc.json.

Where you put a blog post decides when it goes out. A post that announces a
feature belongs in website/src/next/blog alone: it ships with the release that
carries the feature. A post that stands on its own - an announcement, a write-up
about an already released feature - can be added to website/src/latest/blog as
well, and it goes live at the next deploy. Its sidebar entry comes from the
post's own frontmatter, so there is nothing else to update.

Never edit an existing file under website/src/latest: cmd/release overwrites
that directory at every release, so the change would be silently lost. The same
goes for .vitepress/sidebar/latest.ts, which is promoted from next.ts. CI
fails a pull request that modifies either. Adding a file under
website/src/latest is fine - that is how a blog post gets published early.

To preview what taskfile.dev will look like, run task website:start:latest. It
serves the latest channel on port 3002, so it can run next to task website
and the version selector switches between the two.

Writing tests

A lot of Task's tests are held in the task_test.go file in the project root
and this is where you'll most likely want to add new ones too. Most of these
tests also have a subdirectory in the testdata directory where any
Taskfiles/data required to run the tests are stored.

When making a changes, consider whether new tests are required. These tests
should ensure that the functionality you are adding will continue to work in the
future. Existing tests may also need updating if you have changed Task's
behavior.

You may also consider adding unit tests for any new functions you have added.
The unit tests should follow the Go convention of being location in a file named
*_test.go in the same package as the code being tested.

3. Committing your code

Try to write meaningful commit messages and avoid having too many commits on the
PR. Most PRs should likely have a single commit (although for bigger PRs it may
be reasonable to split it in a few). Git squash and rebase is your friend!

If you're not sure how to format your commit message, check out Conventional
Commits
. This style is not enforced, but it is a good way
to make your commit messages more readable and consistent.

4. Submitting a PR

  • Describe your changes - Ensure that you provide a comprehensive
    description of your changes.
  • Issue/PR links - Link any previous work such as related issues or PRs.
    Please describe how your changes differ to/extend this work.
  • Examples - Add any examples or screenshots that you think are useful to
    demonstrate the effect of your changes.
  • Draft PRs - If your changes are incomplete, but you would like to discuss
    them, open the PR as a draft and add a comment to start a discussion. Using
    comments rather than the PR description allows the description to be updated
    later while preserving any discussions.

FAQ

I want to contribute, where do I start?

Take a look at the list of open issues for Task or Task for
Visual Studio Code
. We have a good first
issue
label for simpler issues that are ideal for first time
contributions.

All kinds of contributions are welcome, whether its a typo fix or a shiny new
feature. You can also contribute by upvoting/commenting on issues, helping to
answer questions or contributing to other community projects.

I'm stuck, where can I get help?

If you have questions, feel free to ask them in the #help forum channel on our
Discord server or open a Discussion on GitHub.



Website Src Latest Docs Faq (`website/src/latest/docs/faq.md`)


title: FAQ Frequently asked questions about Task, including ETAs, shell limitations, and Windows compatibility section: Project docType: project outline: deep

FAQ

This page contains a list of frequently asked questions about Task.

When will \ be released? / ETAs

Task is free and open source project maintained by a small group of
volunteers with full time jobs and lives outside of the project. Because of
this, it is difficult to predict how much time we will be able to dedicate to
the project in advance and we don't want to make any promises that we can't
keep. For this reason, we are unable to provide ETAs for new features or
releases. We make a "best effort" to provide regular releases and fix bugs in a
timely fashion, but sometimes our personal lives must take priority.

ETAs are probably the number one question we (and maintainers of other open
source projects) get asked. We understand that you are passionate about the
project, but it can be overwhelming to be asked this question so often. Please
be patient and avoid asking for ETAs.

The best way to speed things up is to contribute to the project yourself. We
always appreciate new contributors. If you are interested in contributing, check
out the contributing guide.

Why won't my task update my shell environment?

This is a limitation of how shells work. Task runs as a subprocess of your
current shell, so it can't change the environment of the shell that started it.
This limitation is shared by other task runners and build tools too.

A common way to work around this is to create a task that will generate output
that can be parsed by your shell. For example, to set an environment variable on
your shell you can write a task like this:

yaml
my-shell-env:
  cmds:
    - echo "export FOO=foo"
    - echo "export BAR=bar"

Now run eval $(task my-shell-env) and the variables $FOO and $BAR will be
available in your shell.

I can't reuse my shell in a task's commands

Task runs each command as a separate shell process, so something you do in one
command won't effect any future commands. For example, this won't work:

yaml
version: '3'

tasks:
  foo:
    cmds:
      - a=foo
      - echo $a
      # outputs ""

To work around this you can either use a multiline command:

yaml
version: '3'

tasks:
  foo:
    cmds:
      - |
        a=foo
        echo $a
      # outputs "foo"

Or for more complex multi-line commands it is recommended to move your code into
a separate file and call that instead:

yaml
version: '3'

tasks:
  foo:
    cmds:
      - ./foo-printer.bash
shell
#!/bin/bash
a=foo
echo $a

Are shell core utilities available on Windows?

The most common ones, yes. And we might add more in the future.
This is possible because Task compiles a small set of core utilities in Go and
enables them by default on Windows for greater compatibility.

It's possible to control whether these builtin core utilities are used or not
with the TASK_CORE_UTILS
environment variable:

bash
# Enable, even on non-Windows platforms
env TASK_CORE_UTILS=1 task ...

# Disable, even on Windows
env TASK_CORE_UTILS=0 task ...

This is the list of core utils that are currently available:

  • base64
  • cat
  • chmod
  • cp
  • find
  • gzip
  • ls
  • mkdir
  • mktemp
  • mv
  • rm
  • shasum
  • tar
  • touch
  • xargs
  • (more might be added in the future)

Website Src Latest Docs Installation (`website/src/latest/docs/installation.md`)


title: Installation section: Getting Started docType: guide outline: deep pageClass: installation-page

Installation

Choose a package manager for your system, or install Task from a binary.

Official packages {#official-package-managers}

Maintained by the Task team and kept up-to-date.

shell
brew install go-task/tap/go-task

Or use the Homebrew core formula:

shell
brew install go-task

Set up the repository:

shell
curl -1sLf 'https://dl.cloudsmith.io/public/task/task/setup.rpm.sh' | sudo -E bash

Install Task:

shell
dnf install task

Set up the repository:

shell
curl -1sLf 'https://dl.cloudsmith.io/public/task/task/setup.deb.sh' | sudo -E bash

Install Task:

shell
apt install task

Set up the repository:

shell
curl -1sLf 'https://dl.cloudsmith.io/public/task/task/setup.alpine.sh' | sudo -E bash

Install Task:

shell
apk add task
shell
sudo snap install task --classic

Requires a Linux distribution with classic confinement support.

shell
npm install @go-task/cli

Task is also available as a project dependency.

shell
winget install Task.Task

Available through the
WinGet community repository.

Package repository hosting for deb/rpm/apk is graciously provided by Cloudsmith.

Community packages {#community-maintained-package-managers}

Maintained by the community, outside the Task team's control. These packages may
lag behind the latest release.

shell
mise use -g task

For a project-local installation, use mise use task instead. This adds Task to
your project's mise.toml.

shell
port install go-task
shell
pip install go-task-bin
shell
choco install go-task
shell
scoop install task
shell
pacman -S go-task
shell
dnf install go-task
shell
pkg install task
shell
nix-env -iA nixpkgs.go-task
shell
pacstall -I go-task-deb
shell
pkgx task

or, if you have pkgx integration enabled:

shell
task

Binaries & CI {#get-the-binary}

Install Task without a package manager: download a binary, use the install
script, or add the setup action to your GitHub workflow.

Download a binary {#binary}

  1. Open the GitHub releases and
    download the archive for your operating system and architecture.
  2. Extract task (task.exe on Windows).
  3. Move the executable to a directory on your PATH.

Each release also includes DEB, RPM and APK packages, plus task_checksums.txt
with SHA-256 checksums for the release files.

Install with a script {#install-script}

Use the
install script for
a shell-based installation, including CI environments. It downloads a prebuilt
binary and verifies its checksum; no Go installation is needed.

By default, the script installs the latest release into ./bin, relative to
your current directory. Choose a different directory or pin a release:

::: code-group

shell [latest release]
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d
shell [custom directory]
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b ~/.local/bin
shell [pinned version]
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d v3.42.1
shell [directory + version]
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b ~/.local/bin v3.42.1

:::

When combining options, keep the
release tag last.

::: tip Make Task available in your shell

Add the installation directory to your PATH to run task from anywhere. With
the default location, you can also run ./bin/task directly.

On Linux, ~/.local/bin and ~/bin are common per-user locations;
/usr/local/bin is a system-wide location and may require elevated permissions.
Do not assume these directories are already on your PATH, especially on macOS
and Windows.

:::

GitHub Actions

Add the official setup action to your
job's steps before running Task:

yaml
- name: Install Task
  uses: go-task/setup-task@v2

- name: Verify Task
  run: task --version

Use the action's version input to pin a Task release. See the
action documentation for examples
and configuration.

Build from source

Ensure that you have a supported version of Go properly
installed and setup. You can find the minimum required version of Go in the
go.mod file.

You can then install the latest release globally by running:

shell
go install github.com/go-task/task/v3/cmd/task@latest

Or you can install into another directory:

shell
env GOBIN=/bin go install github.com/go-task/task/v3/cmd/task@latest

::: tip

For CI environments we recommend using the install script
instead, which is faster and more stable, since it'll just download the latest
released binary.

:::

Go Tool

If you're working in a Go project, a nice possibility is using go tool.
go tool makes it easy to run Task without needing to install the binary
manually. This works well on CI.

To do that, just run the following to add Task as a tool in your Go project.
Task will be added to your go.mod.

bash
go get -tool github.com/go-task/task/v3/cmd/task@latest

Then, prefix go tool when calling Task like below. Go will compile Task on
demand before calling it.

bash
go tool task {arguments...}

Verify installation

After installing, open a terminal and check that Task is available:

shell
task --version

If you installed Task with go tool, run go tool task --version instead.

You're ready to create your first Taskfile. You can also
enable shell completions below.

Shell completions {#setup-completions}

Some installation methods will automatically install completions too, but if
this isn't working for you or your chosen method doesn't include them, you can
run task --completion <shell> to output a completion script for any supported
shell.

Every shell shares a single source of truth: the script is a thin wrapper that
asks the task binary itself what to suggest, so Bash, Zsh, Fish, Nushell and
PowerShell all offer the same task names, aliases, flags, flag values and
requires vars.

There are a couple of ways these completions can be added to your shell config:

This method loads the completion script from the currently installed version of
task every time you create a new shell. This ensures that your completions are
always up-to-date. If your executable isn’t named task, set the TASK_EXE
environment variable before running eval.

::: code-group

shell [bash]
# ~/.bashrc

# export TASK_EXE='go-task' if needed
eval "$(task --completion bash)"
shell [zsh]
# ~/.zshrc

# export TASK_EXE='go-task' if needed
eval "$(task --completion zsh)"
shell [fish]
# ~/.config/fish/config.fish

# export TASK_EXE='go-task' if needed
task --completion fish | source
powershell [powershell]
# $PROFILE\Microsoft.PowerShell_profile.ps1
Invoke-Expression  (&task --completion powershell | Out-String)
nu [nushell]
# ~/.config/nushell/config.nu
#
# Nushell cannot source a script from stdin, so the script is saved where
# Nushell auto-loads it at startup. Autoload directories are read after
# config.nu, so the completions become available in the next shell.
mkdir ($nu.data-dir | path join "vendor/autoload")
task --completion nu | save --force ($nu.data-dir | path join "vendor/autoload/task-completions.nu")

:::

Option 2. Copy the script to your shell's completions directory

This method requires you to manually update the completions whenever Task is
updated. However, it is useful if you want to modify the completions yourself.

::: code-group

shell [bash]
task --completion bash > /etc/bash_completion.d/task
shell [zsh]
task --completion zsh  > /usr/local/share/zsh/site-functions/_task
shell [fish]
task --completion fish > ~/.config/fish/completions/task.fish
nu [nushell]
task --completion nu | save --force ($nu.data-dir | path join "vendor/autoload/task-completions.nu")

:::

Zsh customization

The Zsh completion supports the standard verbose zstyle to control whether
task descriptions are shown. By default, descriptions are displayed. To show
only task names without descriptions, add this to your ~/.zshrc (after the
completion is loaded):

shell
zstyle ':completion:*:*:task:*' verbose false

By default, task aliases are also offered as completions. To complete only the
canonical task names, add the show-aliases zstyle:

shell
zstyle ':completion:*:*:task:*' show-aliases false

Nushell caveats

Nushell cannot source a script from stdin, so both options above write the script
to an autoload directory. Option 1 rewrites it at every startup, which keeps it
in sync with the installed version of Task, and the refreshed completions are
picked up by the next shell. With option 2, re-run the command after upgrading
Task.

Nushell shares a single external completer between every command, so the script
chains to the one already configured β€” carapace and friends keep working. Load it
from an autoload directory as shown above rather than from config.nu, so that
your own completer is the one being chained to. If you would rather wire it
yourself, the script also exposes a task-external-completer command:

nu
$env.config.completions.external.completer = {|spans|
    match ($spans | first) {
        task => (task-external-completer $spans)
        _ => (do $my_other_completer $spans)
    }
}

Two engine directives behave differently under Nushell by design: it never
appends a space after an external completion (so NoSpace is a no-op) and never
re-sorts the results (so KeepOrder is always honoured).


Website Src Latest Docs Integrations (`website/src/latest/docs/integrations.md`)


title: Integrations Official and community integrations for Task, including VS Code, JSON schemas, and other tools section: Getting Started docType: guide outline: deep

Integrations

Visual Studio Code Extension

Task has an
official extension for Visual Studio Code.
The code for this project can be found in
our GitHub repository. To use this
extension, you must have Task v3.45.3+ installed on your system.

This extension provides the following features (and more):

  • View tasks in the sidebar.
  • Run tasks from the sidebar and command palette.
  • Go to definition from the sidebar and command palette.
  • Run last task command.
  • Multi-root workspace support.
  • Initialize a Taskfile in the current workspace.

To get autocompletion and validation for your Taskfile, see the
Schema section below.

Configuration namespace change

In v1.0.0 of the extension, the configuration namespace was changed from task
to taskfile in order to fix
an issue.

If you receive a warning like the one above, you will need to update your
settings to use the new taskfile namespace instead:

Schema

This was initially created by @KROSF in
this Gist and
is now officially maintained in
this file
and made available at https://taskfile.dev/schema.json. This schema can be used
to validate Taskfiles and provide autocompletion in many code editors:

Visual Studio Code

To integrate the schema into VS Code, you need to install the
YAML extension
by Red Hat. Any Taskfile.yml in your project should automatically be detected
and validation/autocompletion should work. If this doesn't work or you want to
manually configure it for files with a different name, you can add the following
to your settings.json:

json
// settings.json
{
  "yaml.schemas": {
    "https://taskfile.dev/schema.json": [
      "**/Taskfile.yml",
      "./path/to/any/other/taskfile.yml"
    ]
  }
}

You can also configure the schema directly inside of a Taskfile by adding the
following comment to the top of the file:

yaml
# yaml-language-server: $schema=https://taskfile.dev/schema.json
version: '3'

You can find more information on this in the
YAML language server project.

AI/LLM Assistants

Task documentation is optimized for AI assistants like Claude Code, Cursor, and
other LLM-powered development tools through the
VitePress LLMs plugin.

This integration provides:

  • Structured documentation in LLM-friendly formats
  • Context-optimized content for AI assistants
  • Automatic generation of llms.txt and llms-full.txt files
  • Enhanced discoverability of Task features for AI tools

AI assistants can access Task documentation through:

  • llms.txt: Lightweight overview of Task documentation
  • llms-full.txt: Complete documentation with all content

These files are automatically generated and kept in sync with the documentation,
ensuring AI assistants always have access to the latest Task features and usage
patterns.

Community Integrations

In addition to our official integrations, there is an amazing community of
developers who have created their own integrations for Task:

If you have made something that integrates with Task, please feel free to open a
PR to add it to this list.


Website Src Latest Docs Releasing (`website/src/latest/docs/releasing.md`)


title: Releasing Task release process including GoReleaser, Homebrew, npm, Snapcraft, winget, and other package managers section: Contributing docType: contributing outline: deep

Releasing

The release process of Task is done with the help of GoReleaser.
You can test the release process locally by calling the goreleaser:test task
of the Taskfile.

GitHub Actions should release
artifacts automatically when a new Git tag is pushed to main branch (raw
executables and DEB and RPM packages).

The body of the GitHub release is the section of the CHANGELOG.md matching the
version being released, extracted by go run ./cmd/release --notes. A version
without changelog entries is released with an empty body.

Raw executables can also be reproduced and verified locally by checking out a
specific tag and calling goreleaser build, using the Go version defined in the
above GitHub Actions.

Website

task release:<version> promotes the documentation before tagging: the docs in
website/src/next/docs, their sidebar and the next-* JSON schemas are copied
over their published counterparts, so the released tag carries the docs of the
version it ships. The release workflow then runs task website:deploy:prod.

A new blog post is a Markdown file in website/src/next/blog with no file at
the same relative path in website/src/latest/blog, excluding index.md.
Renaming a post therefore makes it new. On the next site, new posts display
the build date in UTC (YYYY-MM-DD) and are sorted using that date, without
changing the source files. The latest site uses only the stored dates.

During release preparation, cmd/release replaces or adds the date in each
new post's frontmatter with the same local date used for the changelog. It
validates all new posts' frontmatter before writing; an error identifies the
file to fix. It then copies the blog to latest, so both copies carry the same
date in the release commit. This is the preparation date, even if publication on
GitHub happens later. Already published posts keep their dates, including when
their content changes. The --version and --notes flags do not write files.

Because taskfile.dev is built from the latest copy, it can be redeployed at any
time between releases - to publish a blog post or a documentation fix - without
exposing the docs of unreleased features:

shell
git checkout main && git pull
task website:deploy:prod

Package managers

GoReleaser will automatically publish the release to most package managers:

  • Cloudsmith (DEB and RPM repositories)
  • Homebrew
  • npm
  • Snapcraft
  • winget

Once the release is published, GoReleaser announces it on the
Discord server. Nightly releases are not
announced.

These package managers are updated automatically by the community:


Website Src Latest Docs Remote Taskfiles (`website/src/latest/docs/remote-taskfiles.md`)


title: Remote Taskfiles Guide to loading and securely using Taskfiles from HTTP and Git sources section: Guide docType: guide outline: deep

Remote Taskfiles

Use a remote Taskfile to share tasks across projects without copying the file
into each repository. You can call it directly or include it under a namespace.

::: danger

Only run remote Taskfiles from sources you trust. Their commands execute on your
machine, just like commands from a local Taskfile.

:::

The examples use Task's public sample, whose hello task prints Hello Task!.
On first use, Task asks you to trust the downloaded file. Review it before
accepting; see trust and checksums for subsequent changes and CI.

Run a remote Taskfile {#specifying-a-remote-entrypoint}

Pass the remote location to --taskfile (or -t). With no task name, Task runs
the remote file's default task. Choose a transport below:

::: code-group

shell [http/https]
$ task --taskfile https://raw.githubusercontent.com/go-task/task/main/website/src/public/Taskfile.yml
task: [hello] echo "Hello Task!"
Hello Task!
shell [git over http]
$ task --taskfile 'https://github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main'
task: [hello] echo "Hello Task!"
Hello Task!
shell [git over ssh]
$ task --taskfile '[email protected]/go-task/task.git//website/src/public/Taskfile.yml?ref=main'
task: [hello] echo "Hello Task!"
Hello Task!

:::

Include shared tasks {#including-remote-taskfiles}

Set the include location to a remote URL instead of a local path. The tasks
become available under the namespace you choose, just like
local includes:

::: code-group

yaml [http/https]
version: '3'

includes:
  shared: https://raw.githubusercontent.com/go-task/task/main/website/src/public/Taskfile.yml
yaml [git over http]
version: '3'

includes:
  shared: https://github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main
yaml [git over ssh]
version: '3'

includes:
  shared: [email protected]/go-task/task.git//website/src/public/Taskfile.yml?ref=main

:::

shell
$ task shared:hello
task: [hello] echo "Hello Task!"
Hello Task!

Supply authentication {#authenticating-using-environment-variables}

The Taskfile location is processed by the templating system, so you can
reference environment variables in your URL if you need to add authentication.
For example:

yaml
version: '3'

includes:
  shared: https://{{.TOKEN}}@raw.githubusercontent.com/my-org/my-repo/main/Taskfile.yml

Prefer the remote.headers configuration
option when the server accepts a header. A credential in the URL ends up in
error messages and in the confirmation prompt, and the include can no longer be
committed as-is.

Choose a source {#node-types}

HTTP/HTTPS

https://raw.githubusercontent.com/go-task/task/main/website/src/public/Taskfile.yml

Use a direct URL when the server exposes the Taskfile as plain text. Task
downloads the file from that URL. The file must be a valid Taskfile and can be
of any name. If a file is not found at the specified URL, Task will append each
of the supported file names in turn until it finds a valid file. If it still
does not find a valid Taskfile, an error is returned.

Git over HTTP

https://github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main

Use a Git URL to select a file from a repository over HTTP/HTTPS. The first part
of the URL is the base URL of the Git repository. This is the same URL that you
would use to clone the repo over HTTP.

  • You can optionally add the path to the Taskfile in the repository by appending
    // to the URL.
  • You can also optionally specify a branch or tag to use by appending
    ?ref=<ref> to the end of the URL. If you omit a reference, the default
    branch will be used.

Git over SSH

[email protected]/go-task/task.git//website/src/public/Taskfile.yml?ref=main

Use an SSH Git URL when repository access depends on your SSH credentials. The
first part of the URL is the user and base URL of the Git repository. This is
the same URL that you would use to clone the repo over SSH.

To use Git over SSH, you need to make sure that your SSH agent has your private
SSH keys added so that they can be used during authentication.

  • You can optionally add the path to the Taskfile in the repository by appending
    // to the URL.
  • You can also optionally specify a branch or tag to use by appending
    ?ref=<ref> to the end of the URL. If you omit a reference, the default
    branch will be used.

Locate files and directories {#special-variables}

The file-path special variables behave
differently when a Taskfile is loaded from a remote source, because there is no
local file or directory that corresponds 1:1 to the Taskfile:

Variable Value when loaded remotely
TASKFILE / ROOT_TASKFILE The original URL, unchanged
TASKFILE_DIR / ROOT_DIR Empty string, a directory variable cannot point to a URL
TASK_DIR Resolved against USER_WORKING_DIR (relative dir: β†’ joined with USER_WORKING_DIR, empty dir: β†’ USER_WORKING_DIR, absolute dir: β†’ kept as-is)

If a remote Taskfile includes a local Taskfile (or vice-versa), each variable
reflects the source of the Taskfile it refers to.

Review trust and changes {#security}

Review changed files {#automatic-checksums}

Running commands from sources that you do not control is always a potential
security risk. For this reason, we have added some automatic checks when using
remote Taskfiles:

  1. When running a task from a remote Taskfile for the first time, Task will
    print a warning to the console asking you to check that you are sure that you
    trust the source of the Taskfile. If you do not accept the prompt, then Task
    will exit with code 104 (not trusted) and nothing will run. If you accept
    the prompt, the remote Taskfile will run and further calls to the remote
    Taskfile will not prompt you again.
  2. Whenever you run a remote Taskfile, Task will create and store a checksum of
    the file that you are running. If the checksum changes, then Task will print
    another warning to the console to inform you that the contents of the remote
    file has changed. If you do not accept the prompt, then Task will exit with
    code 104 (not trusted) and nothing will run. If you accept the prompt, the
    checksum will be updated and the remote Taskfile will run.

Sometimes you need to run Task in an environment that does not have an
interactive terminal, so you are not able to accept a prompt. In these cases you
are able to tell task to accept these prompts automatically by using the --yes
flag or the --trusted-hosts flag. The --trusted-hosts flag allows you to
specify trusted hosts for remote Taskfiles, while --yes applies to all prompts
in Task. You can also configure trusted hosts in your
taskrc configuration using
remote.trusted-hosts. Before enabling automatic trust, you should:

  1. Be sure that you trust the source and contents of the remote Taskfile.
  2. Consider using a pinned version of the remote Taskfile (e.g. A link
    containing a commit hash) to prevent Task from automatically accepting a
    prompt that says a remote Taskfile has changed.

Pin reviewed contents {#manual-checksum-pinning}

Alternatively, if you expect the contents of your remote files to be a constant
value, you can pin the checksum of the included file instead:

yaml
version: '3'

includes:
  included:
    taskfile: https://raw.githubusercontent.com/go-task/task/main/website/src/public/Taskfile.yml
    checksum: '<sha256-of-reviewed-file>'

Replace the placeholder with the SHA-256 checksum of the file you reviewed. A
pinned checksum disables the automatic checksum prompts discussed above.
However, if the checksums do not match, Task will exit immediately with an
error. When setting this up for the first time, you may not know the correct
value of the checksum. There are a couple of ways you can obtain this:

  1. Add the include normally without the checksum key. The first time you run
    the included Taskfile, a .task/remote temporary directory is created. Find
    the correct set of files for your included Taskfile and open the file that
    ends with .checksum. You can copy the contents of this file and paste it
    into the checksum key of your include. This method is safest as it allows
    you to inspect the downloaded Taskfile before you pin it.
  2. Alternatively, add the include with a temporary random value in the
    checksum key. When you try to run the Taskfile, you will get an error that
    will report the incorrect expected checksum and the actual checksum. You can
    copy the actual checksum and replace your temporary random value.

Use TLS {#tls}

Task currently supports both http and https URLs. However, the http
requests will not execute by default unless you run the task with the
--insecure flag. This is to protect you from accidentally running a remote
Taskfile that is downloaded via an unencrypted connection. Sources that are not
protected by TLS are vulnerable to man-in-the-middle attacks and should be
avoided unless you know what you are doing.

Add certificates {#custom-certificates}

If your remote Taskfiles are hosted on a server that uses a custom CA
certificate (e.g., a corporate internal server), you can specify the CA
certificate using the --cacert flag:

shell
task --taskfile https://internal.example.com/Taskfile.yml --cacert /path/to/ca.crt

For servers that require client certificate authentication (mTLS), you can
provide a client certificate and key:

shell
task --taskfile https://secure.example.com/Taskfile.yml \
  --cert /path/to/client.crt \
  --cert-key /path/to/client.key

::: warning

Encrypted private keys are not currently supported. If your key is encrypted,
you must decrypt it first:

shell
openssl rsa -in encrypted.key -out decrypted.key

:::

These options can also be configured in the
configuration file.

Reuse cached files {#caching-running-offline}

What do you need? Option
Reuse a downloaded copy for one hour --expiry 1h
Use an existing cache without network access --offline
Fetch a fresh copy now --download
Remove cached remote files --clear-cache

For example, run task --offline shared:hello after downloading and trusting
the include above. Offline mode needs an existing cached copy.

Whenever you run a remote Taskfile, the latest copy will be downloaded from the
internet and cached locally. This cached file will be used for all future
invocations of the Taskfile until the cache expires. Once it expires, Task will
download the latest copy of the file and update the cache. By default, the cache
is set to expire immediately. This means that Task will always fetch the latest
version. However, the cache expiry duration can be modified by setting the
--expiry flag.

If for any reason you lose access to the internet or you are running Task in
offline mode (via the --offline flag or TASK_REMOTE_OFFLINE environment
variable), Task will run any available cached files even if they are expired.
An uncached remote file cannot run offline.

By default, Task will timeout requests to download remote files after 10 seconds
and look for a cached copy instead. This timeout can be configured by setting
the --timeout flag and specifying a duration. For example, --timeout 5s will
set the timeout to 5 seconds.

By default, the cache is stored in the Task temp directory (.task). You can
override the location of the cache by using the --remote-cache-dir flag, the
remote.cache-dir option in your
configuration file, or the
TASK_REMOTE_CACHE_DIR environment variable. This way, you can share the cache
between different projects.

You can force Task to ignore the cache and download the latest version by using
the --download flag.

You can use the --clear-cache flag to clear all cached remote files.

Set remote defaults {#configuration}

It is possible to configure the default behavior of remote Taskfiles using
configuration. Check out the following references for more information on how to
set up this configuration using flags, environment variables or a configuration
file:


Website Src Latest Docs Styleguide (`website/src/latest/docs/styleguide.md`)


Style Guide

This is the official style guide for Taskfile.yml files. It provides basic
instructions for keeping your Taskfiles clean and familiar to other users.

This guide contains general guidelines, but they do not necessarily need to be
followed strictly. Feel free to disagree and do things differently if you need
or want to. Any improvements to this guide are welcome! Please open an issue or
create a pull request to contribute.

Use the suggested ordering of the main sections

yaml
version:
includes:
# optional configurations (output, silent, method, run, etc.)
vars:
env: # followed or replaced by dotenv
tasks:

Use two spaces for indentation

This is the most common convention for YAML files, and Task follows it.

yaml
# bad
tasks:
    foo:
        cmds:
            - echo 'foo'


# good
tasks:
  foo:
    cmds:
      - echo 'foo'

Separate the main sections with empty lines

yaml
# bad
version: '3'
includes:
  docker: ./docker/Taskfile.yml
output: prefixed
vars:
  FOO: bar
env:
  BAR: baz
tasks:
  # ...


# good
version: '3'

includes:
  docker: ./docker/Taskfile.yml

output: prefixed

vars:
  FOO: bar

env:
  BAR: baz

tasks:
  # ...

Separate tasks with empty lines

yaml
# bad
version: '3'

tasks:
  foo:
    cmds:
      - echo 'foo'
  bar:
    cmds:
      - echo 'bar'
  baz:
    cmds:
      - echo 'baz'


# good
version: '3'

tasks:
  foo:
    cmds:
      - echo 'foo'

  bar:
    cmds:
      - echo 'bar'

  baz:
    cmds:
      - echo 'baz'

Use only uppercase letters for variable names

yaml
# bad
version: '3'

vars:
  binary_name: myapp

tasks:
  build:
    cmds:
      - go build -o {{.binary_name}} .


# good
version: '3'

vars:
  BINARY_NAME: myapp

tasks:
  build:
    cmds:
      - go build -o {{.BINARY_NAME}} .

Avoid using whitespace when templating variables

yaml
# bad
version: '3'

tasks:
  greet:
    cmds:
      - echo '{{ .MESSAGE }}'


# good
version: '3'

tasks:
  greet:
    cmds:
      - echo '{{.MESSAGE}}'

This convention is also commonly used in templates for the Go programming
language.

Use kebab case for task names

yaml
# bad
version: '3'

tasks:
  do_something_fancy:
    cmds:
      - echo 'Do something'


# good
version: '3'

tasks:
  do-something-fancy:
    cmds:
      - echo 'Do something'

Use a colon to separate the task namespace and name

yaml
# good
version: '3'

tasks:
  docker:build:
    cmds:
      - docker ...

  docker:run:
    cmds:
      - docker-compose ...

This is also done automatically when using included Taskfiles.

Prefer using external scripts instead of multi-line commands

yaml
# bad
version: '3'

tasks:
  build:
    cmds:
      - |
        for i in $(seq 1 10); do
          echo $i
          echo "some other complex logic"
        done'

# good
version: '3'

tasks:
  build:
    cmds:
      - ./scripts/my_complex_script.sh

Website Src Latest Docs Taskfile Versions (`website/src/latest/docs/taskfile-versions.md`)


title: Taskfile Versions How to use the Taskfile schema version to ensure users are using the correct versions of Task section: Project docType: project outline: deep

Taskfile Versions

The Taskfile schema slowly changes as new features are added and old ones are
removed. This document explains how to use a Taskfile's schema version to ensure
that the users of your Taskfile are using the correct versions of Task.

What the Taskfile version means

The schema version at the top of every Taskfile corresponds to a version of the
Task CLI, and by extension, the features that are provided by that version. When
creating a Taskfile, you should specify the minimum version of Task that
supports the features you require. If you try to run a Taskfile with a version
of Task that does not meet this minimum required version, it will exit with an
error. For example, given a Taskfile that starts with:

yaml
version: '3.2.1'

When executed with Task v3.2.0, it will exit with an error. Running with
version v3.2.1 or higher will work as expected.

Task accepts any SemVer compatible string including versions which
omit the minor or patch numbers. For example, 3, 3.0, and 3.0.0 all mean
the same thing and are all valid. Most Taskfiles only specify the major version
number. However it can be useful to be more specific when you intend to share a
Taskfile with others.

For example, the Taskfile below makes use of aliases:

yaml
version: '3'

tasks:
  hello:
    aliases:
      - hi
      - hey
    cmds:
      - echo "Hello, world!"

Aliases were introduced in Task v3.17.0, but the Taskfile only specifies 3
as the version. This means that a user who has v3.16.0 or lower installed will
get a potentially confusing error message when trying to run the Task as the
Taskfile specifies that any version greater or equal to v3.0.0 is fine.

Instead, we should start the file like this:

yaml
version: '3.17'

Now when someone tries to run the Taskfile with an older version of Task, they
will receive an error prompting them to upgrade their version of Task to
v3.17.0 or greater.

:::info

Note that this functionality was introduced in
v3.34.0, so older
versions are not able to give you this warning.

:::

Versions 1 & 2

Version 1 and 2 of Task are no longer officially supported and anyone still
using them is strongly encouraged to upgrade to the latest version of Task.

While version: 2 of Task did support schema versions, the behavior did not
work in quite the same way and cannot be relied upon for the purposes discussed
above.


Website Src Next Docs Changelog (`website/src/next/docs/changelog.md`)


Changelog

::: v-pre

v3.54.0 - 2026-10-01

πŸš€ Features

  • Added versioned Homebrew casks (go-task@<major>.<minor>) to install a
    specific minor version of Task (#3023 by @vmaerten).
  • Added a remote.headers config option to send HTTP headers when downloading a
    remote Taskfile, configured per host. Header values support templating
    functions, e.g. {{env "GITLAB_TOKEN"}}. This keeps the credential out of the
    include URL, where it would leak into error messages and the confirmation
    prompt (#2329 by @vmaerten).

πŸ› Fixes

  • Fixed remote Git Taskfile cache poisoning on shared hosts (GHSA-679p-658w-m3wr,
    reported by @danielcadev, fixed by @vmaerten).

  • Fixed tasks cancelled by the user returning exit code 201 instead of 205
    (#3040, #3041 by @r3wretrhy).

  • Fixed a bug on Windows where watching source paths did not work as expected
    (#2863, #3028 by @pd93).

  • Fixed a remote Taskfile whose server refuses the credentials being reported as
    a missing Taskfile. A 401 now stops the search and reports the status code,
    instead of retrying every default Taskfile name and concluding that no
    Taskfile exists (#2329 by @vmaerten).

  • task --completion <shell> now serves a new completion engine that unifies
    Bash, Fish, Zsh, Nushell and PowerShell behind a single task __complete
    command, so every shell offers the same suggestions: task names, aliases,
    flags, flag values and per-task CLI variables. The Zsh show-aliases and
    verbose zstyles keep working, now backed by the --no-aliases and
    --no-descriptions completion flags (#2897 by @vmaerten).

πŸ“¦ Package API

  • Bumped the minimum Go version to 1.26. Task follows Go's two-latest support
    window, and is now tested against 1.26 and 1.27. This only affects projects
    importing Task as a Go module (#2920 by @vmaerten).

Other

  • Refactored some functional options to always return a concrete type instead of
    an interface and moved options into their own file (#3037 by @pd93).
  • Refactored the execext package to use mvdan/sh's new BashOpts API (#3035 by
    @pd93).

v3.53.1 - 2026-08-18

πŸš€ Features

  • Remote Taskfiles are now generally available! This has been an
    experimental feature for 3 years, but is now enabled by default. Massive
    thanks to all those that contributed and gave feedback (too many to list
    here). We've also given the
    Remote Taskfiles documentation a
    bit of a polish (#1317, #2906 by @pd93).
  • Added a per-command timeout that terminates a command once it exceeds the
    given duration (Go duration syntax). It covers shell commands, task calls,
    deferred commands, deps and the if condition, obeys ignore_error, and
    reports exit code 124. Callers that join a run: once or when_changed
    task already running now honor their own timeout, and inherit that task's
    failure instead of being told it succeeded (#1569, #2898 by @vmaerten).
  • Considerably improve performance of fingerprinting on large repositories
    (monorepos). Fingerprinting is up to 86% faster and make up to 70% fewer
    memory allocations on the more advanced scenarios. Benchmarks were added as
    well. We're basically skipping work when not needed. (#2853, #2883 by
    @Napolitain, #2884 by @Napolitain).
  • Further improved fingerprinting performance on large repositories: hashing
    source files now reuses a single buffer, reducing memory allocations by ~98%
    and wall-clock time by ~7% (#2925 by @vmaerten).
  • includes.excludes can now exclude a whole namespace: append :* to the
    namespace name, e.g. excludes: ['debug:*']. Bare entries still match a
    single task name exactly (#2300, #2959 by @xmxxc).
  • Added support for enum.ref in --interactive prompts. Required vars using
    enum.ref now show the selection list like static enums, instead of falling
    back to free-form input (#2817 by @vmaerten).
  • Added Nushell completions, available via task --completion nu. They complete
    task names and aliases, every flag with its description, and the values of
    --completion, --output and --sort (#2966 by @vmaerten).
  • Added a verbose log line for failed tasks. In --verbose mode, a task whose
    command exits non-zero now reports task: "<name>" failed: <error> instead of
    stopping without a trace (#2240 by @Drino).

πŸ› Fixes

  • Fixed a pinned checksum: not being verified when a remote Taskfile came from
    the cache (#2980 by @vmaerten).
  • Fixed the fingerprint variable ({{.CHECKSUM}}/{{.TIMESTAMP}}) ignoring a
    method: set at the Taskfile level: the variable now follows the same method
    resolution as the up-to-date check. Only the variable matching the effective
    method is injected, so a task inheriting a Taskfile-level method: timestamp
    gets {{.TIMESTAMP}} and no longer a {{.CHECKSUM}} (which now renders as an
    empty string), and neither variable is injected when the effective method is
    none (#2924 by @vmaerten).
  • Fixed ref: in for: matrix: and enum: only accepting literal lists. Refs
    computed with template functions like keys or splitList no longer fail
    with "must resolve to a list" (#2544, #2956 by @no-hup).
  • Fixed pressing Esc at an interactive variable prompt not cancelling the run
    (#2942 by @anilnatha).
  • Fixed joinUrl collapsing the // in a URL scheme (e.g. producing
    http:/localhost instead of http://localhost) (#2915 by @vsaraikin).
  • Fixed the JSON schema rejecting ignore_error on a command inside a for
    loop. Editors no longer flag a Taskfile that Task runs perfectly fine (#2044
    by @gokeefe-atb).
  • Fixed the JSON schema rejecting more keys the Taskfile parser accepts:
    ignore_error on a task: call, and if, set and shopt on a command
    inside a for loop (#2967 by @vmaerten).

πŸ“š Documentation & Website

  • Updated taskfile versions doc to mention when version checks were introduced
    (#2184 by @jubr).
  • Load the sidebar data and titles/excerpts from the blog post markdown document
    and its frontmatter on the website (#2981 by @pd93).

v3.53.0 - 2026-08-18

  • Failed due to an issue with our release process.

v3.52.0 - 2026-07-02

  • Fixed --interactive prompts for required vars sometimes appearing in a random
    order. Prompts now follow the order the vars are declared in the Taskfile.
    (#2871 by @caproven)
  • Fixed Fish completions not being picked up correctly by installing them to
    Fish's vendor_completions.d directory instead of completions (#2850, #2859
    by @Legimity).
  • PowerShell completions now work with aliases of the task command, not just
    the task binary itself (#2852 by @kojiishi).
  • Fixed task and namespace aliases not being completed by the Zsh completion. A
    show-aliases zstyle can turn this off (#2865, #2864 by @vmaerten).
  • Fixed task names containing certain characters (e.g. \, _, ^) leaking
    into checksum/timestamp filenames, breaking sources:/generates: up-to-date
    detection (#2886 by @s3onghyun).
  • Fixed for: matrix: loops using ref: rows producing wrong values when the
    same task was run concurrently (e.g. by parallel deps) with different vars
    (#2890, #2894 by @amitmishra11).
  • Added a secret: true flag for variables that masks their value in logs,
    task --summary, and command output (#2514 by @vmaerten).
  • Added the use_gitignore setting (global or per-task) to skip files matched
    by your .gitignore when fingerprinting sources/generates and when
    watching (#2773 by @vmaerten).
  • Added support for configuring output flags (--output,
    --output-group-begin, --output-group-end, --output-group-error-only) via
    the TASK_OUTPUT* environment variables (#2873 by @liiight).
  • Added a --temp-dir flag (with TASK_TEMP_DIR env var and temp-dir taskrc
    config) to customise the directory where Task stores temporary files such as
    checksums. Relative paths are resolved against the root Taskfile (#2891 by
    @kjasn).
  • Defined environment variable behavior for remote taskfiles (#2267, #2847 by
    @vmaerten).
  • Added support for remote Taskfiles hosted on Azure DevOps, whose git URLs use
    a /_git/ path segment rather than a .git suffix (#2904 by @pd93).
  • Re-added the example remote taskfile at
    taskfile.dev/Taskfile.yml (#2905 by
    @pd93).
  • Fixed malformed includes: entries (missing taskfile/dir) reporting a
    misleading "include cycle detected" error instead of a clear configuration
    error (#1881, #2892 by @Lewin671).

v3.51.1 - 2026-05-16

  • A significant performance boost was achieved for large Taskfiles (monorepos)
    by skipping templating altogether when the string is static (#2820 by @romnn).
  • Added absPath template function that resolves a path to its absolute form,
    cleaning .. and . components (#2681, #2788 by @mateenanjum).
  • Added joinEnv function to join paths based on your oprating system: ; for
    Windows and : elsewhere, and joinUrl to join URL paths. Also, added two
    new special variables: FILE_PATH_SEPARATOR which returns \ on Windows and
    / elsewhere, and PATH_LIST_SEPARATOR which returns ; on Windows and :
    elsewhere (#2406, #2408 by @solvingj).
  • Update the shell interpreter with a regression fix (#2812, #2832 by
    @andreynering).
  • Fix potential panic with the shell interpreter (#2810 by @trulede).

v3.50.0 - 2026-04-13

  • Added enum.ref support in requires: enum constraints can now reference
    variables or template pipelines (e.g., ref: .ALLOWED_ENVS) instead of
    duplicating static lists. Combined with sh: variables, this enables fully
    dynamic enum validation (#2678 by @vmaerten).
  • Fixed Fish completion using hardcoded task binary name instead of
    $GO_TASK_PROGNAME for experiments cache (#2730, #2727 by @SergioChan).
  • Fixed watch mode ignoring SIGHUP signal, causing the watcher to exit instead
    of restarting (#2764, #2642).
  • Fixed a long time bug where the task wouldn't re-run as it should when using
    method: timestamp and the files listed on generates: were deleted. This
    makes method: timestamp behaves the same as method: checksum (#1230, #2716
    by @drichardson).

v3.49.1 - 2026-03-08

  • Reverted #2632 for now, which caused some regressions. That change will be
    reworked (#2720, #2722, #2723).

v3.49.0 - 2026-03-07

  • Fixed included Taskfiles with watch: true not triggering watch mode when
    called from the root Taskfile (#2686, #1763 by @trulede).
  • Fixed Remote Git Taskfiles failing on Windows due to backslashes in URL paths
    (#2656 by @Trim21).
  • Fixed remote Git Taskfiles timing out when resolving includes after accepting
    the trust prompt (#2669, #2668 by @vmaerten).
  • Fixed unclear error message when Taskfile search stops at a directory
    ownership boundary (#2682, #1683 by @trulede).
  • Fixed global variables from imported Taskfiles not resolving ref: values
    correctly (#2632 by @trulede).
  • Every .taskrc.yml option can now be overridden with a TASK_-prefixed
    environment variable, making CI and container configuration easier (#2607,
    #1066 by @vmaerten).

v3.48.0 - 2026-01-26

  • Fixed if: conditions when using to check dynamic variables. Also, skip
    variable prompt if task would be skipped by if: (#2658, #2660 by @vmaerten).
  • Fixed ROOT_TASKFILE variable pointing to directory instead of the actual
    Taskfile path when no explicit -t flag is provided (#2635, #1706 by
    @trulede).
  • Included Taskfiles with silent: true now properly propagate silence to their
    tasks, while still allowing individual tasks to override with silent: false
    (#2640, #1319 by @trulede).
  • Added TLS certificate options for Remote Taskfiles: use --cacert for
    self-signed certificates and --cert/--cert-key for mTLS authentication
    (#2537, #2242 by @vmaerten).

v3.47.0 - 2026-01-24

  • Fixed remote git Taskfiles: cloning now works without explicit ref, and
    directory includes are properly resolved (#2602 by @vmaerten).
  • For output: prefixed, print prefix: if set instead of task name (#1566,
    #2633 by @trulede).
  • Ensure no ANSI sequences are printed for --color=false (#2560, #2584 by
    @trulede).
  • Task aliases can now contain wildcards and will match accordingly (e.g., s-*
    as alias for start-*) (#1900, #2234 by @vmaerten).
  • Added conditional execution with the if field: skip tasks, commands, or task
    calls based on shell exit codes or template expressions like
    {{ eq .ENV "prod" }} (#2564, #608 by @vmaerten).
  • Task can now interactively prompt for missing required variables when running
    in a TTY, with support for enum selection menus. Enable with --interactive
    flag or interactive: true in .taskrc.yml (#2579, #2079 by @vmaerten).

v3.46.4 - 2025-12-24

  • Fixed regressions in completion script for Fish (#2591, #2604, #2592 by
    @WinkelCode).

v3.46.3 - 2025-12-19

  • Fixed regression in completion script for zsh (#2593, #2594 by @vmaerten).

v3.46.2 - 2025-12-18

  • Fixed a regression on previous release that affected variables passed via
    command line (#2588, #2589 by @vmaerten).

v3.46.1 - 2025-12-18

✨ Features

  • A small behavior change was made to dependencies. Task will now wait for all
    dependencies to finish running before continuing, even if any of them fail. To
    opt for the previous behavior, set failfast: true either on your
    .taskrc.yml or per task, or use the --failfast flag, which will also work
    for --parallel (#1246, #2525 by @andreynering).
  • The --summary flag now displays vars: (both global and task-level),
    env:, and requires: sections. Dynamic variables show their shell command
    (e.g., sh: echo "hello") instead of the evaluated value (#2486 ,#2524 by
    @vmaerten).
  • Improved performance of fuzzy task name matching by implementing lazy
    initialization. Added --disable-fuzzy flag and disable-fuzzy taskrc option
    to allow disabling fuzzy matching entirely (#2521, #2523 by @vmaerten).
  • Added LLM-optimized documentation via VitePress plugin, generating llms.txt
    and llms-full.txt for AI-powered development tools (#2513 by @vmaerten).
  • Added --trusted-hosts CLI flag and remote.trusted-hosts config option to
    skip confirmation prompts for specified hosts when using Remote Taskfiles
    (#2491, #2473 by @maciejlech).
  • When running in GitHub Actions, Task now automatically emits error annotations
    on failure, improving visibility in workflow summaries (#2568 by @vmaerten).
  • The --yes flag is now accessible in templates via the new CLI_ASSUME_YES
    variable (#2577, #2479 by @semihbkgr).
  • Improved shell completion scripts (Zsh, Fish, PowerShell) by adding missing
    flags and dynamic experimental feature detection (#2532 by @vmaerten).
  • Remote Taskfiles now accept application/octet-stream Content-Type (#2536,
    #1944 by @vmaerten).
  • Shell completion now works when Task is installed or aliased under a different
    binary name via TASK_EXE environment variable (#2495, #2468 by @vmaerten).
  • Some small fixes and improvements were made to task --init and to the
    default Taskfile it generates (#2433 by @andreynering).
  • Added --remote-cache-dir flag and remote.cache-dir taskrc option to
    customize the cache directory for Remote Taskfiles (#2572 by @vmaerten).
  • Zsh completion now supports zstyle verbose option to show or hide task
    descriptions (#2571 by @vmaerten).
  • Task now automatically enables colored output in CI environments (GitHub
    Actions, GitLab CI, etc.) without requiring FORCE_COLOR=1 (#2569 by
    @vmaerten).
  • Added color taskrc option to explicitly enable or disable colored output
    globally (#2569 by @vmaerten).
  • Improved Git Remote Taskfiles by switching to go-getter: SSH authentication
    now works out of the box and applyOf is properly supported (#2512 by
    @vmaerten).

πŸ› Fixes

  • Fix RPM upload to Cloudsmith by including the version in the filename to
    ensure unique filenames (#2507 by @vmaerten).
  • Fix run: when_changed to work properly for Taskfiles included multiple times
    (#2508, #2511 by @trulede).
  • Fixed Zsh and Fish completions to stop suggesting task names after --
    separator, allowing proper CLI_ARGS completion (#1843, #1844 by
    @boiledfroginthewell).
  • Watch mode (--watch) now always runs the task, regardless of run: once or
    run: when_changed settings (#2566, #1388 by @trulede).
  • Fixed global variables (CLI_ARGS, CLI_FORCE, etc.) not being accessible in
    root-level vars section (#2403, #2397 by @trulede, @vmaerten).
  • Fixed a bug where ignore_error was ignored when using task: to call
    another task (#2552, #363 by @trulede).
  • Fixed Zsh completion not suggesting global tasks when using -g/--global
    flag (#1574, #2574 by @vmaerten).
  • Fixed Fish completion failing to parse task descriptions containing colons
    (e.g., URLs or namespaced functions) (#2101, #2573 by @vmaerten).
  • Fixed false positive "property 'for' is not allowed" warnings in IntelliJ when
    using for loops in Taskfiles (#2576 by @vmaerten).

v3.45.5 - 2025-11-11

  • Fixed bug that made a generic message, instead of an useful one, appear when a
    Taskfile could not be found (#2431 by @andreynering).
  • Fixed a bug that caused an error when including a Remote Git Taskfile (#2438
    by @twelvelabs).
  • Fixed issue where .taskrc.yml was not returned if reading it failed, and
    corrected handling of remote entrypoint Taskfiles (#2460, #2461 by @vmaerten).
  • Improved performance of --list and --list-all by introducing a faster
    compilation method that skips source globbing and checksum updates (#1322,
    #2053 by @vmaerten).
  • Fixed a concurrency bug with output: group. This ensures that begin/end
    parts won't be mixed up from different tasks (#1208, #2349, #2350 by
    @trulede).
  • Do not re-evaluate variables for defer: (#2244, #2418 by @trulede).
  • Improve error message when a Taskfile is not found (#2441, #2494 by
    @vmaerten).
  • Fixed generic error message exit status 1 when a dependency task failed
    (#2286 by @GrahamDennis).
  • Fixed YAML library from the unmaintained gopkg.in/yaml.v3 to the new fork
    maintained by the official YAML org (#2171, #2434 by @andreynering).
  • On Windows, the built-in version of the rm core utils contains a fix related
    to the -f flag (#2426,
    u-root/u-root#3464,
    mvdan/sh#1199, #2506 by
    @andreynering).

v3.45.4 - 2025-09-17

  • Fixed a bug where cache-expiry could not be defined in .taskrc.yml (#2423
    by @vmaerten).
  • Fixed a bug where .taskrc.yml files in parent folders were not read
    correctly (#2424 by @vmaerten).
  • Fixed a bug where autocomplete in subfolders did not work with zsh (#2425 by
    @vmaerten).

v3.45.3 - 2025-09-15

  • Task now includes built-in core utilities to greatly improve compatibility on
    Windows. This means that your commands that uses cp, mv, mkdir or any
    other common core utility will now work by default on Windows, without extra
    setup. This is something we wanted to address for many many years, and it's
    finally being shipped!
    Read our blog post this the topic.
    (#197, #2360 by @andreynering).
  • :sparkles: Built and deployed a brand new website
    using VitePress (#2359, #2369, #2371, #2375, #2378 by
    @vmaerten, @andreynering, @pd93).
  • Began releasing
    nightly builds. This
    will allow people to test our changes before they are fully released and
    without having to install Go to build them (#2358 by @vmaerten).
  • Added support for global config files in $XDG_CONFIG_HOME/task/taskrc.yml or
    $HOME/.taskrc.yml. Check out our new
    configuration guide for more
    details (#2247, #2380, #2390, #2391 by @vmaerten, @pd93).
  • Added experiments to the taskrc schema to clarify the expected keys and values
    (#2235 by @vmaerten).
  • Added support for new properties in .taskrc.yml: insecure, verbose,
    concurrency, remote offline, remote timeout, and remote expiry. :warning:
    Note: setting offline via environment variable is no longer supported. (#2389
    by @vmaerten)
  • Added a --nested flag when outputting tasks using --list --json. This will
    output tasks in a nested structure when tasks are namespaced (#2415 by @pd93).
  • Enhanced support for tasks with wildcards: they are now logged correctly, and
    wildcard parameters are fully considered during fingerprinting (#1808, #1795
    by @vmaerten).
  • Fixed panic when a variable was declared as an empty hash ({}) (#2416, #2417
    by @trulede).

Package API

  • Bumped the minimum version of Go to 1.24 (#2358 by @vmaerten).

Other news

We recently released our
official GitHub Action. This is based
on the fantastic work by the Arduino team who created and maintained the
community version. Now that this is officially adopted, fixes/updates should be
more timely. We have already merged a couple of longstanding PRs in our
first release (by
@pd93, @shrink, @trim21 and all the previous contributors to
arduino/setup-task).

v3.45.0-v3.45.2 - 2025-09-15

Failed due to an issue with our release process.

v3.44.1 - 2025-07-23

  • Internal tasks will no longer be shown as suggestions since they cannot be
    called (#2309, #2323 by @maxmzkrcensys)
  • Fixed install script for some ARM platforms (#1516, #2291 by @trulede).
  • Fixed a regression where fingerprinting was not working correctly if the path
    to you Taskfile contained a space (#2321, #2322 by @pd93).
  • Reverted a breaking change to randInt (#2312, #2316 by @pd93).
  • Made new variables TEST_NAME and TEST_DIR available in fixture tests
    (#2265 by @pd93).

v3.44.0 - 2025-06-08

  • Added uuid, randInt and randIntN template functions (#1346, #2225 by
    @pd93).
  • Added new CLI_ARGS_LIST array variable which contains the arguments passed
    to Task after the -- (the same as CLI_ARGS, but an array instead of a
    string). (#2138, #2139, #2140 by @pd93).
  • Added toYaml and fromYaml templating functions (#2217, #2219 by @pd93).
  • Added task field the --list --json output (#2256 by @aleksandersh).
  • Added the ability to
    pin included taskfiles
    by specifying a checksum. This works with both local and remote Taskfiles
    (#2222, #2223 by @pd93).
  • When using the
    Remote Taskfiles experiment,
    any credentials used in the URL will now be redacted in Task's output (#2100,
    #2220 by @pd93).
  • Fixed fuzzy suggestions not working when misspelling a task name (#2192, #2200
    by @vmaerten).
  • Fixed a bug where taskfiles in directories containing spaces created
    directories in the wrong location (#2208, #2216 by @pd93).
  • Added support for dual JSON schema files, allowing changes without affecting
    the current schema. The current schemas will only be updated during releases.
    (#2211 by @vmaerten).
  • Improved fingerprint documentation by specifying that the method can be set at
    the root level to apply to all tasks (#2233 by @vmaerten).
  • Fixed some watcher regressions after #2048 (#2199, #2202, #2241, #2196 by
    @wazazaby, #2271 by @andreynering).

v3.43.3 - 2025-04-27

Reverted the changes made in #2113 and #2186 that affected the
USER_WORKING_DIR and built-in variables. This fixes #2206, #2195, #2207 and
#2208.

v3.43.2 - 2025-04-21

  • Fixed regresion of CLI_ARGS being exposed as the wrong type (#2190, #2191 by
    @vmaerten).

v3.43.1 - 2025-04-21

  • Significant improvements were made to the watcher. We migrated from
    watcher to
    fsnotify. The former library used
    polling, which means Task had a high CPU usage when watching too many files.
    fsnotify uses proper the APIs from each operating system to watch files,
    which means a much better performance. The default interval changed from 5
    seconds to 100 milliseconds, because now it configures the wait time for
    duplicated events, instead of the polling time (#2048 by @andreynering, #1508,
    #985, #1179).
  • The Map Variables experiment
    was made generally available so you can now
    define map variables in your Taskfiles!
    (#1585, #1547, #2081 by @pd93).
  • Wildcards can now
    match multiple tasks (#2072,
    #2121 by @pd93).
  • Added the ability to
    loop over the files specified by the generates keyword.
    This works the same way as looping over sources (#2151 by @sedyh).
  • Added the ability to resolve variables when defining an include variable
    (#2108, #2113 by @pd93).
  • A few changes have been made to the
    Remote Taskfiles experiment
    (#1402, #2176 by @pd93):
    • Cached files are now prioritized over remote ones.
    • Added an --expiry flag which sets the TTL for a remote file cache. By
      default the value will be 0 (caching disabled). If Task is running in
      offline mode or fails to make a connection, it will fallback on the cache.
  • .taskrc files can now be used from subdirectories and will be searched for
    recursively up the file tree in the same way that Taskfiles are (#2159, #2166
    by @pd93).
  • The default taskfile (output when using the --init flag) is now an embedded
    file in the binary instead of being stored in the code (#2112 by @pd93).
  • Improved the way we report the Task version when using the --version flag or
    {{.TASK_VERSION}} variable. This should now be more consistent and easier
    for package maintainers to use (#2131 by @pd93).
  • Fixed a bug where globstar (**) matching in sources only resolved the
    first result (#2073, #2075 by @pd93).
  • Fixed a bug where sorting tasks by "none" would use the default sorting
    instead of leaving tasks in the order they were defined (#2124, #2125 by
    @trulede).
  • Fixed Fish completion on newer Fish versions (#2130 by @atusy).
  • Fixed a bug where undefined/null variables resolved to an empty string instead
    of nil (#1911, #2144 by @pd93).
  • The USER_WORKING_DIR special now will now properly account for the --dir
    (-d) flag, if given (#2102, #2103 by @jaynis, #2186 by @andreynering).
  • Fix Fish completions when --global (-g) is given (#2134 by @atusy).
  • Fixed variables not available when using defer: (#1909, #2173 by @vmaerten).

Package API

v3.42.1 - 2025-03-10

  • Fixed a bug where some special variables caused a type error when used global
    variables (#2106, #2107 by @pd93).

v3.42.0 - 2025-03-08

  • Made --init less verbose by default and respect --silent and --verbose
    flags (#2009, #2011 by @HeCorr).
  • --init now accepts a file name or directory as an argument (#2008, #2018 by
    @HeCorr).
  • Fix a bug where an HTTP node's location was being mutated incorrectly (#2007
    by @jeongukjae).
  • Fixed a bug where allowed values didn't work with dynamic var (#2032, #2033 by
    @vmaerten).
  • Use only the relevant checker (timestamp or checksum) to improve performance
    (#2029, #2031 by @vmaerten).
  • Print warnings when attempting to enable an inactive experiment or an active
    experiment with an invalid value (#1979, #2049 by @pd93).
  • Refactored the experiments package and added tests (#2049 by @pd93).
  • Show allowed values when a variable with an enum is missing (#2027, #2052 by
    @vmaerten).
  • Refactored how snippets in error work and added tests (#2068 by @pd93).
  • Fixed a bug where errors decoding commands were sometimes unhelpful (#2068 by
    @pd93).
  • Fixed a bug in the Taskfile schema where defer statements in the shorthand
    cmds syntax were not considered valid (#2068 by @pd93).
  • Refactored how task sorting functions work (#1798 by @pd93).
  • Added a new .taskrc.yml (or .taskrc.yaml) file to let users enable
    experiments (similar to .env) (#1982 by @vmaerten).
  • Added new Getting Started docs (#2086
    by @pd93).
  • Allow matrix to use references to other variables (#2065, #2069 by @pd93).
  • Fixed a bug where, when a dynamic variable is provided, even if it is not
    used, all other variables become unavailable in the templating system within
    the include (#2092 by @vmaerten).

Package API

Unlike our CLI tool,
Task's package API is not currently stable.
In an effort to ease the pain of breaking changes for our users, we will be
providing changelogs for our package API going forwards. The hope is that these
changes will provide a better long-term experience for our users and allow to
stabilize the API in the future. #121 now tracks this piece of work.

  • Bumped the minimum required Go version to 1.23 (#2059 by @pd93).
  • task.InitTaskfile
    (#2011, ff8c913 by @HeCorr and @pd93)
    • No longer accepts an io.Writer (output is now the caller's
      responsibility).
    • The path argument can now be a filename OR a directory.
    • The function now returns the full path of the generated file.
  • TaskfileDecodeError.WithFileInfo
    now accepts a string instead of the arguments required to generate a snippet
    (#2068 by @pd93).
    • The caller is now expected to create the snippet themselves (see below).
  • TaskfileSnippet
    and related code moved from the errors package to the taskfile package
    (#2068 by @pd93).
  • Renamed TaskMissingRequiredVars to
    TaskMissingRequiredVarsError
    (#2052 by @vmaerten).
  • Renamed TaskNotAllowedVars to
    TaskNotAllowedVarsError
    (#2052 by @vmaerten).
  • The
    taskfile.Reader
    is now constructed using the functional options pattern (#2082 by @pd93).
  • Removed our internal logger.Logger from the entire taskfile package (#2082
    by @pd93).
  • Remove Range functions in the taskfile/ast package in favour of new
    iterator functions (#1798 by @pd93).
  • ast.Call was moved from the taskfile/ast package to the main task
    package (#2084 by @pd93).
  • ast.Tasks.FindMatchingTasks was moved from the taskfile/ast package to the
    task.Executor.FindMatchingTasks in the main task package (#2084 by @pd93).
  • The Compiler and its GetVariables and FastGetVariables methods were
    moved from the internal/compiler package to the main task package (#2084
    by @pd93).

v3.41.0 - 2025-01-18

  • Fixed an issue where dynamic variables were not properly logged in verbose
    mode (#1920, #1921 by @mgbowman).
  • Support silent for defer statements (#1877, #1879 by @danilobuerger).
  • Added an option to exclude some tasks from being included (#1859 by
    @vmaerten).
  • Fixed an issue where a required variable was incorrectly handled in a template
    function (#1950, #1962 by @vmaerten).
  • Expose a new TASK_DIR special variable, which will contain the absolute path
    of task directory. (#1959, #1961 by @vmaerten).
  • Fixed fatal bugs that caused concurrent map writes (#1605, #1972, #1974 by
    @pd93, @GrahamDennis and @trim21).
  • Refactored internal ordered map implementation to use
    github.com/elliotchance/orderedmap
    (#1797 by @pd93).
  • Fixed a bug where variables defined at the task level were being ignored in
    the requires section. (#1960, #1955, #1768 by @vmaerten and @mokeko)
  • The CHECKSUM and TIMESTAMP variables are now accessible within cmds
    (#1872 by @niklasr22).
  • Updated installation docs and added pip
    installation method (#935, #1989 by @pd93).
  • Fixed a bug where dynamic variables could not access environment variables
    (#630, #1869 by @rohm1 and @pd93).
  • Disable version check for use as an external library (#1938 by @leaanthony).

v3.40.1 - 2024-12-06

  • Fixed a security issue in git-urls by switching to the maintained fork
    chainguard-dev/git-urls (#1917 by @AlekSi).
  • Added missing platforms property to cmds that use for (#1915 by
    @dkarter).
  • Added misspell linter to check for misspelled English words (#1883 by
    @christiandins).

v3.40.0 - 2024-11-05

  • Fixed output of some functions (e.g. splitArgs/splitLines) not working in
    for loops (#1822, #1823 by @stawii).
  • Added a new TASK_OFFLINE environment variable to configure the --offline
    flag and expose it as a special variable in the templating system (#1470,
    #1716 by @vmaerten and @pd93).
  • Fixed a bug where multiple remote includes caused all prompts to display
    without waiting for user input (#1832, #1833 by @vmaerten and @pd93).
  • When using the
    "Remote Taskfiles".
    experiment, you can now include Taskfiles from Git repositories (#1652 by
    @vmaerten).
  • Improved the error message when a dotenv file cannot be parsed (#1842 by
    @pbitty).
  • Fix issue with directory when using the remote experiment (#1757 by @pbitty).
  • Fixed an issue where a special variable was used in combination with a dotenv
    file (#1232, #1810 by @vmaerten).
  • Refactor the way Task reads Taskfiles to improve readability (#1771 by
    @pbitty).
  • Added a new option to ensure variable is within the list of values (#1827 by
    @vmaerten).
  • Allow multiple prompts to be specified for a task (#1861, #1866 by @mfbmina).
  • Added new template function: numCPU, which returns the number of logical
    CPUs usable (#1890, #1887 by @Amoghrd).
  • Fixed a bug where non-nil, empty dynamic variables are returned as an empty
    interface (#1903, #1904 by @pd93).

v3.39.2 - 2024-09-19

  • Fix dynamic variables not working properly for a defer: statement (#1803,
    #1818 by @vmaerten).

v3.39.1 - 2024-09-18

  • Added Renovate configuration to automatically create PRs to keep dependencies
    up to date (#1783 by @vmaerten).
  • Fixed a bug where the help was displayed twice (#1805, #1806 by @vmaerten).
  • Fixed a bug where ZSH and PowerShell completions did not work when using the
    recommended method. (#1813, #1809 by @vmaerten and @shirayu)
  • Fix variables not working properly for a defer: statement (#1803, #1814 by
    @vmaerten and @andreynering).

v3.39.0 - 2024-09-07

  • Added
    Env Precedence Experiment
    (#1038, #1633 by @vmaerten).
  • Added a CI lint job to ensure that the docs are updated correctly (#1719 by
    @vmaerten).
  • Updated minimum required Go version to 1.22 (#1758 by @pd93).
  • Expose a new EXIT_CODE special variable on defer: when a command finishes
    with a non-zero exit code (#1484, #1762 by @dorimon-1 and @andreynering).
  • Expose a new ALIAS special variable, which will contain the alias used to
    call the current task. Falls back to the task name. (#1764 by @DanStory).
  • Fixed TASK_REMOTE_DIR environment variable not working when the path was
    absolute. (#1715 by @vmaerten).
  • Added an option to declare an included Taskfile as flattened (#1704 by
    @vmaerten).
  • Added a new
    --completion flag to
    output completion scripts for various shells (#293, #1157 by @pd93).
    • This is now the preferred way to install completions.
    • The completion scripts in the completion directory
      are now deprecated.
  • Added the ability to
    loop over a matrix of values
    (#1766, #1767, #1784 by @pd93).
  • Fixed a bug in fish completion where aliases were not displayed (#1781, #1782
    by @vmaerten).
  • Fixed panic when having a flattened included Taskfile that contains a
    default task (#1777, #1778 by @vmaerten).
  • Optimized file existence checks for remote Taskfiles (#1713 by @vmaerten).

v3.38.0 - 2024-06-30

  • Added TASK_EXE special variable (#1616, #1624 by @pd93 and @andreynering).
  • Some YAML parsing errors will now show in a more user friendly way (#1619 by
    @pd93).
  • Prefixed outputs will now be colorized by default (#1572 by
    @AlexanderArvidsson)
  • References are now
    generally available (no experiments required) (#1654 by @pd93).
  • Templating functions can now be used in references (#1645, #1654 by @pd93).
  • Added a new
    templating reference page to the
    documentation (#1614, #1653 by @pd93).
  • If using the
    Map Variables experiment (1),
    references are available by
    prefixing a string with a #
    (#1654 by @pd93).
  • If using the
    Map Variables experiment (2),
    the yaml and json keys are no longer available (#1654 by @pd93).
  • Added a new TASK_REMOTE_DIR environment variable to configure where cached
    remote Taskfiles are stored (#1661 by @vmaerten).
  • Added a new --clear-cache flag to clear the cache of remote Taskfiles (#1639
    by @vmaerten).
  • Improved the readability of cached remote Taskfile filenames (#1636 by
    @vmaerten).
  • Starting releasing a binary for the riscv64 architecture on Linux (#1699 by
    @mengzhuo).
  • Added CLI_SILENT and CLI_VERBOSE variables (#1480, #1669 by @Vince-Smith).
  • Fixed a couple of bugs with the prompt: feature (#1657 by @pd93).
  • Fixed JSON Schema to disallow invalid properties (#1657 by @pd93).
  • Fixed version checks not working as intended (#872, #1663 by @vmaerten).
  • Fixed a bug where included tasks were run multiple times even if run: once
    was set (#852, #1655 by @pd93).
  • Fixed some bugs related to column formatting in the terminal (#1350, #1637,
    #1656 by @vmaerten).

v3.37.2 - 2024-05-12

  • Fixed a bug where an empty Taskfile would cause a panic (#1648 by @pd93).
  • Fixed a bug where includes Taskfile variable were not being merged correctly
    (#1643, #1649 by @pd93).

v3.37.1 - 2024-05-09

  • Fix bug where non-string values (numbers, bools) added to env: weren't been
    correctly exported (#1640, #1641 by @vmaerten and @andreynering).

v3.37.0 - 2024-05-08

  • Released the
    Any Variables experiment, but
    without support for maps
    (#1415, #1547 by @pd93).
  • Refactored how Task reads, parses and merges Taskfiles using a DAG (#1563,
    #1607 by @pd93).
  • Fix a bug which stopped tasks from using stdin as input (#1593, #1623 by
    @pd93).
  • Fix error when a file or directory in the project contained a special char
    like &, ( or ) (#1551, #1584 by @andreynering).
  • Added alias q for template function shellQuote (#1601, #1603 by @vergenzt)
  • Added support for ~ on ZSH completions (#1613 by @jwater7).
  • Added the ability to pass variables by reference using Go template syntax when
    the
    Map Variables experiment is
    enabled (#1612 by @pd93).
  • Added support for environment variables in the templating engine in includes
    (#1610 by @vmaerten).

v3.36.0 - 2024-04-08

  • Added support for
    looping over dependencies
    (#1299, #1541 by @pd93).
  • When using the
    "Remote Taskfiles"
    experiment, you are now able to use
    remote Taskfiles as your entrypoint.
    • includes in remote Taskfiles will now also resolve correctly (#1347 by
      @pd93).
  • When using the
    "Any Variables"
    experiments, templating is now supported in collection-type variables (#1477,
    #1511, #1526 by @pd93).
  • Fixed a bug where variables being passed to an included Taskfile were not
    available when defining global variables (#1503, #1533 by @pd93).
  • Improved support to customized colors by allowing 8-bit colors and multiple
    ANSI attributes (#1576 by @pd93).

v3.35.1 - 2024-03-04

  • Fixed a bug where the TASKFILE_DIR variable was sometimes incorrect (#1522,
    #1523 by @pd93).
  • Added a new TASKFILE special variable that holds the root Taskfile path
    (#1523 by @pd93).
  • Fixed various issues related to running a Taskfile from a subdirectory (#1529,
    #1530 by @pd93).

v3.35.0 - 2024-02-28

  • Added support for
    wildcards in task names
    (#836, #1489 by @pd93).
  • Added the ability to
    run Taskfiles via stdin
    (#655, #1483 by @pd93).
  • Bumped minimum Go version to 1.21 (#1500 by @pd93).
  • Fixed bug related to the --list flag (#1509, #1512 by @pd93, #1514, #1520 by
    @pd93).
  • Add mention on the documentation to the fact that the variable declaration
    order is respected (#1510 by @kirkrodrigues).
  • Improved style guide docs (#1495 by @iwittkau).
  • Removed duplicated entry for requires on the API docs (#1491 by
    @teatimeguest).

v3.34.1 - 2024-01-27

v3.34.0 - 2024-01-25

  • Removed support for version: 2 schemas. See the
    deprecation notice on our website
    (#1197, #1447 by @pd93).
  • Fixed a couple of issues in the JSON Schema + added a CI step to ensure it's
    correct (#1471, #1474, #1476 by @sirosen).
  • Added
    Any Variables experiment proposal 2
    (#1415, #1444 by @pd93).
  • Updated the experiments and deprecations documentation format (#1445 by
    @pd93).
  • Added new template function: spew, which can be used to print variables for
    debugging purposes (#1452 by @pd93).
  • Added new template function: merge, which can be used to merge any number of
    map variables (#1438, #1464 by @pd93).
  • Small change on the API when using as a library: call.Direct became
    call.Indirect (#1459 by @pd93).
  • Refactored the public read and taskfile packages and introduced
    taskfile/ast (#1450 by @pd93).
  • ast.IncludedTaskfiles renamed to ast.Includes and orderedmap package
    renamed to omap plus some internal refactor work (#1456 by @pd93).
  • Fix zsh completion script to allow lowercase taskfile file names (#1482 by
    @xontab).
  • Improvements on how we check the Taskfile version (#1465 by @pd93).
  • Added a new ROOT_TASKFILE special variable (#1468, #1469 by @pd93).
  • Fix experiment flags in .env when the --dir or --taskfile flags were
    used (#1478 by @pd93).

v3.33.1 - 2023-12-21

  • Added support for looping over map variables with the
    Any Variables experiment
    enabled (#1435, #1437 by @pd93).
  • Fixed a bug where dynamic variables were causing errors during fast
    compilation (#1435, #1437 by @pd93)

v3.33.0 - 2023-12-20

  • Added
    Any Variables experiment
    (#1415, #1421 by @pd93).
  • Updated Docusaurus to v3 (#1432 by @pd93).
  • Added aliases to --json flag output (#1430, #1431 by @pd93).
  • Added new CLI_FORCE special variable containing whether the --force or
    --force-all flags were set (#1412, #1434 by @pd93).

v3.32.0 - 2023-11-29

  • Added ability to exclude some files from sources: by using exclude: (#225,
    #1324 by @pd93 and @andreynering).
  • The
    Remote Taskfiles experiment
    now prefers remote files over cached ones by default (#1317, #1345 by @pd93).
  • Added --timeout flag to the
    Remote Taskfiles experiment
    (#1317, #1345 by @pd93).
  • Fix bug where dynamic vars: and env: were being executed when they should
    actually be skipped by platforms: (#1273, #1377 by @andreynering).
  • Fix schema.json to make silent valid in cmds that use for (#1385,
    #1386 by @iainvm).
  • Add new --no-status flag to skip expensive status checks when running
    task --list --json (#1348, #1368 by @amancevice).

v3.31.0 - 2023-10-07

  • Enabled the --yes flag for the
    Remote Taskfiles experiment
    (#1317, #1344 by @pd93).
  • Add ability to set watch: true in a task to automatically run it in watch
    mode (#231, #1361 by @andreynering).
  • Fixed a bug on the watch mode where paths that contained .git (like
    .github), for example, were also being ignored (#1356 by @butuzov).
  • Fixed a nil pointer error when running a Taskfile with no contents (#1341,
    #1342 by @pd93).
  • Added a new exit code (107) for when a
    Taskfile does not contain a schema version (#1342 by @pd93).
  • Increased limit of maximum task calls from 100 to 1000 for now, as some people
    have been reaching this limit organically now that we have loops. This check
    exists to detect recursive calls, but will be removed in favor of a better
    algorithm soon (#1321, #1332).
  • Fixed templating on descriptions on task --list (#1343 by @blackjid).
  • Fixed a bug where precondition errors were incorrectly being printed when task
    execution was aborted (#1337, #1338 by @sylv-io).

v3.30.1 - 2023-09-14

  • Fixed a regression where some special variables weren't being set correctly
    (#1331, #1334 by @pd93).

v3.30.0 - 2023-09-13

  • Prep work for Remote Taskfiles (#1316 by @pd93).
  • Added the
    Remote Taskfiles experiment
    as a draft (#1152, #1317 by @pd93).
  • Improve performance of content checksumming on sources: by replacing md5
    with XXH3 which is much faster. This is a soft breaking
    change because checksums will be invalidated when upgrading to this release
    (#1325 by @ReillyBrogan).

v3.29.1 - 2023-08-26

  • Update to Go 1.21 (bump minimum version to 1.20) (#1302 by @pd93)
  • Fix a missing a line break on log when using --watch mode (#1285, #1297 by
    @FilipSolich).
  • Fix defer on JSON Schema (#1288 by @calvinmclean and @andreynering).
  • Fix bug in usage of special variables like {{.USER_WORKING_DIR}} in
    combination with includes (#1046, #1205, #1250, #1293, #1312, #1274 by
    @andarto, #1309 by @andreynering).
  • Fix bug on --status flag. Running this flag should not have side-effects: it
    should not update the checksum on .task, only report its status (#1305,
    #1307 by @visciang, #1313 by @andreynering).

v3.28.0 - 2023-07-24

  • Added the ability to
    loop over commands and tasks
    using for (#82, #1220 by @pd93).
  • Fixed variable propagation in multi-level includes (#778, #996, #1256 by
    @hudclark).
  • Fixed a bug where the --exit-code code flag was not returning the correct
    exit code when calling commands indirectly (#1266, #1270 by @pd93).
  • Fixed a nil panic when a dependency was commented out or left empty (#1263
    by @neomantra).

v3.27.1 - 2023-06-30

  • Fix panic when a .env directory (not file) is present on current directory
    (#1244, #1245 by @pd93).

v3.27.0 - 2023-06-29

  • Allow Taskfiles starting with lowercase characters (#947, #1221 by @pd93).
    • e.g. taskfile.yml, taskfile.yaml, taskfile.dist.yml &
      taskfile.dist.yaml
  • Bug fixes were made to the
    npm installation method. (#1190, by
    @sounisi5011).
  • Added the
    gentle force experiment as a
    draft (#1200, #1216 by @pd93).
  • Added an --experiments flag to allow you to see which experiments are
    enabled (#1242 by @pd93).
  • Added ability to specify which variables are required in a task (#1203, #1204
    by @benc-uk).

v3.26.0 - 2023-06-10

  • Only rewrite checksum files in .task if the checksum has changed (#1185,
    #1194 by @deviantintegral).
  • Added experiments documentation to the
    website (#1198 by @pd93).
  • Deprecated version: 2 schema. This will be removed in the next major release
    (#1197, #1198, #1199 by @pd93).
  • Added a new prompt: prop to set a warning prompt to be shown before running
    a potential dangerous task (#100, #1163 by @MaxCheetham,
    Documentation).
  • Added support for single command task syntax. With this change, it's now
    possible to declare just cmd: in a task, avoiding the more complex
    cmds: [] when you have only a single command for that task (#1130, #1131 by
    @timdp).

v3.25.0 - 2023-05-22

  • Support silent: when calling another tasks (#680, #1142 by @danquah).
  • Improve PowerShell completion script (#1168 by @trim21).
  • Add more languages to the website menu and show translation progress
    percentage (#1173 by @misitebao).
  • Starting on this release, official binaries for FreeBSD will be available to
    download (#1068 by @andreynering).
  • Fix some errors being unintendedly suppressed (#1134 by @clintmod).
  • Fix a nil pointer error when version is omitted from a Taskfile (#1148,
    #1149 by @pd93).
  • Fix duplicate error message when a task does not exists (#1141, #1144 by
    @pd93).

v3.24.0 - 2023-04-15

  • Fix Fish shell completion for tasks with aliases (#1113 by @patricksjackson).
  • The default branch was renamed from master to main (#1049, #1048 by
    @pd93).
  • Fix bug where "up-to-date" logs were not being omitted for silent tasks (#546,
    #1107 by @danquah).
  • Add .hg (Mercurial) to the list of ignored directories when using --watch
    (#1098 by @misery).
  • More improvements to the release tool (#1096 by @pd93).
  • Enforce gofumpt linter (#1099 by @pd93)
  • Add --sort flag for use with --list and --list-all (#946, #1105 by
    @pd93).
  • Task now has custom exit codes
    depending on the error (#1114 by @pd93).

v3.23.0 - 2023-03-26

Task now has an
official extension for Visual Studio Code
contributed by @pd93! :tada: The extension is maintained in a
new repository under the go-task
organization. We're looking to gather feedback from the community so please give
it a go and let us know what you think via a
discussion,
issue or on our
Discord!

NOTE: The extension requires v3.23.0 to be installed in order to work.

  • The website was integrated with
    Crowdin to allow the community to
    contribute with translations! Chinese is the
    first language available (#1057, #1058 by @misitebao).
  • Added task location data to the --json flag output (#1056 by @pd93)
  • Change the name of the file generated by task --init from Taskfile.yaml to
    Taskfile.yml (#1062 by @misitebao).
  • Added new splitArgs template function
    ({{splitArgs "foo bar 'foo bar baz'"}}) to ensure string is split as
    arguments (#1040, #1059 by @dhanusaputra).
  • Fix the value of {{.CHECKSUM}} variable in status (#1076, #1080 by @pd93).
  • Fixed deep copy implementation (#1072 by @pd93)
  • Created a tool to assist with releases (#1086 by @pd93).

v3.22.0 - 2023-03-10

  • Add a brand new --global (-g) flag that will run a Taskfile from your
    $HOME directory. This is useful to have automation that you can run from
    anywhere in your system!
    (Documentation, #1029
    by @andreynering).
  • Add ability to set error_only: true on the group output mode. This will
    instruct Task to only print a command output if it returned with a non-zero
    exit code (#664, #1022 by @jaedle).
  • Fixed bug where .task/checksum file was sometimes not being created when
    task also declares a status: (#840, #1035 by @harelwa, #1037 by @pd93).
  • Refactored and decoupled fingerprinting from the main Task executor (#1039 by
    @pd93).
  • Fixed deadlock issue when using run: once (#715, #1025 by
    @theunrepentantgeek).

v3.21.0 - 2023-02-22

  • Added new TASK_VERSION special variable (#990, #1014 by @ja1code).
  • Fixed a bug where tasks were sometimes incorrectly marked as internal (#1007
    by @pd93).
  • Update to Go 1.20 (bump minimum version to 1.19) (#1010 by @pd93)
  • Added environment variable FORCE_COLOR support to force color output. Useful
    for environments without TTY (#1003 by @automation-stack)

v3.20.0 - 2023-01-14

  • Improve behavior and performance of status checking when using the timestamp
    mode (#976, #977 by @aminya).
  • Performance optimizations were made for large Taskfiles (#982 by @pd93).
  • Add ability to configure options for the
    set
    and
    shopt
    builtins (#908, #929 by @pd93,
    Documentation).
  • Add new platforms: attribute to task and cmd, so it's now possible to
    choose in which platforms that given task or command will be run on. Possible
    values are operating system (GOOS), architecture (GOARCH) or a combination of
    the two. Example: platforms: [linux], platforms: [amd64] or
    platforms: [linux/amd64]. Other platforms will be skipped (#978, #980 by
    @leaanthony).

v3.19.1 - 2022-12-31

  • Small bug fix: closing Taskfile.yml once we're done reading it (#963, #964
    by @HeCorr).
  • Fixes a bug in v2 that caused a panic when using a Taskfile_{{OS}}.yml file
    (#961, #971 by @pd93).
  • Fixed a bug where watch intervals set in the Taskfile were not being respected
    (#969, #970 by @pd93)
  • Add --json flag (alias -j) with the intent to improve support for code
    editors and add room to other possible integrations. This is basic for now,
    but we plan to add more info in the near future (#936 by @davidalpert, #764).

v3.19.0 - 2022-12-05

  • Installation via npm now supports pnpm as well
    (go-task/go-npm#2,
    go-task/go-npm#3).
  • It's now possible to run Taskfiles from subdirectories! A new
    USER_WORKING_DIR special variable was added to add even more flexibility for
    monorepos (#289, #920).
  • Add task-level dotenv support (#389, #904).
  • It's now possible to use global level variables on includes (#942, #943).
  • The website got a brand new
    translation to Chinese by
    @DeronW. Thanks!

v3.18.0 - 2022-11-12

  • Show aliases on task --list --silent (task --ls). This means that aliases
    will be completed by the completion scripts (#919).
  • Tasks in the root Taskfile will now be displayed first in
    --list/--list-all output (#806, #890).
  • It's now possible to call a default task in an included Taskfile by using
    just the namespace. For example: docs:default is now automatically aliased
    to docs (#661, #815).

v3.17.0 - 2022-10-14

  • Add a "Did you mean ...?" suggestion when a task does not exits another one
    with a similar name is found (#867, #880).
  • Now YAML parse errors will print which Taskfile failed to parse (#885, #887).
  • Add ability to set aliases for tasks and namespaces (#268, #340, #879).
  • Improvements to Fish shell completion (#897).
  • Added ability to set a different watch interval by setting interval: '500ms'
    or using the --interval=500ms flag (#813, #865).
  • Add colored output to --list, --list-all and --summary flags (#845,
    #874).
  • Fix unexpected behavior where label: was being shown instead of the task
    name on --list (#603, #877).

v3.16.0 - 2022-09-29

  • Add npm as new installation method: npm i @go-task/cli (#870, #871,
    npm package).
  • Add support to marking tasks and includes as internal, which will hide them
    from --list and --list-all (#818).

v3.15.2 - 2022-09-08

  • Fix error when using variable in env: introduced in the previous release
    (#858, #866).
  • Fix handling of CLI_ARGS (--) in Bash completion (#863).
  • On zsh completion, add ability to replace --list-all with --list as
    already possible on the Bash completion (#861).

v3.15.0 - 2022-09-03

  • Add new special variables ROOT_DIR and TASKFILE_DIR. This was a highly
    requested feature (#215, #857,
    Documentation).
  • Follow symlinks on sources (#826, #831).
  • Improvements and fixes to Bash completion (#835, #844).

v3.14.1 - 2022-08-03

  • Always resolve relative include paths relative to the including Taskfile
    (#822, #823).
  • Fix ZSH and PowerShell completions to consider all tasks instead of just the
    public ones (those with descriptions) (#803).

v3.14.0 - 2022-07-08

  • Add ability to override the .task directory location with the
    TASK_TEMP_DIR environment variable.
  • Allow to override Task colors using environment variables: TASK_COLOR_RESET,
    TASK_COLOR_BLUE, TASK_COLOR_GREEN, TASK_COLOR_CYAN, TASK_COLOR_YELLOW,
    TASK_COLOR_MAGENTA and TASK_COLOR_RED (#568, #792).
  • Fixed bug when using the output: group mode where STDOUT and STDERR were
    being print in separated blocks instead of in the right order (#779).
  • Starting on this release, ARM architecture binaries are been released to Snap
    as well (#795).
  • i386 binaries won't be available anymore on Snap because Ubuntu removed the
    support for this architecture.
  • Upgrade mvdan.cc/sh, which fixes a bug with associative arrays (#785,
    mvdan/sh#884,
    mvdan/sh#893).

v3.13.0 - 2022-06-13

  • Added -n as an alias to --dry (#776, #777).
  • Fix behavior of interrupt (SIGINT, SIGTERM) signals. Task will now give time
    for the processes running to do cleanup work (#458, #479, #728, #769).
  • Add new --exit-code (-x) flag that will pass-through the exit form the
    command being ran (#755).

v3.12.1 - 2022-05-10

  • Fixed bug where, on Windows, variables were ending with \r because we were
    only removing the final \n but not \r\n (#717).

v3.12.0 - 2022-03-31

  • The --list and --list-all flags can now be combined with the --silent
    flag to print the task names only, without their description (#691).
  • Added support for multi-level inclusion of Taskfiles. This means that included
    Taskfiles can also include other Taskfiles. Before this was limited to one
    level (#390, #623, #656).
  • Add ability to specify vars when including a Taskfile.
    Check out the documentation
    for more information (#677).

v3.11.0 - 2022-02-19

  • Task now supports printing begin and end messages when using the group
    output mode, useful for grouping tasks in CI systems.
    Check out the documentation
    for more information (#647, #651).
  • Add Taskfile.dist.yml and Taskfile.dist.yaml to the supported file name
    list.
    Check out the documentation
    for more information (#498, #666).

v3.10.0 - 2022-01-04

  • A new --list-all (alias -a) flag is now available. It's similar to the
    exiting --list (-l) but prints all tasks, even those without a description
    (#383, #401).
  • It's now possible to schedule cleanup commands to run once a task finishes
    with the defer: keyword
    (Documentation,
    #475, #626).
  • Remove long deprecated and undocumented $ variable prefix and ^ command
    prefix (#642, #644, #645).
  • Add support for .yaml extension (as an alternative to .yml). This was
    requested multiple times throughout the years. Enjoy! (#183, #184, #369, #584,
    #621).
  • Fixed error when computing a variable when the task directory do not exist yet
    (#481, #579).

v3.9.2 - 2021-12-02

v3.9.1 - 2021-11-28

  • Add logging in verbose mode for when a task starts and finishes (#533, #588).
  • Fix an issue with preconditions and context errors (#597, #598).
  • Quote each {{.CLI_ARGS}} argument to prevent one with spaces to become many
    (#613).
  • Fix nil pointer when cmd: was left empty (#612, #614).
  • Upgrade mvdan/sh which contains two relevant
    fixes:
    • Fix quote of empty strings in shellQuote (#609,
      mvdan/sh#763).
    • Fix issue of wrong environment variable being picked when there's another
      very similar one (#586,
      mvdan/sh#745).
  • Install shell completions automatically when installing via Homebrew (#264,
    #592,
    go-task/homebrew-tap#2).

v3.9.0 - 2021-10-02

v3.8.0 - 2021-09-26

  • Add interactive: true setting to improve support for interactive CLI apps
    (#217, #563).
  • Fix some nil errors (#534, #573).
  • Add ability to declare an included Taskfile as optional (#519, #552).
  • Add support for including Taskfiles in the home directory by using ~ (#539,
    #557).

v3.7.3 - 2021-09-04

  • Add official support to Apple M1 (#564, #567).
  • Our official Homebrew tap will
    support more platforms, including Apple M1

v3.7.0 - 2021-07-31

  • Add run: setting to control if tasks should run multiple times or not.
    Available options are always (the default), when_changed (if a variable
    modified the task) and once (run only once no matter what). This is a long
    time requested feature. Enjoy! (#53, #359).

v3.6.0 - 2021-07-10

  • Allow using both sources: and status: in the same task (#411, #427, #477).
  • Small optimization and bug fix: don't compute variables if not needed for
    dotenv: (#517).

v3.5.0 - 2021-07-04

  • Add support for interpolation in dotenv: (#433, #434, #453).

v3.4.3 - 2021-05-30

  • Add support for the NO_COLOR environment variable. (#459,
    fatih/color#137).
  • Fix bug where sources were not considering the right directory in --watch
    mode (#484, #485).

v3.4.2 - 2021-04-23

  • On watch, report which file failed to read (#472).
  • Do not try to catch SIGKILL signal, which are not actually possible (#476).
  • Improve version reporting when building Task from source using Go Modules
    (#462, #473).

v3.4.1 - 2021-04-17

  • Improve error reporting when parsing YAML: in some situations where you would
    just see an generic error, you'll now see the actual error with more detail:
    the YAML line the failed to parse, for example (#467).
  • A JSON Schema was published here
    and is automatically being used by some editors like Visual Studio Code
    (#135).
  • Print task name before the command in the log output (#398).

v3.3.0 - 2021-03-20

  • Add support for delegating CLI arguments to commands with -- and a special
    CLI_ARGS variable (#327).
  • Add a --concurrency (alias -C) flag, to limit the number of tasks that run
    concurrently. This is useful for heavy workloads. (#345).

v3.2.2 - 2021-01-12

  • Improve performance of --list and --summary by skipping running shell
    variables for these flags (#332).
  • Fixed a bug where an environment in a Taskfile was not always overridable by
    the system environment (#425).
  • Fixed environment from .env files not being available as variables (#379).
  • The install script is now working for ARM platforms (#428).

v3.2.1 - 2021-01-09

  • Fixed some bugs and regressions regarding dynamic variables and directories
    (#426).
  • The slim-sprig package was updated
    with the upstream sprig.

v3.2.0 - 2021-01-07

  • Fix the .task directory being created in the task directory instead of the
    Taskfile directory (#247).
  • Fix a bug where dynamic variables (those declared with sh:) were not running
    in the task directory when the task has a custom dir or it was in an included
    Taskfile (#384).
  • The watch feature (via the --watch flag) got a few different bug fixes and
    should be more stable now (#423, #365).

v3.1.0 - 2021-01-03

  • Fix a bug when the checksum up-to-date resolution is used by a task with a
    custom label: attribute (#412).
  • Starting from this release, we're releasing official ARMv6 and ARM64 binaries
    for Linux (#375, #418).
  • Task now respects the order of declaration of included Taskfiles when
    evaluating variables declaring by them (#393).
  • set -e is now automatically set on every command. This was done to fix an
    issue where multiline string commands wouldn't really fail unless the sentence
    was in the last line (#403).

v3.0.1 - 2020-12-26

  • Allow use as a library by moving the required packages out of the internal
    directory (#358).
  • Do not error if a specified dotenv file does not exist (#378, #385).
  • Fix panic when you have empty tasks in your Taskfile (#338, #362).

v3.0.0 - 2020-08-16

  • On v3, all CLI variables will be considered global variables (#336, #341)
  • Add support to .env like files (#324, #356).
  • Add label: to task so you can override the task name in the logs (#321,
    #337).
  • Refactor how variables work on version 3 (#311).
  • Disallow expansions on v3 since it has no effect.
  • Taskvars.yml is not automatically included anymore.
  • Taskfile_{{OS}}.yml is not automatically included anymore.
  • Allow interpolation on includes, so you can manually include a Taskfile
    based on operation system, for example.
  • Expose .TASK variable in templates with the task name (#252).
  • Implement short task syntax (#194, #240).
  • Added option to make included Taskfile run commands on its own directory
    (#260, #144)
  • Taskfiles in version 1 are not supported anymore (#237).
  • Added global method: option. With this option, you can set a default method
    to all tasks in a Taskfile (#246).
  • Changed default method from timestamp to checksum (#246).
  • New magic variables are now available when using status:: .TIMESTAMP which
    contains the greatest modification date from the files listed in sources:,
    and .CHECKSUM, which contains a checksum of all files listed in status:.
    This is useful for manual checking when using external, or even remote,
    artifacts when using status: (#216).
  • We're now using slim-sprig instead of
    sprig, which allowed a file size
    reduction of about 22% (#219).
  • We now use some colors on Task output to better distinguish message types -
    commands are green, errors are red, etc (#207).

v2.8.1 - 2020-05-20

  • Fix error code for the --help flag (#300, #330).
  • Print version to stdout instead of stderr (#299, #329).
  • Suppress context errors when using the --watch flag (#313, #317).
  • Support templating on description (#276, #283).

v2.8.0 - 2019-12-07

  • Add --parallel flag (alias -p) to run tasks given by the command line in
    parallel (#266).
  • Fixed bug where calling the task CLI only informing global vars would not
    execute the default task.
  • Add ability to silent all tasks by adding silent: true a the root of the
    Taskfile.

v2.7.1 - 2019-11-10

  • Fix error being raised when exit 0 was called (#251).

v2.7.0 - 2019-09-22

  • Fixed panic bug when assigning a global variable (#229, #243).
  • A task with method: checksum will now re-run if generated files are deleted
    (#228, #238).

v2.6.0 - 2019-07-21

  • Fixed some bugs regarding minor version checks on version:.
  • Add preconditions: to task (#205).
  • Create directory informed on dir: if it doesn't exist (#209, #211).
  • We now have a --taskfile flag (alias -t), which can be used to run another
    Taskfile (other than the default Taskfile.yml) (#221).
  • It's now possible to install Task using Homebrew on Linux
    (go-task/homebrew-tap#1).

v2.5.2 - 2019-05-11

  • Reverted YAML upgrade due issues with CRLF on Windows (#201,
    go-yaml/yaml#450).
  • Allow setting global variables through the CLI (#192).

2.5.1 - 2019-04-27

  • Fixed some issues with interactive command line tools, where sometimes the
    output were not being shown, and similar issues (#114, #190, #200).
  • Upgraded go-yaml/yaml from v2 to v3.

v2.5.0 - 2019-03-16

v2.4.0 - 2019-02-21

  • Allow calling a task of the root Taskfile from an included Taskfile by
    prefixing it with : (#161, #172).
  • Add flag to override the output option (#173).
  • Fix bug where Task was persisting the new checksum on the disk when the Dry
    Mode is enabled (#166).
  • Fix file timestamp issue when the file name has spaces (#176).
  • Mitigating path expanding issues on Windows (#170).

v2.3.0 - 2019-01-02

  • On Windows, Task can now be installed using Scoop (#152).
  • Fixed issue with file/directory globing (#153).
  • Added ability to globally set environment variables (#138, #159).

v2.2.1 - 2018-12-09

  • This repository now uses Go Modules (#143). We'll still keep the vendor
    directory in sync for some time, though;
  • Fixing a bug when the Taskfile has no tasks but includes another Taskfile
    (#150);
  • Fix a bug when calling another task or a dependency in an included Taskfile
    (#151).

v2.2.0 - 2018-10-25

  • Added support for
    including other Taskfiles
    (#98)
    • This should be considered experimental. For now, only including local files
      is supported, but support for including remote Taskfiles is being discussed.
      If you have any feedback, please comment on #98.
  • Task now have a dedicated documentation site: https://taskfile.org
    • Thanks to Docsify for making this pretty easy. To
      check the source code, just take a look at the
      docs directory of this
      repository. Contributions to the documentation is really appreciated.

v2.1.1 - 2018-09-17

  • Fix suggestion to use task --init not being shown anymore (when a
    Taskfile.yml is not found)
  • Fix error when using checksum method and no file exists for a source glob
    (#131)
  • Fix signal handling when the --watch flag is given (#132)

v2.1.0 - 2018-08-19

  • Add a ignore_error option to task and command (#123)
  • Add a dry run mode (--dry flag) (#126)

v2.0.3 - 2018-06-24

  • Expand environment variables on "dir", "sources" and "generates" (#116)
  • Fix YAML merging syntax (#112)
  • Add ZSH completion (#111)
  • Implement new output option. Please check out the
    documentation

v2.0.2 - 2018-05-01

  • Fix merging of YAML anchors (#112)

v2.0.1 - 2018-03-11

  • Fixes panic on task --list

v2.0.0 - 2018-03-08

Version 2.0.0 is here, with a new Taskfile format.

Please, make sure to read the
Taskfile versions
document, since it describes in depth what changed for this version.

  • New Taskfile version 2 (#77)
  • Possibility to have global variables in the Taskfile.yml instead of
    Taskvars.yml (#66)
  • Small improvements and fixes

v1.4.4 - 2017-11-19

  • Handle SIGINT and SIGTERM (#75);
  • List: print message with there's no task with description;
  • Expand home dir ("~" symbol) on paths (#74);
  • Add Snap as an installation method;
  • Move examples to its own repo;
  • Watch: also walk on tasks called on on "cmds", and not only on "deps";
  • Print logs to stderr instead of stdout (#68);
  • Remove deprecated set keyword;
  • Add checksum based status check, alternative to timestamp based.

v1.4.3 - 2017-09-07

  • Allow assigning variables to tasks at run time via CLI (#33)
  • Added support for multiline variables from sh (#64)
  • Fixes env: remove square braces and evaluate shell (#62)
  • Watch: change watch library and few fixes and improvements
  • When use watching, cancel and restart long running process on file change (#59
    and #60)

v1.4.2 - 2017-07-30

  • Flag to set directory of execution
  • Always echo command if is verbose mode
  • Add silent mode to disable echoing of commands
  • Fixes and improvements of variables (#56)

v1.4.1 - 2017-07-15

  • Allow use of YAML for dynamic variables instead of $ prefix
    • VAR: {sh: echo Hello} instead of VAR: $echo Hello
  • Add --list (or -l) flag to print existing tasks
  • OS specific Taskvars file (e.g. Taskvars_windows.yml, Taskvars_linux.yml,
    etc)
  • Consider task up-to-date on equal timestamps (#49)
  • Allow absolute path in generates section (#48)
  • Bugfix: allow templating when calling deps (#42)
  • Fix panic for invalid task in cyclic dep detection
  • Better error output for dynamic variables in Taskvars.yml (#41)
  • Allow template evaluation in parameters

v1.4.0 - 2017-07-06

  • Cache dynamic variables
  • Add verbose mode (-v flag)
  • Support to task parameters (overriding vars) (#31) (#32)
  • Print command, also when "set:" is specified (#35)
  • Improve task command help text (#35)

v1.3.1 - 2017-06-14

  • Fix glob not working on commands (#28)
  • Add ExeExt template function
  • Add --init flag to create a new Taskfile
  • Add status option to prevent task from running (#27)
  • Allow interpolation on generates and sources attributes (#26)

v1.3.0 - 2017-04-24

  • Migrate from os/exec.Cmd to a native Go sh/bash interpreter
    • This is a potentially breaking change if you use Windows.
    • Now, cmd is not used anymore on Windows. Always use Bash-like syntax for
      your commands, even on Windows.
  • Add "ToSlash" and "FromSlash" to template functions
  • Use functions defined on github.com/Masterminds/sprig
  • Do not redirect stdin while running variables commands
  • Using context and errgroup packages (this will make other tasks to be
    cancelled, if one returned an error)

v1.2.0 - 2017-04-02

  • More tests and Travis integration
  • Watch a task (experimental)
  • Possibility to call another task
  • Fix "=" not being recognized in variables/environment variables
  • Tasks can now have a description, and help will print them (#10)
  • Task dependencies now run concurrently
  • Support for a default task (#16)

v1.1.0 - 2017-03-08

  • Support for YAML, TOML and JSON (#1)
  • Support running command in another directory (#4)
  • --force or -f flag to force execution of task even when it's up-to-date
  • Detection of cyclic dependencies (#5)
  • Support for variables (#6, #9, #14)
  • Operation System specific commands and variables (#13)

v1.0.0 - 2017-02-28

  • Add LICENSE file

:::


Website Src Next Docs Community (`website/src/next/docs/community.md`)


title: Community Task community contributions, installation methods, and integrations maintained by third parties section: Project docType: project outline: deep

Community

Some of the work to improve the Task ecosystem is done by the community, be it
installation methods or integrations with code editor. I (the author) am
thankful for everyone that helps me to improve the overall experience.

Integrations

Many of our integrations are contributed and maintained by the community. You
can view the full list of community integrations
here.

Installation methods

Some installation methods are maintained by third party:

More

Also, thanks for all the
code contributors,
financial contributors, all those who
reported bugs and
answered questions.

If you know something that is missing in this document, please submit a pull
request.


Website Src Next Docs Contributing (`website/src/next/docs/contributing.md`)


title: Contributing Comprehensive guide for contributing to the Task project, including setup, development, testing, and submitting PRs section: Contributing docType: contributing outline: deep

Contributing

Thank you for your interest in contributing to Task! We welcome and appreciate
all forms of contributions, but we kindly ask that you read this document first.
If you have any questions that were not answered by this document, you can reach
out on our Discord or by opening a discussion
on GitHub. If you want to help, but you're not sure where to start, you can
check out our list of
good first issues.

::: info

This document applies to the core Task repository and Task for Visual
Studio Code
.

:::

AI Usage Policy

When using AI tools (including LLMs like ChatGPT, Claude, Copilot, etc.) to
contribute to Task:

  • Please disclose AI usage to reduce maintainer fatigue
  • You are responsible for all AI-generated issues or PRs you submit
  • Low-quality or unreviewed AI content will be closed immediately
  • Keep conversations human - PR descriptions, review comments, and issue
    discussions should be written in your own words, not generated by AI. Code
    review is a discussion between people, not bots.

We encourage the use of AI tools to assist with development, but all
contributions must be thoroughly reviewed and tested by the contributor before
submission. AI-generated code should be understood, validated, and adapted to
meet Task's standards.

Before you start

  • Check existing work - Is there an existing PR? Are there issues discussing
    the feature/change you want to make? Please make sure you consider/address
    these discussions in your work.
  • Backwards compatibility - Will your change break existing Taskfiles? It is
    much more likely that your change will merged if it backwards compatible. Is
    there an approach you can take that maintains this compatibility? If not,
    consider opening an issue first so that API changes can be discussed before
    you invest your time into a PR.
  • Experiments - If there is no way to make your change backward compatible
    then there is a procedure to introduce breaking changes into minor versions.
    We call these "experiments". If you're intending to work on an
    experiment, then please read the experiments workflow
    document carefully and submit a proposal first.

1. Setup

The easiest way to install everything you need to work on Task is mise.
From the repository root, run:

shell
mise install

This installs the pinned versions of Go, Node.js, pnpm and the dev tools
(golangci-lint, mockery, gotestsum, goreleaser and gorelease) declared
in the mise.toml file.

If you'd rather install things manually, you'll need:

  • Go - Task is written in Go. We always support the latest two major
    Go versions, so make sure your version is recent enough.
  • Node.js - Node.js is used to host Task's documentation server
    and is required if you want to run this server locally. It is also required if
    you want to contribute to the Visual Studio Code extension.
  • Pnpm - Pnpm is the Node.js package manager used by Task.

2. Making changes

  • Code style - Try to maintain the existing code style where possible. Go
    code should be formatted and linted by golangci-lint. This
    wraps the gofumpt and gci formatters and a number of
    linters. We recommend that you take a look at the golangci-lint
    docs
    for a guide on how to setup your editor to
    auto-format your code. Any Markdown or TypeScript files should be formatted
    and linted by Prettier. This style is enforced by our CI to ensure
    that we have a consistent style across the project. You can use the
    task lint command to lint the code locally and the task lint:fix command
    to try to automatically fix any issues that are found. You can also use the
    task fmt command to auto-format the files if your editor doesn't do it for
    you.
  • Documentation - Ensure that you add/update any relevant documentation. See
    the updating documentation section below.
  • Tests - Ensure that you add/update any relevant tests and that all tests
    are passing before submitting the PR. See the writing tests
    section below.

Running your changes

To run Task with working changes, you can use go run ./cmd/task. To run a
development build of task against a test Taskfile in testdata, you can use
go run ./cmd/task --dir ./testdata/<my_test_dir> <task_name>.

To run Task for Visual Studio Code, you can open the project in VSCode and hit
F5 (or whatever you debug keybind is set to). This will open a new VSCode window
with the extension running. Debugging this way is recommended as it will allow
you to set breakpoints and step through the code. Otherwise, you can run
task package which will generate a .vsix file that can be used to manually
install the extension.

Updating documentation

Task uses Vitepress to host a documentation server. The code for
this is located in the core Task repository. This can be setup and run locally
by using task website (requires nodejs & pnpm). All content is written in
Markdown and is located in the website/src directory. All Markdown documents
should have an 80 character line wrap limit (enforced by Prettier).

Search is provided by Algolia DocSearch. The crawler runs on Algolia's side and
is configured through their dashboard, but website/docsearch.config.js holds
the same configuration in the repository so it can be read and reviewed. If you
change one, change the other. A page's section: frontmatter is what the
crawler shows as the breadcrumb on a search result, while docType: powers its
search facet, so a new page needs both.

After building the site, run pnpm check:links from website/ to check links
in the generated Markdown pages and LLM indexes. The LLM plugin is patched in
website/patches/ to resolve links before it moves directory indexes such as
docs/guide/index.md to docs/guide.md. When upgrading the plugin, retain the
patch until upstream handles those links, and check both documentation channels.

When making a change, consider whether a change to the Usage
Guide
is necessary. This document contains descriptions and
examples of how to use Task features. If you're adding a new feature, try to
find an appropriate place to add a new section. If you're updating an existing
feature, ensure that the documentation and any examples are up-to-date. Ensure
that any examples follow the Taskfile Styleguide.

If you added a new command or flag, ensure that you add it to the CLI
Reference
. New fields also need to be added to the Schema
Reference
and JSON Schema. The descriptions
for fields in the docs and the schema should match.

Documentation channels

The docs, the blog and the coding-agent guide exist in two copies, so that
taskfile.dev never announces a feature that is not in the released binary yet:

Directory Channel Published on
website/src/next/{docs,blog} next next.taskfile.dev
website/src/latest/{docs,blog} latest taskfile.dev

The coding-agent guide follows the same channels as src/next/agents.md and
src/latest/agents.md, and is promoted at release time too.

Everything else - the homepage, the team, adopters, images - is shared by both
channels and goes live as soon as the site is deployed.

Write in website/src/next. It holds the upcoming release, and
cmd/release copies it over website/src/latest at every release. The same
split applies to the JSON schemas: edit next-schema.json and
next-schema-taskrc.json, never schema.json or schema-taskrc.json.

Where you put a blog post decides when it goes out. A post that announces a
feature belongs in website/src/next/blog alone: it ships with the release that
carries the feature. A post that stands on its own - an announcement, a write-up
about an already released feature - can be added to website/src/latest/blog as
well, and it goes live at the next deploy. Its sidebar entry comes from the
post's own frontmatter, so there is nothing else to update.

Never edit an existing file under website/src/latest: cmd/release overwrites
that directory at every release, so the change would be silently lost. The same
goes for .vitepress/sidebar/latest.ts, which is promoted from next.ts. CI
fails a pull request that modifies either. Adding a file under
website/src/latest is fine - that is how a blog post gets published early.

To preview what taskfile.dev will look like, run task website:start:latest. It
serves the latest channel on port 3002, so it can run next to task website
and the version selector switches between the two.

Writing tests

A lot of Task's tests are held in the task_test.go file in the project root
and this is where you'll most likely want to add new ones too. Most of these
tests also have a subdirectory in the testdata directory where any
Taskfiles/data required to run the tests are stored.

When making a changes, consider whether new tests are required. These tests
should ensure that the functionality you are adding will continue to work in the
future. Existing tests may also need updating if you have changed Task's
behavior.

You may also consider adding unit tests for any new functions you have added.
The unit tests should follow the Go convention of being location in a file named
*_test.go in the same package as the code being tested.

3. Committing your code

Try to write meaningful commit messages and avoid having too many commits on the
PR. Most PRs should likely have a single commit (although for bigger PRs it may
be reasonable to split it in a few). Git squash and rebase is your friend!

If you're not sure how to format your commit message, check out Conventional
Commits
. This style is not enforced, but it is a good way
to make your commit messages more readable and consistent.

4. Submitting a PR

  • Describe your changes - Ensure that you provide a comprehensive
    description of your changes.
  • Issue/PR links - Link any previous work such as related issues or PRs.
    Please describe how your changes differ to/extend this work.
  • Examples - Add any examples or screenshots that you think are useful to
    demonstrate the effect of your changes.
  • Draft PRs - If your changes are incomplete, but you would like to discuss
    them, open the PR as a draft and add a comment to start a discussion. Using
    comments rather than the PR description allows the description to be updated
    later while preserving any discussions.

FAQ

I want to contribute, where do I start?

Take a look at the list of open issues for Task or Task for
Visual Studio Code
. We have a good first
issue
label for simpler issues that are ideal for first time
contributions.

All kinds of contributions are welcome, whether its a typo fix or a shiny new
feature. You can also contribute by upvoting/commenting on issues, helping to
answer questions or contributing to other community projects.

I'm stuck, where can I get help?

If you have questions, feel free to ask them in the #help forum channel on our
Discord server or open a Discussion on GitHub.



Website Src Next Docs Faq (`website/src/next/docs/faq.md`)


title: FAQ Frequently asked questions about Task, including ETAs, shell limitations, and Windows compatibility section: Project docType: project outline: deep

FAQ

This page contains a list of frequently asked questions about Task.

When will \ be released? / ETAs

Task is free and open source project maintained by a small group of
volunteers with full time jobs and lives outside of the project. Because of
this, it is difficult to predict how much time we will be able to dedicate to
the project in advance and we don't want to make any promises that we can't
keep. For this reason, we are unable to provide ETAs for new features or
releases. We make a "best effort" to provide regular releases and fix bugs in a
timely fashion, but sometimes our personal lives must take priority.

ETAs are probably the number one question we (and maintainers of other open
source projects) get asked. We understand that you are passionate about the
project, but it can be overwhelming to be asked this question so often. Please
be patient and avoid asking for ETAs.

The best way to speed things up is to contribute to the project yourself. We
always appreciate new contributors. If you are interested in contributing, check
out the contributing guide.

Why won't my task update my shell environment?

This is a limitation of how shells work. Task runs as a subprocess of your
current shell, so it can't change the environment of the shell that started it.
This limitation is shared by other task runners and build tools too.

A common way to work around this is to create a task that will generate output
that can be parsed by your shell. For example, to set an environment variable on
your shell you can write a task like this:

yaml
my-shell-env:
  cmds:
    - echo "export FOO=foo"
    - echo "export BAR=bar"

Now run eval $(task my-shell-env) and the variables $FOO and $BAR will be
available in your shell.

I can't reuse my shell in a task's commands

Task runs each command as a separate shell process, so something you do in one
command won't effect any future commands. For example, this won't work:

yaml
version: '3'

tasks:
  foo:
    cmds:
      - a=foo
      - echo $a
      # outputs ""

To work around this you can either use a multiline command:

yaml
version: '3'

tasks:
  foo:
    cmds:
      - |
        a=foo
        echo $a
      # outputs "foo"

Or for more complex multi-line commands it is recommended to move your code into
a separate file and call that instead:

yaml
version: '3'

tasks:
  foo:
    cmds:
      - ./foo-printer.bash
shell
#!/bin/bash
a=foo
echo $a

Are shell core utilities available on Windows?

The most common ones, yes. And we might add more in the future.
This is possible because Task compiles a small set of core utilities in Go and
enables them by default on Windows for greater compatibility.

It's possible to control whether these builtin core utilities are used or not
with the TASK_CORE_UTILS
environment variable:

bash
# Enable, even on non-Windows platforms
env TASK_CORE_UTILS=1 task ...

# Disable, even on Windows
env TASK_CORE_UTILS=0 task ...

This is the list of core utils that are currently available:

  • base64
  • cat
  • chmod
  • cp
  • find
  • gzip
  • ls
  • mkdir
  • mktemp
  • mv
  • rm
  • shasum
  • tar
  • touch
  • xargs
  • (more might be added in the future)

Website Src Next Docs Installation (`website/src/next/docs/installation.md`)


title: Installation section: Getting Started docType: guide outline: deep pageClass: installation-page

Installation

Choose a package manager for your system, or install Task from a binary.

Official packages {#official-package-managers}

Maintained by the Task team and kept up-to-date.

shell
brew install go-task/tap/go-task

Or use the Homebrew core formula:

shell
brew install go-task

Set up the repository:

shell
curl -1sLf 'https://dl.cloudsmith.io/public/task/task/setup.rpm.sh' | sudo -E bash

Install Task:

shell
dnf install task

Set up the repository:

shell
curl -1sLf 'https://dl.cloudsmith.io/public/task/task/setup.deb.sh' | sudo -E bash

Install Task:

shell
apt install task

Set up the repository:

shell
curl -1sLf 'https://dl.cloudsmith.io/public/task/task/setup.alpine.sh' | sudo -E bash

Install Task:

shell
apk add task
shell
sudo snap install task --classic

Requires a Linux distribution with classic confinement support.

shell
npm install @go-task/cli

Task is also available as a project dependency.

shell
winget install Task.Task

Available through the
WinGet community repository.

Package repository hosting for deb/rpm/apk is graciously provided by Cloudsmith.

Community packages {#community-maintained-package-managers}

Maintained by the community, outside the Task team's control. These packages may
lag behind the latest release.

shell
mise use -g task

For a project-local installation, use mise use task instead. This adds Task to
your project's mise.toml.

shell
port install go-task
shell
pip install go-task-bin
shell
choco install go-task
shell
scoop install task
shell
pacman -S go-task
shell
dnf install go-task
shell
pkg install task
shell
nix-env -iA nixpkgs.go-task
shell
pacstall -I go-task-deb
shell
pkgx task

or, if you have pkgx integration enabled:

shell
task

Binaries & CI {#get-the-binary}

Install Task without a package manager: download a binary, use the install
script, or add the setup action to your GitHub workflow.

Download a binary {#binary}

  1. Open the GitHub releases and
    download the archive for your operating system and architecture.
  2. Extract task (task.exe on Windows).
  3. Move the executable to a directory on your PATH.

Each release also includes DEB, RPM and APK packages, plus task_checksums.txt
with SHA-256 checksums for the release files.

Install with a script {#install-script}

Use the
install script for
a shell-based installation, including CI environments. It downloads a prebuilt
binary and verifies its checksum; no Go installation is needed.

By default, the script installs the latest release into ./bin, relative to
your current directory. Choose a different directory or pin a release:

::: code-group

shell [latest release]
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d
shell [custom directory]
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b ~/.local/bin
shell [pinned version]
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d v3.42.1
shell [directory + version]
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b ~/.local/bin v3.42.1

:::

When combining options, keep the
release tag last.

::: tip Make Task available in your shell

Add the installation directory to your PATH to run task from anywhere. With
the default location, you can also run ./bin/task directly.

On Linux, ~/.local/bin and ~/bin are common per-user locations;
/usr/local/bin is a system-wide location and may require elevated permissions.
Do not assume these directories are already on your PATH, especially on macOS
and Windows.

:::

GitHub Actions

Add the official setup action to your
job's steps before running Task:

yaml
- name: Install Task
  uses: go-task/setup-task@v2

- name: Verify Task
  run: task --version

Use the action's version input to pin a Task release. See the
action documentation for examples
and configuration.

Build from source

Ensure that you have a supported version of Go properly
installed and setup. You can find the minimum required version of Go in the
go.mod file.

You can then install the latest release globally by running:

shell
go install github.com/go-task/task/v3/cmd/task@latest

Or you can install into another directory:

shell
env GOBIN=/bin go install github.com/go-task/task/v3/cmd/task@latest

::: tip

For CI environments we recommend using the install script
instead, which is faster and more stable, since it'll just download the latest
released binary.

:::

Go Tool

If you're working in a Go project, a nice possibility is using go tool.
go tool makes it easy to run Task without needing to install the binary
manually. This works well on CI.

To do that, just run the following to add Task as a tool in your Go project.
Task will be added to your go.mod.

bash
go get -tool github.com/go-task/task/v3/cmd/task@latest

Then, prefix go tool when calling Task like below. Go will compile Task on
demand before calling it.

bash
go tool task {arguments...}

Verify installation

After installing, open a terminal and check that Task is available:

shell
task --version

If you installed Task with go tool, run go tool task --version instead.

You're ready to create your first Taskfile. You can also
enable shell completions below.

Shell completions {#setup-completions}

Some installation methods will automatically install completions too, but if
this isn't working for you or your chosen method doesn't include them, you can
run task --completion <shell> to output a completion script for any supported
shell.

Every shell shares a single source of truth: the script is a thin wrapper that
asks the task binary itself what to suggest, so Bash, Zsh, Fish, Nushell and
PowerShell all offer the same task names, aliases, flags, flag values and
requires vars.

There are a couple of ways these completions can be added to your shell config:

This method loads the completion script from the currently installed version of
task every time you create a new shell. This ensures that your completions are
always up-to-date. If your executable isn’t named task, set the TASK_EXE
environment variable before running eval.

::: code-group

shell [bash]
# ~/.bashrc

# export TASK_EXE='go-task' if needed
eval "$(task --completion bash)"
shell [zsh]
# ~/.zshrc

# export TASK_EXE='go-task' if needed
eval "$(task --completion zsh)"
shell [fish]
# ~/.config/fish/config.fish

# export TASK_EXE='go-task' if needed
task --completion fish | source
powershell [powershell]
# $PROFILE\Microsoft.PowerShell_profile.ps1
Invoke-Expression  (&task --completion powershell | Out-String)
nu [nushell]
# ~/.config/nushell/config.nu
#
# Nushell cannot source a script from stdin, so the script is saved where
# Nushell auto-loads it at startup. Autoload directories are read after
# config.nu, so the completions become available in the next shell.
mkdir ($nu.data-dir | path join "vendor/autoload")
task --completion nu | save --force ($nu.data-dir | path join "vendor/autoload/task-completions.nu")

:::

Option 2. Copy the script to your shell's completions directory

This method requires you to manually update the completions whenever Task is
updated. However, it is useful if you want to modify the completions yourself.

::: code-group

shell [bash]
task --completion bash > /etc/bash_completion.d/task
shell [zsh]
task --completion zsh  > /usr/local/share/zsh/site-functions/_task
shell [fish]
task --completion fish > ~/.config/fish/completions/task.fish
nu [nushell]
task --completion nu | save --force ($nu.data-dir | path join "vendor/autoload/task-completions.nu")

:::

Zsh customization

The Zsh completion supports the standard verbose zstyle to control whether
task descriptions are shown. By default, descriptions are displayed. To show
only task names without descriptions, add this to your ~/.zshrc (after the
completion is loaded):

shell
zstyle ':completion:*:*:task:*' verbose false

By default, task aliases are also offered as completions. To complete only the
canonical task names, add the show-aliases zstyle:

shell
zstyle ':completion:*:*:task:*' show-aliases false

Nushell caveats

Nushell cannot source a script from stdin, so both options above write the script
to an autoload directory. Option 1 rewrites it at every startup, which keeps it
in sync with the installed version of Task, and the refreshed completions are
picked up by the next shell. With option 2, re-run the command after upgrading
Task.

Nushell shares a single external completer between every command, so the script
chains to the one already configured β€” carapace and friends keep working. Load it
from an autoload directory as shown above rather than from config.nu, so that
your own completer is the one being chained to. If you would rather wire it
yourself, the script also exposes a task-external-completer command:

nu
$env.config.completions.external.completer = {|spans|
    match ($spans | first) {
        task => (task-external-completer $spans)
        _ => (do $my_other_completer $spans)
    }
}

Two engine directives behave differently under Nushell by design: it never
appends a space after an external completion (so NoSpace is a no-op) and never
re-sorts the results (so KeepOrder is always honoured).


Website Src Next Docs Integrations (`website/src/next/docs/integrations.md`)


title: Integrations Official and community integrations for Task, including VS Code, JSON schemas, and other tools section: Getting Started docType: guide outline: deep

Integrations

Visual Studio Code Extension

Task has an
official extension for Visual Studio Code.
The code for this project can be found in
our GitHub repository. To use this
extension, you must have Task v3.45.3+ installed on your system.

This extension provides the following features (and more):

  • View tasks in the sidebar.
  • Run tasks from the sidebar and command palette.
  • Go to definition from the sidebar and command palette.
  • Run last task command.
  • Multi-root workspace support.
  • Initialize a Taskfile in the current workspace.

To get autocompletion and validation for your Taskfile, see the
Schema section below.

Configuration namespace change

In v1.0.0 of the extension, the configuration namespace was changed from task
to taskfile in order to fix
an issue.

If you receive a warning like the one above, you will need to update your
settings to use the new taskfile namespace instead:

Schema

This was initially created by @KROSF in
this Gist and
is now officially maintained in
this file
and made available at https://taskfile.dev/schema.json. This schema can be used
to validate Taskfiles and provide autocompletion in many code editors:

Visual Studio Code

To integrate the schema into VS Code, you need to install the
YAML extension
by Red Hat. Any Taskfile.yml in your project should automatically be detected
and validation/autocompletion should work. If this doesn't work or you want to
manually configure it for files with a different name, you can add the following
to your settings.json:

json
// settings.json
{
  "yaml.schemas": {
    "https://taskfile.dev/schema.json": [
      "**/Taskfile.yml",
      "./path/to/any/other/taskfile.yml"
    ]
  }
}

You can also configure the schema directly inside of a Taskfile by adding the
following comment to the top of the file:

yaml
# yaml-language-server: $schema=https://taskfile.dev/schema.json
version: '3'

You can find more information on this in the
YAML language server project.

AI/LLM Assistants

Task documentation is optimized for AI assistants like Claude Code, Cursor, and
other LLM-powered development tools through the
VitePress LLMs plugin.

This integration provides:

  • Structured documentation in LLM-friendly formats
  • Context-optimized content for AI assistants
  • Automatic generation of llms.txt and llms-full.txt files
  • Enhanced discoverability of Task features for AI tools

AI assistants can access Task documentation through:

  • llms.txt: Lightweight overview of Task documentation
  • llms-full.txt: Complete documentation with all content

These files are automatically generated and kept in sync with the documentation,
ensuring AI assistants always have access to the latest Task features and usage
patterns.

Community Integrations

In addition to our official integrations, there is an amazing community of
developers who have created their own integrations for Task:

If you have made something that integrates with Task, please feel free to open a
PR to add it to this list.


Website Src Next Docs Releasing (`website/src/next/docs/releasing.md`)


title: Releasing Task release process including GoReleaser, Homebrew, npm, Snapcraft, winget, and other package managers section: Contributing docType: contributing outline: deep

Releasing

The release process of Task is done with the help of GoReleaser.
You can test the release process locally by calling the goreleaser:test task
of the Taskfile.

GitHub Actions should release
artifacts automatically when a new Git tag is pushed to main branch (raw
executables and DEB and RPM packages).

The body of the GitHub release is the section of the CHANGELOG.md matching the
version being released, extracted by go run ./cmd/release --notes. A version
without changelog entries is released with an empty body.

Raw executables can also be reproduced and verified locally by checking out a
specific tag and calling goreleaser build, using the Go version defined in the
above GitHub Actions.

Website

task release:<version> promotes the documentation before tagging: the docs in
website/src/next/docs, their sidebar and the next-* JSON schemas are copied
over their published counterparts, so the released tag carries the docs of the
version it ships. The release workflow then runs task website:deploy:prod.

A new blog post is a Markdown file in website/src/next/blog with no file at
the same relative path in website/src/latest/blog, excluding index.md.
Renaming a post therefore makes it new. On the next site, new posts display
the build date in UTC (YYYY-MM-DD) and are sorted using that date, without
changing the source files. The latest site uses only the stored dates.

During release preparation, cmd/release replaces or adds the date in each
new post's frontmatter with the same local date used for the changelog. It
validates all new posts' frontmatter before writing; an error identifies the
file to fix. It then copies the blog to latest, so both copies carry the same
date in the release commit. This is the preparation date, even if publication on
GitHub happens later. Already published posts keep their dates, including when
their content changes. The --version and --notes flags do not write files.

Because taskfile.dev is built from the latest copy, it can be redeployed at any
time between releases - to publish a blog post or a documentation fix - without
exposing the docs of unreleased features:

shell
git checkout main && git pull
task website:deploy:prod

Package managers

GoReleaser will automatically publish the release to most package managers:

  • Cloudsmith (DEB and RPM repositories)
  • Homebrew
  • npm
  • Snapcraft
  • winget

Once the release is published, GoReleaser announces it on the
Discord server. Nightly releases are not
announced.

These package managers are updated automatically by the community:


Website Src Next Docs Remote Taskfiles (`website/src/next/docs/remote-taskfiles.md`)


title: Remote Taskfiles Guide to loading and securely using Taskfiles from HTTP and Git sources section: Guide docType: guide outline: deep

Remote Taskfiles

Use a remote Taskfile to share tasks across projects without copying the file
into each repository. You can call it directly or include it under a namespace.

::: danger

Only run remote Taskfiles from sources you trust. Their commands execute on your
machine, just like commands from a local Taskfile.

:::

The examples use Task's public sample, whose hello task prints Hello Task!.
On first use, Task asks you to trust the downloaded file. Review it before
accepting; see trust and checksums for subsequent changes and CI.

Run a remote Taskfile {#specifying-a-remote-entrypoint}

Pass the remote location to --taskfile (or -t). With no task name, Task runs
the remote file's default task. Choose a transport below:

::: code-group

shell [http/https]
$ task --taskfile https://raw.githubusercontent.com/go-task/task/main/website/src/public/Taskfile.yml
task: [hello] echo "Hello Task!"
Hello Task!
shell [git over http]
$ task --taskfile 'https://github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main'
task: [hello] echo "Hello Task!"
Hello Task!
shell [git over ssh]
$ task --taskfile '[email protected]/go-task/task.git//website/src/public/Taskfile.yml?ref=main'
task: [hello] echo "Hello Task!"
Hello Task!

:::

Include shared tasks {#including-remote-taskfiles}

Set the include location to a remote URL instead of a local path. The tasks
become available under the namespace you choose, just like
local includes:

::: code-group

yaml [http/https]
version: '3'

includes:
  shared: https://raw.githubusercontent.com/go-task/task/main/website/src/public/Taskfile.yml
yaml [git over http]
version: '3'

includes:
  shared: https://github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main
yaml [git over ssh]
version: '3'

includes:
  shared: [email protected]/go-task/task.git//website/src/public/Taskfile.yml?ref=main

:::

shell
$ task shared:hello
task: [hello] echo "Hello Task!"
Hello Task!

Supply authentication {#authenticating-using-environment-variables}

The Taskfile location is processed by the templating system, so you can
reference environment variables in your URL if you need to add authentication.
For example:

yaml
version: '3'

includes:
  shared: https://{{.TOKEN}}@raw.githubusercontent.com/my-org/my-repo/main/Taskfile.yml

Prefer the remote.headers configuration
option when the server accepts a header. A credential in the URL ends up in
error messages and in the confirmation prompt, and the include can no longer be
committed as-is.

Choose a source {#node-types}

HTTP/HTTPS

https://raw.githubusercontent.com/go-task/task/main/website/src/public/Taskfile.yml

Use a direct URL when the server exposes the Taskfile as plain text. Task
downloads the file from that URL. The file must be a valid Taskfile and can be
of any name. If a file is not found at the specified URL, Task will append each
of the supported file names in turn until it finds a valid file. If it still
does not find a valid Taskfile, an error is returned.

Git over HTTP

https://github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main

Use a Git URL to select a file from a repository over HTTP/HTTPS. The first part
of the URL is the base URL of the Git repository. This is the same URL that you
would use to clone the repo over HTTP.

  • You can optionally add the path to the Taskfile in the repository by appending
    // to the URL.
  • You can also optionally specify a branch or tag to use by appending
    ?ref=<ref> to the end of the URL. If you omit a reference, the default
    branch will be used.

Git over SSH

[email protected]/go-task/task.git//website/src/public/Taskfile.yml?ref=main

Use an SSH Git URL when repository access depends on your SSH credentials. The
first part of the URL is the user and base URL of the Git repository. This is
the same URL that you would use to clone the repo over SSH.

To use Git over SSH, you need to make sure that your SSH agent has your private
SSH keys added so that they can be used during authentication.

  • You can optionally add the path to the Taskfile in the repository by appending
    // to the URL.
  • You can also optionally specify a branch or tag to use by appending
    ?ref=<ref> to the end of the URL. If you omit a reference, the default
    branch will be used.

Locate files and directories {#special-variables}

The file-path special variables behave
differently when a Taskfile is loaded from a remote source, because there is no
local file or directory that corresponds 1:1 to the Taskfile:

Variable Value when loaded remotely
TASKFILE / ROOT_TASKFILE The original URL, unchanged
TASKFILE_DIR / ROOT_DIR Empty string, a directory variable cannot point to a URL
TASK_DIR Resolved against USER_WORKING_DIR (relative dir: β†’ joined with USER_WORKING_DIR, empty dir: β†’ USER_WORKING_DIR, absolute dir: β†’ kept as-is)

If a remote Taskfile includes a local Taskfile (or vice-versa), each variable
reflects the source of the Taskfile it refers to.

Review trust and changes {#security}

Review changed files {#automatic-checksums}

Running commands from sources that you do not control is always a potential
security risk. For this reason, we have added some automatic checks when using
remote Taskfiles:

  1. When running a task from a remote Taskfile for the first time, Task will
    print a warning to the console asking you to check that you are sure that you
    trust the source of the Taskfile. If you do not accept the prompt, then Task
    will exit with code 104 (not trusted) and nothing will run. If you accept
    the prompt, the remote Taskfile will run and further calls to the remote
    Taskfile will not prompt you again.
  2. Whenever you run a remote Taskfile, Task will create and store a checksum of
    the file that you are running. If the checksum changes, then Task will print
    another warning to the console to inform you that the contents of the remote
    file has changed. If you do not accept the prompt, then Task will exit with
    code 104 (not trusted) and nothing will run. If you accept the prompt, the
    checksum will be updated and the remote Taskfile will run.

Sometimes you need to run Task in an environment that does not have an
interactive terminal, so you are not able to accept a prompt. In these cases you
are able to tell task to accept these prompts automatically by using the --yes
flag or the --trusted-hosts flag. The --trusted-hosts flag allows you to
specify trusted hosts for remote Taskfiles, while --yes applies to all prompts
in Task. You can also configure trusted hosts in your
taskrc configuration using
remote.trusted-hosts. Before enabling automatic trust, you should:

  1. Be sure that you trust the source and contents of the remote Taskfile.
  2. Consider using a pinned version of the remote Taskfile (e.g. A link
    containing a commit hash) to prevent Task from automatically accepting a
    prompt that says a remote Taskfile has changed.

Pin reviewed contents {#manual-checksum-pinning}

Alternatively, if you expect the contents of your remote files to be a constant
value, you can pin the checksum of the included file instead:

yaml
version: '3'

includes:
  included:
    taskfile: https://raw.githubusercontent.com/go-task/task/main/website/src/public/Taskfile.yml
    checksum: '<sha256-of-reviewed-file>'

Replace the placeholder with the SHA-256 checksum of the file you reviewed. A
pinned checksum disables the automatic checksum prompts discussed above.
However, if the checksums do not match, Task will exit immediately with an
error. When setting this up for the first time, you may not know the correct
value of the checksum. There are a couple of ways you can obtain this:

  1. Add the include normally without the checksum key. The first time you run
    the included Taskfile, a .task/remote temporary directory is created. Find
    the correct set of files for your included Taskfile and open the file that
    ends with .checksum. You can copy the contents of this file and paste it
    into the checksum key of your include. This method is safest as it allows
    you to inspect the downloaded Taskfile before you pin it.
  2. Alternatively, add the include with a temporary random value in the
    checksum key. When you try to run the Taskfile, you will get an error that
    will report the incorrect expected checksum and the actual checksum. You can
    copy the actual checksum and replace your temporary random value.

Use TLS {#tls}

Task currently supports both http and https URLs. However, the http
requests will not execute by default unless you run the task with the
--insecure flag. This is to protect you from accidentally running a remote
Taskfile that is downloaded via an unencrypted connection. Sources that are not
protected by TLS are vulnerable to man-in-the-middle attacks and should be
avoided unless you know what you are doing.

Add certificates {#custom-certificates}

If your remote Taskfiles are hosted on a server that uses a custom CA
certificate (e.g., a corporate internal server), you can specify the CA
certificate using the --cacert flag:

shell
task --taskfile https://internal.example.com/Taskfile.yml --cacert /path/to/ca.crt

For servers that require client certificate authentication (mTLS), you can
provide a client certificate and key:

shell
task --taskfile https://secure.example.com/Taskfile.yml \
  --cert /path/to/client.crt \
  --cert-key /path/to/client.key

::: warning

Encrypted private keys are not currently supported. If your key is encrypted,
you must decrypt it first:

shell
openssl rsa -in encrypted.key -out decrypted.key

:::

These options can also be configured in the
configuration file.

Reuse cached files {#caching-running-offline}

What do you need? Option
Reuse a downloaded copy for one hour --expiry 1h
Use an existing cache without network access --offline
Fetch a fresh copy now --download
Remove cached remote files --clear-cache

For example, run task --offline shared:hello after downloading and trusting
the include above. Offline mode needs an existing cached copy.

Whenever you run a remote Taskfile, the latest copy will be downloaded from the
internet and cached locally. This cached file will be used for all future
invocations of the Taskfile until the cache expires. Once it expires, Task will
download the latest copy of the file and update the cache. By default, the cache
is set to expire immediately. This means that Task will always fetch the latest
version. However, the cache expiry duration can be modified by setting the
--expiry flag.

If for any reason you lose access to the internet or you are running Task in
offline mode (via the --offline flag or TASK_REMOTE_OFFLINE environment
variable), Task will run any available cached files even if they are expired.
An uncached remote file cannot run offline.

By default, Task will timeout requests to download remote files after 10 seconds
and look for a cached copy instead. This timeout can be configured by setting
the --timeout flag and specifying a duration. For example, --timeout 5s will
set the timeout to 5 seconds.

By default, the cache is stored in the Task temp directory (.task). You can
override the location of the cache by using the --remote-cache-dir flag, the
remote.cache-dir option in your
configuration file, or the
TASK_REMOTE_CACHE_DIR environment variable. This way, you can share the cache
between different projects.

You can force Task to ignore the cache and download the latest version by using
the --download flag.

You can use the --clear-cache flag to clear all cached remote files.

Set remote defaults {#configuration}

It is possible to configure the default behavior of remote Taskfiles using
configuration. Check out the following references for more information on how to
set up this configuration using flags, environment variables or a configuration
file:


Website Src Next Docs Styleguide (`website/src/next/docs/styleguide.md`)


Style Guide

This is the official style guide for Taskfile.yml files. It provides basic
instructions for keeping your Taskfiles clean and familiar to other users.

This guide contains general guidelines, but they do not necessarily need to be
followed strictly. Feel free to disagree and do things differently if you need
or want to. Any improvements to this guide are welcome! Please open an issue or
create a pull request to contribute.

Use the suggested ordering of the main sections

yaml
version:
includes:
# optional configurations (output, silent, method, run, etc.)
vars:
env: # followed or replaced by dotenv
tasks:

Use two spaces for indentation

This is the most common convention for YAML files, and Task follows it.

yaml
# bad
tasks:
    foo:
        cmds:
            - echo 'foo'


# good
tasks:
  foo:
    cmds:
      - echo 'foo'

Separate the main sections with empty lines

yaml
# bad
version: '3'
includes:
  docker: ./docker/Taskfile.yml
output: prefixed
vars:
  FOO: bar
env:
  BAR: baz
tasks:
  # ...


# good
version: '3'

includes:
  docker: ./docker/Taskfile.yml

output: prefixed

vars:
  FOO: bar

env:
  BAR: baz

tasks:
  # ...

Separate tasks with empty lines

yaml
# bad
version: '3'

tasks:
  foo:
    cmds:
      - echo 'foo'
  bar:
    cmds:
      - echo 'bar'
  baz:
    cmds:
      - echo 'baz'


# good
version: '3'

tasks:
  foo:
    cmds:
      - echo 'foo'

  bar:
    cmds:
      - echo 'bar'

  baz:
    cmds:
      - echo 'baz'

Use only uppercase letters for variable names

yaml
# bad
version: '3'

vars:
  binary_name: myapp

tasks:
  build:
    cmds:
      - go build -o {{.binary_name}} .


# good
version: '3'

vars:
  BINARY_NAME: myapp

tasks:
  build:
    cmds:
      - go build -o {{.BINARY_NAME}} .

Avoid using whitespace when templating variables

yaml
# bad
version: '3'

tasks:
  greet:
    cmds:
      - echo '{{ .MESSAGE }}'


# good
version: '3'

tasks:
  greet:
    cmds:
      - echo '{{.MESSAGE}}'

This convention is also commonly used in templates for the Go programming
language.

Use kebab case for task names

yaml
# bad
version: '3'

tasks:
  do_something_fancy:
    cmds:
      - echo 'Do something'


# good
version: '3'

tasks:
  do-something-fancy:
    cmds:
      - echo 'Do something'

Use a colon to separate the task namespace and name

yaml
# good
version: '3'

tasks:
  docker:build:
    cmds:
      - docker ...

  docker:run:
    cmds:
      - docker-compose ...

This is also done automatically when using included Taskfiles.

Prefer using external scripts instead of multi-line commands

yaml
# bad
version: '3'

tasks:
  build:
    cmds:
      - |
        for i in $(seq 1 10); do
          echo $i
          echo "some other complex logic"
        done'

# good
version: '3'

tasks:
  build:
    cmds:
      - ./scripts/my_complex_script.sh

Website Src Next Docs Taskfile Versions (`website/src/next/docs/taskfile-versions.md`)


title: Taskfile Versions How to use the Taskfile schema version to ensure users are using the correct versions of Task section: Project docType: project outline: deep

Taskfile Versions

The Taskfile schema slowly changes as new features are added and old ones are
removed. This document explains how to use a Taskfile's schema version to ensure
that the users of your Taskfile are using the correct versions of Task.

What the Taskfile version means

The schema version at the top of every Taskfile corresponds to a version of the
Task CLI, and by extension, the features that are provided by that version. When
creating a Taskfile, you should specify the minimum version of Task that
supports the features you require. If you try to run a Taskfile with a version
of Task that does not meet this minimum required version, it will exit with an
error. For example, given a Taskfile that starts with:

yaml
version: '3.2.1'

When executed with Task v3.2.0, it will exit with an error. Running with
version v3.2.1 or higher will work as expected.

Task accepts any SemVer compatible string including versions which
omit the minor or patch numbers. For example, 3, 3.0, and 3.0.0 all mean
the same thing and are all valid. Most Taskfiles only specify the major version
number. However it can be useful to be more specific when you intend to share a
Taskfile with others.

For example, the Taskfile below makes use of aliases:

yaml
version: '3'

tasks:
  hello:
    aliases:
      - hi
      - hey
    cmds:
      - echo "Hello, world!"

Aliases were introduced in Task v3.17.0, but the Taskfile only specifies 3
as the version. This means that a user who has v3.16.0 or lower installed will
get a potentially confusing error message when trying to run the Task as the
Taskfile specifies that any version greater or equal to v3.0.0 is fine.

Instead, we should start the file like this:

yaml
version: '3.17'

Now when someone tries to run the Taskfile with an older version of Task, they
will receive an error prompting them to upgrade their version of Task to
v3.17.0 or greater.

:::info

Note that this functionality was introduced in
v3.34.0, so older
versions are not able to give you this warning.

:::

Versions 1 & 2

Version 1 and 2 of Task are no longer officially supported and anyone still
using them is strongly encouraged to upgrade to the latest version of Task.

While version: 2 of Task did support schema versions, the behavior did not
work in quite the same way and cannot be relied upon for the purposes discussed
above.


Website Src Latest Docs Deprecations Completion Scripts (`website/src/latest/docs/deprecations/completion-scripts.md`)


title: 'Completion Scripts' section: Project docType: project outline: deep

Completion Scripts

::: danger

This deprecation breaks the following functionality:

  • Any direct references to the completion scripts in the Task git repository

:::

Direct use of the completion scripts in the completion/* directory of the
github.com/go-task/task Git repository is deprecated. Any shell
configuration that directly refers to these scripts will potentially break in
the future as the scripts may be moved or deleted entirely. Any configuration
should be updated to use the new method for generating shell
completions
instead.


Website Src Latest Docs Deprecations Template Functions (`website/src/latest/docs/deprecations/template-functions.md`)


title: 'Template Functions' Deprecation of some templating functions in Task, with guidance on their replacements. section: Project docType: project outline: deep

Template Functions

::: danger

This deprecation breaks the following functionality:

  • A small set of templating functions

:::

The following templating functions are deprecated. Any replacement functions are
listed besides the function being removed.

Deprecated function Replaced by
IsSH -
FromSlash fromSlash
ToSlash toSlash
ExeExt exeExt

Website Src Latest Docs Deprecations Template (`website/src/latest/docs/deprecations/template.md`)


This is a template for deprecation documentation

Copy this page and fill in the details as necessary

title: '--- Template ---' draft: true # Hide in production outline: deep

{Name of Deprecated Feature} (#{Issue})

::: danger

This deprecation breaks the following functionality:

  • {list any existing functionality that will be broken by this deprecation}
  • {if there are no breaking changes, remove this admonition}

:::

{Short description of the feature/behavior and why it is being deprecated}

{Short explanation of any replacement features/behaviors and how users should
migrate to it}


Website Src Latest Docs Deprecations Version 2 Schema (`website/src/latest/docs/deprecations/version-2-schema.md`)


title: 'Version 2 Schema (#1197)' section: Project docType: project outline: deep

Version 2 Schema (#1197)

::: danger

This deprecation breaks the following functionality:

  • Any Taskfiles that use the version 2 schema
  • Taskvar.yml files

:::

The Taskfile version 2 schema was introduced in March 2018 and replaced by
version 3 in August 2019. In May 2023 we published a deprecation
notice
for the version 2 schema on the basis that the vast
majority of users had already upgraded to version 3 and removing support for
version 2 would allow us to tidy up the codebase and focus on new functionality
instead.

In December 2023, the final version of Task that supports the version 2 schema
(v3.33.0) was published and all legacy code was removed from Task's
main branch. To use a more recent version of Task, you will need to ensure that
your Taskfile uses the version 3 schema instead. A list of changes between
version 2 and version 3 are available in the Task v3 Release Notes.


Website Src Latest Docs Experiments Env Precedence (`website/src/latest/docs/experiments/env-precedence.md`)


title: 'Env Precedence (#1038)' Experiment to change the precedence of environment variables in Task section: Project docType: project outline: deep

Env Precedence (#1038)

::: warning

All experimental features are subject to breaking changes and/or removal at any
time
. We strongly recommend that you do not use these features in a production
environment. They are intended for testing and feedback only.

:::

::: danger

This experiment breaks the following functionality:

  • environment variable will take precedence over OS environment variables

:::

::: info

To enable this experiment, set the environment variable:
TASK_X_ENV_PRECEDENCE=1. Check out
our guide to enabling experiments for more
information.

:::

Before this experiment, the OS variable took precedence over the task
environment variable. This experiment changes the precedence to make the task
environment variable take precedence over the OS variable.

Consider the following example:

yml
version: '3'

tasks:
  default:
    env:
      KEY: 'other'
    cmds:
      - echo "$KEY"

Running KEY=some task before this experiment, the output would be some, but
after this experiment, the output would be other.

If you still want to get the OS variable, you can use the template function env
like follow : {{env "OS_VAR"}}.

yml
version: '3'

tasks:
  default:
    env:
      KEY: 'other'
    cmds:
      - echo "$KEY"
      - echo {{env "KEY"}}

Running KEY=some task, the output would be other and some.

Like other variables/envs, you can also fall back to a given value using the
default template function:

yml
MY_ENV: '{{.MY_ENV | default "fallback"}}'

Website Src Latest Docs Experiments Gentle Force (`website/src/latest/docs/experiments/gentle-force.md`)


title: 'Gentle Force (#1200)' section: Project docType: project outline: deep

Gentle Force (#1200)

::: warning

All experimental features are subject to breaking changes and/or removal at any
time
. We strongly recommend that you do not use these features in a production
environment. They are intended for testing and feedback only.

:::

::: danger

This experiment breaks the following functionality:

  • The --force flag

:::

::: info

To enable this experiment, set the environment variable:
TASK_X_GENTLE_FORCE=1. Check out
our guide to enabling experiments for more
information.

:::

The --force flag currently forces all tasks to run regardless of the status
checks. This can be useful, but we have found that most of the time users only
expect the direct task they are calling to be forced and not all of its
dependent tasks.

This experiment changes the --force flag to only force the directly called
task. All dependent tasks will have their statuses checked as normal and will
only run if Task considers them to be out of date. A new --force-all flag will
also be added to maintain the current behavior for users that need this
functionality.

If you want to migrate, but continue to force all dependent tasks to run, you
should replace all uses of the --force flag with --force-all. Alternatively,
if you want to adopt the new behavior, you can continue to use the --force
flag as you do now!


Website Src Latest Docs Experiments Remote Taskfiles (`website/src/latest/docs/experiments/remote-taskfiles.md`)


title: Remote Taskfiles (#1317) section: Project docType: project outline: deep

Remote Taskfiles (#1317)

The Remote Taskfiles experiment has now been released :tada:. To
learn more, you can read the remote Taskfile docs or
check out our blog post.


Website Src Latest Docs Experiments Template (`website/src/latest/docs/experiments/template.md`)


title: '--- Template ---'

\{Name of Experiment\} (#\{Issue\})

::: warning

All experimental features are subject to breaking changes and/or removal at any
time
. We strongly recommend that you do not use these features in a production
environment. They are intended for testing and feedback only.

:::

::: warning

This experiment breaks the following functionality:

  • {list any existing functionality that will be broken by this experiment}
  • {if there are no breaking changes, remove this admonition}

:::

:::info

To enable this experiment, set the environment variable: TASK_X_{feature}=1.
Check out our guide to enabling experiments for more
information.

:::

{Short description of the feature}

{Short explanation of how users should migrate to the new behavior}


Website Src Latest Docs Guide Arguments (`website/src/latest/docs/guide/arguments.md`)


title: Command-line arguments Supply variables with NAME=value, forward arguments after --, and capture values with wildcard task names. section: Guide docType: guide outline: deep

Command-line arguments {#passing-arguments}

Choose how to pass input based on what needs to receive it:

Input Example Read it with
A Task variable task greet NAME=Bob {{.NAME}}
Arguments for a command task yarn -- install {{.CLI_ARGS}}
Part of a task name task start:api {{index .MATCH 0}}

Pass named values {#variable-assignments}

Pass NAME=value to supply a Task variable. A default in the root vars block
can be overridden from the command line:

yaml
version: '3'

vars:
  NAME: World

tasks:
  greet:
    cmds:
      - echo "Hello, {{.NAME}}!"
shell
task greet NAME=Bob
task greet "NAME=Jane Doe"

Quote assignments that contain spaces. These assignments work across shells,
including Windows, and are shared by all tasks in the invocation:

shell
task build test ENV=production

A value declared in a task's own vars can override the command-line value. See
variable resolution for precedence and
configurable defaults. To set values in a command's shell environment, see
Environment variables.

Forward command arguments {#forwarding-cli-arguments-to-commands}

Everything after -- is available in .CLI_ARGS, including values containing
=. Insert it into a command to forward those arguments. This example runs
yarn install:

shell
$ task yarn -- install
yaml
version: '3'

tasks:
  yarn:
    cmds:
      - yarn {{.CLI_ARGS}}

Capture task-name inputs {#wildcard-arguments}

Use * in a task name to turn a call such as task start:api into an input.
Task captures each wildcard in the .MATCH array. Give the captured values
names with vars so their meaning stays clear:

yaml
version: '3'

tasks:
  start:*:*:
    vars:
      SERVICE: '{{index .MATCH 0}}'
      REPLICAS: '{{index .MATCH 1}}'
    cmds:
      - echo "Starting {{.SERVICE}} with {{.REPLICAS}} replicas"

  start:*:
    vars:
      SERVICE: '{{index .MATCH 0}}'
    cmds:
      - echo "Starting {{.SERVICE}}"

The first captured value becomes SERVICE:

shell
$ task start:foo
Starting foo

You can use whitespace in your arguments as long as you quote the task name:

shell
$ task "start:foo bar"
Starting foo bar

If multiple matching tasks are found, the first one listed in the Taskfile will
be used. If you are using included Taskfiles, tasks in parent files will be
considered first.

shell
$ task start:foo:3
Starting foo with 3 replicas

Wildcard task names also work with aliases:

yaml
version: '3'

tasks:
  start:*:
    aliases: [run:*]
    vars:
      SERVICE: '{{index .MATCH 0}}'
    cmds:
      - echo "Running {{.SERVICE}}"

Call the task through the run:* alias:

shell
$ task run:foo
Running foo

Website Src Latest Docs Guide Conditional Execution (`website/src/latest/docs/guide/conditional-execution.md`)


title: Conditional execution Skip optional work with if, enforce requirements with preconditions, and ask for confirmation before execution with prompt. section: Guide docType: guide outline: deep

Conditional execution

Decide what a failed check should mean before choosing a setting: skip optional
work, stop with an error, or ask the user whether to continue.

What do you need? Use
Skip optional work if
Stop when a requirement is unmet preconditions
Ask before executing commands prompt
Skip work already completed Up-to-date checks

Skip optional work {#conditional-execution-with-if}

An if condition is a shell command. Exit code 0 allows execution; a non-zero
exit code skips the guarded task or command without failing the run.

Skip a whole task {#task-level-if}

Use a task-level condition for optional work. This task only runs when a docs/
directory exists:

yaml
version: '3'

tasks:
  docs:
    if: test -d docs
    cmds:
      - echo 'Building documentation'

Run task docs with and without the directory. If it is absent, Task skips the
task and its dependencies. Other tasks in the invocation can continue.

Skip one command {#command-level-if}

Put if on a command when the rest of the task should still run:

yaml
version: '3'

tasks:
  build:
    cmds:
      - cmd: echo 'Building documentation'
        if: test -d docs
      - echo 'Building the application'

task build always prints the application message. It prints the documentation
message first only if docs/ exists.

Check a Task variable {#using-templates-in-if-conditions}

Template comparisons produce true or false, which are also shell commands
with the corresponding exit codes. Put a configurable default at the root:

yaml
version: '3'

vars:
  ENABLE_FEATURE: 'false'

tasks:
  feature:
    if: '{{eq .ENABLE_FEATURE "true"}}'
    cmds:
      - echo 'Feature is enabled'

task feature ENABLE_FEATURE=true runs the command. Without that override, Task
skips it.

Filter loop iterations {#using-if-with-for-loops}

A command's condition is evaluated for each iteration, with that iteration's
values:

yaml
version: '3'

tasks:
  process-items:
    cmds:
      - for: ['a', 'b', 'c']
        cmd: echo "processing {{.ITEM}}"
        if: '[ "{{.ITEM}}" != "b" ]'

Run task process-items to print processing a and processing c. See
Loops for the other iteration forms.

Enforce a requirement {#using-programmatic-checks-to-cancel-the-execution-of-a-task-and-its-dependencies}

Use preconditions when missing a requirement should fail the task. Every check
must exit with code 0. Add msg to explain how to resolve a failure:

yaml
version: '3'

tasks:
  generate-files:
    preconditions:
      - sh: test -f .env
        msg: 'Create a .env file before generating files.'
    cmds:
      - mkdir -p directory
      - touch directory/file.txt

task generate-files fails with the message if .env is missing. Create the
file and run it again to generate directory/file.txt.

A plain shell string also works when no custom message is needed. A failed
precondition fails tasks that call or depend on this task. Dependencies of the
checked task have already run before its preconditions are evaluated; put a
check on the task whose commands need protecting.

--force bypasses preconditions as well as up-to-date checks.

Choose skip or failure {#if-vs-preconditions}

Use if when skipping is an acceptable result. Use preconditions when a
caller should receive an error instead. To require a variable or restrict its
allowed values, use Validation and prompts.

Ask for confirmation {#confirmation-prompts}

Use prompt to ask for approval before a task's commands run. For example, this
task asks before deleting a local build directory:

yaml
version: '3'

tasks:
  clean:
    prompt: Remove the local build directory?
    cmds:
      - rm -rf build/

Run task clean in a terminal and answer the confirmation. Declining stops the
task with exit code 205.

Unlike
prompts for missing input,
confirmation prompts do not require --interactive. Supplying every required
variable does not bypass them.

For several confirmations, use a list:

yaml
prompt:
  - Remove the local build directory?
  - Have you saved everything you need from it?

Task asks after dependencies have completed and before running cmds. If
approval must precede other tasks, call them from cmds in the prompted task
instead of listing them as dependencies.

Use task --yes clean (or task -y clean) to accept automatically. In CI or
another environment without a terminal, confirmation fails unless automatic
acceptance is enabled.

::: tip Related guide

To control how often a task runs when several tasks call it, use
run: once or run: when_changed. These
settings apply within one invocation. Use up-to-date checks
to skip completed work across invocations.

:::


Website Src Latest Docs Guide Defining Tasks (`website/src/latest/docs/guide/defining-tasks.md`)


title: Defining tasks Task syntax shortcuts, internal tasks, aliases, the directory a task runs in, and the help text Task shows for it. section: Guide docType: guide outline: deep searchKeywords: task-aliases: [aliases, task aliases]

Defining tasks

Define tasks under tasks. Each task has a name and a list of commands in
cmds. Add desc to explain what a task does:

yaml
version: '3'

tasks:
  greet:
    desc: Print a greeting
    cmds:
      - echo "Hello, World!"

Run task greet to execute it, or task --list to see its description. See
Running tasks for selecting a Taskfile and previewing
commands.

Choose a task name

The name under tasks is the name you pass to the CLI. Call your main task
default if it should run when someone types task without a name.

Use desc for the short explanation shown by task --list, aliases for
alternative names, and label to customize log messages. The sections below
show each independently.

Use command shortcuts {#short-task-syntax}

Use shorthand syntax for tasks that only need commands. Use the full form when
you need properties such as env, vars, desc or silent:

yaml
version: '3'

tasks:
  build: go build -v -o ./app{{exeExt}} .

  run:
    - task: build
    - ./app{{exeExt}} -h localhost -p 8080

Keep helpers internal {#internal-tasks}

Set internal: true on a helper that should only be called by other tasks. It
stays out of task --list and task --list-all, and a direct CLI call fails.
Expose a public task that supplies the helper's inputs:

yaml
version: '3'

tasks:
  build-image-1:
    cmds:
      - task: build-image
        vars:
          DOCKER_IMAGE: image-1

  build-image:
    internal: true
    cmds:
      - docker build -t {{.DOCKER_IMAGE}} .

Set the working directory {#task-directory}

Set dir when commands need to run in a subdirectory. Relative paths are
resolved from the Taskfile's execution directory:

yaml
version: '3'

tasks:
  serve:
    dir: public/www
    cmds:
      # run http server
      - caddy

Run task serve to start the server in public/www. Task creates the directory
if it does not exist. For included Taskfiles, configure the
include directory.

Add shorter names {#task-aliases}

Aliases are alternative names for tasks. They can be used to make it easier and
quicker to run tasks with long or hard-to-type names. You can use them on the
command line, when calling sub-tasks
in your Taskfile and when including tasks with aliases from
another Taskfile. They can also be used together with
namespace aliases.

yaml
version: '3'

tasks:
  generate:
    aliases: [gen]
    cmds:
      - task: gen-mocks

  generate-mocks:
    aliases: [gen-mocks]
    cmds:
      - echo "generating..."

Customize log labels {#overriding-task-name}

Use label to customize the name shown in summaries and status messages. Labels
can contain templates. They do not rename the task you call:

yaml
version: '3'

tasks:
  default:
    cmds:
      - task: print
        vars:
          MESSAGE: hello
      - task: print
        vars:
          MESSAGE: world

  print:
    label: 'print-{{.MESSAGE}}'
    cmds:
      - echo "{{.MESSAGE}}"

Describe public tasks {#help}

Running task --list (or task -l) lists all tasks with a description. The
following Taskfile:

yaml
version: '3'

tasks:
  build:
    desc: Build the Go binary.
    cmds:
      - go build -v main.go

  test:
    desc: Run all Go tests.
    cmds:
      - go test -race ./...

  js:
    cmds:
      - esbuild --bundle --minify js/index.js > public/bundle.js

  css:
    cmds:
      - esbuild --bundle --minify css/index.css > public/bundle.css

would print the following output:

shell
* build:   Build the Go binary.
* test:    Run all Go tests.

Use --list-all (or -a) to also list tasks without a description. Internal
tasks remain hidden.

Explain a task in detail {#display-summary-of-task}

Running task --summary task-name will show a summary of a task. The following
Taskfile:

yaml
version: '3'

tasks:
  release:
    deps: [build]
    summary: |
      Release your project to GitHub

      It will build your project before starting the release.
      Please make sure that you have set GITHUB_TOKEN before starting.
    cmds:
      - your-release-tool

  build:
    cmds:
      - your-build-tool

task --summary release prints:

text
task: release

Release your project to GitHub

It will build your project before starting the release.
Please make sure that you have set GITHUB_TOKEN before starting.

dependencies:
 - build

commands:
 - your-release-tool

If a summary is missing, the description will be printed. If the task does not
have a summary or a description, a warning is printed.

Showing a summary does not execute the task.


Website Src Latest Docs Guide Dependencies (`website/src/latest/docs/guide/dependencies.md`)


title: Dependencies and task calls Run checks before a build, put tasks in order, pass variables, and control repeated calls and cleanup. section: Guide docType: guide outline: deep

Dependencies and task calls

A build often needs several steps: lint the code, run tests, then compile. Use
deps when the checks can run in parallel, or task calls in cmds when each
step must finish before the next starts.

Run dependencies first {#task-dependencies}

In a Go project, this Taskfile runs lint and tests before building:

yaml
version: '3'

tasks:
  build:
    deps: [lint, test]
    cmds:
      - go build ./...

  lint:
    cmds:
      - go vet ./...

  test:
    cmds:
      - go test ./...

Run task build. Task starts lint and test concurrently and waits for both
to succeed before running go build. If either fails, the build command does
not run.

The order of entries in deps does not set their execution order. Use
task calls in cmds if tests must wait for lint to
finish.

You can also group tasks without adding commands. Add this task to the same
Taskfile to run only the checks with task check:

yaml
tasks:
  check:
    deps: [lint, test]

Run task calls in order {#calling-another-task}

To run lint, then tests, then the build, replace build in the example above
with:

yaml
tasks:
  build:
    cmds:
      - task: lint
      - task: test
      - go build ./...

Task waits for each command or task call to succeed before starting the next. If
lint fails, neither tests nor the build run.

Each called task still runs its own dependencies first. You can combine the two
forms: use deps for independent prerequisites and cmds for the steps that
need an order.

::: tip Calling tasks from another Taskfile

To call a task declared in the root Taskfile from an
included Taskfile, add a leading :, for example
task: :build.

:::

Pass variables to a task

Use the object form of a task call to provide vars. You can also set
silent: true to hide the command being executed for that call:

yaml
version: '3'

tasks:
  greet:
    cmds:
      - echo "Hello, {{.RECIPIENT}}!"

  greet:all:
    cmds:
      - task: greet
        vars: { RECIPIENT: 'World' }
      - task: greet
        vars: { RECIPIENT: 'Cruel World' }
        silent: true

task greet:all prints both greetings in order. The second call still prints
its greeting: silent mode hides the command, not its
output.

The same task, vars, and silent fields work in deps. Use
references to pass arrays and maps
without turning them into strings. To call a task for each value in a list, see
Looping over tasks.

Control parallel work

Dependencies run concurrently by default. To run tasks from the command line in
parallel too, use task --parallel lint test (or task -p lint test).

Limit concurrent tasks {#limiting-how-much-runs-at-once}

Use --concurrency (or -C) when tasks compete for resources such as database
connections or memory:

shell
task --concurrency 2 build

The default is 0, meaning no limit. A limit of 1 restricts concurrency but
does not establish an order between dependencies; use task calls in cmds when
order matters.

Cancel on failure {#fail-fast-dependencies}

By default, Task lets the other dependencies finish if one fails. In either
case, the parent task's commands do not run after a dependency failure.

Set failfast: true on a task to cancel its remaining dependency work when one
dependency fails. For the build example:

yaml
tasks:
  build:
    deps: [lint, test]
    failfast: true
    cmds:
      - go build ./...

Already-running commands receive cancellation; this does not undo work they have
completed. You can also set failfast: true in .taskrc.yml or use
task --failfast build. The CLI flag also applies to tasks started with
--parallel.

Read parallel output {#interleaved-output-is-expected}

Concurrent tasks can interleave their output, and the order may change between
runs. Set output: prefixed to label each line with its task, or
output: group to print each command's buffered output in one block when that
command finishes. A group is per command, so blocks from different tasks can
still alternate. See Output and logging for examples.

Control repeated calls {#repeated-calls}

A shared dependency can be reached through several tasks. By default, Task
attempts to run it for each call. Use run to control repeated calls within one
invocation:

Value Behavior
always (default) Attempt to run the task on every call.
once Run the task once, even if it is called again.
when_changed Run once for each distinct set of call variables.

Set run on a task, or at the root of the Taskfile to provide a default for all
tasks. A task's own setting takes precedence.

Run shared setup once {#running-a-task-only-once}

If lint and tests both need setup, mark the setup task with run: once:

yaml
version: '3'

tasks:
  check:
    deps: [lint, test]

  lint:
    deps: [setup]
    cmds:
      - echo "Linting"

  test:
    deps: [setup]
    cmds:
      - echo "Testing"

  setup:
    run: once
    cmds:
      - echo "Setting up"

task check prints Setting up once. Both lint and tests wait for that setup
to finish. Without run: once, setup runs for each task that depends on it.

Run once per input {#once-per-set-of-variables}

Use run: when_changed when a task may be called several times with the same
inputs:

yaml
version: '3'

tasks:
  default:
    cmds:
      - task: generate
        vars: { CONTENT: '1' }
      - task: generate
        vars: { CONTENT: '2' }
      - task: generate
        vars: { CONTENT: '2' }

  generate:
    run: when_changed
    cmds:
      - echo {{.CONTENT}}

This prints 1 and 2. The third call repeats the second call's variables and
is skipped.

The run settings do not remember earlier invocations of Task. To skip work
when files or external artifacts have not changed, use
up-to-date checks.

Clean up after a task {#doing-task-cleanup-with-defer}

Use defer when a task acquires a resource that needs to be released. For
example, this task starts Docker Compose services, runs integration tests, and
stops the services even if the tests fail:

yaml
version: '3'

tasks:
  integration:
    cmds:
      - docker compose up -d
      - defer: docker compose down
      - go test -tags=integration ./...

Cleanup is registered when Task reaches the defer entry. Dependencies run
before cmds, so a failed dependency prevents that registration. Keep the
resource setup, defer, and the work that uses the resource in the command
sequence, as above.

For multiple cleanup steps, cleanup tasks, and inspecting failures with
.EXIT_CODE, see
Errors and cleanup.


Website Src Latest Docs Guide Environment (`website/src/latest/docs/guide/environment.md`)


title: Environment variables Set environment variables on a single task or on every task, and load them from `.env` files. section: Guide docType: guide outline: deep

Environment variables

Use env for values a program reads from its environment. In this example, the
shell reads GREETING with $GREETING:

yaml
version: '3'

tasks:
  greet:
    env:
      GREETING: Hello, World!
    cmds:
      - echo "$GREETING"

Run task greet to print the greeting. Task uses the same shell syntax on
supported platforms, including Windows. For values used in Task templates, use
Variables.

Set values for commands {#task}

Put env on a task to configure its commands, or at the root to provide values
for every task:

yaml
version: '3'

env:
  GREETING: Hello, World!

tasks:
  greet:
    cmds:
      - echo "$GREETING"

  greet:local:
    env:
      GREETING: Hello from this task!
    cmds:
      - echo "$GREETING"

With no GREETING in the process environment, task greet uses the root value
and task greet:local uses the task's value.

By default, a variable already present in the process environment takes
precedence over Taskfile env values. If the result differs from the example,
check the environment used to launch Task. The
Env Precedence experiment changes this rule.

env values support templates and dynamic sh commands. For example, an entry
BUILD_MODE: '{{.MODE}}' exports a Task variable to a
command's environment. A vars entry alone is not exported to commands in
cmds.

Load values from files {#env-files}

Use dotenv to load values from files instead of repeating them in the
Taskfile. Create these two files in your project:

::: code-group

dotenv [.env]
GREETING=Hello from .env!
yaml [taskfile.yml]
version: '3'

dotenv: ['.env']

tasks:
  greet:
    cmds:
      - echo "$GREETING"

:::

Run task greet to use the value from .env, assuming the process environment
does not already set GREETING.

Choose file precedence

When several dotenv files define a name, the first file wins. Put local
overrides before shared defaults:

yaml
version: '3'

vars:
  ENV: development

tasks:
  greet:
    dotenv:
      - .env.local
      - .env.{{.ENV}}
      - .env
    cmds:
      - echo "$GREETING"

task greet ENV=testing selects .env.testing for the middle entry. This
example puts dotenv on the task so it can use call variables; root-level
dotenv files are loaded before those variables are available. Missing dotenv
files are skipped. Keep files containing local credentials out of version
control.

Load values for one task

Put dotenv on a task when only that task needs the file. Explicit task-level
env values take precedence over values loaded from dotenv files:

yaml
version: '3'

tasks:
  greet:
    dotenv: ['.env']
    env:
      GREETING: Hello from the task!
    cmds:
      - echo "$GREETING"

The process environment still takes precedence by default. Dotenv paths can
contain templates, as in '{{.HOME}}/.env'.

The dotenv key is not supported inside included Taskfiles. Load shared values
in the entrypoint Taskfile instead. See Including Taskfiles.


Website Src Latest Docs Guide Errors And Cleanup (`website/src/latest/docs/guide/errors-and-cleanup.md`)


title: Errors and cleanup Continue after selected command failures with ignore_error, schedule cleanup with defer, and inspect a failed command's exit code. section: Guide docType: guide outline: deep

Errors and cleanup

By default, a failed command stops its task. Use ignore_error when a failure
can be tolerated, and defer for cleanup that must run after work finishes. For
concurrent dependencies, see
fail-fast behavior.

Clean up after a task {#cleanup-with-defer}

Schedule a cleanup command with defer. Once Task reaches that entry in cmds,
it registers the command to run when the task finishes, including if a later
command fails. Deferred commands run in reverse order of registration. A defer
that Task never reaches is not registered, for example when an earlier command
or a dependency fails.

In this example, Task removes tmpdir/ after the work command finishes:

yaml
version: '3'

tasks:
  default:
    cmds:
      - mkdir -p tmpdir/
      - defer: rm -rf tmpdir/
      - echo 'Work completed' > tmpdir/result.txt

Run task, then check that tmpdir/ was removed. Replace the last command with
exit 1 to try the failure path: cleanup still runs and Task reports the
failure. The directory name here is for the example; choose a task-specific path
for real work.

Reuse a cleanup task

Use a deferred task call when several tasks share the same cleanup:

yaml
version: '3'

tasks:
  default:
    cmds:
      - mkdir -p tmpdir/
      - defer: { task: cleanup }
      - echo 'Work completed' > tmpdir/result.txt

  cleanup: rm -rf tmpdir/

Inspect a failed command

A special variable .EXIT_CODE is exposed when a command exited with a non-zero
exit code. You can check its presence to know
if the task completed successfully or not:

yaml
version: '3'

tasks:
  default:
    cmds:
      - defer:
          echo '{{if .EXIT_CODE}}Failed with
          {{.EXIT_CODE}}!{{else}}Success!{{end}}'
      - exit 1

Continue after an error {#ignoring-command-errors}

Set ignore_error: true on a command to continue after it fails:

yaml
version: '3'

tasks:
  example:
    cmds:
      - cmd: exit 1
        ignore_error: true
      - echo "Continuing after the failed command"

Without ignore_error, the echo command would not run.

You can also set ignore_error on a task to apply it to that task's commands.
The setting does not propagate to other tasks called through cmds or deps.


Website Src Latest Docs Guide Includes (`website/src/latest/docs/guide/includes.md`)


title: Including Taskfiles Reuse tasks across projects with `includes`, covering namespaces, optional and internal includes, flattening, and per-include variables. section: Guide docType: guide outline: deep searchKeywords: namespace-aliases: [aliases, namespace aliases]

Including Taskfiles {#including-other-taskfiles}

Use includes to split a project into smaller Taskfiles or reuse tasks across
projects. Give each included file a namespace, then call its tasks through that
name.

Start with a Markdown file at docs/README.md, then create these two Taskfiles:

::: code-group

yaml [taskfile.yml]
version: '3'

includes:
  docs:
    taskfile: ./docs/Taskfile.yml
    dir: ./docs
yaml [docs/taskfile.yml]
version: '3'

tasks:
  build:
    cmds:
      - mkdir -p build
      - cp README.md build/index.md

:::

Run task docs:build to copy docs/README.md to docs/build/index.md. The
docs namespace comes from the include key, not the directory name. You can
also call docs:build from another task's cmds or deps.

An include path can point to a file or a directory. With docs: ./docs, Task
looks for a supported Taskfile name in that directory. Paths are relative to the
including file, and included Taskfiles must use the same schema version.

Set the working directory {#directory-of-included-taskfile}

The dir: ./docs setting makes the included task read docs/README.md and
write into docs/build/, even when you run task docs:build from the project
root.

Without dir, included tasks use the including Taskfile's execution directory.
The same commands would look for README.md and create build/ at the project
root. A Taskfile's location alone does not set its execution directory.

Individual tasks can also specify their own
working directory.

Configure reusable tasks {#vars-of-included-taskfiles}

Use vars on an include to configure reusable tasks. This example includes the
same file twice with different image names:

::: code-group

yaml [taskfile.yml]
version: '3'

includes:
  backend:
    taskfile: ./taskfiles/Docker.yml
    vars:
      DOCKER_IMAGE: backend_image
  frontend:
    taskfile: ./taskfiles/Docker.yml
    vars:
      DOCKER_IMAGE: frontend_image
yaml [taskfiles/docker.yml]
version: '3'

vars:
  DOCKER_IMAGE: '{{.DOCKER_IMAGE | default "app"}}'

tasks:
  build:
    cmds:
      - echo 'Building {{.DOCKER_IMAGE}}'

:::

task backend:build prints Building backend_image; task frontend:build
prints Building frontend_image.

The template default in the included file is deliberate. A constant value in
that file's vars would override the value supplied by the include. See
variable precedence for the full rules.

Shorten namespace names {#namespace-aliases}

Add namespace aliases to shorten frequently used task names:

yaml
version: '3'

includes:
  documentation:
    taskfile: ./docs/Taskfile.yml
    dir: ./docs
    aliases: [docs]

Both task documentation:build and task docs:build call the same task.
Namespace aliases can be combined with
task aliases.

Allow a missing file {#optional-includes}

Use optional: true when a missing local Taskfile should not prevent the rest
of the project from running:

yaml
version: '3'

includes:
  local:
    taskfile: ./Taskfile.local.yml
    optional: true

tasks:
  greet:
    cmds:
      - echo 'Hello, World!'

task greet works even without Taskfile.local.yml. Optional includes do not
make tasks from a missing file available.

Keep included tasks internal {#internal-includes}

Use internal: true when all tasks in an included file are helpers for your
public tasks:

yaml
version: '3'

includes:
  docs:
    taskfile: ./docs/Taskfile.yml
    dir: ./docs
    internal: true

tasks:
  build:
    cmds:
      - task: docs:build

With the docs/Taskfile.yml from the first example, task build works, but
task docs:build cannot be called directly. Internal tasks are also hidden from
task listings.

Remove the namespace {#flatten-includes}

Use flatten: true to expose included tasks without a namespace:

yaml
version: '3'

includes:
  docs:
    taskfile: ./docs/Taskfile.yml
    dir: ./docs
    flatten: true

With the first example's included file, call task build instead of
task docs:build. Calls within the Taskfile can also use the flattened name.

If the root Taskfile already defines build, this inclusion fails with a name
collision. Keep the namespace or exclude the conflicting included task.

Exclude selected tasks {#exclude-tasks-from-being-included}

Use excludes to remove selected tasks from an include. Names match exactly;
append :* to exclude a namespace:

::: code-group

yaml [taskfile.yml]
version: '3'

includes:
  tools:
    taskfile: ./Tools.yml
    excludes: [debug, 'internal:*']
yaml [tools.yml]
version: '3'

tasks:
  check: echo 'Checking project'
  debug: echo 'Debug details'
  internal:setup: echo 'Internal setup'

:::

task tools:check works. task tools:debug and task tools:internal:setup
fail because those tasks were excluded. excludes also works with flatten.

Choose a file by OS {#os-specific-taskfiles}

Use the OS template function to select a file for the current platform:

yaml
version: '3'

includes:
  build: ./Taskfile_{{OS}}.yml

Provide files such as Taskfile_linux.yml, Taskfile_darwin.yml, and
Taskfile_windows.yml for the platforms you support. If only a few commands
differ,
platform restrictions may
be easier to maintain.

::: tip Related guide

Replace the local path with an HTTP or Git location to reuse tasks maintained
outside the project. Only run remote Taskfiles from sources you trust; they
execute commands on your machine. See Remote Taskfiles
for a complete example, checksum pinning, and offline use.

:::


Website Src Latest Docs Guide Loops (`website/src/latest/docs/guide/loops.md`)


title: Loops Repeat a command over a static list, a matrix, a variable, your task's sources, or other tasks. section: Guide docType: guide outline: deep

Loops

Use for to repeat a command or task call with different values. Start with a
list, then choose a different input source when the values come from a variable,
files, or several combinations.

Repeat a command {#looping-over-a-static-list}

In a project containing README.md and LICENSE, this task saves a copy of
each file in backup/. Put for beside cmd and read the current filename
through .ITEM:

yaml
version: '3'

tasks:
  backup:
    cmds:
      - mkdir -p backup
      - for: [README.md, LICENSE]
        cmd: cp '{{.ITEM}}' backup/

Run task backup to create backup/README.md and backup/LICENSE. Command
loops run in list order. Use dependency loops for
iterations that may run concurrently.

For a changing set of files, use
a source glob instead of
maintaining a fixed list.

Read values from variables {#looping-over-variables}

Use var to read an existing variable. Strings are split on whitespace:

yaml
version: '3'

tasks:
  greet:
    vars:
      NAMES: Alice Bob
    cmds:
      - for: { var: NAMES }
        cmd: echo "Hello, {{.ITEM}}!"

For another separator, set split:

yaml
version: '3'

tasks:
  greet:
    vars:
      NAMES: Alice,Bob
    cmds:
      - for: { var: NAMES, split: ',' }
        cmd: echo "Hello, {{.ITEM}}!"

Arrays preserve values containing spaces:

yaml
version: '3'

tasks:
  greet:
    vars:
      NAMES: ['Alice Smith', 'Bob Jones']
    cmds:
      - for: { var: NAMES }
        cmd: echo "Hello, {{.ITEM}}!"

Maps expose the key as .KEY and the value as .ITEM. Their iteration order is
not guaranteed:

yaml
version: '3'

tasks:
  services:
    vars:
      PORTS:
        map: { api: 8080, worker: 9090 }
    cmds:
      - for: { var: PORTS }
        cmd: echo "{{.KEY}} uses port {{.ITEM}}"

Dynamic variables work too. This example reads newline-separated names from an
existing names.txt file:

yaml
version: '3'

tasks:
  greet:
    vars:
      NAMES:
        sh: cat names.txt
    cmds:
      - for: { var: NAMES, split: "\n" }
        cmd: echo "Hello, {{.ITEM}}!"

Name the current item {#renaming-variables}

Use as to name the current item when that makes a command easier to read:

yaml
version: '3'

tasks:
  greet:
    cmds:
      - for: { var: NAMES, as: NAME }
        cmd: echo "Hello, {{.NAME}}!"
    vars:
      NAMES: [Alice, Bob]

Repeat a task call {#looping-over-tasks}

Put task beside for to reuse another task for each item:

yaml
version: '3'

tasks:
  default:
    cmds:
      - for: [api, worker]
        task: check
        vars:
          SERVICE: '{{.ITEM}}'

  check:
    cmds:
      - echo "Checking {{.SERVICE}}"

task checks api before worker. Each call finishes before the next starts.
You can also template the task name itself:

yaml
version: '3'

tasks:
  default:
    cmds:
      - for: [api, worker]
        task: check:{{.ITEM}}

  check:api: echo 'Checking API'
  check:worker: echo 'Checking worker'

Run iterations in parallel {#looping-over-dependencies}

Use a loop in deps when the calls can run concurrently:

yaml
version: '3'

tasks:
  default:
    deps:
      - for: [api, worker]
        task: check
        vars:
          SERVICE: '{{.ITEM}}'

  check:
    cmds:
      - echo "Checking {{.SERVICE}}"

The messages may appear in either order. All the input forms shown on this page
also work with dependency loops. See
Dependencies and task calls for concurrency limits and
repeated-call policies.

Try every combination {#looping-over-a-matrix}

Use matrix to visit every combination of several lists:

yaml
version: '3'

tasks:
  targets:
    cmds:
      - for:
          matrix:
            OS: [linux, darwin]
            ARCH: [amd64, arm64]
        cmd: echo "{{.ITEM.OS}}/{{.ITEM.ARCH}}"

task targets prints linux/amd64, linux/arm64, darwin/amd64, and
darwin/arm64. These are ordinary iteration values; they do not change the
platform on which Task runs.

Use ref to reuse lists defined elsewhere:

yaml
version: '3'

vars:
  SYSTEMS: [linux, darwin]
  ARCHITECTURES: [amd64, arm64]

tasks:
  targets:
    cmds:
      - for:
          matrix:
            OS: { ref: .SYSTEMS }
            ARCH: { ref: .ARCHITECTURES }
        cmd: echo "{{.ITEM.OS}}/{{.ITEM.ARCH}}"

Loop over files {#looping-over-your-task-s-sources-or-generated-files}

Use for: sources or for: generates to reuse the task's file declarations.
Globs are expanded before iteration:

::: code-group

yaml [sources]
version: '3'

tasks:
  show:
    sources: ['src/*.txt']
    cmds:
      - for: sources
        cmd: cat '{{.ITEM}}'
yaml [generates]
version: '3'

tasks:
  show:
    generates: ['output/*.txt']
    cmds:
      - for: generates
        cmd: cat '{{.ITEM}}'

:::

Run task show with matching files present. Paths are relative to the task's
working directory. Source declarations also enable
up-to-date checks; use method: none if this task should
print the files every time.

To build an absolute path, combine a directory with the item using the
joinPath template function, for example
{{joinPath .TASK_DIR .ITEM}}. See the
file-path variables for the available
directory values.


Website Src Latest Docs Guide Output (`website/src/latest/docs/guide/output.md`)


title: Output and logging Choose an output mode, hide command echoes, and display colors and failure annotations in CI. section: Guide docType: guide outline: deep

Output and logging

When several tasks run together, their output can be hard to follow. Choose an
output mode to identify the source of each line or keep each command's output
together. Use silent separately to hide the command text Task logs.

Choose an output mode {#output-syntax}

What do you need? Mode
Live output without extra formatting interleaved (default)
Live output labeled by task prefixed
Each command's output in one block group

Identify parallel output

Set output: prefixed at the root of the Taskfile:

yaml
version: '3'

output: prefixed

tasks:
  check:
    deps: [lint, test]

  lint:
    cmds:
      - echo 'Lint passed'

  test:
    cmds:
      - echo 'Tests passed'

Run task --silent check. The command output identifies each task:

text
[lint] Lint passed
[test] Tests passed

The lines may appear in either order because the tasks run concurrently. You can
override the output mode for one invocation with task --output group check (or
task -o group check).

Use a task's prefix to distinguish repeated calls with different inputs:

yaml
version: '3'

output: prefixed

tasks:
  default:
    deps:
      - task: check
        vars: { SERVICE: api }
      - task: check
        vars: { SERVICE: worker }

  check:
    prefix: 'check-{{.SERVICE}}'
    silent: true
    cmds:
      - echo 'Passed'

The output uses [check-api] and [check-worker] prefixes.

Group command output

Set output: group to buffer each command's stdout and stderr until that
command finishes. Long-running commands do not provide live feedback in this
mode. Groups are per command, so blocks from different tasks can still alternate
between commands.

To show buffered output only when a command fails:

yaml
version: '3'

silent: true
output:
  group:
    error_only: true

tasks:
  passes: echo 'Everything passed'
  fails: echo 'Failure details' && exit 1

task passes prints nothing. task fails prints Failure details and the
failure message. Hiding successful output does not change exit codes.

Hide command echoes {#silent-mode}

Use --silent (or -s) to hide the command text Task logs before execution.
The command's own output remains visible:

yaml
version: '3'

tasks:
  greet:
    cmds:
      - echo 'Hello, World!'

task greet shows the command and its output. task --silent greet prints only
Hello, World!.

To make this permanent for selected commands:

yaml
version: '3'

tasks:
  greet:
    cmds:
      - cmd: echo 'Hello, World!'
        silent: true

You can also set silent: true on a task for all its commands, or at the root
of the Taskfile for all tasks.

To suppress a command's stdout, use shell redirection instead:

yaml
version: '3'

tasks:
  quiet:
    cmds:
      - echo 'This output is discarded' > /dev/null

Stderr remains visible unless you redirect it too. Silent mode is not a
substitute for secret masking.

Make CI logs readable {#ci-integration}

Fold command logs

Use output.group.begin and end to add the markers a CI system uses for
collapsible logs. For GitHub Actions:

yaml
version: '3'

output:
  group:
    begin: '::group::{{.TASK}}'
    end: '::endgroup::'

tasks:
  default:
    silent: true
    cmds:
      - echo 'Hello, World!'

Running task produces:

text
::group::default
Hello, World!
::endgroup::

These markers follow
GitHub Actions' grouping format.
Other providers, such as
Azure Pipelines,
use different markers.

Control colors {#colored-output}

Task enables its colored output when CI=true, which most CI providers set
automatically. Use FORCE_COLOR=1 to force colors or NO_COLOR=1 to disable
them. Programs launched by Task may have their own color settings.

Surface failures {#error-annotations}

When GITHUB_ACTIONS=true, Task automatically emits an annotation when a task
fails, so the workflow can surface the error:

text
::error title=Task 'build' failed::exit status 1

No Taskfile configuration is required for these annotations.

::: tip Related guide

To continue after a selected failure, use ignore_error. See
Errors and cleanup for its
scope and examples.

:::


Website Src Latest Docs Guide Platforms (`website/src/latest/docs/guide/platforms.md`)


title: Platforms and shells Restrict tasks and commands to an operating system or architecture, and set shell options with `set` and `shopt`. section: Guide docType: guide outline: deep

Platforms and shells {#platform-specific-behaviour}

Task runs on Linux, macOS, and Windows. A portable Taskfile also needs commands
and tools that work on the machines where you run it. Use platforms to select
OS-specific steps, and keep shared work in the same task.

Select platform commands {#platform-specific-tasks-and-commands}

Set platforms on an individual command when only part of a task differs by
platform:

yaml
version: '3'

tasks:
  setup:
    cmds:
      - cmd: echo 'Preparing Windows tools'
        platforms: [windows]
      - cmd: echo 'Preparing Unix tools'
        platforms: [linux, darwin]
      - echo 'Preparing shared files'

Run task setup. A command whose platform does not match is skipped without an
error; the shared command runs on every platform.

Restrict a whole task

Put platforms on the task when none of its commands should run elsewhere:

yaml
version: '3'

tasks:
  setup:windows:
    platforms: [windows/amd64]
    cmds:
      - echo 'Preparing tools for Windows on amd64'
Restriction Matches
[windows] Windows on any architecture
[amd64] Any supported OS on amd64
[windows/amd64] Windows on amd64
[windows/amd64, darwin] Windows on amd64, or macOS on any architecture

OS and architecture names use Go's GOOS and GOARCH values. These
restrictions check the machine running Task; they do not configure a compiler's
target.

Share platform values

The OS and ARCH template functions expose the current platform. Use them to
select OS-specific Taskfiles or construct
arguments. Use exeExt for executable names that need .exe on Windows:

yaml
version: '3'

tasks:
  build:
    cmds:
      - go build -o app{{exeExt}} main.go

Understand command shells

Task runs commands through its embedded shell interpreter. It does not start
your interactive shell or load that shell's startup configuration. Use
Taskfile env and dotenv for values commands need.

Each cmds entry gets a separate shell context. A cd or export in one entry
does not carry over to the next. Set dir and env on the task instead:

yaml
version: '3'

tasks:
  inspect:
    dir: src
    env:
      BUILD_MODE: development
    cmds:
      - pwd
      - echo "$BUILD_MODE"

If several commands need to share shell state, put them in one multiline cmd
or a script. Programs such as go, npm, or docker must still be installed.
Invoke bash, pwsh, or cmd /c explicitly when a command needs that
particular shell, and restrict it to machines where it is available.

Configure shell options {#set-and-shopt}

Use set for POSIX shell options and shopt for supported Bash-style options.
For example, pipefail makes a pipeline fail when an earlier command fails, and
globstar enables recursive ** globs in shell commands:

yaml
version: '3'

set: [pipefail]
shopt: [globstar]

tasks:
  list:
    cmds:
      - echo **/*.go

These options can be set at the root, task, or command level. The shell
interpreter supports a subset of shell options; see the
shell options reference.

shopt controls shell expansion inside commands. Globs in sources and
generates use Task's file matching
and do not require globstar.


Website Src Latest Docs Guide Required Variables (`website/src/latest/docs/guide/required-variables.md`)


title: Validation and prompts Require variables to be set, restrict them to allowed values, and prompt for missing input. section: Guide docType: guide outline: deep

Validation and prompts {#required-variables-and-prompts}

Use requires to catch missing inputs before a task runs. Add enum when only
certain values are allowed, and enable interactive prompts when users should be
able to fill in missing values at the terminal.

Require an input {#ensuring-required-variables-are-set}

Declare inputs in requires.vars, then pass them on the command line:

yaml
version: '3'

tasks:
  release:
    requires:
      vars: [VERSION]
    cmds:
      - echo "Preparing release {{.VERSION}}"

Run task release VERSION=1.2.3 to print the message. Without VERSION, Task
fails and identifies the missing input. Task variables and values inherited from
the process environment can satisfy the requirement.

A variable set to an empty string counts as present. To reject an empty value,
use an enum of nonempty strings or a
precondition.

Restrict allowed values {#ensuring-required-variables-have-allowed-values}

Use name and enum to require a string from a fixed list:

yaml
version: '3'

tasks:
  deploy:
    requires:
      vars:
        - name: ENV
          enum: [dev, staging, prod]
    cmds:
      - echo "Deploying to {{.ENV}}"

task deploy ENV=staging succeeds. task deploy ENV=preview fails before
running the command. Enum validation applies to string variables, including
strings inherited from the environment.

Ask for missing input {#prompting-for-missing-variables-interactively}

Run task --interactive deploy with the example above to choose the missing
ENV from a menu. Required variables without an enum use a text input instead.

To enable this behavior by default, set it in your
Task configuration:

yaml [~/.taskrc.yml]
interactive: true

For a task with both kinds of input:

yaml
version: '3'

tasks:
  deploy:
    requires:
      vars:
        - name: ENVIRONMENT
          enum: [dev, staging, prod]
        - VERSION
    cmds:
      - echo "Deploying {{.VERSION}} to {{.ENVIRONMENT}}"

task --interactive deploy asks for an environment and a version. Values
already supplied through the CLI, environment, or Taskfile do not prompt:

shell
task deploy ENVIRONMENT=prod VERSION=1.0.0

Prompts require a terminal. In CI or another non-interactive environment,
missing variables cause an error; supply all required values explicitly.

Reuse allowed values {#using-variable-references-for-enum-values}

Define a shared list and reference it from an enum:

yaml
version: '3'

vars:
  ALLOWED_ENVS: [dev, staging, prod]

tasks:
  deploy:
    requires:
      vars:
        - name: ENV
          enum:
            ref: .ALLOWED_ENVS
    cmds:
      - echo "Deploying to {{.ENV}}"

References can also transform values. Given a config.json file containing
{"allowed_environments": ["dev", "prod"]}, this reads the list from it:

yaml
version: '3'

vars:
  CONFIG:
    sh: cat config.json

tasks:
  deploy:
    requires:
      vars:
        - name: ENV
          enum:
            ref: ( .CONFIG | fromJson ).allowed_environments
    cmds:
      - echo "Deploying to {{.ENV}}"

For newline-separated command output, convert it to a list before using it as an
enum. This example uses the entries in an existing services/ directory:

yaml
version: '3'

vars:
  AVAILABLE_SERVICES:
    sh: ls services/

tasks:
  deploy:
    requires:
      vars:
        - name: SERVICE
          enum:
            ref: .AVAILABLE_SERVICES | splitLines | compact
    cmds:
      - echo "Deploying {{.SERVICE}}"

::: tip Related guide

A prompt for input fills in a value. A
confirmation prompt asks
whether execution should proceed, even if all input values are already present.

:::


Website Src Latest Docs Guide Running Tasks (`website/src/latest/docs/guide/running-tasks.md`)


title: Running tasks How Task finds a Taskfile, and how to run one from a subdirectory, from your home directory, from standard input or as a dry run. section: Guide docType: guide outline: deep

Running tasks

Run task <name> from your project to execute a task. With no name, Task runs
the default task. Start by listing tasks, then run one:

shell
task --list
task build

--list shows tasks with descriptions. Use --list-all to include tasks
without descriptions; internal tasks
remain hidden. See Defining tasks to create these
entries.

Pass several names, such as task lint test, to run them in order. Use
--parallel for independent
tasks that can run concurrently. To pass values or command arguments, see
Command-line arguments.

Preview commands {#dry-run-mode}

Use --dry (or -n) to print the commands Task would run:

shell
task --dry build

Task still resolves templates and dynamic variables while preparing the
commands. A variable declared with sh can therefore execute its shell command
during a dry run. See Variables.

Run from a subdirectory {#running-a-taskfile-from-a-subdirectory}

If Task cannot find a Taskfile in the current directory, it searches parent
directories. Tasks run from the directory containing that Taskfile unless
their dir setting changes it.

Use {{.USER_WORKING_DIR}} when the task should act on the
directory where you invoked it. In a monorepo, this lets each service use the
same task to start its Docker Compose services:

yaml
version: '3'

tasks:
  up:
    dir: '{{.USER_WORKING_DIR}}'
    preconditions:
      - test -f docker-compose.yml
    cmds:
      - docker compose up -d

From a service directory containing docker-compose.yml, run task up. The
root Taskfile supplies the task; the service directory supplies its files.

Use a personal Taskfile {#running-a-global-taskfile}

Store a Taskfile in your home directory and use --global (or -g) to call it
from anywhere:

shell
task --global from-working-directory

Global tasks run in your home directory by default. Set dir to
{{.USER_WORKING_DIR}} when a personal utility should work
on the current project:

yaml
version: '3'

tasks:
  from-home:
    cmds:
      - pwd

  from-working-directory:
    dir: '{{.USER_WORKING_DIR}}'
    cmds:
      - pwd

Read a Taskfile from stdin {#running-a-taskfile-from-stdin}

Use --taskfile - (or -t -) to read a generated Taskfile from standard input.
For example, to read an existing file through stdin:

shell
task --taskfile - < ./Taskfile.yml

You can also pipe the output of a Taskfile generator into task --taskfile -.
With no task name, these commands run the generated file's default task.

Run a terminal app {#interactive-cli-application}

Set interactive: true on a task that launches a terminal application:

yaml
version: '3'

tasks:
  edit:
    interactive: true
    cmds:
      - vim my-file.txt

Run task edit to open the editor. Interactive applications need direct access
to the terminal; buffered or prefixed output modes
and other tasks running concurrently can interfere with their input and display.

This task setting is distinct from the CLI --interactive option, which
prompts for missing variables.

Choose a file name {#supported-file-names}

Use --taskfile to choose a specific file or --dir to run in another project:

shell
task --taskfile Taskfile.ci.yml build
task --dir ./backend build

Task looks for these names in order of priority:

  • Taskfile.yml
  • taskfile.yml
  • Taskfile.yaml
  • taskfile.yaml
  • Taskfile.dist.yml
  • taskfile.dist.yml
  • Taskfile.dist.yaml
  • taskfile.dist.yaml

Commit a .dist variant if users need to supply their own Taskfile.yml
override. The local file takes priority; add it to .gitignore if it should
remain personal.


Website Src Latest Docs Guide Secret Variables (`website/src/latest/docs/guide/secret-variables.md`)


title: Secret variables Mask sensitive variable values in Task's command logs, load secrets from external sources, and understand what masking does not protect. section: Guide docType: guide outline: deep

Secret variables

Set secret: true on a variable to replace its value with ***** in Task's own
command logs. The command still receives the original value.

yaml
version: '3'

vars:
  API_TOKEN:
    sh: echo "$MY_API_TOKEN"
    secret: true

tasks:
  request:
    cmds:
      - 'curl -H "Authorization: Bearer {{.API_TOKEN}}" https://api.example.com'
      # Logged as: curl -H "Authorization: Bearer *****" https://api.example.com

Set MY_API_TOKEN in the environment before running task request. Task's log
masks the token, while curl receives the real value. The example URL is a
placeholder; replace it with your API endpoint.

Secret variables can be declared globally or on a task. Use value instead of
sh for a literal or template value, and keep real credentials out of committed
Taskfiles.

Load from a secret store {#loading-secrets}

Use a dynamic variable to read a secret from an external source:

yaml
version: '3'

vars:
  API_TOKEN:
    sh: vault kv get -field=api_key secret/myapp
    secret: true

tasks:
  request:
    cmds:
      - 'curl -H "Authorization: Bearer {{.API_TOKEN}}" https://api.example.com'

To read an existing environment variable, replace the sh command with
echo "$MY_API_TOKEN". Keep local credential files, such as .env.local, out
of version control.

For dynamic variable evaluation and caching, see
When values are computed.

Mark derived secrets {#derived-values}

The secret flag does not propagate to variables that reference a secret. Mark
every variable carrying the sensitive value as secret:

yaml
version: '3'

vars:
  API_TOKEN:
    sh: echo "$MY_API_TOKEN"
    secret: true
  AUTH_HEADER:
    value: 'Bearer {{.API_TOKEN}}'
    secret: true

tasks:
  request:
    cmds:
      - 'curl -H "Authorization: {{.AUTH_HEADER}}" https://api.example.com'
      # Logged as: curl -H "Authorization: *****" https://api.example.com

Without secret: true on AUTH_HEADER, Task's command log would expose the
derived value.

Understand masking limits {#limits-of-masking}

Masking applies to Task's own command logs, including when those logs are
collected by a CI system. It does not redact:

  • stdout or stderr produced by commands;
  • process arguments visible to tools such as ps;
  • values stored in shell history or committed files;
  • derived variables that are not themselves marked as secret.

For example, a command that echoes a secret still prints its real value, even
though Task masks the command text it logs before execution.

The secret flag applies to vars, not env. Use your command's supported
credential mechanism to control how it receives secrets.


Website Src Latest Docs Guide Up To Date (`website/src/latest/docs/guide/up-to-date.md`)


title: Up-to-date checks Skip unchanged builds, check whether work is already done, and choose between source fingerprints and status commands. section: Guide docType: guide outline: deep

Up-to-date checks {#skipping-work-that-is-up-to-date}

A build should run when its inputs change or its output is missing. Declare
those files with sources and generates, and Task can skip the commands on
your next run. For other kinds of work, use status to check whether the result
is already available.

Skip unchanged builds {#by-fingerprinting-locally-generated-files-and-their-sources}

For a Go application in main.go, declare the source file and the executable
that the build produces:

yaml
version: '3'

tasks:
  build:
    sources: [main.go]
    generates: ['app{{exeExt}}']
    cmds:
      - go build -o app{{exeExt}} main.go

Run task build to create the executable. Run it again without changing
main.go, and Task reports that build is up to date. Edit main.go or delete
the executable, and the next call builds it again.

The default method, checksum, compares the content of source files with a
saved fingerprint. It checks that declared outputs exist; it does not compare
their contents. Editing the executable alone will not trigger a rebuild.

These checks skip the task's commands. Its dependencies
still run first and perform their own up-to-date checks.

Track the right files

sources and generates accept files and glob patterns, relative to the task's
working directory. Include every file that
affects the result, such as source code, configuration, and dependency
lockfiles.

For a Go module with several source files, replace sources and cmds in the
example above with:

yaml
sources:
  - '**/*.go'
  - go.mod
  - go.sum
  - exclude: '**/*_test.go'
cmds:
  - go build -o app{{exeExt}} .

Patterns are evaluated in order. Put each exclude after the positive glob it
narrows. Here, test files are excluded because this task builds the application;
a test task should track them.

Set use_gitignore: true at the root of the Taskfile to filter glob matches
using .gitignore rules. A task can override that setting. Keep it disabled for
tasks that need to track ignored files as inputs.

generates is optional. A task such as a test suite can use sources alone to
skip work when its inputs have not changed. generates alone does not provide a
file fingerprint; use status if you only need to check that a result exists.

Choose a check method

Method How it checks sources
checksum (default) Compares file contents with a saved fingerprint.
timestamp Compares modification times with outputs and Task's saved timestamp.
none Disables file-based skipping.

To use modification times for the build above, add method: timestamp to the
task:

yaml
tasks:
  build:
    method: timestamp
    sources: [main.go]
    generates: ['app{{exeExt}}']
    cmds:
      - go build -o app{{exeExt}} main.go

You can also set method at the root of the Taskfile to change the default for
all tasks. A task's own setting takes precedence.

With timestamp, touching a source can cause a rerun even if its content has
not changed. Without generates, Task uses its saved timestamp for the
comparison. Use method: none when sources should drive
watch mode without making the task up to date.

Check existing work {#using-programmatic-checks-to-indicate-a-task-is-up-to-date}

Use status when a command can determine whether work is needed. Every check
must exit with code 0 for Task to skip the commands. If any check fails, Task
runs the commands:

yaml
version: '3'

tasks:
  prepare:
    status:
      - test -d directory
      - test -f directory/file1.txt
      - test -f directory/file2.txt
    cmds:
      - mkdir -p directory
      - touch directory/file1.txt directory/file2.txt

Run task prepare twice: the first call creates the files, and the second skips
the commands. Delete either file, and Task runs the commands again.

Keep status checks fast and read-only: they may run each time the task is
called. They can inspect files, installed tools, services, or remote artifacts.
A failed check means "do the work", so the commands should handle partially
completed work, as mkdir -p does above.

If a failed check should stop execution with an error, use
preconditions.

Combine files and status

Use both sources and status when the result depends on local files but
cannot be checked with generates. This Docker example tags the image with a
checksum of its build inputs:

yaml
version: '3'

tasks:
  image:
    sources:
      - Dockerfile
      - src/**/*
    status:
      - docker image inspect example/app:{{.CHECKSUM}} > /dev/null 2>&1
    cmds:
      - docker build -t example/app:{{.CHECKSUM}} .

Task skips the build only when the sources are unchanged and the status
check succeeds. A changed source produces a new tag; a missing image makes the
check fail. Include any other files used by your Dockerfile in sources.

You can also combine sources, generates, and status: every configured
check must pass for Task to consider the work up to date.

Use source values

With method: checksum, {{.CHECKSUM}} contains the source
fingerprint. With method: timestamp, {{.TIMESTAMP}}
contains the latest source modification time. Both can be used in cmds and
status; they describe the sources, not the generated files.

.TIMESTAMP is a Go time.Time value. For example,
{{.TIMESTAMP.Unix}} produces a Unix timestamp, and
{{.TIMESTAMP.Format "2006-01-02"}} formats a date.

Check or force a run

To check whether tasks are up to date without running their commands:

shell
task --status build

You can pass multiple task names. The command exits with a non-zero
exit code if any task is not up to date.

To run a task even when its checks say the work is already done:

shell
task --force build

-f is the short form of --force. To rerun automatically when files change,
use Watch mode.

Track different inputs

With the checksum method, Task stores one source fingerprint per task label. If
build variables affect the result, include them in the label and use separate
output paths. For example, to build with different Go build tags:

yaml
version: '3'

tasks:
  build:
    label: 'build-{{.MODE}}'
    sources: [main.go]
    generates: ['app-{{.MODE}}{{exeExt}}']
    cmds:
      - go build -tags '{{.MODE}}' -o app-{{.MODE}}{{exeExt}} main.go

Run task build MODE=debug, then task build MODE=release. Each mode has its
own executable and saved checksum, so a later task build MODE=debug can skip
the build. A change to main.go makes both modes need a rebuild when next
called.

These saved checks apply across invocations. To limit repeated task calls within
a single invocation, use
run: once or run: when_changed.

Store fingerprints

Task stores its file fingerprints in .task/ under the project directory.
Usually, add this directory to .gitignore. For generated code committed to
version control, you may choose to commit the corresponding checksum too.

Set TASK_TEMP_DIR to store fingerprints elsewhere:

shell
export TASK_TEMP_DIR='~/.task'

Relative paths, such as tmp/task, are resolved from the project directory.
Absolute paths and paths starting with ~ use a separate subdirectory for each
project.


Website Src Latest Docs Guide Variables (`website/src/latest/docs/guide/variables.md`)


title: Variables Declare variables, compute values with shell commands, preserve types with references, and understand resolution order. section: Guide docType: guide outline: deep

Variables

Declare variables with vars, then read them in a command with a template:

yaml
version: '3'

vars:
  NAME: World

tasks:
  greet:
    cmds:
      - echo "Hello, {{.NAME}}!"

Run task greet to print Hello, World!, or task greet NAME=Bob to print
Hello, Bob!. This example puts the default at the root of the Taskfile so
callers can override it.

Use a literal for a fixed value, sh to compute text with a command, and ref
to preserve arrays and maps. The examples come first;
resolution order explains how values from different places
interact.

Pass NAME=value on the command line to supply variables to Task. See
Command-line arguments for quoting,
multiple tasks and the difference from arguments after --.

::: tip

The special variable .TASK contains the name of the task being run.

:::

Choose a value type {#variable-types}

Variables support the following types:

  • string
  • bool
  • int
  • float
  • array
  • map

::: info

Defining a map requires that you use a special map subkey (see example below).

:::

yaml
version: 3

tasks:
  foo:
    vars:
      STRING: 'Hello, World!'
      BOOL: true
      INT: 42
      FLOAT: 3.14
      ARRAY: [1, 2, 3]
      MAP:
        map: { A: 1, B: 2, C: 3 }
    cmds:
      - 'echo {{.STRING}}' # Hello, World!
      - 'echo {{.BOOL}}' # true
      - 'echo {{.INT}}' # 42
      - 'echo {{.FLOAT}}' # 3.14
      - 'echo {{.ARRAY}}' # [1 2 3]
      - 'echo {{index .ARRAY 0}}' # 1
      - 'echo {{.MAP}}' # map[A:1 B:2 C:3]
      - 'echo {{.MAP.A}}' # 1

Compute a value {#dynamic-variables}

Use sh to compute a variable from a shell command. Task captures its output
and trims the final trailing newline, if present.

yaml
version: '3'

tasks:
  build:
    cmds:
      - go build -ldflags="-X main.Version={{.GIT_COMMIT}}" main.go
    vars:
      GIT_COMMIT:
        sh: git log -n 1 --format=%h

The result is text. To convert JSON or YAML output into structured data, use
parsing functions with ref.

Pass lists and maps {#referencing-other-variables}

Use ref to pass an array or map to another task without converting it to text.
In this example, show receives the original list:

yaml
version: '3'

tasks:
  default:
    vars:
      SERVICES: [api, worker]
    cmds:
      - task: show
        vars:
          SERVICES:
            ref: .SERVICES

  show:
    cmds:
      - echo '{{index .SERVICES 0}}'

Run task to print api. Replacing the reference with
SERVICES: '{{.SERVICES}}' would pass the string
[api worker]. Indexing that string returns a byte, not a list element.

References also work in dependency calls and variable definitions:

yaml
version: '3'

tasks:
  default:
    vars:
      SERVICES: [api, worker]
      SELECTED:
        ref: .SERVICES
    deps:
      - task: show
        vars:
          SERVICE:
            ref: index .SELECTED 0

  show:
    cmds:
      - echo '{{.SERVICE}}'

Use subkeys, indexes, and functions inside ref, without the template braces.
See the Templating reference for available functions.

Parse JSON or YAML {#parsing-json-yaml-into-map-variables}

If you have a raw JSON or YAML string that you want to process in Task, you can
use a combination of the ref keyword and the fromJson or fromYaml
templating functions to parse the string into a map variable. For example:

yaml
version: '3'

tasks:
  task-with-map:
    vars:
      JSON: '{"a": 1, "b": 2, "c": 3}'
      FOO:
        ref: 'fromJson .JSON'
    cmds:
      - echo {{.FOO}}
txt
map[a:1 b:2 c:3]

Understand precedence {#resolution-order}

Applied first to last. Later wins.

# Source Set by
1 The process environment the shell that ran task
2 Special variables Task itself (TASK, ROOT_DIR, CLI_ARGS, …)
3 Taskfile env: the env: block; dotenv: files fill only names env: does not already set
4 Global vars: the vars: block of every Taskfile in the run
5 Include vars: the vars: given on an includes: entry
6 The included Taskfile's own vars: the vars: block of the file being included
7 Call variables task foo BAR=1, or vars: on a task: command
8 The task's vars: the vars: block of the task being run

Apply precedence rules {#what-this-means-in-practice}

Let callers override {#a-task-s-own-variables-cannot-be-overridden-from-the-command-line}

Step 8 comes after step 7, so a variable declared on the task always wins:

yaml
version: '3'

tasks:
  greet:
    vars:
      NAME: from-task
    cmds:
      - echo "{{.NAME}}"
shell
$ task greet NAME=from-cli
from-task

To let a caller supply a value, give the default somewhere earlier, in global
vars:, or use a template default:

yaml
version: '3'

vars:
  NAME: from-global

tasks:
  greet:
    cmds:
      - echo "{{.NAME}}"
shell
$ task greet NAME=from-cli
from-cli

To keep the default on the task itself, read the caller's value in a template:

yaml
vars:
  NAME: '{{.NAME | default "World"}}'

Configure include defaults {#let-callers-configure-an-included-taskfile}

Step 6 comes after step 5, so a constant declared in the included Taskfile's
vars: overrides the value supplied by includes.vars.

To keep a configurable default in the included Taskfile, use a template that
reads the previously resolved value:

yaml
version: '3'

vars:
  DOCKER_IMAGE: '{{.DOCKER_IMAGE | default "app"}}'

tasks:
  build:
    cmds:
      - echo "building {{.DOCKER_IMAGE}}"

An inclusion that supplies DOCKER_IMAGE: backend_image now prints
building backend_image; without a supplied value, it prints building app.
The default stays in one place and applies to every task in the included file.

Avoid global collisions {#global-variable-names-are-shared-across-every-taskfile-in-the-run}

Global vars: are merged into one set before any task runs, so a name declared
in both the entrypoint and an included Taskfile resolves to the included one,
including for tasks defined in the entrypoint.

Give globals that belong to an included Taskfile a distinctive name, or move
them onto the tasks that use them, where step 8 keeps them local.

Choose vars or env {#env-and-vars-are-not-the-same-thing}

A vars: entry is not exported to commands in cmds, whichever level it was
declared at. Read it with a template instead of $FOO. Dynamic variables
(sh:) have a different environment, described below.

env: is exported to the environment of the commands Task runs, so $FOO
works. Whether a template also sees it depends on where it was declared:

Declared at {{.FOO}} $FOO
the root of the Taskfile yes, it is step 3 above yes
on a task keeps the value from other sources, if any yes

A task's env: is assembled after the variable set has been resolved, so it
never takes part in the order on this page. If global env: sets FOO: root
and a task's env: sets FOO: task, the template {{.FOO}}
renders root, while $FOO in a command reads task (assuming the process
environment does not already set FOO). The template only renders empty if no
other source defines the variable. Read a task-level environment value with
$FOO, or declare it in vars: if a template needs it.

Understand evaluation {#when-values-are-computed}

Dynamic variables (sh:) are executed while the set is being built, in the
order above. Within a block, variables are resolved in declaration order, so a
sh: command can also reference variables declared earlier in the same block:

yaml
vars:
  INPUT: hello
  OUTPUT:
    sh: echo {{.INPUT}}

Here OUTPUT resolves to hello. Variables from later declarations or later
steps are not available yet.

The shell used by sh: also receives previously resolved scalar variables, so
sh: echo $INPUT works in this example too. The process environment takes
precedence for shell lookups unless the
Env Precedence experiment is enabled.
Commands in cmds only receive the process environment and Task's env: and
dotenv: values; they do not inherit vars: this way.

Results are cached for the run, keyed on the command string, so the same sh:
command appearing twice runs once.

To pass a variable without flattening it to text, an array or a map, use ref:
instead of {{ }}. A template renders a string; ref:
preserves the type.

::: tip Related guide

Mark sensitive values with secret: true to mask them in Task's own command
logs. See Secret variables for examples, loading values
from external sources and the limits of masking.

:::


Website Src Latest Docs Guide Watch (`website/src/latest/docs/guide/watch.md`)


title: Watch mode section: Guide docType: guide outline: deep

Watch mode

Use --watch (or -w) to keep a task running and rerun it when its source
files change. For a Go project:

yaml
version: '3'

tasks:
  build:
    sources:
      - '**/*.go'
      - go.mod
      - go.sum
    cmds:
      - go build ./...

Run task --watch build, edit a Go file, and save it to trigger another build.
Press Ctrl+C to stop watching.

Watch mode detects changes; up-to-date checks decide whether
the task's commands need to run. Both use the same sources.

Enable watching by default

Set watch: true on a task if its normal CLI use should start a watcher:

yaml
version: '3'

tasks:
  build:
    watch: true
    sources: ['**/*.go']
    cmds:
      - go build ./...

Now task build starts watch mode. The watch setting applies when the task is
called from the CLI; calls from another task through cmds or deps do not
start a watcher.

Combine rapid changes

The default watch interval is 100 milliseconds. Increase it if saving several
files produces duplicate events:

shell
task --watch --interval=500ms build

You can also set interval: '500ms' at the root of the Taskfile. The interval
groups events close together so that Task reruns the task once for the batch.

Watch long-running apps

Builds and checks finish after each run. Servers keep running and need to stop
before a replacement can take over their port.

::: warning

There is a known issue where watch
mode may leave child processes running. Prefer building and running the
executable directly over go run, which starts another process.

:::

For applications that need dedicated live-reload behavior, consider tools such
as Air. Report Task-specific problems with
a small reproducer in the
issue tracker.


Website Src Latest Docs Reference Cli (`website/src/latest/docs/reference/cli.md`)


Command Line Interface Reference

Task has multiple ways of being configured. These methods are parsed, in
sequence, in the following order with the highest priority last:

In this document, we will look at the last of the three options, command-line
flags. All CLI commands override their configuration file and environment
variable equivalents.

Format

Task commands have the following syntax:

bash
task [options] [tasks...] [-- CLI_ARGS...]

::: tip

If -- is given, all remaining arguments will be assigned to a special
CLI_ARGS variable.

:::

Commands

`task [tasks...]`

Run one or more tasks defined in your Taskfile.

bash
task build
task test lint
task deploy --force

`task --list`

List all available tasks with their descriptions.

bash
task --list
task -l

`task --list-all`

List all tasks, including those without descriptions.

bash
task --list-all
task -a

`task --init`

Create a new Taskfile.yml in the current directory.

bash
task --init
task -i

::: tip

Combine --list or --list-all with --silent (-ls or -as for shortants)
to list only the task names in each line. Useful for scripting with grep or
similar.

:::

Options

General

`-h, --help`

Show help information.

bash
task --help

`--version`

Show Task version.

bash
task --version

`-v, --verbose`

Enable verbose mode for detailed output.

bash
task build --verbose

`-s, --silent`

Disable command echoing.

bash
task deploy --silent

`--disable-fuzzy`

Disable fuzzy matching for task names. When enabled, Task will not suggest
similar task names when you mistype a task name.

bash
task buidl --disable-fuzzy
# Output: Task "buidl" does not exist
# (without "Did you mean 'build'?" suggestion)

Execution Control

`-F, --failfast`

Stop executing dependencies as soon as one of them fails.

bash
task build --failfast

`-f, --force`

Force execution even when the task is up-to-date.

bash
task build --force

`-n, --dry`

Compile and print tasks without executing them.

bash
task deploy --dry

`-p, --parallel`

Execute multiple tasks in parallel.

bash
task test lint --parallel

`-C, --concurrency `

Limit the number of concurrent tasks. Zero means unlimited.

bash
task test --concurrency 4

`-x, --exit-code`

Pass through the exit code of failed commands.

bash
task test --exit-code

File and Directory

`-d, --dir `

Set the directory where Task will run and look for Taskfiles.

bash
task build --dir ./backend

`-t, --taskfile `

Specify a custom Taskfile path.

bash
task build --taskfile ./custom/Taskfile.yml

`-g, --global`

Run the global Taskfile from $HOME/Taskfile.{yml,yaml}.

bash
task backup --global

`--temp-dir `

Set the directory used to store Task temporary files, such as checksums.
Relative paths are relative to the root Taskfile.

bash
task build --temp-dir .task-cache

Output Control

`-o, --output `

Set output style. Available modes: interleaved, group, prefixed.

bash
task test --output group

`--output-group-begin