# Technical Documentation: go-task/task

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/go-task/task)

### Overview (`README.md`)

<div align="center">
  <a href="https://taskfile.dev">
    <img src="website/src/public/img/logo.svg" width="200px" height="200px" />
  </a>

  <h1>Task: The Modern Task Runner</h1>

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

  <p>
    <a href="https://taskfile.dev/docs/installation">Installation</a> &bullet; <a href="https://taskfile.dev/docs/getting-started">Getting Started</a> &bullet; <a href="https://taskfile.dev/docs/guide">Docs</a> &bullet; <a href="https://twitter.com/taskfiledev">Twitter</a> &bullet; <a href="https://bsky.app/profile/taskfile.dev">Bluesky</a> &bullet; <a href="https://fosstodon.org/@task">Mastodon</a> &bullet; <a href="https://discord.gg/6TY36E39UK">Discord</a>
  </p>

  <h1>Gold Sponsors</h1>

  <table>
    <tr>
      <td align="center" valign="middle">
        <a target="_blank" href="https://devowl.io">
          <img src="website/src/public/img/devowl.io.svg" height="100px" width="200px" title="devowl.io" />
        </a>
      </td>
      <td align="center" valign="middle">
        <a target="_blank" href="https://goodx.international/">
          <img src="website/src/public/img/goodx.svg" height="80px" width="200px" title="GoodX" />
        </a>
      </td>
      <td align="center" valign="middle">
        <a target="_blank" href="https://magic.dev/">
          <img src="website/src/public/img/magic.png" height="100px" width="200px" title="Magic" />
        </a>
      </td>
    </tr>
  </table>

  <h2>Community Sponsors</h2>

  <table>
    <tr>
      <td align="center" valign="middle">
        <a target="_blank" href="https://cloudsmith.com/">
          <img src="website/src/public/img/cloudsmith.svg" height="100px" width="200px" title="Cloudsmith" />
        </a>
      </td>
      <td align="center" valign="middle">
        <a target="_blank" href="https://jb.gg/OpenSource">
          <picture>
            <source media="(prefers-color-scheme: dark)" srcset="website/src/public/img/jetbrains-dark.svg" />
            <img src="website/src/public/img/jetbrains.svg" height="100px" width="200px" title="JetBrains" alt="JetBrains logo" />
          </picture>
        </a>
      </td>
    </tr>
    <tr>
      <td align="center">
        Package hosting provided by <a target="_blank" href="https://cloudsmith.com/">Cloudsmith</a>.
      </td>
      <td align="center">
        Tooling provided by <a target="_blank" href="https://jb.gg/OpenSource">JetBrains</a>.
      </td>
    </tr>
  </table>
</div>

---

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

---
title: Quick Start
description: Guide for getting started with Task
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](./installation.md).

## 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](https://yaml.org/).
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](./guide/running-tasks.md#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](https://github.com/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](./guide/index.md) next. Alternatively, you can check out our
reference docs for the [Taskfile schema](./reference/schema.md) and
[CLI](./reference/cli.md).

---

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

---
title: Documentation
description:
  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`.

<div class="docs-start">
<div class="docs-card">

## Start with Task {#new-to-task}

Install Task and run your first Taskfile.

- [Installation](./installation.md)
- [Quick Start](./getting-started.md)

</div>
<div class="docs-card">

## Use Task {#using-task}

Find a guide for your everyday workflows.

- [Browse the guide](./guide/index.md)
- [Variables](./guide/variables.md)
- [Dependencies and task calls](./guide/dependencies.md)

</div>
<div class="docs-card">

## Reference {#looking-something-up}

Look up syntax, flags and functions.

- [Taskfile Schema](./reference/schema.md)
- [CLI](./reference/cli.md)
- [Templating](./reference/templating.md)

</div>
</div>

For settings outside the Taskfile, see [Configuration](./reference/config.md)
and [Environment](./reference/environment.md).

## Keeping up

- [Changelog](./changelog.md): what shipped, and when.
- [Experiments](./experiments/index.md) and
  [Deprecations](./deprecations/index.md): what is coming, and what is going
  away.
- [FAQ](./faq.md): the questions that come up most often.
- [Community](./community.md): integrations and tools built by other people.

## Using an AI coding assistant

[Task documentation for coding agents](../agents.md) 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](/llms.txt).

---

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

---
title: Quick Start
description: Guide for getting started with Task
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](./installation.md).

## 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](https://yaml.org/).
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](./guide/running-tasks.md#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](https://github.com/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](./guide/index.md) next. Alternatively, you can check out our
reference docs for the [Taskfile schema](./reference/schema.md) and
[CLI](./reference/cli.md).

---

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

---
title: Documentation
description:
  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`.

<div class="docs-start">
<div class="docs-card">

## Start with Task {#new-to-task}

Install Task and run your first Taskfile.

- [Installation](./installation.md)
- [Quick Start](./getting-started.md)

</div>
<div class="docs-card">

## Use Task {#using-task}

Find a guide for your everyday workflows.

- [Browse the guide](./guide/index.md)
- [Variables](./guide/variables.md)
- [Dependencies and task calls](./guide/dependencies.md)

</div>
<div class="docs-card">

## Reference {#looking-something-up}

Look up syntax, flags and functions.

- [Taskfile Schema](./reference/schema.md)
- [CLI](./reference/cli.md)
- [Templating](./reference/templating.md)

</div>
</div>

For settings outside the Taskfile, see [Configuration](./reference/config.md)
and [Environment](./reference/environment.md).

## Keeping up

- [Changelog](./changelog.md): what shipped, and when.
- [Experiments](./experiments/index.md) and
  [Deprecations](./deprecations/index.md): what is coming, and what is going
  away.
- [FAQ](./faq.md): the questions that come up most often.
- [Community](./community.md): integrations and tools built by other people.

## Using an AI coding assistant

[Task documentation for coding agents](../agents.md) 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](/llms.txt).

---

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

---
title: Deprecations
description:
  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
description: Guide to Task’s experimental features and how to use them
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](#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
description:
  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](../getting-started.md). For accepted keys,
flags and functions, use the [Taskfile Schema](../reference/schema.md),
[CLI](../reference/cli.md) and [Templating](../reference/templating.md)
references.

<GuideRedirect />

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

- [Defining tasks](./defining-tasks.md): command lists, descriptions, aliases
  and display labels.
- [Running tasks](./running-tasks.md): choosing a Taskfile, running from other
  directories, previewing commands and using interactive applications.

## Variables and arguments {#variables-and-environment}

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

## Task execution {#controlling-what-runs}

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

## Environment and output {#execution-environment}

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

## Including Taskfiles {#composing-taskfiles}

- [Including Taskfiles](./includes.md): sharing tasks with namespaces,
  configuring includes and passing variables to them.
- [Remote Taskfiles](../remote-taskfiles.md): 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
description:
  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][pvr] or send an email to
[task@taskfile.dev](mailto:task@taskfile.dev). 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][irp] and [Threat Model][tm].

[pvr]: https://github.com/go-task/task/security/advisories/new
[irp]: ./incident-response-plan.md
[tm]: ./threat-model.md

---

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

---
title: Deprecations
description:
  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
description: Guide to Task’s experimental features and how to use them
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](#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
description:
  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](../getting-started.md). For accepted keys,
flags and functions, use the [Taskfile Schema](../reference/schema.md),
[CLI](../reference/cli.md) and [Templating](../reference/templating.md)
references.

<GuideRedirect />

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

- [Defining tasks](./defining-tasks.md): command lists, descriptions, aliases
  and display labels.
- [Running tasks](./running-tasks.md): choosing a Taskfile, running from other
  directories, previewing commands and using interactive applications.

## Variables and arguments {#variables-and-environment}

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

## Task execution {#controlling-what-runs}

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

## Environment and output {#execution-environment}

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

## Including Taskfiles {#composing-taskfiles}

- [Including Taskfiles](./includes.md): sharing tasks with namespaces,
  configuring includes and passing variables to them.
- [Remote Taskfiles](../remote-taskfiles.md): 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
description:
  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][pvr] or send an email to
[task@taskfile.dev](mailto:task@taskfile.dev). 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][irp] and [Threat Model][tm].

[pvr]: https://github.com/go-task/task/security/advisories/new
[irp]: ./incident-response-plan.md
[tm]: ./threat-model.md

---

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

---
title: Changelog
description:
  Release history for Task, including new features, improvements, fixes, and
  breaking changes
section: Project
docType: project
outline: deep
editLink: false
---

# 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](https://taskfile.dev/docs/remote-taskfiles) 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](https://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](https://github.com/u-root/u-root/pull/3464),
  [mvdan/sh#1199](https://github.com/mvdan/sh/pull/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](https://taskfile.dev/blog/windows-core-utils).
  (#197, #2360 by @andreynering).
- :sparkles: Built and deployed a [brand new website](https://taskfile.dev)
  using [VitePress](https://vitepress.dev) (#2359, #2369, #2371, #2375, #2378 by
  @vmaerten, @andreynering, @pd93).
- Began releasing
  [nightly builds](https://github.com/go-task/task/releases/tag/nightly). 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](https://taskfile.dev/docs/reference/config) 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](https://github.com/go-task/setup-task). 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](https://github.com/go-task/setup-task/releases/tag/v1.0.0) (by
@pd93, @shrink, @trim21 and all the previous contributors to
[arduino/setup-task](https://github.com/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](https://taskfile.dev/next/experiments/remote-taskfiles/#manual-checksum-pinning)
  by specifying a checksum. This works with both local and remote Taskfiles
  (#2222, #2223 by @pd93).
- When using the
  [Remote Taskfiles experiment](https://github.com/go-task/task/issues/1317),
  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](https://github.com/radovskyb/watcher) to
  [fsnotify](https://github.com/fsnotify/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](https://github.com/go-task/task/issues/1585)
  was made generally available so you can now
  [define map variables in your Taskfiles!](https://taskfile.dev/usage/#variables)
  (#1585, #1547, #2081 by @pd93).
- Wildcards can now
  [match multiple tasks](https://taskfile.dev/usage/#wildcard-arguments) (#2072,
  #2121 by @pd93).
- Added the ability to
  [loop over the files specified by the `generates` keyword](https://taskfile.dev/usage/#looping-over-your-tasks-sources-or-generated-files).
  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](https://github.com/go-task/task/issues/1317)
  (#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

- The [`Executor`](https://pkg.go.dev/github.com/go-task/task/v3#Executor) now
  uses the functional options pattern (#2085, #2147, #2148 by @pd93).
- The functional options for the
  [`taskfile.Reader`](https://pkg.go.dev/github.com/go-task/task/v3/taskfile#Reader)
  and
  [`taskfile.Snippet`](https://pkg.go.dev/github.com/go-task/task/v3/taskfile#Snippet)
  types no longer have the `Reader`/`Snippet` respective prefixes (#2148 by
  @pd93).
- [`taskfile.Reader`](https://pkg.go.dev/github.com/go-task/task/v3/taskfile#Reader)
  no longer accepts a
  [`taskfile.Node`](https://pkg.go.dev/github.com/go-task/task/v3/taskfile#Node).
  Instead nodes are passed directly into the
  [`Reader.Read`](https://pkg.go.dev/github.com/go-task/task/v3/taskfile#Reader.Read)
  method (#2169 by @pd93).
- [`Reader.Read`](https://pkg.go.dev/github.com/go-task/task/v3/taskfile#Reader.Read)
  also now accepts a [`context.Context`](https://pkg.go.dev/context#Context)
  (#2176 by @pd93).

## 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](https://taskfile.dev/getting-started) (#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](https://taskfile.dev/reference/package).
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`](https://pkg.go.dev/github.com/go-task/task/v3#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`](https://pkg.go.dev/github.com/go-task/task/v3/errors#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`](https://pkg.go.dev/github.com/go-task/task/v3/taskfile#Snippet)
  and related code moved from the `errors` package to the `taskfile` package
  (#2068 by @pd93).
- Renamed `TaskMissingRequiredVars` to
  [`TaskMissingRequiredVarsError`](https://pkg.go.dev/github.com/go-task/task/v3/errors#TaskMissingRequiredVarsError)
  (#2052 by @vmaerten).
- Renamed `TaskNotAllowedVars` to
  [`TaskNotAllowedVarsError`](https://pkg.go.dev/github.com/go-task/task/v3/errors#TaskNotAllowedVarsError)
  (#2052 by @vmaerten).
- The
  [`taskfile.Reader`](https://pkg.go.dev/github.com/go-task/task/v3/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).
  - Users are now expected to pass a custom debug/prompt functions into
    [`taskfile.Reader`](https://pkg.go.dev/github.com/go-task/task/v3/taskfile#Reader)
    if they want this functionality by using the new
    [`WithDebugFunc`](https://pkg.go.dev/github.com/go-task/task/v3/taskfile#WithDebugFunc)
    and
    [`WithPromptFunc`](https://pkg.go.dev/github.com/go-task/task/v3/taskfile#WithPromptFunc)
    functional options.
- 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](https://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](https://taskfile.dev/installation) 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](https://taskfile.dev/experiments/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](https://taskfile.dev/experiments/env-precedence)
  (#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](https://taskfile.dev/installation/#setup-completions) 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](https://taskfile.dev/deprecations/completion-scripts/).
- Added the ability to
  [loop over a matrix of values](https://taskfile.dev/usage/#looping-over-a-matrix)
  (#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](https://taskfile.dev/usage/#referencing-other-variables) 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](https://taskfile.dev/reference/templating/) to the
  documentation (#1614, #1653 by @pd93).
- If using the
  [Map Variables experiment (1)](https://taskfile.dev/experiments/map-variables/?proposal=1),
  references are available by
  [prefixing a string with a `#`](https://taskfile.dev/experiments/map-variables/?proposal=1#references)
  (#1654 by @pd93).
- If using the
  [Map Variables experiment (2)](https://taskfile.dev/experiments/map-variables/?proposal=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](https://taskfile.dev/blog/any-variables), but
  [_without support for maps_](https://github.com/go-task/task/issues/1415#issuecomment-2044756925)
  (#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](https://taskfile.dev/experiments/map-variables/) 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](https://taskfile.dev/usage/#looping-over-dependencies)
  (#1299, #1541 by @pd93).
- When using the
  "[Remote Taskfiles](https://taskfile.dev/experiments/remote-taskfiles/)"
  experiment, you are now able to use
  [remote Taskfiles as your entrypoint](https://taskfile.dev/experiments/remote-taskfiles/#root-remote-taskfiles).
  - `includes` in remote Taskfiles will now also resolve correctly (#1347 by
    @pd93).
- When using the
  "[Any Variables](https://taskfile.dev/experiments/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](https://taskfile.dev/usage/#wildcard-arguments)
  (#836, #1489 by @pd93).
- Added the ability to
  [run Taskfiles via stdin](https://taskfile.dev/usage/#reading-a-taskfile-from-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

- Fixed prompt regression on
  [Remote Taskfiles experiment](https://taskfile.dev/experiments/remote-taskfiles/)
  (#1486, #1487 by @pd93).

## v3.34.0 - 2024-01-25

- Removed support for `version: 2` schemas. See the
  [deprecation notice on our website](https://taskfile.dev/deprecations/version-2-schema)
  (#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](https://taskfile.dev/experiments/any-variables/?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](https://taskfile.dev/experiments/any-variables)
  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](https://taskfile.dev/experiments/any-variables)
  (#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](https://taskfile.dev/experiments/remote-taskfiles)
  now prefers remote files over cached ones by default (#1317, #1345 by @pd93).
- Added `--timeout` flag to the
  [Remote Taskfiles experiment](https://taskfile.dev/experiments/remote-taskfiles)
  (#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](https://taskfile.dev/experiments/remote-taskfiles)
  (#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](https://taskfile.dev/api/#exit-codes) (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](https://taskfile.dev/experiments/remote-taskfiles)
  as a draft (#1152, #1317 by @pd93).
- Improve performance of content checksumming on `sources:` by replacing md5
  with [XXH3](https://xxhash.com/) 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](https://taskfile.dev/usage/#looping-over-values)
  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](https://taskfile.dev/installation/#npm). (#1190, by
  @sounisi5011).
- Added the
  [gentle force experiment](https://taskfile.dev/experiments/gentle-force) 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](https://taskfile.dev/experiments) 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](https://taskfile.dev/usage/#warning-prompts)).
- 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](https://github.com/mvdan/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](https://taskfile.dev/api/#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](https://marketplace.visualstudio.com/items?itemName=task.vscode-task)
contributed by @pd93! :tada: The extension is maintained in a
[new repository](https://github.com/go-task/vscode-task) 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](https://github.com/go-task/vscode-task/discussions),
[issue](https://github.com/go-task/vscode-task/issues) or on our
[Discord](https://discord.gg/6TY36E39UK)!

> **NOTE:** The extension _requires_ v3.23.0 to be installed in order to work.

- The website was integrated with
  [Crowdin](https://crowdin.com/project/taskfile) to allow the community to
  contribute with translations! [Chinese](https://taskfile.dev/zh-Hans/) 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](https://taskfile.dev/usage/#running-a-global-taskfile), #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`](https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html)
  and
  [`shopt`](https://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html)
  builtins (#908, #929 by @pd93,
  [Documentation](http://taskfile.dev/usage/#set-and-shopt)).
- 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](https://pnpm.io/) as well
  ([go-task/go-npm#2](https://github.com/go-task/go-npm/issues/2),
  [go-task/go-npm#3](https://github.com/go-task/go-npm/pull/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](https://task-zh.readthedocs.io/zh_CN/latest/) by
  [@DeronW](https://github.com/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](https://www.npmjs.com/package/@go-task/cli)).
- 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](https://taskfile.dev/api/#special-variables)).
- 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](https://github.com/mvdan/sh/issues/884),
  [mvdan/sh#893](https://github.com/mvdan/sh/pull/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](https://taskfile.dev/#/usage?id=vars-of-included-taskfiles)
  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](http://taskfile.dev/#/usage?id=output-syntax)
  for more information (#647, #651).
- Add `Taskfile.dist.yml` and `Taskfile.dist.yaml` to the supported file name
  list.
  [Check out the documentation](https://taskfile.dev/#/usage?id=supported-file-names)
  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](https://taskfile.dev/#/usage?id=doing-task-cleanup-with-defer),
  #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

- Upgrade [mvdan/sh](https://github.com/mvdan/sh) which contains a fix a for a
  important regression on Windows (#619,
  [mvdan/sh#768](https://github.com/mvdan/sh/issues/768),
  [mvdan/sh#769](https://github.com/mvdan/sh/pull/769)).

## 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](https://github.com/mvdan/sh) which contains two relevant
  fixes:
  - Fix quote of empty strings in `shellQuote` (#609,
    [mvdan/sh#763](https://github.com/mvdan/sh/issues/763)).
  - Fix issue of wrong environment variable being picked when there's another
    very similar one (#586,
    [mvdan/sh#745](https://github.com/mvdan/sh/pull/745)).
- Install shell completions automatically when installing via Homebrew (#264,
  #592,
  [go-task/homebrew-tap#2](https://github.com/go-task/homebrew-tap/pull/2)).

## v3.9.0 - 2021-10-02

- A new `shellQuote` function was added to the template system
  (`{{shellQuote "a string"}}`) to ensure a string is safe for use in shell
  ([mvdan/sh#727](https://github.com/mvdan/sh/pull/727),
  [mvdan/sh#737](https://github.com/mvdan/sh/pull/737),
  [Documentation](https://pkg.go.dev/mvdan.cc/sh/v3@v3.4.0/syntax#Quote))
- In this version [mvdan.cc/sh](https://github.com/mvdan/sh) was upgraded with
  some small fixes and features
  - The `read -p` flag is now supported (#314,
    [mvdan/sh#551](https://github.com/mvdan/sh/issues/551),
    [mvdan/sh#772](https://github.com/mvdan/sh/pull/722))
  - The `pwd -P` and `pwd -L` flags are now supported (#553,
    [mvdan/sh#724](https://github.com/mvdan/sh/issues/724),
    [mvdan/sh#728](https://github.com/mvdan/sh/pull/728))
  - The `$GID` environment variable is now correctly being set (#561,
    [mvdan/sh#723](https://github.com/mvdan/sh/pull/723))

## 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](https://github.com/go-task/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](https://github.com/fatih/color/pull/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](https://json.schemastore.org/taskfile.json)
  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](https://github.com/go-task/slim-sprig) package was updated
  with the upstream [sprig](https://github.com/Masterminds/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](https://github.com/go-task/slim-sprig) instead of
  [sprig](https://github.com/Masterminds/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](https://github.com/go-task/homebrew-tap/pull/1)).

## v2.5.2 - 2019-05-11

- Reverted YAML upgrade due issues with CRLF on Windows (#201,
  [go-yaml/yaml#450](https://github.com/go-yaml/yaml/issues/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](https://github.com/go-yaml/yaml) from v2 to v3.

## v2.5.0 - 2019-03-16

- We moved from the taskfile.org domain to the new fancy taskfile.dev domain.
  While stuff is being redirected, we strongly recommend to everyone that use
  [this install script](https://taskfile.dev/#/installation?id=install-script)
  to use the new taskfile.dev domain on scripts from now on.
- Fixed to the ZSH completion (#182).
- Add
  [`--summary` flag along with `summary:` task attribute](https://taskfile.org/#/usage?id=display-summary-of-task)
  (#180).

## 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](https://scoop.sh/) (#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](https://taskfile.org/#/usage?id=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](https://docsify.js.org/) for making this pretty easy. To
    check the source code, just take a look at the
    [docs](https://github.com/go-task/task/tree/main/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](https://github.com/go-task/task#output-syntax)

## 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](https://github.com/go-task/task/blob/main/TASKFILE_VERSIONS.md)
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
description:
  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](./integrations.md#community-integrations).

## Installation methods

Some installation methods are maintained by third party:

- [Arch Linux](https://archlinux.org/packages/extra/x86_64/go-task/)
- [AUR](https://aur.archlinux.org/packages/go-task-git) by @C0rn3j
- [Scoop](https://github.com/ScoopInstaller/Main/blob/master/bucket/task.json)
- [Fedora](https://packages.fedoraproject.org/pkgs/golang-github-task/go-task/)
- [Nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/go/go-task/package.nix)
- [Conda](https://github.com/conda-forge/go-task-feedstock/)

## More

Also, thanks for all the
[code contributors](https://github.com/go-task/task/graphs/contributors),
[financial contributors](https://opencollective.com/task), all those who
[reported bugs](https://github.com/go-task/task/issues?q=is%3Aissue) and
[answered questions](https://github.com/go-task/task/discussions).

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
description:
  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](https://discord.gg/6TY36E39UK) 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](https://github.com/go-task/task/contribute).

::: info

This document applies to the core [Task][task] repository _and_ [Task for Visual
Studio Code][vscode-task].

:::

## 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][experiments]". If you're intending to work on an
  experiment, then please read the [experiments workflow][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][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][go]. We always support the latest two major
  Go versions, so make sure your version is recent enough.
- **Node.js** - [Node.js][nodejs] 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][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`][golangci-lint]. This
  wraps the [`gofumpt`][gofumpt] and [`gci`][gci] formatters and a number of
  linters. We recommend that you take a look at the [golangci-lint
  docs][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][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](#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](#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][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][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][styleguide].

If you added a new command or flag, ensure that you add it to the [CLI
Reference][cli-reference]. New fields also need to be added to the [Schema
Reference][schema-reference] and [JSON Schema][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][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][task-open-issues] or [Task for
Visual Studio Code][vscode-task-open-issues]. We have a [good first
issue][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](./community.md).

> 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][discord-server] or open a [Discussion][discussion] on GitHub.

---

[task]: https://github.com/go-task/task
[vscode-task]: https://github.com/go-task/vscode-task
[go]: https://go.dev
[gofumpt]: https://github.com/mvdan/gofumpt
[gci]: https://github.com/daixiang0/gci
[golangci-lint]: https://golangci-lint.run
[golangci-lint-docs]: https://golangci-lint.run/welcome/integrations/
[prettier]: https://prettier.io
[nodejs]: https://nodejs.org/en/
[pnpm]: https://pnpm.io/
[mise]: https://mise.jdx.dev
[vitepress]: https://vitepress.dev
[json-schema]:
  https://github.com/go-task/task/blob/main/website/src/public/schema.json
[task-open-issues]: https://github.com/go-task/task/issues
[vscode-task-open-issues]: https://github.com/go-task/vscode-task/issues
[good-first-issue]:
  https://github.com/go-task/task/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22
[discord-server]: https://discord.gg/6TY36E39UK
[discussion]: https://github.com/go-task/task/discussions
[conventional-commits]: https://www.conventionalcommits.org
[experiments]: ./experiments/index.md
[experiments-workflow]: ./experiments/index.md#workflow
[styleguide]: ./styleguide.md
[cli-reference]: ./reference/cli.md
[schema-reference]: ./reference/schema.md
[usage-guide]: ./guide/index.md

---

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

---
title: FAQ
description:
  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 \<feature\> 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](./contributing.md).

## 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`](./reference/environment.md#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
description: Installation methods for Task
section: Getting Started
docType: guide
outline: deep
pageClass: installation-page
---

<script setup>
import InstallationMethod from '../../../.vitepress/components/InstallationMethod.vue';
import InstallationMethods from '../../../.vitepress/components/InstallationMethods.vue';
</script>

# Installation

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

<InstallationMethods>

<nav class="installation-shortcuts" aria-label="Installation shortcuts">
  <a href="#get-the-binary">Binaries &amp; CI</a>
  <a href="#verify-installation">Verify installation</a>
  <a href="#setup-completions">Shell completions</a>
</nav>

## Official packages {#official-package-managers}

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

<InstallationMethod platforms="macos" platform-label="macOS">

<template v-slot:heading>

### [Homebrew](https://brew.sh) {#homebrew}

</template>

<template v-slot:links>

[Tap source](https://github.com/go-task/homebrew-tap/blob/main/Casks/go-task.rb)
[Homebrew package](https://formulae.brew.sh/formula/go-task)
[Formula source](https://github.com/Homebrew/homebrew-core/blob/master/Formula/g/go-task.rb)

</template>

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

Or use the Homebrew core formula:

```shell
brew install go-task
```

</InstallationMethod>

<InstallationMethod platforms="linux" platform-label="Fedora · CentOS · Red Hat">

<template v-slot:heading>

### [dnf](https://docs.fedoraproject.org/en-US/quick-docs/dnf) {#dnf}

</template>

<template v-slot:links>

[View package](https://cloudsmith.io/~task/repos/task/packages/?sort=-format&q=format%3Arpm)

</template>

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
```

</InstallationMethod>

<InstallationMethod platforms="linux" platform-label="Ubuntu · Debian · Linux Mint">

<template v-slot:heading>

### [apt](https://doc.ubuntu-fr.org/apt) {#apt}

</template>

<template v-slot:links>

[View package](https://cloudsmith.io/~task/repos/task/packages/?sort=-format&q=format%3Adeb)

</template>

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
```

</InstallationMethod>

<InstallationMethod platforms="linux" platform-label="Alpine Linux">

<template v-slot:heading>

### [apk](https://wiki.alpinelinux.org/wiki/Alpine_Package_Keeper) {#apk}

</template>

<template v-slot:links>

[View package](https://cloudsmith.io/~task/repos/task/packages/?sort=-format&q=format%3Aalpine)

</template>

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
```

</InstallationMethod>

<InstallationMethod platforms="linux" platform-label="Linux">

<template v-slot:heading>

### [Snap](https://snapcraft.io/task) {#snap}

</template>

<template v-slot:links>

[Source](https://github.com/go-task/snap/blob/main/snap/snapcraft.yaml)

</template>

```shell
sudo snap install task --classic
```

Requires a Linux distribution with classic confinement support.

</InstallationMethod>

<InstallationMethod platforms="macos linux windows" platform-label="macOS · Linux · Windows">

<template v-slot:heading>

### [npm](https://www.npmjs.com) {#npm}

</template>

<template v-slot:links>

[View package](https://www.npmjs.com/package/@go-task/cli)
[Source](https://github.com/go-task/task/blob/main/package.json)

</template>

```shell
npm install @go-task/cli
```

Task is also available as a project dependency.

</InstallationMethod>

<InstallationMethod platforms="windows" platform-label="Windows">

<template v-slot:heading>

### [WinGet](https://github.com/microsoft/winget-cli) {#winget}

</template>

<template v-slot:links>

[Source](https://github.com/microsoft/winget-pkgs/tree/master/manifests/t/Task/Task)

</template>

```shell
winget install Task.Task
```

Available through the
[WinGet community repository](https://github.com/microsoft/winget-pkgs).

</InstallationMethod>

<p class="install-hosting">Package repository hosting for deb/rpm/apk is graciously provided by <a href="https://cloudsmith.com">Cloudsmith</a>.</p>

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

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

<InstallationMethod platforms="macos linux windows" platform-label="macOS · Linux · Windows">

<template v-slot:heading>

### [Mise](https://mise.jdx.dev/) {#mise}

</template>

<template v-slot:links>

[View package](https://mise-tools.jdx.dev/tools/task)

</template>

```shell
mise use -g task
```

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

</InstallationMethod>

<InstallationMethod platforms="macos" platform-label="macOS">

<template v-slot:heading>

### [Macports](https://macports.org) {#macports}

</template>

<template v-slot:links>

[View package](https://ports.macports.org/port/go-task/details/)
[Source](https://github.com/macports/macports-ports/blob/master/devel/go-task/Portfile)

</template>

```shell
port install go-task
```

</InstallationMethod>

<InstallationMethod platforms="macos linux windows" platform-label="macOS · Linux · Windows">

<template v-slot:heading>

### [pip](https://pip.pypa.io) {#pip}

</template>

<template v-slot:links>

[View package](https://pypi.org/project/go-task-bin)
[Source](https://github.com/Bing-su/pip-binary-factory/tree/main/task)

</template>

```shell
pip install go-task-bin
```

</InstallationMethod>

<InstallationMethod platforms="windows" platform-label="Windows">

<template v-slot:heading>

### [Chocolatey](https://chocolatey.org) {#chocolatey}

</template>

<template v-slot:links>

[View package](https://community.chocolatey.org/packages/go-task)
[Source](https://github.com/Starz0r/ChocolateyPackagingScripts/blob/master/src/go-task_gh_build.py)

</template>

```shell
choco install go-task
```

</InstallationMethod>

<InstallationMethod platforms="windows" platform-label="Windows">

<template v-slot:heading>

### [Scoop](https://scoop.sh) {#scoop}

</template>

<template v-slot:links>

[Source](https://github.com/ScoopInstaller/Main/blob/master/bucket/task.json)

</template>

```shell
scoop install task
```

</InstallationMethod>

<InstallationMethod platforms="linux" platform-label="Arch Linux">

<template v-slot:heading>

### Arch ([pacman](https://wiki.archlinux.org/title/Pacman)) {#arch}

</template>

<template v-slot:links>

[View package](https://archlinux.org/packages/extra/x86_64/go-task/)
[Source](https://gitlab.archlinux.org/archlinux/packaging/packages/go-task)

</template>

```shell
pacman -S go-task
```

</InstallationMethod>

<InstallationMethod platforms="linux" platform-label="Fedora">

<template v-slot:heading>

### Fedora ([dnf](https://docs.fedoraproject.org/en-US/quick-docs/dnf)) {#fedora-community}

</template>

<template v-slot:links>

[View package](https://packages.fedoraproject.org/pkgs/golang-github-task/go-task/)
[Source](https://src.fedoraproject.org/rpms/golang-github-task)

</template>

```shell
dnf install go-task
```

</InstallationMethod>

<InstallationMethod platforms="freebsd" platform-label="FreeBSD">

<template v-slot:heading>

### FreeBSD ([Ports](https://ports.freebsd.org/cgi/ports.cgi)) {#freebsd}

</template>

<template v-slot:links>

[View package](https://cgit.freebsd.org/ports/tree/devel/task)
[Source](https://cgit.freebsd.org/ports/tree/devel/task/Makefile)

</template>

```shell
pkg install task
```

</InstallationMethod>

<InstallationMethod platforms="linux macos" platform-label="Nix · NixOS · Linux · macOS">

<template v-slot:heading>

### [Nix](https://nixos.org) {#nix}

</template>

<template v-slot:links>

[Source](https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/go/go-task/package.nix)

</template>

```shell
nix-env -iA nixpkgs.go-task
```

</InstallationMethod>

<InstallationMethod platforms="linux" platform-label="Debian · Ubuntu">

<template v-slot:heading>

### [pacstall](https://github.com/pacstall/pacstall) {#pacstall}

</template>

<template v-slot:links>

[View package](https://pacstall.dev/packages/go-task-deb)
[Source](https://github.com/pacstall/pacstall-programs/blob/master/packages/go-task-deb/go-task-deb.pacscript)

</template>

```shell
pacstall -I go-task-deb
```

</InstallationMethod>

<InstallationMethod platforms="macos linux" platform-label="macOS · Linux">

<template v-slot:heading>

### [pkgx](https://pkgx.sh) {#pkgx}

</template>

<template v-slot:links>

[View package](https://pkgx.dev/pkgs/taskfile.dev)
[Source](https://github.com/pkgxdev/pantry/blob/main/projects/taskfile.dev/package.yml)

</template>

```shell
pkgx task
```

or, if you have pkgx integration enabled:

```shell
task
```

</InstallationMethod>

</InstallationMethods>

## 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](https://github.com/go-task/task/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](https://github.com/go-task/task/blob/main/install-task.sh) 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](https://github.com/go-task/task/releases) 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](https://github.com/go-task/setup-task) 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](https://github.com/go-task/setup-task#usage) for examples
and configuration.

## Build from source

Ensure that you have a supported version of [Go](https://golang.org) properly
installed and setup. You can find the minimum required version of Go in the
[go.mod](https://github.com/go-task/task/blob/main/go.mod#L3) 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](#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](./getting-started.md). 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:

### Option 1. Load the completions in your shell's startup config (Recommended)

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
description:
  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](https://marketplace.visualstudio.com/items?itemName=task.vscode-task).
The code for this project can be found in
[our GitHub repository](https://github.com/go-task/vscode-task). 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](#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](https://github.com/go-task/vscode-task/issues/56).



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](https://gist.github.com/KROSF/c5435acf590acd632f71bb720f685895) and
is now officially maintained in
[this file](https://github.com/go-task/task/blob/main/website/src/public/schema.json)
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](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml)
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](https://github.com/redhat-developer/yaml-language-server).

## 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](https://github.com/okineadev/vitepress-plugin-llms).

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](https://taskfile.dev/llms.txt)**: Lightweight overview of Task documentation
- **[llms-full.txt](https://taskfile.dev/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:

- [Sublime Text Plugin](https://packagecontrol.io/packages/Taskfile)
  [[source](https://github.com/biozz/sublime-taskfile)] by @biozz
- [IntelliJ Plugin](https://plugins.jetbrains.com/plugin/17058-taskfile)
  [[source](https://github.com/lechuckroh/task-intellij-plugin)] by @lechuckroh
- [Zed Extension](https://zed.dev/extensions/taskfile)
  [[source](https://github.com/nickalie/zed-taskfile)] by @nickalie
- [mk](https://github.com/pycontribs/mk) command line tool recognizes Taskfiles
  natively.
- [fzf-make](https://github.com/kyu08/fzf-make) fuzzy finder with preview window
  for make, pnpm, yarn, just & 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
description:
  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][goreleaser].
You can test the release process locally by calling the `goreleaser:test` task
of the Taskfile.

[GitHub Actions](https://github.com/go-task/task/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](https://discord.gg/6TY36E39UK). Nightly releases are not
announced.

These package managers are updated automatically by the community:

- [Scoop](https://github.com/ScoopInstaller/Main/blob/master/bucket/task.json)
- [Nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/go/go-task/package.nix)

[goreleaser]: https://goreleaser.com/

---

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

---
title: Remote Taskfiles
description:
  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](#security) 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 'git@github.com/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](./guide/includes.md):

::: 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: git@github.com/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`](./reference/config.md#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
  `//<path>` 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

`git@github.com/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
  `//<path>` 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](./reference/templating.md#file-paths) 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](./reference/config.md#remote-trusted-hosts) 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](#configuration).

## 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](./reference/config.md#remote-cache-dir), 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:

- [CLI flags](./reference/cli.md#remote)
- [Environment Variables](./reference/environment.md#remote-taskfile-variables)
- [Config File](./reference/config.md#remote)

---

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

---
title: Style Guide
description:
  Official style guide for Taskfile.yml files with best practices and
  recommended conventions
section: Contributing
docType: contributing
outline: deep
---

# 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
description:
  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][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](https://github.com/go-task/task/releases/tag/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.

[semver]: https://semver.org/

---

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

---
title: Changelog
description:
  Release history for Task, including new features, improvements, fixes, and
  breaking changes
section: Project
docType: project
outline: deep
editLink: false
---

# 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](https://taskfile.dev/docs/remote-taskfiles) 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](https://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](https://github.com/u-root/u-root/pull/3464),
  [mvdan/sh#1199](https://github.com/mvdan/sh/pull/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](https://taskfile.dev/blog/windows-core-utils).
  (#197, #2360 by @andreynering).
- :sparkles: Built and deployed a [brand new website](https://taskfile.dev)
  using [VitePress](https://vitepress.dev) (#2359, #2369, #2371, #2375, #2378 by
  @vmaerten, @andreynering, @pd93).
- Began releasing
  [nightly builds](https://github.com/go-task/task/releases/tag/nightly). 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](https://taskfile.dev/docs/reference/config) 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](https://github.com/go-task/setup-task). 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](https://github.com/go-task/setup-task/releases/tag/v1.0.0) (by
@pd93, @shrink, @trim21 and all the previous contributors to
[arduino/setup-task](https://github.com/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](https://taskfile.dev/next/experiments/remote-taskfiles/#manual-checksum-pinning)
  by specifying a checksum. This works with both local and remote Taskfiles
  (#2222, #2223 by @pd93).
- When using the
  [Remote Taskfiles experiment](https://github.com/go-task/task/issues/1317),
  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](https://github.com/radovskyb/watcher) to
  [fsnotify](https://github.com/fsnotify/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](https://github.com/go-task/task/issues/1585)
  was made generally available so you can now
  [define map variables in your Taskfiles!](https://taskfile.dev/usage/#variables)
  (#1585, #1547, #2081 by @pd93).
- Wildcards can now
  [match multiple tasks](https://taskfile.dev/usage/#wildcard-arguments) (#2072,
  #2121 by @pd93).
- Added the ability to
  [loop over the files specified by the `generates` keyword](https://taskfile.dev/usage/#looping-over-your-tasks-sources-or-generated-files).
  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](https://github.com/go-task/task/issues/1317)
  (#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

- The [`Executor`](https://pkg.go.dev/github.com/go-task/task/v3#Executor) now
  uses the functional options pattern (#2085, #2147, #2148 by @pd93).
- The functional options for the
  [`taskfile.Reader`](https://pkg.go.dev/github.com/go-task/task/v3/taskfile#Reader)
  and
  [`taskfile.Snippet`](https://pkg.go.dev/github.com/go-task/task/v3/taskfile#Snippet)
  types no longer have the `Reader`/`Snippet` respective prefixes (#2148 by
  @pd93).
- [`taskfile.Reader`](https://pkg.go.dev/github.com/go-task/task/v3/taskfile#Reader)
  no longer accepts a
  [`taskfile.Node`](https://pkg.go.dev/github.com/go-task/task/v3/taskfile#Node).
  Instead nodes are passed directly into the
  [`Reader.Read`](https://pkg.go.dev/github.com/go-task/task/v3/taskfile#Reader.Read)
  method (#2169 by @pd93).
- [`Reader.Read`](https://pkg.go.dev/github.com/go-task/task/v3/taskfile#Reader.Read)
  also now accepts a [`context.Context`](https://pkg.go.dev/context#Context)
  (#2176 by @pd93).

## 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](https://taskfile.dev/getting-started) (#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](https://taskfile.dev/reference/package).
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`](https://pkg.go.dev/github.com/go-task/task/v3#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`](https://pkg.go.dev/github.com/go-task/task/v3/errors#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`](https://pkg.go.dev/github.com/go-task/task/v3/taskfile#Snippet)
  and related code moved from the `errors` package to the `taskfile` package
  (#2068 by @pd93).
- Renamed `TaskMissingRequiredVars` to
  [`TaskMissingRequiredVarsError`](https://pkg.go.dev/github.com/go-task/task/v3/errors#TaskMissingRequiredVarsError)
  (#2052 by @vmaerten).
- Renamed `TaskNotAllowedVars` to
  [`TaskNotAllowedVarsError`](https://pkg.go.dev/github.com/go-task/task/v3/errors#TaskNotAllowedVarsError)
  (#2052 by @vmaerten).
- The
  [`taskfile.Reader`](https://pkg.go.dev/github.com/go-task/task/v3/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).
  - Users are now expected to pass a custom debug/prompt functions into
    [`taskfile.Reader`](https://pkg.go.dev/github.com/go-task/task/v3/taskfile#Reader)
    if they want this functionality by using the new
    [`WithDebugFunc`](https://pkg.go.dev/github.com/go-task/task/v3/taskfile#WithDebugFunc)
    and
    [`WithPromptFunc`](https://pkg.go.dev/github.com/go-task/task/v3/taskfile#WithPromptFunc)
    functional options.
- 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](https://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](https://taskfile.dev/installation) 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](https://taskfile.dev/experiments/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](https://taskfile.dev/experiments/env-precedence)
  (#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](https://taskfile.dev/installation/#setup-completions) 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](https://taskfile.dev/deprecations/completion-scripts/).
- Added the ability to
  [loop over a matrix of values](https://taskfile.dev/usage/#looping-over-a-matrix)
  (#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](https://taskfile.dev/usage/#referencing-other-variables) 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](https://taskfile.dev/reference/templating/) to the
  documentation (#1614, #1653 by @pd93).
- If using the
  [Map Variables experiment (1)](https://taskfile.dev/experiments/map-variables/?proposal=1),
  references are available by
  [prefixing a string with a `#`](https://taskfile.dev/experiments/map-variables/?proposal=1#references)
  (#1654 by @pd93).
- If using the
  [Map Variables experiment (2)](https://taskfile.dev/experiments/map-variables/?proposal=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](https://taskfile.dev/blog/any-variables), but
  [_without support for maps_](https://github.com/go-task/task/issues/1415#issuecomment-2044756925)
  (#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](https://taskfile.dev/experiments/map-variables/) 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](https://taskfile.dev/usage/#looping-over-dependencies)
  (#1299, #1541 by @pd93).
- When using the
  "[Remote Taskfiles](https://taskfile.dev/experiments/remote-taskfiles/)"
  experiment, you are now able to use
  [remote Taskfiles as your entrypoint](https://taskfile.dev/experiments/remote-taskfiles/#root-remote-taskfiles).
  - `includes` in remote Taskfiles will now also resolve correctly (#1347 by
    @pd93).
- When using the
  "[Any Variables](https://taskfile.dev/experiments/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](https://taskfile.dev/usage/#wildcard-arguments)
  (#836, #1489 by @pd93).
- Added the ability to
  [run Taskfiles via stdin](https://taskfile.dev/usage/#reading-a-taskfile-from-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

- Fixed prompt regression on
  [Remote Taskfiles experiment](https://taskfile.dev/experiments/remote-taskfiles/)
  (#1486, #1487 by @pd93).

## v3.34.0 - 2024-01-25

- Removed support for `version: 2` schemas. See the
  [deprecation notice on our website](https://taskfile.dev/deprecations/version-2-schema)
  (#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](https://taskfile.dev/experiments/any-variables/?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](https://taskfile.dev/experiments/any-variables)
  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](https://taskfile.dev/experiments/any-variables)
  (#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](https://taskfile.dev/experiments/remote-taskfiles)
  now prefers remote files over cached ones by default (#1317, #1345 by @pd93).
- Added `--timeout` flag to the
  [Remote Taskfiles experiment](https://taskfile.dev/experiments/remote-taskfiles)
  (#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](https://taskfile.dev/experiments/remote-taskfiles)
  (#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](https://taskfile.dev/api/#exit-codes) (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](https://taskfile.dev/experiments/remote-taskfiles)
  as a draft (#1152, #1317 by @pd93).
- Improve performance of content checksumming on `sources:` by replacing md5
  with [XXH3](https://xxhash.com/) 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](https://taskfile.dev/usage/#looping-over-values)
  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](https://taskfile.dev/installation/#npm). (#1190, by
  @sounisi5011).
- Added the
  [gentle force experiment](https://taskfile.dev/experiments/gentle-force) 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](https://taskfile.dev/experiments) 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](https://taskfile.dev/usage/#warning-prompts)).
- 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](https://github.com/mvdan/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](https://taskfile.dev/api/#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](https://marketplace.visualstudio.com/items?itemName=task.vscode-task)
contributed by @pd93! :tada: The extension is maintained in a
[new repository](https://github.com/go-task/vscode-task) 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](https://github.com/go-task/vscode-task/discussions),
[issue](https://github.com/go-task/vscode-task/issues) or on our
[Discord](https://discord.gg/6TY36E39UK)!

> **NOTE:** The extension _requires_ v3.23.0 to be installed in order to work.

- The website was integrated with
  [Crowdin](https://crowdin.com/project/taskfile) to allow the community to
  contribute with translations! [Chinese](https://taskfile.dev/zh-Hans/) 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](https://taskfile.dev/usage/#running-a-global-taskfile), #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`](https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html)
  and
  [`shopt`](https://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html)
  builtins (#908, #929 by @pd93,
  [Documentation](http://taskfile.dev/usage/#set-and-shopt)).
- 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](https://pnpm.io/) as well
  ([go-task/go-npm#2](https://github.com/go-task/go-npm/issues/2),
  [go-task/go-npm#3](https://github.com/go-task/go-npm/pull/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](https://task-zh.readthedocs.io/zh_CN/latest/) by
  [@DeronW](https://github.com/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](https://www.npmjs.com/package/@go-task/cli)).
- 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](https://taskfile.dev/api/#special-variables)).
- 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](https://github.com/mvdan/sh/issues/884),
  [mvdan/sh#893](https://github.com/mvdan/sh/pull/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](https://taskfile.dev/#/usage?id=vars-of-included-taskfiles)
  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](http://taskfile.dev/#/usage?id=output-syntax)
  for more information (#647, #651).
- Add `Taskfile.dist.yml` and `Taskfile.dist.yaml` to the supported file name
  list.
  [Check out the documentation](https://taskfile.dev/#/usage?id=supported-file-names)
  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](https://taskfile.dev/#/usage?id=doing-task-cleanup-with-defer),
  #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

- Upgrade [mvdan/sh](https://github.com/mvdan/sh) which contains a fix a for a
  important regression on Windows (#619,
  [mvdan/sh#768](https://github.com/mvdan/sh/issues/768),
  [mvdan/sh#769](https://github.com/mvdan/sh/pull/769)).

## 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](https://github.com/mvdan/sh) which contains two relevant
  fixes:
  - Fix quote of empty strings in `shellQuote` (#609,
    [mvdan/sh#763](https://github.com/mvdan/sh/issues/763)).
  - Fix issue of wrong environment variable being picked when there's another
    very similar one (#586,
    [mvdan/sh#745](https://github.com/mvdan/sh/pull/745)).
- Install shell completions automatically when installing via Homebrew (#264,
  #592,
  [go-task/homebrew-tap#2](https://github.com/go-task/homebrew-tap/pull/2)).

## v3.9.0 - 2021-10-02

- A new `shellQuote` function was added to the template system
  (`{{shellQuote "a string"}}`) to ensure a string is safe for use in shell
  ([mvdan/sh#727](https://github.com/mvdan/sh/pull/727),
  [mvdan/sh#737](https://github.com/mvdan/sh/pull/737),
  [Documentation](https://pkg.go.dev/mvdan.cc/sh/v3@v3.4.0/syntax#Quote))
- In this version [mvdan.cc/sh](https://github.com/mvdan/sh) was upgraded with
  some small fixes and features
  - The `read -p` flag is now supported (#314,
    [mvdan/sh#551](https://github.com/mvdan/sh/issues/551),
    [mvdan/sh#772](https://github.com/mvdan/sh/pull/722))
  - The `pwd -P` and `pwd -L` flags are now supported (#553,
    [mvdan/sh#724](https://github.com/mvdan/sh/issues/724),
    [mvdan/sh#728](https://github.com/mvdan/sh/pull/728))
  - The `$GID` environment variable is now correctly being set (#561,
    [mvdan/sh#723](https://github.com/mvdan/sh/pull/723))

## 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](https://github.com/go-task/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](https://github.com/fatih/color/pull/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](https://json.schemastore.org/taskfile.json)
  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](https://github.com/go-task/slim-sprig) package was updated
  with the upstream [sprig](https://github.com/Masterminds/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](https://github.com/go-task/slim-sprig) instead of
  [sprig](https://github.com/Masterminds/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](https://github.com/go-task/homebrew-tap/pull/1)).

## v2.5.2 - 2019-05-11

- Reverted YAML upgrade due issues with CRLF on Windows (#201,
  [go-yaml/yaml#450](https://github.com/go-yaml/yaml/issues/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](https://github.com/go-yaml/yaml) from v2 to v3.

## v2.5.0 - 2019-03-16

- We moved from the taskfile.org domain to the new fancy taskfile.dev domain.
  While stuff is being redirected, we strongly recommend to everyone that use
  [this install script](https://taskfile.dev/#/installation?id=install-script)
  to use the new taskfile.dev domain on scripts from now on.
- Fixed to the ZSH completion (#182).
- Add
  [`--summary` flag along with `summary:` task attribute](https://taskfile.org/#/usage?id=display-summary-of-task)
  (#180).

## 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](https://scoop.sh/) (#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](https://taskfile.org/#/usage?id=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](https://docsify.js.org/) for making this pretty easy. To
    check the source code, just take a look at the
    [docs](https://github.com/go-task/task/tree/main/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](https://github.com/go-task/task#output-syntax)

## 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](https://github.com/go-task/task/blob/main/TASKFILE_VERSIONS.md)
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
description:
  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](./integrations.md#community-integrations).

## Installation methods

Some installation methods are maintained by third party:

- [Arch Linux](https://archlinux.org/packages/extra/x86_64/go-task/)
- [AUR](https://aur.archlinux.org/packages/go-task-git) by @C0rn3j
- [Scoop](https://github.com/ScoopInstaller/Main/blob/master/bucket/task.json)
- [Fedora](https://packages.fedoraproject.org/pkgs/golang-github-task/go-task/)
- [Nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/go/go-task/package.nix)
- [Conda](https://github.com/conda-forge/go-task-feedstock/)

## More

Also, thanks for all the
[code contributors](https://github.com/go-task/task/graphs/contributors),
[financial contributors](https://opencollective.com/task), all those who
[reported bugs](https://github.com/go-task/task/issues?q=is%3Aissue) and
[answered questions](https://github.com/go-task/task/discussions).

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
description:
  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](https://discord.gg/6TY36E39UK) 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](https://github.com/go-task/task/contribute).

::: info

This document applies to the core [Task][task] repository _and_ [Task for Visual
Studio Code][vscode-task].

:::

## 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][experiments]". If you're intending to work on an
  experiment, then please read the [experiments workflow][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][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][go]. We always support the latest two major
  Go versions, so make sure your version is recent enough.
- **Node.js** - [Node.js][nodejs] 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][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`][golangci-lint]. This
  wraps the [`gofumpt`][gofumpt] and [`gci`][gci] formatters and a number of
  linters. We recommend that you take a look at the [golangci-lint
  docs][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][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](#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](#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][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][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][styleguide].

If you added a new command or flag, ensure that you add it to the [CLI
Reference][cli-reference]. New fields also need to be added to the [Schema
Reference][schema-reference] and [JSON Schema][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][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][task-open-issues] or [Task for
Visual Studio Code][vscode-task-open-issues]. We have a [good first
issue][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](./community.md).

> 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][discord-server] or open a [Discussion][discussion] on GitHub.

---

[task]: https://github.com/go-task/task
[vscode-task]: https://github.com/go-task/vscode-task
[go]: https://go.dev
[gofumpt]: https://github.com/mvdan/gofumpt
[gci]: https://github.com/daixiang0/gci
[golangci-lint]: https://golangci-lint.run
[golangci-lint-docs]: https://golangci-lint.run/welcome/integrations/
[prettier]: https://prettier.io
[nodejs]: https://nodejs.org/en/
[pnpm]: https://pnpm.io/
[mise]: https://mise.jdx.dev
[vitepress]: https://vitepress.dev
[json-schema]:
  https://github.com/go-task/task/blob/main/website/src/public/schema.json
[task-open-issues]: https://github.com/go-task/task/issues
[vscode-task-open-issues]: https://github.com/go-task/vscode-task/issues
[good-first-issue]:
  https://github.com/go-task/task/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22
[discord-server]: https://discord.gg/6TY36E39UK
[discussion]: https://github.com/go-task/task/discussions
[conventional-commits]: https://www.conventionalcommits.org
[experiments]: ./experiments/index.md
[experiments-workflow]: ./experiments/index.md#workflow
[styleguide]: ./styleguide.md
[cli-reference]: ./reference/cli.md
[schema-reference]: ./reference/schema.md
[usage-guide]: ./guide/index.md

---

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

---
title: FAQ
description:
  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 \<feature\> 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](./contributing.md).

## 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`](./reference/environment.md#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
description: Installation methods for Task
section: Getting Started
docType: guide
outline: deep
pageClass: installation-page
---

<script setup>
import InstallationMethod from '../../../.vitepress/components/InstallationMethod.vue';
import InstallationMethods from '../../../.vitepress/components/InstallationMethods.vue';
</script>

# Installation

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

<InstallationMethods>

<nav class="installation-shortcuts" aria-label="Installation shortcuts">
  <a href="#get-the-binary">Binaries &amp; CI</a>
  <a href="#verify-installation">Verify installation</a>
  <a href="#setup-completions">Shell completions</a>
</nav>

## Official packages {#official-package-managers}

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

<InstallationMethod platforms="macos" platform-label="macOS">

<template v-slot:heading>

### [Homebrew](https://brew.sh) {#homebrew}

</template>

<template v-slot:links>

[Tap source](https://github.com/go-task/homebrew-tap/blob/main/Casks/go-task.rb)
[Homebrew package](https://formulae.brew.sh/formula/go-task)
[Formula source](https://github.com/Homebrew/homebrew-core/blob/master/Formula/g/go-task.rb)

</template>

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

Or use the Homebrew core formula:

```shell
brew install go-task
```

</InstallationMethod>

<InstallationMethod platforms="linux" platform-label="Fedora · CentOS · Red Hat">

<template v-slot:heading>

### [dnf](https://docs.fedoraproject.org/en-US/quick-docs/dnf) {#dnf}

</template>

<template v-slot:links>

[View package](https://cloudsmith.io/~task/repos/task/packages/?sort=-format&q=format%3Arpm)

</template>

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
```

</InstallationMethod>

<InstallationMethod platforms="linux" platform-label="Ubuntu · Debian · Linux Mint">

<template v-slot:heading>

### [apt](https://doc.ubuntu-fr.org/apt) {#apt}

</template>

<template v-slot:links>

[View package](https://cloudsmith.io/~task/repos/task/packages/?sort=-format&q=format%3Adeb)

</template>

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
```

</InstallationMethod>

<InstallationMethod platforms="linux" platform-label="Alpine Linux">

<template v-slot:heading>

### [apk](https://wiki.alpinelinux.org/wiki/Alpine_Package_Keeper) {#apk}

</template>

<template v-slot:links>

[View package](https://cloudsmith.io/~task/repos/task/packages/?sort=-format&q=format%3Aalpine)

</template>

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
```

</InstallationMethod>

<InstallationMethod platforms="linux" platform-label="Linux">

<template v-slot:heading>

### [Snap](https://snapcraft.io/task) {#snap}

</template>

<template v-slot:links>

[Source](https://github.com/go-task/snap/blob/main/snap/snapcraft.yaml)

</template>

```shell
sudo snap install task --classic
```

Requires a Linux distribution with classic confinement support.

</InstallationMethod>

<InstallationMethod platforms="macos linux windows" platform-label="macOS · Linux · Windows">

<template v-slot:heading>

### [npm](https://www.npmjs.com) {#npm}

</template>

<template v-slot:links>

[View package](https://www.npmjs.com/package/@go-task/cli)
[Source](https://github.com/go-task/task/blob/main/package.json)

</template>

```shell
npm install @go-task/cli
```

Task is also available as a project dependency.

</InstallationMethod>

<InstallationMethod platforms="windows" platform-label="Windows">

<template v-slot:heading>

### [WinGet](https://github.com/microsoft/winget-cli) {#winget}

</template>

<template v-slot:links>

[Source](https://github.com/microsoft/winget-pkgs/tree/master/manifests/t/Task/Task)

</template>

```shell
winget install Task.Task
```

Available through the
[WinGet community repository](https://github.com/microsoft/winget-pkgs).

</InstallationMethod>

<p class="install-hosting">Package repository hosting for deb/rpm/apk is graciously provided by <a href="https://cloudsmith.com">Cloudsmith</a>.</p>

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

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

<InstallationMethod platforms="macos linux windows" platform-label="macOS · Linux · Windows">

<template v-slot:heading>

### [Mise](https://mise.jdx.dev/) {#mise}

</template>

<template v-slot:links>

[View package](https://mise-tools.jdx.dev/tools/task)

</template>

```shell
mise use -g task
```

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

</InstallationMethod>

<InstallationMethod platforms="macos" platform-label="macOS">

<template v-slot:heading>

### [Macports](https://macports.org) {#macports}

</template>

<template v-slot:links>

[View package](https://ports.macports.org/port/go-task/details/)
[Source](https://github.com/macports/macports-ports/blob/master/devel/go-task/Portfile)

</template>

```shell
port install go-task
```

</InstallationMethod>

<InstallationMethod platforms="macos linux windows" platform-label="macOS · Linux · Windows">

<template v-slot:heading>

### [pip](https://pip.pypa.io) {#pip}

</template>

<template v-slot:links>

[View package](https://pypi.org/project/go-task-bin)
[Source](https://github.com/Bing-su/pip-binary-factory/tree/main/task)

</template>

```shell
pip install go-task-bin
```

</InstallationMethod>

<InstallationMethod platforms="windows" platform-label="Windows">

<template v-slot:heading>

### [Chocolatey](https://chocolatey.org) {#chocolatey}

</template>

<template v-slot:links>

[View package](https://community.chocolatey.org/packages/go-task)
[Source](https://github.com/Starz0r/ChocolateyPackagingScripts/blob/master/src/go-task_gh_build.py)

</template>

```shell
choco install go-task
```

</InstallationMethod>

<InstallationMethod platforms="windows" platform-label="Windows">

<template v-slot:heading>

### [Scoop](https://scoop.sh) {#scoop}

</template>

<template v-slot:links>

[Source](https://github.com/ScoopInstaller/Main/blob/master/bucket/task.json)

</template>

```shell
scoop install task
```

</InstallationMethod>

<InstallationMethod platforms="linux" platform-label="Arch Linux">

<template v-slot:heading>

### Arch ([pacman](https://wiki.archlinux.org/title/Pacman)) {#arch}

</template>

<template v-slot:links>

[View package](https://archlinux.org/packages/extra/x86_64/go-task/)
[Source](https://gitlab.archlinux.org/archlinux/packaging/packages/go-task)

</template>

```shell
pacman -S go-task
```

</InstallationMethod>

<InstallationMethod platforms="linux" platform-label="Fedora">

<template v-slot:heading>

### Fedora ([dnf](https://docs.fedoraproject.org/en-US/quick-docs/dnf)) {#fedora-community}

</template>

<template v-slot:links>

[View package](https://packages.fedoraproject.org/pkgs/golang-github-task/go-task/)
[Source](https://src.fedoraproject.org/rpms/golang-github-task)

</template>

```shell
dnf install go-task
```

</InstallationMethod>

<InstallationMethod platforms="freebsd" platform-label="FreeBSD">

<template v-slot:heading>

### FreeBSD ([Ports](https://ports.freebsd.org/cgi/ports.cgi)) {#freebsd}

</template>

<template v-slot:links>

[View package](https://cgit.freebsd.org/ports/tree/devel/task)
[Source](https://cgit.freebsd.org/ports/tree/devel/task/Makefile)

</template>

```shell
pkg install task
```

</InstallationMethod>

<InstallationMethod platforms="linux macos" platform-label="Nix · NixOS · Linux · macOS">

<template v-slot:heading>

### [Nix](https://nixos.org) {#nix}

</template>

<template v-slot:links>

[Source](https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/go/go-task/package.nix)

</template>

```shell
nix-env -iA nixpkgs.go-task
```

</InstallationMethod>

<InstallationMethod platforms="linux" platform-label="Debian · Ubuntu">

<template v-slot:heading>

### [pacstall](https://github.com/pacstall/pacstall) {#pacstall}

</template>

<template v-slot:links>

[View package](https://pacstall.dev/packages/go-task-deb)
[Source](https://github.com/pacstall/pacstall-programs/blob/master/packages/go-task-deb/go-task-deb.pacscript)

</template>

```shell
pacstall -I go-task-deb
```

</InstallationMethod>

<InstallationMethod platforms="macos linux" platform-label="macOS · Linux">

<template v-slot:heading>

### [pkgx](https://pkgx.sh) {#pkgx}

</template>

<template v-slot:links>

[View package](https://pkgx.dev/pkgs/taskfile.dev)
[Source](https://github.com/pkgxdev/pantry/blob/main/projects/taskfile.dev/package.yml)

</template>

```shell
pkgx task
```

or, if you have pkgx integration enabled:

```shell
task
```

</InstallationMethod>

</InstallationMethods>

## 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](https://github.com/go-task/task/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](https://github.com/go-task/task/blob/main/install-task.sh) 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](https://github.com/go-task/task/releases) 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](https://github.com/go-task/setup-task) 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](https://github.com/go-task/setup-task#usage) for examples
and configuration.

## Build from source

Ensure that you have a supported version of [Go](https://golang.org) properly
installed and setup. You can find the minimum required version of Go in the
[go.mod](https://github.com/go-task/task/blob/main/go.mod#L3) 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](#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](./getting-started.md). 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:

### Option 1. Load the completions in your shell's startup config (Recommended)

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
description:
  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](https://marketplace.visualstudio.com/items?itemName=task.vscode-task).
The code for this project can be found in
[our GitHub repository](https://github.com/go-task/vscode-task). 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](#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](https://github.com/go-task/vscode-task/issues/56).



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](https://gist.github.com/KROSF/c5435acf590acd632f71bb720f685895) and
is now officially maintained in
[this file](https://github.com/go-task/task/blob/main/website/src/public/schema.json)
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](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml)
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](https://github.com/redhat-developer/yaml-language-server).

## 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](https://github.com/okineadev/vitepress-plugin-llms).

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](https://taskfile.dev/llms.txt)**: Lightweight overview of Task documentation
- **[llms-full.txt](https://taskfile.dev/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:

- [Sublime Text Plugin](https://packagecontrol.io/packages/Taskfile)
  [[source](https://github.com/biozz/sublime-taskfile)] by @biozz
- [IntelliJ Plugin](https://plugins.jetbrains.com/plugin/17058-taskfile)
  [[source](https://github.com/lechuckroh/task-intellij-plugin)] by @lechuckroh
- [Zed Extension](https://zed.dev/extensions/taskfile)
  [[source](https://github.com/nickalie/zed-taskfile)] by @nickalie
- [mk](https://github.com/pycontribs/mk) command line tool recognizes Taskfiles
  natively.
- [fzf-make](https://github.com/kyu08/fzf-make) fuzzy finder with preview window
  for make, pnpm, yarn, just & 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
description:
  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][goreleaser].
You can test the release process locally by calling the `goreleaser:test` task
of the Taskfile.

[GitHub Actions](https://github.com/go-task/task/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](https://discord.gg/6TY36E39UK). Nightly releases are not
announced.

These package managers are updated automatically by the community:

- [Scoop](https://github.com/ScoopInstaller/Main/blob/master/bucket/task.json)
- [Nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/go/go-task/package.nix)

[goreleaser]: https://goreleaser.com/

---

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

---
title: Remote Taskfiles
description:
  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](#security) 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 'git@github.com/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](./guide/includes.md):

::: 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: git@github.com/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`](./reference/config.md#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
  `//<path>` 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

`git@github.com/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
  `//<path>` 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](./reference/templating.md#file-paths) 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](./reference/config.md#remote-trusted-hosts) 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](#configuration).

## 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](./reference/config.md#remote-cache-dir), 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:

- [CLI flags](./reference/cli.md#remote)
- [Environment Variables](./reference/environment.md#remote-taskfile-variables)
- [Config File](./reference/config.md#remote)

---

### Website Src Next Docs Styleguide (`website/src/next/docs/styleguide.md`)

---
title: Style Guide
description:
  Official style guide for Taskfile.yml files with best practices and
  recommended conventions
section: Contributing
docType: contributing
outline: deep
---

# 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
description:
  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][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](https://github.com/go-task/task/releases/tag/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.

[semver]: https://semver.org/

---

### Website Src Latest Docs Deprecations Completion Scripts (`website/src/latest/docs/deprecations/completion-scripts.md`)

---
title: 'Completion Scripts'
description: Deprecation of direct completion scripts in Task’s Git directory
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][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][completions] instead.

[completions]: ../installation.md#setup-completions
[task]: https://github.com/go-task/task

---

### Website Src Latest Docs Deprecations Template Functions (`website/src/latest/docs/deprecations/template-functions.md`)

---
title: 'Template Functions'
description:
  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 ---'
description: Template for documenting deprecated features in Task
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)'
description: Deprecation of Taskfile schema version 2 and migration to version 3
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][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][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][v3.0.0].

[v3.0.0]: https://github.com/go-task/task/releases/tag/v3.0.0
[v3.33.0]: https://github.com/go-task/task/releases/tag/v3.33.0
[deprecation-notice]: https://github.com/go-task/task/issues/1197

---

### Website Src Latest Docs Experiments Env Precedence (`website/src/latest/docs/experiments/env-precedence.md`)

---
title: 'Env Precedence (#1038)'
description:
  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](./index.md#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 : <span v-pre>`{{env "OS_VAR"}}`</span>.

```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)'
description: Experiment to modify the behavior of the --force flag in Task
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](./index.md#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)
description: Experimentation for using Taskfiles stored in remote locations
section: Project
docType: project
outline: deep
---

# Remote Taskfiles (#1317)

The Remote Taskfiles experiment has now [been released][changelog] :tada:. To
learn more, you can read the [remote Taskfile docs][remote-taskfile-docs] or
check out our [blog post][blog-post].

[changelog]: ../changelog.md#v3-51-1-2026-05-16
[remote-taskfile-docs]: ../remote-taskfiles.md
[blog-post]: ../../blog/remote-taskfiles.md

---

### Website Src Latest Docs Experiments Template (`website/src/latest/docs/experiments/template.md`)

---
title: '--- Template ---'
description: Template for documenting a new experiment.
---

# \{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 ][enabling-experiments] for more
information.

:::

\{Short description of the feature\}

\{Short explanation of how users should migrate to the new behavior\}

[enabling-experiments]: ./index.md#enabling-experiments

---

### Website Src Latest Docs Guide Arguments (`website/src/latest/docs/guide/arguments.md`)

---
title: Command-line arguments
description:
  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`  | <span v-pre>`{{.NAME}}`</span>          |
| Arguments for a command | `task yarn -- install` | <span v-pre>`{{.CLI_ARGS}}`</span>      |
| Part of a task name     | `task start:api`       | <span v-pre>`{{index .MATCH 0}}`</span> |

## 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](./variables.md#resolution-order) for precedence and
configurable defaults. To set values in a command's shell environment, see
[Environment variables](./environment.md).

## 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
description:
  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`](#conditional-execution-with-if)                                                               |
| Stop when a requirement is unmet | [`preconditions`](#using-programmatic-checks-to-cancel-the-execution-of-a-task-and-its-dependencies) |
| Ask before executing commands    | [`prompt`](#confirmation-prompts)                                                                    |
| Skip work already completed      | [Up-to-date checks](./up-to-date.md)                                                                 |

## 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](./loops.md) 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](./required-variables.md).

## 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](../reference/cli.md#exit-codes) `205`.

Unlike
[prompts for missing input](./required-variables.md#prompting-for-missing-variables-interactively),
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

<span id="limiting-when-tasks-run"></span>

To control how often a task runs when several tasks call it, use
[`run: once` or `run: when_changed`](./dependencies.md#repeated-calls). These
settings apply within one invocation. Use [up-to-date checks](./up-to-date.md)
to skip completed work across invocations.

:::

---

### Website Src Latest Docs Guide Defining Tasks (`website/src/latest/docs/guide/defining-tasks.md`)

---
title: Defining tasks
description:
  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](./running-tasks.md) 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](./includes.md#directory-of-included-taskfile).

## 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](./dependencies.md#calling-another-task)
in your Taskfile and when [including tasks](./includes.md) with aliases from
another Taskfile. They can also be used together with
[namespace aliases](./includes.md#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:

```
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
description:
  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`](#calling-another-task) 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](./includes.md), 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](./output.md#silent-mode) hides the command, not its
output.

The same `task`, `vars`, and `silent` fields work in `deps`. Use
[references](./variables.md#referencing-other-variables) to pass arrays and maps
without turning them into strings. To call a task for each value in a list, see
[Looping over tasks](./loops.md#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`][config] 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](./output.md) 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](./up-to-date.md).

## 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](./errors-and-cleanup.md#cleanup-with-defer).

[config]: ../reference/config.md

---

### Website Src Latest Docs Guide Environment (`website/src/latest/docs/guide/environment.md`)

---
title: Environment variables
description:
  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](./variables.md#env-and-vars-are-not-the-same-thing).

## 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](../experiments/env-precedence.md) changes this rule.

`env` values support templates and dynamic `sh` commands. For example, an entry
<span v-pre>`BUILD_MODE: '{{.MODE}}'`</span> 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 <span v-pre>`'{{.HOME}}/.env'`</span>.

The `dotenv` key is not supported inside included Taskfiles. Load shared values
in the entrypoint Taskfile instead. See [Including Taskfiles](./includes.md).

---

### Website Src Latest Docs Guide Errors And Cleanup (`website/src/latest/docs/guide/errors-and-cleanup.md`)

---
title: Errors and cleanup
description:
  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](./dependencies.md#fail-fast-dependencies).

## 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](../reference/cli.md#exit-codes). 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
description:
  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](./defining-tasks.md#task-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](./variables.md#resolution-order) 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](./defining-tasks.md#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](./platforms.md#platform-specific-tasks-and-commands) may
be easier to maintain.

::: tip Related guide

<span id="remote-taskfiles"></span>

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](../remote-taskfiles.md)
for a complete example, checksum pinning, and offline use.

:::

---

### Website Src Latest Docs Guide Loops (`website/src/latest/docs/guide/loops.md`)

---
title: Loops
description:
  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](#looping-over-dependencies) for
iterations that may run concurrently.

For a changing set of files, use
[a source glob](#looping-over-your-task-s-sources-or-generated-files) 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](./dependencies.md) 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](./up-to-date.md); 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
<span v-pre>`{{joinPath .TASK_DIR .ITEM}}`</span>. See the
[file-path variables](../reference/templating.md#file-paths) for the available
directory values.

---

### Website Src Latest Docs Guide Output (`website/src/latest/docs/guide/output.md`)

---
title: Output and logging
description:
  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](./secret-variables.md).

## 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](https://docs.github.com/en/actions/learn-github-actions/workflow-commands-for-github-actions#grouping-log-lines).
Other providers, such as
[Azure Pipelines](https://docs.microsoft.com/en-us/azure/devops/pipelines/scripts/logging-commands?expand=1&view=azure-devops&tabs=bash#formatting-commands),
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

<span id="ignore-errors"></span>

To continue after a selected failure, use `ignore_error`. See
[Errors and cleanup](./errors-and-cleanup.md#ignoring-command-errors) for its
scope and examples.

:::

---

### Website Src Latest Docs Guide Platforms (`website/src/latest/docs/guide/platforms.md`)

---
title: Platforms and shells
description:
  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](./includes.md#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`](./environment.md) 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](../reference/schema.md#shell-options).

`shopt` controls shell expansion inside commands. Globs in `sources` and
`generates` use [Task's file matching](./up-to-date.md#track-the-right-files)
and do not require `globstar`.

---

### Website Src Latest Docs Guide Required Variables (`website/src/latest/docs/guide/required-variables.md`)

---
title: Validation and prompts
description:
  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](./conditional-execution.md#using-programmatic-checks-to-cancel-the-execution-of-a-task-and-its-dependencies).

## 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](../reference/config.md#interactive):

```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

<span id="warning-prompts"></span>

A prompt for input fills in a value. A
[confirmation prompt](./conditional-execution.md#confirmation-prompts) 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
description:
  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](./defining-tasks.md#internal-tasks)
remain hidden. See [Defining tasks](./defining-tasks.md) to create these
entries.

Pass several names, such as `task lint test`, to run them in order. Use
[`--parallel`](./dependencies.md#limiting-how-much-runs-at-once) for independent
tasks that can run concurrently. To pass values or command arguments, see
[Command-line arguments](./arguments.md).

## 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](./variables.md#when-values-are-computed).

## 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](./defining-tasks.md#task-directory) changes it.

Use <span v-pre>`{{.USER_WORKING_DIR}}`</span> 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
<span v-pre>`{{.USER_WORKING_DIR}}`</span> 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](./output.md#output-syntax)
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](./required-variables.md#prompting-for-missing-variables-interactively).

## 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
description:
  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](./variables.md#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
description:
  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](./dependencies.md)
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](./defining-tasks.md#task-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](./watch.md) 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](./conditional-execution.md#using-programmatic-checks-to-cancel-the-execution-of-a-task-and-its-dependencies).

### 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`, <span v-pre>`{{.CHECKSUM}}`</span> contains the source
fingerprint. With `method: timestamp`, <span v-pre>`{{.TIMESTAMP}}`</span>
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,
<span v-pre>`{{.TIMESTAMP.Unix}}`</span> produces a Unix timestamp, and
<span v-pre>`{{.TIMESTAMP.Format "2006-01-02"}}`</span> 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](../reference/cli.md#exit-codes) 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](./watch.md).

## 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`](./dependencies.md#repeated-calls).

## 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
description:
  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](#resolution-order) explains how values from different places
interact.

<span id="command-line-values"></span>

Pass `NAME=value` on the command line to supply variables to Task. See
[Command-line arguments](./arguments.md#variable-assignments) 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`](#parsing-json-yaml-into-map-variables).

## 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
<span v-pre>`SERVICES: '{{.SERVICES}}'`</span> 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][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              | <span v-pre>`{{.FOO}}`</span>              | `$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 <span v-pre>`{{.FOO}}`</span>
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](../experiments/env-precedence.md) 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 <span v-pre>`{{ }}`</span>. A template renders a string; `ref:`
preserves the type.

::: tip Related guide

<span id="secret-variables"></span>

Mark sensitive values with `secret: true` to mask them in Task's own command
logs. See [Secret variables](./secret-variables.md) for examples, loading values
from external sources and the limits of masking.

:::

[templating-reference]: ../reference/templating.md

---

### Website Src Latest Docs Guide Watch (`website/src/latest/docs/guide/watch.md`)

---
title: Watch mode
description: Re-run a task automatically whenever its sources change.
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](./up-to-date.md) 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](https://github.com/go-task/task/issues/160) 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](https://github.com/air-verse/air/). Report Task-specific problems with
a small reproducer in the
[issue tracker](https://github.com/go-task/task/issues/new?template=bug_report.yml).

---

### Website Src Latest Docs Reference Cli (`website/src/latest/docs/reference/cli.md`)

---
title: Command Line Interface Reference
description: Complete reference for Task CLI commands, flags, and exit codes
permalink: /reference/cli/
section: Reference
docType: reference
outline: deep
---

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

- [Configuration files](./config.md)
- [Environment variables](./environment.md)
- _Command-line flags_

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.

- **Config equivalent**: [`verbose`](./config.md#verbose)
- **Environment variable**: [`TASK_VERBOSE`](./environment.md#task-verbose)

```bash
task build --verbose
```

#### `-s, --silent`

Disable command echoing.

- **Config equivalent**: [`silent`](./config.md#silent)
- **Environment variable**: [`TASK_SILENT`](./environment.md#task-silent)

```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.

- **Config equivalent**: [`disable-fuzzy`](./config.md#disable-fuzzy)
- **Environment variable**:
  [`TASK_DISABLE_FUZZY`](./environment.md#task-disable-fuzzy)

```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.

- **Config equivalent**: [`failfast`](./config.md#failfast)
- **Environment variable**: [`TASK_FAILFAST`](./environment.md#task-failfast)

```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.

- **Environment variable**: [`TASK_DRY`](./environment.md#task-dry)

```bash
task deploy --dry
```

#### `-p, --parallel`

Execute multiple tasks in parallel.

```bash
task test lint --parallel
```

#### `-C, --concurrency <number>`

Limit the number of concurrent tasks. Zero means unlimited.

- **Config equivalent**: [`concurrency`](./config.md#concurrency)
- **Environment variable**:
  [`TASK_CONCURRENCY`](./environment.md#task-concurrency)

```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 <path>`

Set the directory where Task will run and look for Taskfiles.

```bash
task build --dir ./backend
```

#### `-t, --taskfile <file>`

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 <path>`

Set the directory used to store Task temporary files, such as checksums.
Relative paths are relative to the root Taskfile.

- **Config equivalent**: [`temp-dir`](./config.md#temp-dir)
- **Environment variable**: [`TASK_TEMP_DIR`](./environment.md#task-temp-dir)

```bash
task build --temp-dir .task-cache
```

### Output Control

#### `-o, --output <mode>`

Set output style. Available modes: `interleaved`, `group`, `prefixed`.

- **Environment variable**: [`TASK_OUTPUT`](./environment.md#task-output)

```bash
task test --output group
```

#### `--output-group-begin <template>`

Message template to print before grouped output.

- **Environment variable**:
  [`TASK_OUTPUT_GROUP_BEGIN`](./environment.md#task-output-group-begin)

```bash
task test --output group --output-group-begin "::group::{{.TASK}}"
```

#### `--output-group-end <template>`

Message template to print after grouped output.

- **Environment variable**:
  [`TASK_OUTPUT_GROUP_END`](./environment.md#task-output-group-end)

```bash
task test --output group --output-group-end "::endgroup::"
```

#### `--output-group-error-only`

Only show command output on non-zero exit codes.

- **Environment variable**:
  [`TASK_OUTPUT_GROUP_ERROR_ONLY`](./environment.md#task-output-group-error-only)

```bash
task test --output group --output-group-error-only
```

#### `-c, --color`

Control colored output. Enabled by default.

- **Config equivalent**: [`color`](./config.md#color)
- **Environment variable**: [`TASK_COLOR`](./environment.md#task-color)

```bash
task build --color=false
# or use environment variable
NO_COLOR=1 task build
```

### Task Information

#### `--status`

Check if tasks are up-to-date without running them.

```bash
task build --status
```

#### `--summary`

Show detailed information about a task.

```bash
task build --summary
```

#### `--json`

Output task information in JSON format (use with `--list` or `--list-all`).

```bash
task --list --json
```

#### `--sort <mode>`

Change task listing order. Available modes:

- `default` - Sorts tasks alphabetically by name, but ensures that root tasks
  (tasks without a namespace) are listed before namespaced tasks.
- `alphanumeric` - Sort tasks alphabetically by name.
- `none` - No sorting. Uses the order as defined in the Taskfile.

```bash
task --list --sort alphanumeric
```

### Watch Mode

#### `-w, --watch`

Watch for file changes and re-run tasks automatically.

```bash
task build --watch
```

#### `-I, --interval <duration>`

Set watch interval (default: `5s`). Must be a valid
[Go duration](https://pkg.go.dev/time#ParseDuration).

```bash
task build --watch --interval 1s
```

### Interactive

#### `-y, --yes`

Automatically answer "yes" to all prompts.

- **Environment variable**:
  [`TASK_ASSUME_YES`](./environment.md#task-assume-yes)

```bash
task deploy --yes
```

#### `--interactive`

Enable interactive prompts for missing required variables. When a required
variable is not provided, Task will prompt for input instead of failing.

Task automatically detects non-TTY environments (like CI pipelines) and skips
prompts. This flag can also be set in `.taskrc.yml` to enable prompts by
default.

- **Environment variable**:
  [`TASK_INTERACTIVE`](./environment.md#task-interactive)

```bash
task deploy --interactive
```

### Remote

The following flags are used to control the behavior of
[remote Taskfiles](../remote-taskfiles.md).

#### `--insecure`

Allow insecure connections when fetching remote Taskfiles.

#### `--offline`

Work in offline mode, preventing remote Taskfile fetching.

#### `--download`

Forces task to download remote Taskfiles and ignore any cached versions.

#### `--timeout`

Timeout duration for remote operations (e.g., '30s', '5m').

#### `--clear-cache`

Wipe the cache of remote Taskfiles and checksums.

#### `--expiry`

Cache expiry duration for remote Taskfiles (e.g., '1h', '24h').

#### `--remote-cache-dir`

Directory where remote Taskfiles are cached. Can be an absolute path (e.g.,
`/var/cache/task`) or relative to the Taskfile directory.

#### `--trusted-hosts`

List of (comma-separated) trusted hosts for remote Taskfiles. Hosts in this list
will not prompt for confirmation when downloading Taskfiles.

Hosts in the trusted hosts list will automatically be trusted without prompting
for confirmation when they are first downloaded or when their checksums change.
The host matching includes the port if specified in the URL. Use with caution
and only add hosts you fully trust.

#### `--cacert`

Path to a custom CA certificate file for TLS verification.

#### `--cert`

Path to a client certificate file for mTLS authentication.

#### `--cert-key`

Path to the client certificate private key file.

## Exit Codes

Task uses specific exit codes to indicate different types of errors:

### Success

- **0** - Success

### General Errors (1-99)

- **1** - Unknown error occurred

### Taskfile Errors (100-199)

- **100** - No Taskfile found
- **101** - Taskfile already exists (when using `--init`)
- **102** - Invalid or unparseable Taskfile
- **103** - Remote Taskfile download failed
- **104** - Remote Taskfile not trusted
- **105** - Remote Taskfile fetch not secure
- **106** - No cache for remote Taskfile in offline mode
- **107** - No schema version defined in Taskfile
- **108** - Remote Taskfile network timeout
- **109** - Invalid Taskfile
- **110** - Taskfile cycle detected
- **111** - Taskfile does not match checksum

### Task Errors (200-255)

- **200** - Task not found
- **201** - Command execution error
- **202** - Attempted to run internal task
- **203** - Multiple tasks with same name/alias
- **204** - Task called too many times (recursion limit)
- **205** - Task cancelled by user
- **206** - Missing required variables
- **207** - Variable has incorrect value
- **208** - Task timed out

::: info

When using `-x/--exit-code`, failed command exit codes are passed through
instead of the above codes.

:::

::: tip

The complete list of exit codes is available in the repository at
[`errors/errors.go`](https://github.com/go-task/task/blob/main/errors/errors.go).

:::

## JSON Output Format

When using `--json` with `--list` or `--list-all`:

```json
{
  "tasks": [
    {
      "name": "build",
      "task": "build",
      "desc": "Build the application",
      "summary": "Compiles the source code and generates binaries",
      "up_to_date": false,
      "location": {
        "line": 12,
        "column": 3,
        "taskfile": "/path/to/Taskfile.yml"
      }
    }
  ],
  "location": "/path/to/Taskfile.yml"
}
```

---

### Website Src Latest Docs Reference Config (`website/src/latest/docs/reference/config.md`)

---
title: Configuration Reference
description: Complete reference for the Task config files and env vars
permalink: /reference/config/
section: Reference
docType: reference
outline: deep
---

# Configuration Reference

Task has multiple ways of being configured. These methods are parsed, in
sequence, in the following order with the highest priority last:

- _Configuration files_
- [Environment variables](./environment.md)
- [Command-line flags](./cli.md)

In this document, we will look at the first of the three options, configuration
files.

## File Precedence

Task will automatically look for directories containing configuration files in
the following order with the highest priority first:

- Current directory (or the one specified by the `--taskfile`/`--entrypoint`
  flags).
- Each directory walking up the file tree from the current directory (or the one
  specified by the `--taskfile`/`--entrypoint` flags) until we reach the user's
  home directory or the root directory of that drive.
- The users `$HOME` directory.
- The `$XDG_CONFIG_HOME/task` directory.

Config files in the current directory, its parent folders or home directory
should be called `.taskrc.yml` or `.taskrc.yaml`. Config files in the
`$XDG_CONFIG_HOME/task` directory are named the same way, but should not contain
the `.` prefix.

All config files will be merged together into a unified config, starting with
the lowest priority file in `$XDG_CONFIG_HOME/task` with each subsequent file
overwriting the previous one if values are set.

For example, given the following files:

```yaml [$XDG_CONFIG_HOME/task/taskrc.yml]
# lowest priority global config
option_1: foo
option_2: foo
option_3: foo
```

```yaml [$HOME/.taskrc.yml]
option_1: bar
option_2: bar
```

```yaml [$HOME/path/to/project/.taskrc.yml]
# highest priority project config
option_1: baz
```

You would end up with the following configuration:

```yaml
option_1: baz # Taken from $HOME/path/to/project/.taskrc.yml
option_2: bar # Taken from $HOME/.taskrc.yml
option_3: foo # Taken from $XDG_CONFIG_HOME/task/.taskrc.yml
```

## Configuration Options

### `experiments`

The experiments section allows you to enable Task's experimental features. These
options are not enumerated here. Instead, please refer to our
[experiments documentation](../experiments/index.md) for more information.

```yaml
experiments:
  feature_name: 1
  another_feature: 2
```

### `verbose`

- **Type**: `boolean`
- **Default**: `false`
- **Description**: Enable verbose output for all tasks
- **CLI equivalent**: [`-v, --verbose`](./cli.md#v-verbose)
- **Environment variable**: [`TASK_VERBOSE`](./environment.md#task-verbose)

```yaml
verbose: true
```

### `silent`

- **Type**: `boolean`
- **Default**: `false`
- **Description**: Disables echoing of commands
- **CLI equivalent**: [`-s, --silent`](./cli.md#s-silent)
- **Environment variable**: [`TASK_SILENT`](./environment.md#task-silent)

```yaml
silent: true
```

### `color`

- **Type**: `boolean`
- **Default**: `true`
- **Description**: Enable colored output. Colors are automatically enabled in CI
  environments (`CI=true`).
- **CLI equivalent**: [`-c, --color`](./cli.md#c-color)
- **Environment variable**: [`TASK_COLOR`](./environment.md#task-color)

```yaml
color: false
```

### `disable-fuzzy`

- **Type**: `boolean`
- **Default**: `false`
- **Description**: Disable fuzzy matching for task names. When enabled, Task
  will not suggest similar task names when you mistype a task name.
- **CLI equivalent**: [`--disable-fuzzy`](./cli.md#disable-fuzzy)
- **Environment variable**:
  [`TASK_DISABLE_FUZZY`](./environment.md#task-disable-fuzzy)

```yaml
disable-fuzzy: true
```

### `concurrency`

- **Type**: `integer`
- **Minimum**: `1`
- **Description**: Number of concurrent tasks to run
- **CLI equivalent**: [`-C, --concurrency`](./cli.md#c-concurrency-number)
- **Environment variable**:
  [`TASK_CONCURRENCY`](./environment.md#task-concurrency)

```yaml
concurrency: 4
```

### `failfast`

- **Type**: `boolean`
- **Default**: `false`
- **Description**: Stop executing dependencies as soon as one of them fail
- **CLI equivalent**: [`-F, --failfast`](./cli.md#f-failfast)
- **Environment variable**: [`TASK_FAILFAST`](./environment.md#task-failfast)

```yaml
failfast: true
```

### `interactive`

- **Type**: `boolean`
- **Default**: `false`
- **Description**: Prompt for missing required variables instead of failing.
  When enabled, Task will display an interactive prompt for any missing required
  variable. Requires a TTY. Task automatically detects non-TTY environments (CI
  pipelines, etc.) and skips prompts.
- **CLI equivalent**: [`--interactive`](./cli.md#interactive)

```yaml
interactive: true
```

### `temp-dir`

- **Type**: `string`
- **Default**: `./.task`
- **Description**: Directory to store Task temporary files, such as checksums
  and temporary metadata. Relative paths are relative to the root Taskfile.
- **Environment variable**: [`TASK_TEMP_DIR`](./environment.md#task-temp-dir)

```yaml
temp-dir: .task
```

### `remote`

- **Type**: `object`
- **Description**: Remote configuration settings for handling
  [remote Taskfiles](../remote-taskfiles.md).

#### `remote.insecure`

- **Type**: `boolean`
- **Default**: `false`
- **Description**: Allow insecure connections when fetching remote Taskfiles
- **CLI equivalent**: `--insecure`
- **Environment variable**:
  [`TASK_REMOTE_INSECURE`](./environment.md#task-remote-insecure)

```yaml
remote:
  insecure: true
```

#### `remote.offline`

- **Type**: `boolean`
- **Default**: `false`
- **Description**: Work in offline mode, preventing remote Taskfile fetching
- **CLI equivalent**: `--offline`
- **Environment variable**:
  [`TASK_REMOTE_OFFLINE`](./environment.md#task-remote-offline)

```yaml
remote:
  offline: true
```

#### `remote.timeout`

- **Type**: `string`
- **Default**: 10s
- **Pattern**: `^[0-9]+(ns|us|µs|ms|s|m|h)$`
- **Description**: Timeout duration for remote operations (e.g., '30s', '5m')
- **CLI equivalent**: `--timeout`
- **Environment variable**:
  [`TASK_REMOTE_TIMEOUT`](./environment.md#task-remote-timeout)

```yaml
remote:
  timeout: '1m'
```

#### `remote.cache-expiry`

- **Type**: `string`
- **Default**: 0s (no cache)
- **Pattern**: `^[0-9]+(ns|us|µs|ms|s|m|h)$`
- **Description**: Cache expiry duration for remote Taskfiles (e.g., '1h',
  '24h')
- **CLI equivalent**: `--expiry`
- **Environment variable**:
  [`TASK_REMOTE_CACHE_EXPIRY`](./environment.md#task-remote-cache-expiry)

```yaml
remote:
  cache-expiry: '6h'
```

#### `remote.cache-dir`

- **Type**: `string`
- **Default**: `.task`
- **Description**: Directory where remote Taskfiles are cached. Can be an
  absolute path (e.g., `/var/cache/task`) or relative to the Taskfile directory.
- **CLI equivalent**: `--remote-cache-dir`
- **Environment variable**:
  [`TASK_REMOTE_CACHE_DIR`](./environment.md#task-remote-cache-dir)

```yaml
remote:
  cache-dir: ~/.task
```

#### `remote.trusted-hosts`

- **Type**: `array of strings`
- **Default**: `[]` (empty list)
- **Description**: List of trusted hosts for remote Taskfiles. Hosts in this
  list will not prompt for confirmation when downloading Taskfiles
- **CLI equivalent**: `--trusted-hosts`
- **Environment variable**:
  [`TASK_REMOTE_TRUSTED_HOSTS`](./environment.md#task-remote-trusted-hosts)
  (comma-separated)

```yaml
remote:
  trusted-hosts:
    - github.com
    - gitlab.com
    - raw.githubusercontent.com
    - example.com:8080
```

Hosts in the trusted hosts list will automatically be trusted without prompting
for confirmation when they are first downloaded or when their checksums change.
The host matching includes the port if specified in the URL. Use with caution
and only add hosts you fully trust.

You can also specify trusted hosts via the command line:

```shell
# Trust specific host for this execution
task --trusted-hosts github.com -t https://github.com/user/repo.git//Taskfile.yml

# Trust multiple hosts (comma-separated)
task --trusted-hosts github.com,gitlab.com -t https://github.com/user/repo.git//Taskfile.yml

# Trust a host with a specific port
task --trusted-hosts example.com:8080 -t https://example.com:8080/Taskfile.yml
```

#### `remote.headers`

- **Type**: `array of objects`
- **Default**: `[]` (empty list)
- **Description**: HTTP headers to send when downloading a remote Taskfile from
  a given host, including authentication and custom headers

```yaml
remote:
  headers:
    - host: gitlab.com
      headers:
        PRIVATE-TOKEN: '{{env "GITLAB_TOKEN"}}'
    - host: artifacts.example.com:8443
      headers:
        Authorization: 'Bearer {{env "ARTIFACTS_TOKEN"}}'
        Accept: application/yaml
        X-Custom-Header: custom-value
```

Use this option for authentication, content negotiation or other headers your
server expects. For authentication, this is the recommended way to access a
remote Taskfile. Unlike a credential placed in the URL, the header never appears
in your Taskfile, in the confirmation prompt or in an error message, so the
include URL stays safe to commit.

Each entry applies to a single host, matched exactly and including the port if
the URL has one — the same rule as
[`remote.trusted-hosts`](#remote-trusted-hosts). Header values may reference
[templating functions](./templating.md), evaluated when Task contacts the host.
Values starting with <span v-pre>`{{`</span> must be quoted, as YAML would
otherwise read them as a mapping. An undefined environment variable expands to
nothing, so the header is sent empty. For an authentication header, this may
cause the server to reject the request with a `401`.

Functions compose, so an `Authorization` header needs no manual encoding:

```yaml
remote:
  headers:
    - host: artifacts.example.com
      headers:
        Authorization: 'Basic {{ printf "%s:%s" (env "USER") (env "PASS") | b64enc }}'
```

::: warning

Only functions are available here — <span v-pre>`{{.GITLAB_TOKEN}}`</span> and
other variable references resolve to nothing. The configuration file is read
before any Taskfile, so no variable exists yet. Use
<span v-pre>`{{env "GITLAB_TOKEN"}}`</span> instead.

:::

The header your server expects depends on the service:

| Service     | Header                                 |
| ----------- | -------------------------------------- |
| GitLab API  | `PRIVATE-TOKEN` (or `JOB-TOKEN` in CI) |
| GitHub API  | `Authorization: Bearer <token>`        |
| Artifactory | `X-JFrog-Art-Api`                      |

There is no CLI flag or environment variable for this option: a token given on
the command line would be visible to any process listing it.

::: warning

Headers are only sent to the host they are configured for. If that host answers
with a redirect to another one, the request follows the redirect **without**
them, and will likely fail — point the URL at the final host instead. Headers
are also HTTP-only: a Taskfile fetched over `git` should authenticate with SSH
or a git credential helper.

:::

#### `remote.cacert`

- **Type**: `string`
- **Default**: `""`
- **Description**: Path to a custom CA certificate file for TLS verification

```yaml
remote:
  cacert: '/path/to/ca.crt'
```

#### `remote.cert`

- **Type**: `string`
- **Default**: `""`
- **Description**: Path to a client certificate file for mTLS authentication

```yaml
remote:
  cert: '/path/to/client.crt'
```

#### `remote.cert-key`

- **Type**: `string`
- **Default**: `""`
- **Description**: Path to the client certificate private key file

```yaml
remote:
  cert-key: '/path/to/client.key'
```

## Example Configuration

Here's a complete example of a `.taskrc.yml` file with all available options:

```yaml
# Global settings
verbose: true
silent: false
color: true
disable-fuzzy: false
concurrency: 2
temp-dir: .task
remote:
  insecure: false
  offline: false
  timeout: '30s'
  cache-expiry: '24h'
  cache-dir: ~/.task
  trusted-hosts:
    - github.com
    - gitlab.com
  headers:
    - host: gitlab.com
      headers:
        PRIVATE-TOKEN: '{{env "GITLAB_TOKEN"}}'
  cacert: ''
  cert: ''
  cert-key: ''

# Enable experimental features
experiments:
  GENTLE_FORCE: 1
```

---

### Website Src Latest Docs Reference Environment (`website/src/latest/docs/reference/environment.md`)

---
title: Environment Reference
description: A reference for the Taskfile environment variables
section: Reference
docType: reference
outline: deep
---

# Environment Reference

Task has multiple ways of being configured. These methods are parsed, in
sequence, in the following order with the highest priority last:

- [Configuration files](./config.md)
- _Environment variables_
- [Command-line flags](./cli.md)

In this document, we will look at the second of the three options, environment
variables. All Task-specific variables are prefixed with `TASK_` and override
their configuration file equivalents.

## Variables

All [configuration file options](./config.md) can also be set via environment
variables. The priority order is: CLI flags > environment variables > config
files > defaults.

### `TASK_VERBOSE`

- **Type**: `boolean` (`true`, `false`, `1`, `0`)
- **Default**: `false`
- **Description**: Enable verbose output for all tasks
- **Config equivalent**: [`verbose`](./config.md#verbose)

### `TASK_SILENT`

- **Type**: `boolean` (`true`, `false`, `1`, `0`)
- **Default**: `false`
- **Description**: Disables echoing of commands
- **Config equivalent**: [`silent`](./config.md#silent)

### `TASK_COLOR`

- **Type**: `boolean` (`true`, `false`, `1`, `0`)
- **Default**: `true`
- **Description**: Enable colored output
- **Config equivalent**: [`color`](./config.md#color)

### `TASK_DISABLE_FUZZY`

- **Type**: `boolean` (`true`, `false`, `1`, `0`)
- **Default**: `false`
- **Description**: Disable fuzzy matching for task names
- **Config equivalent**: [`disable-fuzzy`](./config.md#disable-fuzzy)

### `TASK_CONCURRENCY`

- **Type**: `integer`
- **Description**: Limit number of tasks to run concurrently
- **Config equivalent**: [`concurrency`](./config.md#concurrency)

### `TASK_FAILFAST`

- **Type**: `boolean` (`true`, `false`, `1`, `0`)
- **Default**: `false`
- **Description**: When running tasks in parallel, stop all tasks if one fails
- **Config equivalent**: [`failfast`](./config.md#failfast)

### `TASK_DRY`

- **Type**: `boolean` (`true`, `false`, `1`, `0`)
- **Default**: `false`
- **Description**: Compiles and prints tasks in the order that they would be
  run, without executing them

### `TASK_ASSUME_YES`

- **Type**: `boolean` (`true`, `false`, `1`, `0`)
- **Default**: `false`
- **Description**: Assume "yes" as answer to all prompts

### `TASK_INTERACTIVE`

- **Type**: `boolean` (`true`, `false`, `1`, `0`)
- **Default**: `false`
- **Description**: Prompt for missing required variables

### `TASK_OUTPUT`

- **Type**: `string` (`interleaved`, `group`, `prefixed`)
- **Description**: Sets the output style
- **CLI equivalent**: [`--output`](./cli.md#o-output-mode)

### `TASK_OUTPUT_GROUP_BEGIN`

- **Type**: `string`
- **Description**: Message template to print before a task's grouped output.
  Only applies when the output style is `group`.
- **CLI equivalent**:
  [`--output-group-begin`](./cli.md#output-group-begin-template)

### `TASK_OUTPUT_GROUP_END`

- **Type**: `string`
- **Description**: Message template to print after a task's grouped output. Only
  applies when the output style is `group`.
- **CLI equivalent**:
  [`--output-group-end`](./cli.md#output-group-end-template)

### `TASK_OUTPUT_GROUP_ERROR_ONLY`

- **Type**: `boolean` (`true`, `false`, `1`, `0`)
- **Default**: `false`
- **Description**: Swallow output from successful tasks. Only applies when the
  output style is `group`.
- **CLI equivalent**:
  [`--output-group-error-only`](./cli.md#output-group-error-only)

### `TASK_TEMP_DIR`

Defines the location of Task's temporary directory which is used for storing
checksums and temporary metadata. Can be relative like `tmp/task` or absolute
like `/tmp/.task` or `~/.task`. Relative paths are relative to the root
Taskfile, not the working directory. Defaults to: `./.task`.

### `TASK_CORE_UTILS`

This env controls whether the Bash interpreter will use its own core utilities
implemented in Go, or the ones available in the system. Valid values are `true`
(`1`) or `false` (`0`). By default, this is `true` on Windows and `false` on
other operating systems. We might consider making this enabled by default on all
platforms in the future.

### `FORCE_COLOR`

Force color output usage.

## Remote Taskfile Variables

The following variables are used to control the behavior of
[remote Taskfiles](../remote-taskfiles.md).

### `TASK_REMOTE_INSECURE`

Allow insecure connections when fetching remote Taskfiles.

### `TASK_REMOTE_OFFLINE`

Work in offline mode, preventing remote Taskfile fetching.

### `TASK_REMOTE_TIMEOUT`

Timeout duration for remote operations (e.g., '30s', '5m').

### `TASK_REMOTE_CACHE_EXPIRY`

Cache expiry duration for remote Taskfiles (e.g., '1h', '24h').

### `TASK_REMOTE_CACHE_DIR`

Directory where remote Taskfiles are cached. Can be an absolute path (e.g.,
`/var/cache/task`) or relative to the Taskfile directory.

### `TASK_REMOTE_TRUSTED_HOSTS`

List of (comma-separated) trusted hosts for remote Taskfiles. Hosts in this list
will not prompt for confirmation when downloading Taskfiles.

Hosts in the trusted hosts list will automatically be trusted without prompting
for confirmation when they are first downloaded or when their checksums change.
The host matching includes the port if specified in the URL. Use with caution
and only add hosts you fully trust.

### `TASK_REMOTE_CACERT`

Path to a custom CA certificate file for TLS verification.

### `TASK_REMOTE_CERT`

Path to a client certificate file for mTLS authentication.

### `TASK_REMOTE_CERT_KEY`

Path to the client certificate private key file.

### Custom Colors

All color variables are [ANSI color codes][ansi]. You can specify multiple codes
separated by a semicolon. For example: `31;1` will make the text bold and red.
Task also supports 8-bit color (256 colors). You can specify these colors by
using the sequence `38;2;R:G:B` for foreground colors and `48;2;R:G:B` for
background colors where `R`, `G` and `B` should be replaced with values between
0 and 255.

For convenience, we allow foreground colors to be specified using shorthand,
comma-separated syntax: `R,G,B`. For example, `255,0,0` is equivalent to
`38;2;255:0:0`.

A table of variables and their defaults can be found below:

| ENV                         | Default |
| --------------------------- | ------- |
| `TASK_COLOR_RESET`          | `0`     |
| `TASK_COLOR_RED`            | `31`    |
| `TASK_COLOR_GREEN`          | `32`    |
| `TASK_COLOR_YELLOW`         | `33`    |
| `TASK_COLOR_BLUE`           | `34`    |
| `TASK_COLOR_MAGENTA`        | `35`    |
| `TASK_COLOR_CYAN`           | `36`    |
| `TASK_COLOR_BRIGHT_RED`     | `91`    |
| `TASK_COLOR_BRIGHT_GREEN`   | `92`    |
| `TASK_COLOR_BRIGHT_YELLOW`  | `93`    |
| `TASK_COLOR_BRIGHT_BLUE`    | `94`    |
| `TASK_COLOR_BRIGHT_MAGENTA` | `95`    |
| `TASK_COLOR_BRIGHT_CYAN`    | `96`    |

[ansi]: https://en.wikipedia.org/wiki/ANSI_escape_code

---

### Website Src Latest Docs Reference Package (`website/src/latest/docs/reference/package.md`)

---
title: Package API Reference
description: A reference for Task's Golang package API
section: Reference
docType: reference
---

# Package API Reference

::: warning

**_Task's package API is still experimental and subject to breaking changes._**

This means that unlike our CLI, we may make breaking changes to the package API
in minor (or even patch) releases. We try to avoid this when possible, but it
may be necessary in order to improve the overall design of the package API.

In the future we may stabilize the package API. However, this is not currently
planned. For now, if you need to use Task as a Go package, we recommend pinning
the version in your `go.mod` file. Where possible we will try to include a
changelog entry for breaking changes to the package API.

:::

Task is primarily a CLI tool that is agnostic of any programming language.
However, it is written in Go and therefore can also be used as a Go package too.
This can be useful if you are already using Go in your project and you need to
extend Task's functionality in some way. In this document, we describe the
public API surface of Task and how to use it. This may also be useful if you
want to contribute to Task or understand how it works in more detail.

## Key packages

The following packages make up the most important parts of Task's package API.
Below we have listed what they are for and some of the key types available:

### [`github.com/go-task/task/v3`]

The core task package provides most of the main functionality for Task including
fetching and executing tasks from a Taskfile. At this time, the vast majority of
the this package's functionality is exposed via the [`task.Executor`] which
allows the user to fetch and execute tasks from a Taskfile.

::: info

This is the package which is most likely to be the subject of breaking changes
as we refine the API.

:::

### [`github.com/go-task/task/v3/taskfile`]

The `taskfile` package provides utilities for _reading_ Taskfiles from various
sources. These sources can be local files, remote files, or even in-memory
strings (via stdin).

- [`taskfile.Node`] - A reference to the location of a Taskfile. A `Node` is an
  interface that has several implementations:
  - [`taskfile.FileNode`] - Local files
  - [`taskfile.HTTPNode`] - Remote files via HTTP/HTTPS
  - [`taskfile.GitNode`] - Remote files via Git
  - [`taskfile.StdinNode`] - In-memory strings (via stdin)
- [`taskfile.Reader`] - Accepts a `Node` and reads the Taskfile from it.
- [`taskfile.Snippet`] - Mostly used for rendering Taskfile errors. A snippet
  stores a small part of a taskfile around a given line number and column. The
  output can be syntax highlighted for CLIs and include line/column indicators.

### [`github.com/go-task/task/v3/taskfile/ast`]

AST stands for ["Abstract Syntax Tree"][ast]. An AST allows us to easily
represent the Taskfile syntax in Go. This package provides a way to parse
Taskfile YAML into an AST and store them in memory.

- [`ast.TaskfileGraph`] - Represents a set of Taskfiles and their dependencies
  between one another.
- [`ast.Taskfile`] - Represents a single Taskfile or a set of merged Taskfiles.
  The `Taskfile` type contains all of the subtypes for the Taskfile syntax, such
  as `tasks`, `includes`, `vars`, etc. These are not listed here for brevity.

### [`github.com/go-task/task/v3/errors`]

Contains all of the error types used in Task. All of these types implement the
[`errors.TaskError`] interface which wraps Go's standard [`error`] interface.
This allows you to call the `Code` method on the error to obtain the unique exit
code for any error.

## Reading Taskfiles

Start by importing the `github.com/go-task/task/v3/taskfile` package. This
provides all of the functions you need to read a Taskfile into memory:

```go
import (
    "github.com/go-task/task/v3/taskfile"
)
```

Reading Taskfiles is done by using a [`taskfile.Reader`] and an implementation
of [`taskfile.Node`]. In this example we will read a local file by using the
[`taskfile.FileNode`] type. You can create this by calling the
[`taskfile.NewFileNode`] function:

```go
node := taskfile.NewFileNode("Taskfile.yml", "./path/to/dir")
```

and then create a your reader by calling the [`taskfile.NewReader`] function and
passing any functional options you want to use. For example, you could pass a
debug function to the reader which will be called with debug messages:

```go
reader := taskfile.NewReader(
  taskfile.WithDebugFunc(func(s string) {
    slog.Debug(s)
  }),
)
```

Now that everything is set up, you can read the Taskfile (and any included
Taskfiles) by calling the `Read` method on the reader and pass the `Node` as an
argument:

```go
ctx := context.Background()
tfg, err := reader.Read(ctx, node)
// handle error
```

This returns an instance of [`ast.TaskfileGraph`] which is a "Directed Acyclic
Graph" (DAG) of all the parsed Taskfiles. We use this graph to store and resolve
the `includes` directives in Taskfiles. However most of the time, you will want
a merged Taskfile. To do this, simply call the `Merge` method on the Taskfile
graph:

```go
tf, err := tfg.Merge()
// handle error
```

This compiles the DAG into a single [`ast.Taskfile`] containing all the
namespaces and tasks from all the Taskfiles we read.

::: info

We plan to remove AST merging in the future as it is unnecessarily complex and
causes lots of issues with scoping.

:::

[`github.com/go-task/task/v3`]: https://pkg.go.dev/github.com/go-task/task/v3
[`github.com/go-task/task/v3/taskfile`]:
  https://pkg.go.dev/github.com/go-task/task/v3/taskfile
[`github.com/go-task/task/v3/taskfile/ast`]:
  https://pkg.go.dev/github.com/go-task/task/v3/taskfile/ast
[`github.com/go-task/task/v3/errors`]:
  https://pkg.go.dev/github.com/go-task/task/v3/errors
[`ast.TaskfileGraph`]:
  https://pkg.go.dev/github.com/go-task/task/v3/taskfile/ast#TaskfileGraph
[`ast.Taskfile`]:
  https://pkg.go.dev/github.com/go-task/task/v3/taskfile/ast#Taskfile
[`taskfile.Node`]: https://pkg.go.dev/github.com/go-task/task/v3/taskfile#Node
[`taskfile.FileNode`]:
  https://pkg.go.dev/github.com/go-task/task/v3/taskfile#FileNode
[`taskfile.HTTPNode`]:
  https://pkg.go.dev/github.com/go-task/task/v3/taskfile#HTTPNode
[`taskfile.GitNode`]:
  https://pkg.go.dev/github.com/go-task/task/v3/taskfile#GitNode
[`taskfile.StdinNode`]:
  https://pkg.go.dev/github.com/go-task/task/v3/taskfile#StdinNode
[`taskfile.NewFileNode`]:
  https://pkg.go.dev/github.com/go-task/task/v3/taskfile#NewFileNode
[`taskfile.Reader`]:
  https://pkg.go.dev/github.com/go-task/task/v3/taskfile#Reader
[`taskfile.NewReader`]:
  https://pkg.go.dev/github.com/go-task/task/v3/taskfile#NewReader
[`taskfile.Snippet`]:
  https://pkg.go.dev/github.com/go-task/task/v3/taskfile#Snippet
[`task.Executor`]: https://pkg.go.dev/github.com/go-task/task/v3#Executor
[`task.Formatter`]: https://pkg.go.dev/github.com/go-task/task/v3#Formatter
[`errors.TaskError`]:
  https://pkg.go.dev/github.com/go-task/task/v3/errors#TaskError
[`error`]: https://pkg.go.dev/builtin#error
[ast]: https://en.wikipedia.org/wiki/Abstract_syntax_tree

---

### Website Src Latest Docs Reference Schema (`website/src/latest/docs/reference/schema.md`)

---
title: Taskfile Schema Reference
description: A reference for the Taskfile schema
section: Reference
docType: reference
outline: deep
---

# Taskfile Schema Reference

This page documents all available properties and types for the Taskfile schema
version 3, based on the
[official JSON schema](https://taskfile.dev/schema.json).

## Root Schema

The root Taskfile schema defines the structure of your main `Taskfile.yml`.

### `version`

- **Type**: `string` or `number`
- **Required**: Yes
- **Valid values**: `"3"`, `3`, or any valid semver string
- **Description**: Version of the Taskfile schema

```yaml
version: '3'
```

### `output`

- **Type**: `string` or `object`
- **Default**: `interleaved`
- **Options**: `interleaved`, `group`, `prefixed`
- **Description**: Controls how task output is displayed

```yaml
# Simple string format
output: group

# Advanced object format
output:
  group:
    begin: "::group::{{.TASK}}"
    end: "::endgroup::"
    error_only: false
```

### `method`

- **Type**: `string`
- **Default**: `checksum`
- **Options**: `checksum`, `timestamp`, `none`
- **Description**: Default method for checking if tasks are up-to-date

```yaml
method: timestamp
```

### [`includes`](#include)

- **Type**: `map[string]Include`
- **Description**: Include other Taskfiles

```yaml
includes:
  # Simple string format
  docs: ./Taskfile.yml

  # Full object format
  backend:
    taskfile: ./backend
    dir: ./backend
    optional: false
    flatten: false
    internal: false
    aliases: [api]
    excludes: [internal-task]
    vars:
      SERVICE_NAME: backend
    checksum: abc123...
```

### [`vars`](#variable)

- **Type**: `map[string]Variable`
- **Description**: Global variables available to all tasks

```yaml
vars:
  # Simple values
  APP_NAME: myapp
  VERSION: 1.0.0
  DEBUG: true
  PORT: 8080
  FEATURES: [auth, logging]

  # Dynamic variables
  COMMIT_HASH:
    sh: git rev-parse HEAD

  # Variable references
  BUILD_VERSION:
    ref: .VERSION

  # Map variables
  CONFIG:
    map:
      database: postgres
      cache: redis
```

### `env`

- **Type**: `map[string]Variable`
- **Description**: Global environment variables

```yaml
env:
  NODE_ENV: production
  DATABASE_URL:
    sh: echo $DATABASE_URL
```

### [`tasks`](#task)

- **Type**: `map[string]Task`
- **Description**: Task definitions

```yaml
tasks:
  # Simple string format
  hello: echo "Hello World"

  # Array format
  build:
    - go mod tidy
    - go build ./...

  # Full object format
  deploy:
    desc: Deploy the application
    cmds:
      - ./scripts/deploy.sh
```

### `silent`

- **Type**: `bool`
- **Default**: `false`
- **Description**: Suppress task name and command output by default

```yaml
silent: true
```

### `dotenv`

- **Type**: `[]string`
- **Description**: Load environment variables from .env files. When the same
  variable is defined in multiple files, the first file in the list takes
  precedence.

```yaml
dotenv:
  - .env.local # Highest priority
  - .env # Lowest priority
```

### `run`

- **Type**: `string`
- **Default**: `always`
- **Options**: `always`, `once`, `when_changed`
- **Description**: Default execution behavior for tasks

```yaml
run: once
```

### `interval`

- **Type**: `string`
- **Default**: `100ms`
- **Pattern**: `^[0-9]+(?:m|s|ms)$`
- **Description**: Watch interval for file changes

```yaml
interval: 1s
```

### `set`

- **Type**: `[]string`
- **Options**: `allexport`, `a`, `errexit`, `e`, `noexec`, `n`, `noglob`, `f`,
  `nounset`, `u`, `xtrace`, `x`, `pipefail`
- **Description**: POSIX shell options for all commands

```yaml
set: [errexit, nounset, pipefail]
```

### `shopt`

- **Type**: `[]string`
- **Options**: `expand_aliases`, `globstar`, `nullglob`
- **Description**: Bash shell options for all commands

```yaml
shopt: [globstar]
```

### `use_gitignore`

- **Type**: `bool`
- **Default**: `false`
- **Description**: Exclude files matched by `.gitignore` rules when resolving
  `sources` and `generates` globs for all tasks. Can be overridden per task.

```yaml
use_gitignore: true
```

## Include

Configuration for including external Taskfiles.

### `taskfile`

- **Type**: `string`
- **Required**: Yes
- **Description**: Path to the Taskfile or directory to include

```yaml
includes:
  backend: ./backend/Taskfile.yml
  # Shorthand for above
  frontend: ./frontend
```

### `dir`

- **Type**: `string`
- **Description**: Working directory for included tasks

```yaml
includes:
  api:
    taskfile: ./api
    dir: ./api
```

### `optional`

- **Type**: `bool`
- **Default**: `false`
- **Description**: Don't error if the included file doesn't exist

```yaml
includes:
  optional-tasks:
    taskfile: ./optional.yml
    optional: true
```

### `flatten`

- **Type**: `bool`
- **Default**: `false`
- **Description**: Include tasks without namespace prefix

```yaml
includes:
  common:
    taskfile: ./common.yml
    flatten: true
```

### `internal`

- **Type**: `bool`
- **Default**: `false`
- **Description**: Hide included tasks from command line and `--list`

```yaml
includes:
  internal:
    taskfile: ./internal.yml
    internal: true
[...]
tasks:
  example:
    desc: using an internal task
    cmds:
      - task: internal:default
```

### `aliases`

- **Type**: `[]string`
- **Description**: Alternative names for the namespace

```yaml
includes:
  database:
    taskfile: ./db.yml
    aliases: [db, data]
```

### `excludes`

- **Type**: `[]string`
- **Description**: Task names or namespace patterns ending in `:*` to exclude
  from inclusion

```yaml
includes:
  shared:
    taskfile: ./shared.yml
    excludes: [internal-setup, 'debug:*', 'experimental:*']
```

### `vars`

- **Type**: `map[string]Variable`
- **Description**: Variables to pass to the included Taskfile

```yaml
includes:
  deploy:
    taskfile: ./deploy.yml
    vars:
      ENVIRONMENT: production
```

### `checksum`

- **Type**: `string`
- **Description**: Expected checksum of the included file

```yaml
includes:
  remote:
    taskfile: https://example.com/tasks.yml
    checksum: c153e97e0b3a998a7ed2e61064c6ddaddd0de0c525feefd6bba8569827d8efe9
```

## Variable

Variables support multiple types and can be static values, dynamic commands,
references, or maps.

### Static Variables

```yaml
vars:
  # String
  APP_NAME: myapp
  # Number
  PORT: 8080
  # Boolean
  DEBUG: true
  # Array
  FEATURES: [auth, logging, metrics]
  # Null
  OPTIONAL_VAR: null
```

### Dynamic Variables (`sh`)

```yaml
vars:
  COMMIT_HASH:
    sh: git rev-parse HEAD
  BUILD_TIME:
    sh: date -u +"%Y-%m-%dT%H:%M:%SZ"
```

### Variable References (`ref`)

```yaml
vars:
  BASE_VERSION: 1.0.0
  FULL_VERSION:
    ref: .BASE_VERSION
```

### Map Variables (`map`)

```yaml
vars:
  CONFIG:
    map:
      database:
        host: localhost
        port: 5432
      cache:
        type: redis
        ttl: 3600
```

### Secret Variables (`secret`)

Mark variables as secret to mask their values in command logs.

```yaml
vars:
  API_KEY:
    value: 'sk-1234567890abcdef'
    secret: true  # This variable will be masked in logs

  DB_PASSWORD:
    sh: vault read -field=password secret/db
    secret: true  # Works with dynamic variables too
```

When a variable is marked as `secret: true`, Task will replace its value with
`*****` in command logs. The actual command execution still receives the real
value.

::: info

For complete documentation on secret variables, including security
considerations and best practices, see the
[Secret variables](../guide/secret-variables.md) section in the Guide.

:::

### Variable Ordering

Variables can reference previously defined variables:

```yaml
vars:
  GREETING: Hello
  TARGET: World
  MESSAGE: '{{.GREETING}} {{.TARGET}}!'
```

## Task

Individual task configuration with multiple syntax options.

### Simple Task Formats

```yaml
tasks:
  # String command
  hello: echo "Hello World"

  # Array of commands
  build:
    - go mod tidy
    - go build ./...

  # Object with cmd shorthand
  test:
    cmd: go test ./...
```

### Task Properties

#### `cmds`

- **Type**: `[]Command`
- **Description**: Commands to execute

```yaml
tasks:
  build:
    cmds:
      - go build ./...
      - echo "Build complete"
```

#### `cmd`

- **Type**: `string`
- **Description**: Single command (alternative to `cmds`)

```yaml
tasks:
  test:
    cmd: go test ./...
```

#### `deps`

- **Type**: `[]Dependency`
- **Description**: Tasks to run before this task

```yaml
tasks:
  # Simple dependencies
  deploy:
    deps: [build, test]
    cmds:
      - ./deploy.sh

  # Dependencies with variables
  advanced-deploy:
    deps:
      - task: build
        vars:
          ENVIRONMENT: production
      - task: test
        vars:
          COVERAGE: true
    cmds:
      - ./deploy.sh

  # Silent dependencies
  main:
    deps:
      - task: setup
        silent: true
    cmds:
      - echo "Main task"

  # Loop dependencies
  test-all:
    deps:
      - for: [unit, integration, e2e]
        task: test
        vars:
          TEST_TYPE: '{{.ITEM}}'
    cmds:
      - echo "All tests completed"
```

#### `desc`

- **Type**: `string`
- **Description**: Short description shown in `--list`

```yaml
tasks:
  test:
    desc: Run unit tests
    cmds:
      - go test ./...
```

#### `summary`

- **Type**: `string`
- **Description**: Detailed description shown in `--summary`

```yaml
tasks:
  deploy:
    desc: Deploy to production
    summary: |
      Deploy the application to production environment.
      This includes building, testing, and uploading artifacts.
```

#### `prompt`

- **Type**: `string` or `[]string`
- **Description**: Prompts shown before task execution

```yaml
tasks:
  # Single prompt
  deploy:
    prompt: "Deploy to production?"
    cmds:
      - ./deploy.sh

  # Multiple prompts
  deploy-multi:
    prompt:
      - "Are you sure?"
      - "This will affect live users!"
    cmds:
      - ./deploy.sh
```

#### `aliases`

- **Type**: `[]string`
- **Description**: Alternative names for the task

```yaml
tasks:
  build:
    aliases: [compile, make]
    cmds:
      - go build ./...
```

#### `method`

- **Type**: `string`
- **Default**: `checksum`
- **Options**: `checksum`, `timestamp`, `none`
- **Description**: Method for checking if the task is up-to-date. Refer to the `method` root property for details.

```yaml
tasks:
  build:
    sources:
      - go.mod
    method: timestamp
```

#### `sources`

- **Type**: `[]string` or `[]Glob`
- **Description**: Source files to monitor for changes

```yaml
tasks:
  build:
    sources:
      - '**/*.go'
      - go.mod
      # With exclusions
      - exclude: '**/*_test.go'
    cmds:
      - go build ./...
```

#### `generates`

- **Type**: `[]string` or `[]Glob`
- **Description**: Files generated by this task

```yaml
tasks:
  build:
    sources: ['**/*.go']
    generates:
      - './app'
      - exclude: '*.debug'
    cmds:
      - go build -o app ./cmd
```

#### `use_gitignore`

- **Type**: `bool`
- **Default**: `false`
- **Description**: Exclude files matched by `.gitignore` rules when resolving
  this task's `sources` and `generates` globs. Overrides the root-level
  `use_gitignore` setting.

```yaml
tasks:
  build:
    use_gitignore: true
    sources:
      - '**/*.go'
    cmds:
      - go build ./...
```

#### `status`

- **Type**: `[]string`
- **Description**: Commands to check if task should run

```yaml
tasks:
  install-deps:
    status:
      - test -f node_modules/.installed
    cmds:
      - npm install
      - touch node_modules/.installed
```

#### `preconditions`

- **Type**: `[]Precondition`
- **Description**: Conditions that must be met before running

```yaml
tasks:
  # Simple precondition (shorthand)
  build:
    preconditions:
      - test -d ./src
    cmds:
      - go build ./...

  # Preconditions with custom messages
  deploy:
    preconditions:
      - sh: test -n "$API_KEY"
        msg: 'API_KEY environment variable is required'
      - sh: test -f ./app
        msg: "Application binary not found. Run 'task build' first."
    cmds:
      - ./deploy.sh
```

#### `if`

- **Type**: `string`
- **Description**: Shell command to conditionally execute the task. If the
  command exits with a non-zero code, the task is skipped (not failed).

```yaml
tasks:
  # Task only runs in CI environment
  deploy:
    if: '[ "$CI" = "true" ]'
    cmds:
      - ./deploy.sh

  # Using Go template expressions
  build-prod:
    if: '{{eq .ENV "production"}}'
    cmds:
      - go build -ldflags="-s -w" ./...
```

#### `dir`

- **Type**: `string`
- **Description**: The directory in which this task should run
- **Default**: If the task is in the root Taskfile, the default `dir` is
  `ROOT_DIR`. For included Taskfiles, the default `dir` is the value specified in
  their respective `includes.*.dir` field (if any).

```yaml
tasks:
  current-dir:
    dir: '{{.USER_WORKING_DIR}}'
    cmd: pwd
```

#### `requires`

- **Type**: `Requires`
- **Description**: Required variables with optional enum validation

```yaml
tasks:
  deploy:
    requires:
      vars: [API_KEY, ENVIRONMENT]
    cmds:
      - ./deploy.sh

  advanced-deploy:
    requires:
      vars:
        - API_KEY
        - name: ENVIRONMENT
          enum: [development, staging, production]
        - name: LOG_LEVEL
          enum: [debug, info, warn, error]
    cmds:
      - echo "Deploying to {{.ENVIRONMENT}} with log level {{.LOG_LEVEL}}"
      - ./deploy.sh


  # Requirements with enum from variable reference
  reusable-deploy:
    requires:
      vars:
        - name: ENVIRONMENT
          enum:
            ref: .ALLOWED_ENVS
    cmds:
      - ./deploy.sh
```

#### [`vars`](#variable)

- **Type**: `map[string]Variable`
- **Description**: Task level variables available to individual task

```yaml
tasks:
  default:
    vars:
      # Simple values
      APP_NAME: myapp
      VERSION: 1.0.0
      DEBUG: true
      PORT: 8080
      FEATURES: [auth, logging]
  cmds:
    # …
```

See
[Prompting for missing variables interactively](../guide/required-variables.md#prompting-for-missing-variables-interactively)
for information on enabling interactive prompts for missing required variables.

#### `watch`

- **Type**: `bool`
- **Default**: `false`
- **Description**: Automatically run task in watch mode

```yaml
tasks:
  dev:
    watch: true
    cmds:
      - npm run dev
```

#### `platforms`

- **Type**: `[]string`
- **Description**: Platforms where this task should run

```yaml
tasks:
  windows-build:
    platforms: [windows]
    cmds:
      - go build -o app.exe ./cmd

  unix-build:
    platforms: [linux, darwin]
    cmds:
      - go build -o app ./cmd
```

## Command

Individual command configuration within a task.

### Basic Commands

```yaml
tasks:
  example:
    cmds:
      - echo "Simple command"
      - ls -la
```

### Command Object

```yaml
tasks:
  example:
    cmds:
      - cmd: echo "Hello World"
        silent: true
        ignore_error: false
        platforms: [linux, darwin]
        set: [errexit]
        shopt: [globstar]
        timeout: 5m
```

### Task References

```yaml
tasks:
  example:
    cmds:
      - task: other-task
        vars:
          PARAM: value
        silent: false
```

### Deferred Commands

```yaml
tasks:
  with-cleanup:
    cmds:
      - echo "Starting work"
      # Deferred command string
      - defer: echo "Cleaning up"
      # Deferred task reference
      - defer:
          task: cleanup-task
          vars:
            CLEANUP_MODE: full
```

### For Loops

#### Loop Over List

```yaml
tasks:
  greet-all:
    cmds:
      - for: [alice, bob, charlie]
        cmd: echo "Hello {{.ITEM}}"
```

#### Loop Over Sources/Generates

```yaml
tasks:
  process-files:
    sources: ['*.txt']
    cmds:
      - for: sources
        cmd: wc -l {{.ITEM}}
      - for: generates
        cmd: gzip {{.ITEM}}
```

#### Loop Over Variable

```yaml
tasks:
  process-items:
    vars:
      ITEMS: 'item1,item2,item3'
    cmds:
      - for:
          var: ITEMS
          split: ','
          as: CURRENT
        cmd: echo "Processing {{.CURRENT}}"
```

#### Loop Over Matrix

```yaml
tasks:
  test-matrix:
    cmds:
      - for:
          matrix:
            OS: [linux, windows, darwin]
            ARCH: [amd64, arm64]
        cmd: echo "Testing {{.ITEM.OS}}/{{.ITEM.ARCH}}"
```

#### Loop in Dependencies

```yaml
tasks:
  build-all:
    deps:
      - for: [frontend, backend, worker]
        task: build
        vars:
          SERVICE: '{{.ITEM}}'
```

### Conditional Commands

Use `if` to conditionally execute a command. If the shell command exits with a
non-zero code, the command is skipped.

```yaml
tasks:
  build:
    cmds:
      # Only run in production
      - cmd: echo "Optimizing for production"
        if: '[ "$ENV" = "production" ]'
      # Using Go templates
      - cmd: echo "Feature enabled"
        if: '{{eq .ENABLE_FEATURE "true"}}'
      # Inside for loops (evaluated per iteration)
      - for: [a, b, c]
        cmd: echo "processing {{.ITEM}}"
        if: '[ "{{.ITEM}}" != "b" ]'
```

### Command Timeouts

Use `timeout` to limit how long a command may run. The value uses Go duration
syntax (e.g. `30s`, `5m`, `1h30m`) and must be greater than zero.

```yaml
tasks:
  deploy:
    cmds:
      - cmd: npm run build
        timeout: 5m
      - cmd: ./deploy.sh
        timeout: 30m
```

When a command exceeds its timeout, it is terminated and the task fails with an
error, preventing commands from hanging indefinitely in a pipeline. The timeout
bounds the whole step, so an [`if`](#command) condition that hangs is cut short
too, and [`ignore_error`](#command) covers a timeout like any other failure. A
timed-out command reports [`EXIT_CODE`](./templating.md#exit-code)
`124`, following the convention of `timeout(1)`.

A dependency takes the same key:

```yaml
tasks:
  build:
    deps:
      - task: fetch-assets
        timeout: 2m
```

The key goes next to the command whatever form it takes, including a `defer`:

```yaml
tasks:
  deploy:
    cmds:
      - defer:
          task: cleanup
        timeout: 30s
      - defer: ./cleanup.sh
        timeout: 30s
```

A timed-out deferred command is logged and ignored, like other deferred errors.

Calling a task that is already running under [`run: once`](#task) or
[`run: when_changed`](#task) joins that execution instead of starting a second
one. A `timeout` on such a call bounds how long you wait for it, not the shared
execution itself, which only the caller that started it can bound.

## Shell Options

### Set Options

Available `set` options for POSIX shell features:

- `allexport` / `a` - Export all variables
- `errexit` / `e` - Exit on error
- `noexec` / `n` - Read commands but don't execute
- `noglob` / `f` - Disable pathname expansion
- `nounset` / `u` - Error on undefined variables
- `xtrace` / `x` - Print commands before execution
- `pipefail` - Pipe failures propagate

```yaml
# Global level
set: [errexit, nounset, pipefail]

tasks:
  debug:
    # Task level
    set: [xtrace]
    cmds:
      - cmd: echo "This will be traced"
        # Command level
        set: [noexec]
```

### Shopt Options

Available `shopt` options for Bash features:

- `expand_aliases` - Enable alias expansion
- `globstar` - Enable `**` recursive globbing
- `nullglob` - Null glob expansion

```yaml
# Global level
shopt: [globstar]

tasks:
  find-files:
    # Task level
    shopt: [nullglob]
    cmds:
      - cmd: ls **/*.go
        # Command level
        shopt: [globstar]
```

---

### Website Src Latest Docs Reference Templating (`website/src/latest/docs/reference/templating.md`)

---
title: Templating Reference
description:
  Comprehensive guide to Task's templating system with Go text/template, special
  variables, and available functions
section: Reference
docType: reference
outline: deep
---

# Templating Reference

Task's templating engine uses Go's
[text/template](https://pkg.go.dev/text/template) package to interpolate values.
This reference covers the main features and all available functions for creating
dynamic Taskfiles. Most of the provided functions come from the
[slim-sprig](https://sprig.taskfile.dev/) library.

## Basic Usage

Most string values in Task can be templated using double curly braces
<span v-pre>`{{` and `}}`</span>. Anything inside the braces is executed as a Go
template.

### Simple Variable Interpolation

```yaml
version: '3'

tasks:
  hello:
    vars:
      MESSAGE: 'Hello, World!'
    cmds:
      - 'echo {{.MESSAGE}}'
```

**Output:**

```
Hello, World!
```

### Conditional Logic

```yaml
version: '3'

tasks:
  maybe-happy:
    vars:
      SMILE: ':\)'
      FROWN: ':\('
      HAPPY: true
    cmds:
      - 'echo {{if .HAPPY}}{{.SMILE}}{{else}}{{.FROWN}}{{end}}'
```

**Output:**

```
:)
```

### Function Calls and Pipes

```yaml
version: '3'

tasks:
  uniq:
    vars:
      NUMBERS: '0,1,1,1,2,2,3'
    cmds:
      - 'echo {{splitList "," .NUMBERS | uniq | join ", "}}'
```

**Output:**

```
0, 1, 2, 3
```

### Control Flow with Loops

```yaml
version: '3'

tasks:
  loop:
    vars:
      NUMBERS: [0, 1, 1, 1, 2, 2, 3]
    cmds:
      - |
        {{range $index, $num := .NUMBERS}}
        {{if gt $num 1}}{{break}}{{end}}
        echo {{$index}}: {{$num}}
        {{end}}
```

**Output:**

```
0: 0
1: 1
2: 1
3: 1
```

## Special Variables

Task provides special variables that are always available in templates. These
override any user-defined variables with the same name.

### CLI

#### `CLI_ARGS`

- **Type**: `string`
- **Description**: All extra arguments passed after `--` as a string

```yaml
tasks:
  test:
    cmds:
      - go test {{.CLI_ARGS}}
```

```bash
task test -- -v -race
# Runs: go test -v -race
```

#### `CLI_ARGS_LIST`

- **Type**: `[]string`
- **Description**: All extra arguments passed after `--` as a shell parsed list

```yaml
tasks:
  docker-run:
    cmds:
      - docker run {{range .CLI_ARGS_LIST}}{{.}} {{end}}myapp
```

#### `CLI_FORCE`

- **Type**: `bool`
- **Description**: Whether `--force` or `--force-all` flags were set

```yaml
tasks:
  deploy:
    cmds:
      - |
        {{if .CLI_FORCE}}
        echo "Force deployment enabled"
        {{end}}
        ./deploy.sh
```

#### `CLI_SILENT`

- **Type**: `bool`
- **Description**: Whether `--silent` flag was set

#### `CLI_VERBOSE`

- **Type**: `bool`
- **Description**: Whether `--verbose` flag was set

#### `CLI_OFFLINE`

- **Type**: `bool`
- **Description**: Whether `--offline` flag was set

#### `CLI_ASSUME_YES`

- **Type**: `bool`
- **Description**: Whether `--yes` flag was set

### Task

#### `TASK`

- **Type**: `string`
- **Description**: Name of the current task

```yaml
tasks:
  build:
    cmds:
      - echo "Running task {{.TASK}}"
```

#### `ALIAS`

- **Type**: `string`
- **Description**: Alias used for the current task, otherwise matches `TASK`

#### `TASK_EXE`

- **Type**: `string`
- **Description**: Task executable name or path

```yaml
tasks:
  self-update:
    cmds:
      - echo "Updating {{.TASK_EXE}}"
```

### File Paths

#### `ROOT_TASKFILE`

- **Type**: `string`
- **Description**: Absolute path of the root Taskfile

#### `ROOT_DIR`

- **Type**: `string`
- **Description**: Absolute path of the root Taskfile directory

#### `TASKFILE`

- **Type**: `string`
- **Description**: Absolute path of the current (included) Taskfile

#### `TASKFILE_DIR`

- **Type**: `string`
- **Description**: Absolute path of the current Taskfile directory

#### `TASK_DIR`

- **Type**: `string`
- **Description**: Absolute path where the task is executed

#### `USER_WORKING_DIR`

- **Type**: `string`
- **Description**: Absolute path where `task` was called from

```yaml
tasks:
  info:
    cmds:
      - echo "Root {{.ROOT_DIR}}"
      - echo "Current {{.TASKFILE_DIR}}"
      - echo "Working {{.USER_WORKING_DIR}}"
```

#### `FILE_PATH_SEPARATOR`

- **Type**: `string`
- **Description**: OS-specific path separator: Windows = `\`, others = `/`

::: info

> See `joinPath` in [Path Functions](#path-functions) for joining filesystem paths for use with
> file system operations.

:::

### Environment Variables

#### `PATH_LIST_SEPARATOR`

- **Type**: `string`
- **Description**: OS-specific path separator for environment variables: Windows = `;`, others = `:`

::: info

> See `joinEnv` in [Environment Variable Functions](#environment-variable-functions) for joining
> paths for use in environment variables.

:::

### Status

#### `CHECKSUM`

- **Type**: `string`
- **Description**: Checksum of files in `sources` (only in `status` with
  `checksum` method)

#### `TIMESTAMP`

- **Type**: `time.Time`
- **Description**: Greatest timestamp of files in `sources` (only in `status`
  with `timestamp` method)

```yaml
tasks:
  build:
    method: checksum
    sources: ['**/*.go']
    status:
      - test "{{.CHECKSUM}}" = "$(cat .last-checksum)"
    cmds:
      - go build ./...
      - echo "{{.CHECKSUM}}" > .last-checksum
```

### Loop

#### `ITEM`

- **Type**: `any`
- **Description**: Current iteration value when using `for` property

```yaml
tasks:
  greet:
    cmds:
      - for: [alice, bob, charlie]
        cmd: echo "Hello {{.ITEM}}"
```

Can be renamed using `as`:

```yaml
tasks:
  greet:
    cmds:
      - for:
          var: NAMES
          as: NAME
        cmd: echo "Hello {{.NAME}}"
```

### Defer

#### `EXIT_CODE`

- **Type**: `int`
- **Description**: Failed command exit code (only in `defer`, only when
  non-zero). A command killed by its [`timeout`](./schema.md#command)
  is reported as `124`, following the convention of `timeout(1)`.

```yaml
tasks:
  deploy:
    cmds:
      - ./deploy.sh
      - defer: |
          {{if .EXIT_CODE}}
          echo "Deployment failed with code {{.EXIT_CODE}}"
          ./rollback.sh
          {{end}}
```

### System

#### `TASK_VERSION`

- **Type**: `string`
- **Description**: Current version of Task

```yaml
tasks:
  version:
    cmds:
      - echo "Using Task {{.TASK_VERSION}}"
```

## Available Functions

Task provides a comprehensive set of functions for templating. Functions can be chained using pipes (`|`) and combined for powerful templating capabilities.

### Logic and Control Flow

#### `and`, `or`, `not`

Boolean operations for conditional logic

```yaml
tasks:
  conditional:
    vars:
      DEBUG: true
      VERBOSE: false
      PRODUCTION: false
    cmds:
      - echo "{{if and .DEBUG .VERBOSE}}Debug mode with verbose{{end}}"
      - echo "{{if or .DEBUG .VERBOSE}}Some kind of debug{{end}}"
      - echo "{{if not .PRODUCTION}}Development build{{end}}"
```

#### `eq`, `ne`, `lt`, `le`, `gt`, `ge`

Comparison operations

```yaml
tasks:
  compare:
    vars:
      VERSION: 3
    cmds:
      - echo "{{if gt .VERSION 2}}Version 3 or higher{{end}}"
      - echo "{{if eq .VERSION 3}}Exactly version 3{{end}}"
```

### Data Access and Manipulation

#### `index`

Access array/map elements by index or key

```yaml
tasks:
  access:
    vars:
      SERVICES: [api, web, worker]
      CONFIG:
        map:
          database: postgres
          port: 5432
    cmds:
      - echo "First service {{index .SERVICES 0}}"
      - echo "Database {{index .CONFIG "database"}}"
```

#### `len`

Get length of arrays, maps, or strings

```yaml
tasks:
  length:
    vars:
      ITEMS: [a, b, c, d]
      TEXT: "Hello World"
    cmds:
      - echo "Found {{len .ITEMS}} items"
      - echo "Text has {{len .TEXT}} characters"
```

#### `slice`

Extract a portion of an array or string

```yaml
tasks:
  slice-demo:
    vars:
      ITEMS: [a, b, c, d, e]
    cmds:
      - echo "{{slice .ITEMS 1 3}}"     # [b c]
```

### String Functions

#### Basic String Operations

```yaml
tasks:
  string-basic:
    vars:
      MESSAGE: '  Hello World  '
      NAME: 'john doe'
      TEXT: "Hello World"
    cmds:
      - echo "{{.MESSAGE | trim}}"          # "Hello World"
      - echo "{{.NAME | title}}"            # "John Doe"
      - echo "{{.NAME | upper}}"            # "JOHN DOE"
      - echo "{{.MESSAGE | lower}}"         # "hello world"
      - echo "{{.NAME | trunc 4}}"          # "john"
      - echo "{{"test" | repeat 3}}"        # "testtesttest"
      - echo "{{.TEXT | substr 0 5}}"       # "Hello"
```

#### String Testing and Searching

```yaml
tasks:
  string-test:
    vars:
      FILENAME: 'app.tar.gz'
      EMAIL: 'user@example.com'
    cmds:
      - echo "{{.FILENAME | hasPrefix "app"}}"    # true
      - echo "{{.FILENAME | hasSuffix ".gz"}}"    # true
      - echo "{{.EMAIL | contains "@"}}"          # true
```

#### String Replacement and Formatting

```yaml
tasks:
  string-format:
    vars:
      TEXT: 'Hello, World!'
      UNSAFE: 'file with spaces.txt'
    cmds:
      - echo "{{.TEXT | replace "," ""}}"         # "Hello World!"
      - echo "{{.TEXT | quote}}"                  # "\"Hello, World!\""
      - echo "{{.UNSAFE | shellQuote}}"           # Shell-safe quoting
      - echo "{{.UNSAFE | q}}"                    # Short alias for shellQuote
```

#### Regular Expressions

```yaml
tasks:
  regex:
    vars:
      EMAIL: 'user@example.com'
      TEXT: 'abc123def456'
    cmds:
      - echo "{{regexMatch "@" .EMAIL}}"                    # true
      - echo "{{regexFind "[0-9]+" .TEXT}}"                # "123"
      - echo "{{regexFindAll "[0-9]+" .TEXT -1}}"          # ["123", "456"]
      - echo "{{regexReplaceAll "[0-9]+" .TEXT "X"}}"      # "abcXdefX"
```

### List Functions

#### List Access and Basic Operations

```yaml
tasks:
  list-basic:
    vars:
      ITEMS: ["apple", "banana", "cherry", "date"]
    cmds:
      - echo "First {{.ITEMS | first}}"          # "apple"
      - echo "Last {{.ITEMS | last}}"            # "date"
      - echo "Rest {{.ITEMS | rest}}"            # ["banana", "cherry", "date"]
      - echo "Initial {{.ITEMS | initial}}"      # ["apple", "banana", "cherry"]
      - echo "Length {{.ITEMS | len}}"           # 4
```

#### List Manipulation

```yaml
tasks:
  list-manipulate:
    vars:
      NUMBERS: [3, 1, 4, 1, 5, 9, 1]
      FRUITS: ["apple", "banana"]
    cmds:
      - echo "{{.NUMBERS | uniq}}"                       # [3, 1, 4, 5, 9]
      - echo "{{.NUMBERS | sortAlpha}}"                  # [1, 1, 1, 3, 4, 5, 9]
      - echo"'{{append .FRUITS "cherry"}}""              # ["apple", "banana", "cherry"]
      - echo "{{ without .NUMBERS 1}}"                   # [3, 4, 5, 9]
      - echo "{{.NUMBERS | has 5}}"                      # true
```

#### String Lists

```yaml
tasks:
  string-lists:
    vars:
      CSV: 'apple,banana,cherry'
      WORDS: ['hello', 'world', 'from', 'task']
      MULTILINE: |
        line1
        line2
        line3
    cmds:
      - echo "{{.CSV | splitList ","}}"           # ["apple", "banana", "cherry"]
      - echo "{{.WORDS | join " "}}"              # "hello world from task"
      - echo "{{.WORDS | sortAlpha}}"             # ["from", "hello", "task", "world"]
      - echo "{{.MULTILINE | splitLines}}"        # Split on newlines (Unix/Windows)
      - echo "{{.MULTILINE | catLines}}"          # Replace newlines with spaces
```

In pipeline form, `join` receives the list from the left-hand side. The
equivalent non-pipeline form is <span v-pre>`{{join " " .WORDS}}`</span>.

#### Shell Argument Parsing

```yaml
tasks:
  shell-args:
    vars:
      ARGS: 'file1.txt -v --output="result file.txt"'
    cmds:
      - |
        {{range .ARGS | splitArgs}}
        echo "Arg: {{.}}"
        {{end}}
```

### Math Functions

```yaml
tasks:
  math:
    vars:
      A: 10
      B: 3
      NUMBERS: [1, 5, 3, 9, 2]
    cmds:
      - echo "Addition {{add .A .B}}"            # 13
      - echo "Subtraction {{sub .A .B}}"         # 7
      - echo "Multiplication {{mul .A .B}}"      # 30
      - echo "Division {{div .A .B}}"            # 3
      - echo "Modulo {{mod .A .B}}"              # 1
      - echo "Maximum {{.NUMBERS | max}}"        # 9
      - echo "Minimum {{.NUMBERS | min}}"        # 1
      - echo "Random 1-99 {{randInt 1 100}}"     # Random number
      - echo "Random 0-999 {{randIntN 1000}}"    # Random number 0-999
```

### Date and Time Functions

```yaml
tasks:
  date-time:
    vars:
      BUILD_DATE: "2023-12-25"
    cmds:
      - echo "Now {{now | date "2006-01-02 15:04:05"}}"
      - echo {{ toDate "2006-01-02" .BUILD_DATE }}
      - echo "Build {{.BUILD_DATE | toDate "2006-01-02" | date "Jan 2, 2006"}}"
      - echo "Unix timestamp {{now | unixEpoch}}"
      - echo "Duration ago {{now | ago}}"
```

### System Functions

#### Platform Information

```yaml
tasks:
  platform:
    cmds:
      - echo "OS {{OS}}"                    # linux, darwin, windows, etc.
      - echo "Architecture {{ARCH}}"        # amd64, arm64, etc.
      - echo "CPU cores {{numCPU}}"         # Number of CPU cores
      - echo "Building for {{OS}}/{{ARCH}}"
```

#### Path Functions

```yaml
tasks:
  paths:
    vars:
      WIN_PATH: 'C:\Users\name\file.txt'
      OUTPUT_DIR: 'dist'
      BINARY_NAME: 'myapp'
    cmds:
      - echo "{{.WIN_PATH | toSlash}}"                      # Convert to forward slashes
      - echo "{{.WIN_PATH | fromSlash}}"                    # Convert to OS-specific slashes
      - echo "{{joinPath .OUTPUT_DIR .BINARY_NAME}}"        # Join path elements
      - echo "Relative {{relPath .ROOT_DIR .TASKFILE_DIR}}" # Get relative path
      - echo '{{absPath "../sibling"}}'                     # Resolve to an absolute path
```

#### Environment Variable Functions

```yaml
tasks:
  paths:
    vars:
      WIN_PATH1: 'C:\Users\Person\bin'
      WIN_PATH2: 'C:\Shared\bin'
    cmds:
      # Join paths for Windows ENV vars:
      # C:\Users\Person\bin;C:\Shared\bin
      - echo "{{joinEnv .WIN_PATH1 .WIN_PATH2}}"
```

```yaml
tasks:
  paths:
    vars:
      POSIX_PATH1: '/users/person/.local/bin'
      POSIX_PATH2: '/usr/bin'
    cmds:
      # Join paths for POSIX ENV vars:
      # /users/person/.local/bin:/usr/bin
      - echo "{{joinEnv .POSIX_PATH1 .POSIX_PATH2}}"
```

#### URLs

```yaml
tasks:
  paths:
    vars:
      SERVER: 'http://localhost'
      PATH1: 'path1'
      PATH2: 'path2'
    cmds:
      # Join paths for URL:
      # http://localhost/path1/path2
      - echo "{{joinUrl .SERVER .PATH1 .PATH2}}"
```

### Data Structure Functions

#### Dictionary Operations

```yaml
tasks:
  dict:
    vars:
      CONFIG:
        map:
          database: postgres
          port: 5432
          ssl: true
    cmds:
      - echo "Database {{get .CONFIG "database"}}"
      - echo "Database {{"database" | get .CONFIG}}"
      - echo "Keys {{.CONFIG | keys}}"
      - echo "Keys {{keys .CONFIG }}"
      - echo "Has SSL {{hasKey .CONFIG "ssl"}}"
      - echo "{{dict "env" "prod" "debug" false}}"
```

#### Merging and Combining

```yaml
tasks:
  merge:
    vars:
      BASE_CONFIG:
        map:
          timeout: 30
          retries: 3
      USER_CONFIG:
        map:
          timeout: 60
          debug: true
    cmds:
      - echo "{{merge .BASE_CONFIG .USER_CONFIG | toJson}}"
```

### Default Values and Coalescing

```yaml
tasks:
  defaults:
    vars:
      API_URL: ""
      DEBUG: false
      ITEMS: []
    cmds:
      - echo "{{.API_URL | default "http://localhost:8080"}}"
      - echo "{{.DEBUG | default true}}"
      - echo "{{.MISSING_VAR | default "fallback"}}"
      - echo "{{coalesce .API_URL .FALLBACK_URL "default"}}"
      - echo "Is empty {{empty .ITEMS}}"                     # true
```

### Encoding and Serialization

#### JSON

```yaml
tasks:
  json:
    vars:
      DATA:
        map:
          name: 'Task'
          version: '3.0'
      JSON_STRING: '{"key": "value", "number": 42}'
    cmds:
      - echo "{{.DATA | toJson}}"
      - echo "{{.DATA | toPrettyJson}}"
      - echo "{{.JSON_STRING | fromJson }}"
```

#### YAML

```yaml
tasks:
  yaml:
    vars:
      CONFIG:
        map:
          database:
            host: localhost
            port: 5432
      YAML_STRING: |
        key: value
        items:
          - one
          - two
    cmds:
      - echo "{{.CONFIG | toYaml}}"
      - echo "{{.YAML_STRING | fromYaml}}"
```

#### Base64

```yaml
tasks:
  base64:
    vars:
      SECRET: 'my-secret-key'
    cmds:
      - echo "{{.SECRET | b64enc}}"               # Encode to base64
      - echo "{{"bXktc2VjcmV0LWtleQ==" | b64dec}}"   # Decode from base64
```

### Type Conversion

```yaml
tasks:
  convert:
    vars:
      NUM_STR: '42'
      FLOAT_STR: '3.14'
      BOOL_STR: 'true'
      ITEMS: [1, 2, 3]
    cmds:
      - echo "{{.NUM_STR | atoi | add 8}}"        # String to int: 50
      - echo "{{.FLOAT_STR | float64}}"           # String to float: 3.14
      - echo "{{.ITEMS | toStrings}}"             # Convert to strings: ["1", "2", "3"]
```

### Utility Functions

#### UUID Generation

```yaml
tasks:
  generate:
    vars:
      DEPLOYMENT_ID: "{{uuid}}"
    cmds:
      - echo "Deployment ID {{.DEPLOYMENT_ID}}"
```

#### Debugging

```yaml
tasks:
  debug:
    vars:
      COMPLEX_VAR:
        map:
          items: [1, 2, 3]
          nested:
            key: value
    cmds:
      - echo "{{spew .COMPLEX_VAR}}"              # Pretty-print for debugging
```

### Output Functions

#### Formatted Output

```yaml
tasks:
  output:
    vars:
      VERSION: "1.2.3"
      BUILD: 42
    cmds:
      - echo '{{print "Simple output"}}'
      - echo '{{printf "Version %s.%d" .VERSION .BUILD}}'
      - echo '{{println "With newline"}}'
```

---

### Website Src Latest Docs Security Incident Response Plan (`website/src/latest/docs/security/incident-response-plan.md`)

---
title: Incident Response Plan
description:
  Task's process for detecting, triaging, mitigating, and disclosing security
  incidents
section: Project
docType: project
outline: deep
---

# Incident Response Plan

This document outlines our incident response plan in the event that a
vulnerability is reported to the Task project. This serves as a high-level,
public guide and is published as part of our commitment to transparency.

Below are the security principles that we aim to adhere to as a project:

- **Transparency**: All incidents and fixes are documented here for the
  community.
- **Stewardship**: Take responsibility for protecting users and the project.
- **Protection**: Act to minimize harm and provide guidance.

## Scope

This plan applies to the core Task repository and all _official_ Task projects.
For example, the Visual Studio Code extension and officially supported
installation methods. In the event that a vulnerability is reported with a
community-managed installation method, we will work with the community and make
a "best-effort" attempt to help resolve the issue.

## Steps

### 🔍 1. Detect

- All security issues should be **privately reported** as described in our
  [security documentation][security-docs].
- Maintainers should also regularly monitor and respond to:
  - Pull requests from dependency scanners such as Dependabot.
  - GitHub notifications and vulnerability alerts.
  - Messages in community channels such as Discord.

### 🩺 2. Triage

- Upon first receipt of a security issue, one of our team will immediately
  notify the other maintainers via a secure and private channel. This ensures
  that all maintainers are able to contribute to the issue where possible.
- A maintainer should respond to the reporter in a timely manner in order to
  acknowledge receipt of the issue.
- The issue must then be triaged into one of the following categories:
  - ‼️**Critical**: Has a serious and immediate impact on users or affects
    critical infrastructure related to the project.
  - ❗**High**: Has the potential to seriously impact users of a distributed
    asset.
  - 🟰**Medium**: Has the potential to impact users, but is obscure or low-risk.
  - ➖**Low**: No direct or immediate impact to users, but requires attention.
- Open a draft
  [GitHub Security Advisory (GHSA)](https://github.com/go-task/task/security/advisories)
  in the Task repository.
  - Optionally create a CVE. This can be skipped for low/medium impact issues at
    the discretion of the maintainers.

### 🩹 3. Mitigate

- Act calmly and communicate decisions.
- Stop the bleed.
  - Before attempting to fix the issue, perform any actions that stop the
    problem from becoming worse. For example:
    - Rotate any affected secrets.
    - Rebuild any affected services (website, etc.).
  - It may be difficult to do some of this in cases where packages are
    maintained by the community if we are not yet ready to disclose the
    vulnerability publicly. This should be decided on a case-by-case basis.
- Address the root cause.
  - Plan and document a fix.
  - Patch the issue.
  - Test the fix.
  - Release new versions.

### 📢 4. Disclose

- Publish the GitHub Security Advisory (GHSE). Make sure to include:
  - The affected version(s)/services.
  - The impact of the issue.
  - The root cause.
  - The steps taken to resolve.
- Optionally, create a blog post and/or share the information via our socials
  and public communication channels.

### 🧠 5. Learn

- Document the disclosure in a permanent location.
- Make and document any changes that can be made to prevent similar issues from
  arising in the future.

[security-docs]: ./index.md

---

### Website Src Latest Docs Security Threat Model (`website/src/latest/docs/security/threat-model.md`)

---
title: Threat Model
description:
  Threats, assets, trust boundaries, and mitigations for the Task project and
  its release infrastructure
section: Project
docType: project
outline: deep
---

# Threat Model

This document outlines the security threats, assets, and mitigations for the
Task project. It serves as a high-level, public guide and is published as part
of our commitment to transparency.

## Asset Inventory

### Critical Assets

- **Source Code:** The Task CLI, build scripts, and configuration files (e.g.,
  `Taskfile.yml`, `.goreleaser.yml`).
- **Build Artifacts:** Compiled binaries, packages, and containers distributed
  to users.
- **Secrets:** API tokens, signing keys, and repository credentials used in
  CI/CD and release pipelines.
- **Release Metadata:** Version numbers, changelogs, and checksums.
- **CI/CD Pipelines & Runners:** GitHub Actions workflows that build, test, and
  release the project.
- **Third-party Dependencies:** Go modules and tools used to build and
  distribute Task.
- **Website & Documentation:** The taskfile.dev site and installation scripts.

### Asset Locations

- Local developer machines
- GitHub Actions runners
- GitHub Releases
- Public package registries (npm, Homebrew, Winget, Cloudsmith)
- Source control platforms (GitHub)
- Netlify (website hosting)

## Threat Model

### Actors

- **Maintainers & Contributors:** Trusted users with varying levels of
  repository access.
- **External Attackers:** Untrusted users seeking to compromise builds,
  releases, or user systems.
- **Supply Chain Threats:** Malicious dependencies or compromised third-party
  services.
- **CI/CD Systems:** Automated agents that may be exploited if misconfigured.

### Entry Points

- Source code contributions (pull requests, issues)
- Configuration files and build scripts
- CI/CD integration and environment variables
- Third-party dependencies
- Release pipelines and artifact repositories
- Remote Taskfile fetching (HTTP, Git)
- Installation scripts

### Trust Boundaries

- Between the project repository and the CI/CD environment
- Between Task and remote Taskfiles fetched over the network
- Between artifact generation and distribution channels
- Between the Task binary and user-defined shell commands

### Threats

#### Supply Chain Attacks

- Compromised Go dependencies or build tools
- Unauthorized changes to source code or configuration
- Exploitation of third-party CI/CD or package registry services
- Compromised installation scripts or distribution channels

#### Secrets Leakage

- Exposure of tokens, credentials, or signing keys in logs, error messages, or
  artifacts
- Hardcoded secrets in code or configuration
- Improper secret management in CI/CD environments

#### Code Execution / Injection

- Malicious code execution via compromised pull requests or dependencies
- Remote code execution vulnerabilities in Task or its dependencies
- **Note:** Task intentionally executes user-defined shell commands as part of
  its core functionality. Users are responsible for the commands they define in
  their Taskfiles.

#### Unauthorized Access

- Unauthorized users triggering releases or accessing sensitive artifacts
- Insecure permissions on runners, repositories, or artifact stores
- Compromised maintainer accounts

#### Data Integrity & Tampering

- Tampering with build artifacts, changelogs, or metadata
- Compromise of signing keys, leading to malicious releases
- Man-in-the-middle attacks against remote Taskfile fetching

#### Denial of Service

- Abuse of CI/CD resources, bandwidth, or artifact storage
- Overloading automated processes or API endpoints
- Malicious Taskfiles designed to exhaust system resources

## Mitigations

### Supply Chain Security

- Pin dependencies and use trusted sources
- Mandatory code review and CI checks on all incoming pull requests
- Signed commits and release tags
- Enable immutable releases where supported
- Run `govulncheck` on every commit and tag
- Pin GitHub Actions to specific commit SHAs

### Secrets Management

- Secure storage using GitHub Secrets
- Never log or expose secrets in build or release outputs
- Regularly rotate secrets and monitor for suspicious activity
- Use least-privilege tokens scoped to specific repositories

### Secure Code Execution

- Validate and sanitize configuration files and user inputs
- Audit dependencies for vulnerabilities
- HTTP is rejected for remote Taskfiles by default (requires `--insecure` flag)
- TLS certificate verification for remote Git repositories

### Access Control

- Enforce least privilege for CI/CD runners, repositories, and artifact stores
- Require multi-factor authentication for maintainers
- Restrict release triggers to tagged releases only
- Lower permissions of less active maintainers

### Artifact Integrity

- Generate checksums for all release artifacts
- Distribute artifacts via trusted, access-controlled repositories
- Verify signatures and checksums in installation scripts where possible

### Availability Protection

- Implement rate limiting and resource quotas on CI/CD jobs
- Monitor for abnormal activity and automate alerts
- Set timeouts on network operations (e.g., remote Taskfile fetching)

## Residual Risks

- Zero-day vulnerabilities in dependencies, CI/CD systems, or Task itself
- Social engineering attacks targeting maintainers
- Unnoticed supply chain compromises
- Human error in configuration or secret management
- Users fetching malicious remote Taskfiles from untrusted sources

## Security Best Practices

- Regularly update dependencies and build tools
- Monitor security advisories and patch vulnerabilities promptly
- Educate contributors on secure coding and secrets hygiene
- Document security policies and incident response procedures

## References

- [Task Documentation](https://taskfile.dev/)
- [Incident Response Plan](./incident-response-plan.md)
- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
- [Supply Chain Security](https://slsa.dev/)
- [GitHub Security Best Practices](https://docs.github.com/en/code-security)

---

### Website Src Next Docs Deprecations Completion Scripts (`website/src/next/docs/deprecations/completion-scripts.md`)

---
title: 'Completion Scripts'
description: Deprecation of direct completion scripts in Task’s Git directory
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][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][completions] instead.

[completions]: ../installation.md#setup-completions
[task]: https://github.com/go-task/task

---

### Website Src Next Docs Deprecations Template Functions (`website/src/next/docs/deprecations/template-functions.md`)

---
title: 'Template Functions'
description:
  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 Next Docs Deprecations Template (`website/src/next/docs/deprecations/template.md`)

---
# This is a template for deprecation documentation
# Copy this page and fill in the details as necessary
title: '--- Template ---'
description: Template for documenting deprecated features in Task
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 Next Docs Deprecations Version 2 Schema (`website/src/next/docs/deprecations/version-2-schema.md`)

---
title: 'Version 2 Schema (#1197)'
description: Deprecation of Taskfile schema version 2 and migration to version 3
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][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][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][v3.0.0].

[v3.0.0]: https://github.com/go-task/task/releases/tag/v3.0.0
[v3.33.0]: https://github.com/go-task/task/releases/tag/v3.33.0
[deprecation-notice]: https://github.com/go-task/task/issues/1197

---

--- METRICS ---
- Files Extracted: 69
- Estimated Token Budget: ~125134 tokens
- Canonical Reference: https://codewiki.google/github.com/go-task/task
