1
0
mirror of https://github.com/go-task/task.git synced 2026-10-23 11:48:55 +03:00
This commit is contained in:
Valentin Maerten
2026-10-01 22:21:39 +02:00
parent 54db90d712
commit b5aef1c287
58 changed files with 4611 additions and 3490 deletions

View File

@@ -1,6 +1,6 @@
# Changelog
## Unreleased
## v3.54.0 - 2026-10-01
### 🚀 Features

View File

@@ -1 +1 @@
3.53.1
3.54.0

View File

@@ -3,39 +3,106 @@ import type { DefaultTheme } from 'vitepress';
// Navigation for the `/docs` section. next.ts is the source of both sidebars;
// cmd/release copies it over latest.ts alongside the content it describes. See
// the "Documentation channels" section of website/src/next/docs/contributing.md.
//
// Grouped by what the reader is trying to do: get going, learn Task, look
// something up, follow the project. The DocSearch crawler puts the active
// sidebar section into hierarchy.lvl0, so these labels are also the breadcrumbs
// on every search result.
export const sidebar: DefaultTheme.SidebarItem[] = [
{
text: 'Installation',
link: '/docs/installation'
text: 'Overview',
link: '/docs/'
},
{
text: 'Getting Started',
link: '/docs/getting-started'
items: [
{
text: 'Installation',
link: '/docs/installation'
},
{
text: 'Quick Start',
link: '/docs/getting-started'
},
{
text: 'Editors and Integrations',
link: '/docs/integrations'
}
]
},
{
text: 'Guide',
link: '/docs/guide'
},
{
text: 'Remote Taskfiles',
link: '/docs/remote-taskfiles'
link: '/docs/guide/',
items: [
{
text: 'Writing and running tasks',
collapsed: false,
items: [
{ text: 'Defining tasks', link: '/docs/guide/defining-tasks' },
{ text: 'Running tasks', link: '/docs/guide/running-tasks' }
]
},
{
text: 'Variables and arguments',
collapsed: false,
items: [
{ text: 'Variables', link: '/docs/guide/variables' },
{ text: 'Command-line arguments', link: '/docs/guide/arguments' },
{
text: 'Validation and prompts',
link: '/docs/guide/required-variables'
},
{ text: 'Secret variables', link: '/docs/guide/secret-variables' }
]
},
{
text: 'Task execution',
collapsed: false,
items: [
{
text: 'Dependencies and task calls',
link: '/docs/guide/dependencies'
},
{ text: 'Loops', link: '/docs/guide/loops' },
{
text: 'Conditional execution',
link: '/docs/guide/conditional-execution'
},
{
text: 'Errors and cleanup',
link: '/docs/guide/errors-and-cleanup'
},
{ text: 'Up-to-date checks', link: '/docs/guide/up-to-date' },
{ text: 'Watch mode', link: '/docs/guide/watch' }
]
},
{
text: 'Environment and output',
collapsed: false,
items: [
{ text: 'Environment variables', link: '/docs/guide/environment' },
{ text: 'Platforms and shells', link: '/docs/guide/platforms' },
{ text: 'Output and logging', link: '/docs/guide/output' }
]
},
{
text: 'Including Taskfiles',
collapsed: false,
items: [
{ text: 'Including Taskfiles', link: '/docs/guide/includes' },
{ text: 'Remote Taskfiles', link: '/docs/remote-taskfiles' }
]
}
]
},
{
text: 'Reference',
collapsed: true,
collapsed: false,
items: [
{
text: 'Taskfile Schema',
link: '/docs/reference/schema'
},
{
text: 'Environment',
link: '/docs/reference/environment'
},
{
text: 'Configuration',
link: '/docs/reference/config'
},
{
text: 'CLI',
link: '/docs/reference/cli'
@@ -44,6 +111,14 @@ export const sidebar: DefaultTheme.SidebarItem[] = [
text: 'Templating',
link: '/docs/reference/templating'
},
{
text: 'Environment',
link: '/docs/reference/environment'
},
{
text: 'Configuration',
link: '/docs/reference/config'
},
{
text: 'Package API',
link: '/docs/reference/package'
@@ -51,88 +126,96 @@ export const sidebar: DefaultTheme.SidebarItem[] = [
]
},
{
text: 'Experiments',
text: 'Project',
collapsed: true,
link: '/docs/experiments/',
items: [
{
text: 'Env Precedence (#1038)',
link: '/docs/experiments/env-precedence'
text: 'Changelog',
link: '/docs/changelog'
},
{
text: 'Gentle Force (#1200)',
link: '/docs/experiments/gentle-force'
text: 'FAQ',
link: '/docs/faq'
},
{
text: 'Remote Taskfiles (#1317)',
link: '/docs/experiments/remote-taskfiles'
text: 'Taskfile Versions',
link: '/docs/taskfile-versions'
},
{
text: 'Community',
link: '/docs/community'
},
{
text: 'Experiments',
collapsed: true,
link: '/docs/experiments/',
items: [
{
text: 'Env Precedence (#1038)',
link: '/docs/experiments/env-precedence'
},
{
text: 'Gentle Force (#1200)',
link: '/docs/experiments/gentle-force'
},
{
text: 'Remote Taskfiles (#1317)',
link: '/docs/experiments/remote-taskfiles'
}
]
},
{
text: 'Deprecations',
collapsed: true,
link: '/docs/deprecations/',
items: [
{
text: 'Completion Scripts',
link: '/docs/deprecations/completion-scripts'
},
{
text: 'Template Functions',
link: '/docs/deprecations/template-functions'
},
{
text: 'Version 2 Schema (#1197)',
link: '/docs/deprecations/version-2-schema'
}
]
},
{
text: 'Security',
collapsed: true,
link: '/docs/security/',
items: [
{
text: 'Incident Response Plan',
link: '/docs/security/incident-response-plan'
},
{
text: 'Threat Model',
link: '/docs/security/threat-model'
}
]
}
]
},
{
text: 'Deprecations',
collapsed: true,
link: '/docs/deprecations/',
items: [
{
text: 'Completion Scripts',
link: '/docs/deprecations/completion-scripts'
},
{
text: 'Template Functions',
link: '/docs/deprecations/template-functions'
},
{
text: 'Version 2 Schema (#1197)',
link: '/docs/deprecations/version-2-schema'
}
]
},
{
text: 'Taskfile Versions',
link: '/docs/taskfile-versions'
},
{
text: 'Integrations',
link: '/docs/integrations'
},
{
text: 'Community',
link: '/docs/community'
},
{
text: 'Style Guide',
link: '/docs/styleguide'
},
{
text: 'Contributing',
link: '/docs/contributing'
},
{
text: 'Releasing',
link: '/docs/releasing'
},
{
text: 'Security',
collapsed: true,
link: '/docs/security/',
items: [
{
text: 'Incident Response Plan',
link: '/docs/security/incident-response-plan'
text: 'Contributing',
link: '/docs/contributing'
},
{
text: 'Threat Model',
link: '/docs/security/threat-model'
text: 'Style Guide',
link: '/docs/styleguide'
},
{
text: 'Releasing',
link: '/docs/releasing'
}
]
},
{
text: 'Changelog',
link: '/docs/changelog'
},
{
text: 'FAQ',
link: '/docs/faq'
}
];

View File

@@ -0,0 +1,77 @@
---
title: Task documentation for coding agents
description:
A compact map of Task's documentation, plus the execution semantics that are
easiest to get wrong when generating a Taskfile.
outline: deep
---
# Task documentation for coding agents
Task is a cross-platform task runner and build tool. Its configuration file is
normally named `Taskfile.yml`, and new files should use schema version `3`.
Every page linked below is also available as raw Markdown: append `.md` to its
URL. The curated index is at [/llms.txt](/llms.txt) and the full corpus at
[/llms-full.txt](/llms-full.txt).
## Where to look
- [Quick Start](./docs/getting-started.md): the shape of a Taskfile.
- [Taskfile Schema](./docs/reference/schema.md): the source of truth for keys,
types and accepted values. Check here before assuming a field exists.
- [CLI](./docs/reference/cli.md): commands, flags and exit codes.
- [Templating](./docs/reference/templating.md): every template function and
special variable. Check here before inventing one.
- [Guide](./docs/guide/): task definitions, inputs, execution and shared
Taskfiles.
- [Errors and cleanup](./docs/guide/errors-and-cleanup.md): failure handling and
`defer`.
- [Secret variables](./docs/guide/secret-variables.md): masking and its limits.
- [Resolution order](./docs/guide/variables.md#resolution-order) and
[Task dependencies](./docs/guide/dependencies.md#task-dependencies): for when
the behaviour matters more than the procedure.
## Semantics that are easy to get wrong
1. `vars` are not exported to `cmds`: use templates to read them there. Dynamic
variables (`sh:`) also receive previously resolved scalar variables in their
shell environment. `env` is exported to commands. Root-level `env` also
participates in templates; task-level `env` does not. A template keeps any
value resolved from other sources, or renders empty if none exists.
2. A constant in a task's own `vars:` overrides the command line. Put the
default in global `vars:`, or use a template such as
<span v-pre>`NAME: '{{.NAME | default "World"}}'`</span> to preserve caller
input.
3. The included Taskfile's own `vars:` are applied after `includes.vars`. A
constant overrides the include's value; a self-referencing template with
`default` can preserve it.
4. Everything in `deps` may run concurrently and in any order. A `task:`
reference inside `cmds` runs at its position and blocks the next command. If
order matters, use `cmds`.
5. Each command runs in its own shell. Nothing carries over between them, not
`cd` and not an exported variable. Use Task's `dir:` and `env:` instead.
6. A template renders text. Use `ref:` to pass an array or a map without
flattening it to a string.
7. A passing `status:` means the task is already up to date and is skipped. A
failing `preconditions:` means the task must not run at all. They are not
interchangeable.
8. `defer:` commands run in reverse order of declaration, and run whether the
task succeeded or failed.
9. Remote Taskfiles execute code from wherever they are fetched. See
[Remote Taskfiles](./docs/remote-taskfiles.md) for the trust and checksum
rules.
10. Portability is about every command inside a task, not just Task itself. A
task is only cross-platform if its commands are.
## Before writing a Taskfile
- Confirm the feature exists in the schema for the version in use.
- Prefer plain, readable tasks over dense templating.
- Use `deps` only where concurrent execution is actually correct.
- Never embed credentials. Read them from the environment or a secret manager.
`secret: true` masks a value in Task's own logs, but it only works on `vars:`,
not on `env:`, and it never masks what a command itself prints. Treat it as
one less place a secret is echoed, not as protection.
- Give tasks a `desc:` so they show up in `task --list`, and validate inputs
with `requires:` or `preconditions:`.

View File

@@ -150,6 +150,8 @@ experiment.
We're looking for feedback on a couple of different proposals, so please give
them a go and let us know what you think. :pray:
[map-variables]:
../docs/guide/variables.md#parsing-json-yaml-into-map-variables
[v3.37.0]: https://github.com/go-task/task/releases/tag/v3.37.0
[slim-sprig-math]: https://sprig.taskfile.dev/math.html
[slim-sprig-list]: https://sprig.taskfile.dev/lists.html

View File

@@ -0,0 +1,225 @@
---
title: One Completion Engine for Every Shell
description:
A new completion engine that gives every shell the same suggestions, and that
can finally complete your required variables.
author: vmaerten
date: 2026-10-01
tags: ['new-features', 'completion']
outline: deep
editLink: false
---
# One Completion Engine for Every Shell
<AuthorCard :author="$frontmatter.author" />
Task has shipped shell completions for a long time. They were written as one
script per shell: a Bash script, a Zsh script, a Fish script, one for PowerShell
and one for Nushell. Each of them had to work out on its own what your Taskfile
contains and what flags Task accepts. Over the years, they drifted.
<!-- more -->
[Task v3.54.0][release] brings a shared completion engine to Bash, Zsh, Fish,
PowerShell and Nushell. It is the default behind `task --completion <shell>`.
Let me show you what it fixes.
## The same TAB, five different answers
With the old scripts, asking Task to complete the value of `--output` could
produce different answers depending on the shell:
```shell
# bash, zsh, fish
$ task --output <TAB>
interleaved group prefixed
# powershell
PS> task --output <TAB>
build deploy
```
PowerShell had no idea `--output` takes a value, so it fell back to listing task
names where a value was expected.
The differences also affected which Taskfile was read:
```shell
$ task --dir ./sub <TAB>
```
The old Zsh, Fish and PowerShell scripts suggested tasks from the _current_
directory, since none of them passed `--dir` along when asking Task for a task
list. Bash and Nushell handled it correctly.
Behind these symptoms was one structural problem: the logic lived in the
scripts. Several scripts maintained their own lists of flags and descriptions,
so adding a flag meant updating each of them. Some also parsed the
human-readable output of `--list-all` to learn about your tasks. Here is part of
what the Fish completion had to do:
```fish
sed -e '1d; s/\* \(.*\):[[:space:]]\{2,\}\(.*\)[[:space:]]\{2,\}(\(aliases.*\))/\1\t\2\t\3/'
```
Even reformatting a line of `task --list-all` could break those completions.
## One engine instead of five scripts
The new scripts hand the command line over to a hidden `task __complete`
command. The binary returns suggestions and instructions for the shell, such as
whether to offer files or preserve the order of the results.
Each wrapper still handles the details of its shell: reading the words under the
cursor, quoting values and displaying suggestions. Task names, required
variables and flags now come from one implementation in the binary.
## What this unlocks
### Completing required variables
This is the one I wanted for a long time. The old scripts did not suggest a
task's [required variables][requires] or their allowed values. The engine does:
```yaml
version: '3'
tasks:
deploy:
desc: Deploy the app
requires:
vars:
- name: ENVIRONMENT
enum: [dev, staging, prod]
- REGION
cmds:
- ./deploy.sh
```
```shell
$ task deploy <TAB>
ENVIRONMENT=dev ENVIRONMENT=staging ENVIRONMENT=prod REGION=
```
Variables with an `enum` give you the allowed values directly. Variables without
one give you `VAR=`. The engine returns these suggestions in the order of your
`requires` block.
Assignments already on the command line are left out of the suggestions:
```shell
$ task deploy ENVIRONMENT=prod <TAB>
REGION=
```
Once both variables are supplied, completion offers task names again so you can
add another task to the same command. When several tasks are already named, the
engine combines their required variables without suggesting a name twice.
Enums defined by reference work too:
```yaml
version: '3'
vars:
ALLOWED_ENVS: [dev, staging, prod]
tasks:
deploy:
requires:
vars:
- name: ENVIRONMENT
enum:
ref: .ALLOWED_ENVS
```
This uses the same enum resolver as the [interactive prompt][prompt-post], with
one important limit: completion does not run `sh:` variables. If an enum needs a
shell command to produce its values, completion offers `ENVIRONMENT=` instead.
### Everything else, everywhere
All five shells now get their task names, aliases, flags and flag values from
the engine. `--dir`, `--taskfile` and `--global` are honoured when loading the
Taskfile, so completing inside another directory works. Completing `--taskfile`
offers `.yml` and `.yaml` files, plus directories you can navigate into.
Flags gated behind an [experiment][experiments] are another good example. They
are read from Task's own flag set at the moment you press TAB, so they show up
when the experiment is enabled. The wrappers no longer need separate flag lists
or their own checks of `task --experiments`.
The suggestions are shared, but the shells still control how they are inserted
and displayed. For example, PowerShell can add a space after `VAR=`, older Bash
versions may sort the results, and Nushell does not append a trailing space.
## Completions should never surprise you
Completion runs on a keystroke, so it is allowed to do very little:
- No remote Taskfile downloads. Completion uses local files and cached remote
Taskfiles. If an uncached include prevents the Taskfile from loading, task
suggestions are unavailable until it has been fetched by a normal Task run.
- Nothing is read from stdin. A Taskfile supplied with `--taskfile -` is skipped
during completion.
- No `sh:` variable is evaluated. Pressing TAB never runs a command from your
Taskfile.
- A broken or missing Taskfile still leaves you with flag completion.
## Load the new completions
Starting with Task v3.54.0, `--completion` generates the new wrappers. If your
shell configuration already runs that command at startup, restart your shell
after upgrading. If you saved a completion script to a file, regenerate it with
the updated binary.
Here are the startup commands for each shell:
::: code-group
```shell [bash]
# ~/.bashrc
eval "$(task --completion bash)"
```
```shell [zsh]
# ~/.zshrc
eval "$(task --completion zsh)"
```
```shell [fish]
# ~/.config/fish/config.fish
task --completion fish | source
```
```powershell [powershell]
# Add to your PowerShell profile ($PROFILE)
Invoke-Expression (&task --completion powershell | Out-String)
```
```nu [nushell]
# Add to config.nu; completions are loaded 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")
```
:::
The [installation docs][install] cover saving scripts to completion directories,
Nushell's external completer and the Zsh `verbose` and `show-aliases` settings.
## Feedback
Please tell us how it behaves in your shell. If a suggestion is missing or
inserted incorrectly, include your Task version, shell version and a small
Taskfile that reproduces it. You can find us on our [Discord server][discord] or
[open an issue][gh-issue].
[release]: https://github.com/go-task/task/releases/tag/v3.54.0
[requires]: /docs/reference/schema#requires
[prompt-post]: /blog/if-and-variable-prompt
[experiments]: /docs/experiments/
[install]: /docs/installation#setup-completions
[discord]: https://discord.com/invite/6TY36E39UK
[gh-issue]: https://github.com/go-task/task/issues

View File

@@ -135,7 +135,7 @@ project][sponsor]!
[uroot-base]: https://github.com/u-root/u-root/blob/main/pkg/core/base.go
[middleware]:
https://github.com/mvdan/sh/blob/master/x/coreutils/coreutils.go
[task-core-utils]: /docs/reference/environment#task-core-utils
[task-core-utils]: ../docs/reference/environment.md#task-core-utils
[discord]: https://discord.com/invite/6TY36E39UK
[gh-issue]: https://github.com/go-task/task/issues
[sponsor]: /donate

View File

@@ -1,5 +1,10 @@
---
title: Changelog
description:
Release history for Task, including new features, improvements, fixes, and
breaking changes
section: Project
docType: project
outline: deep
editLink: false
---
@@ -8,7 +13,54 @@ editLink: false
::: v-pre
## v3.53.0 - 2026-08-18
## 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
@@ -16,21 +68,37 @@ editLink: false
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).
- Updated taskfile versions doc to mention when version checks were introduced
(#2184 by @jubr).
- Fixed `joinUrl` collapsing the `//` in a URL scheme (e.g. producing
`http:/localhost` instead of `http://localhost`) (#2915 by @vsaraikin).
- 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).
- 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
@@ -38,37 +106,31 @@ editLink: false
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).
- `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).
- 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).
- 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).
- Fixed pressing `Esc` at an interactive variable prompt not cancelling the run
(#2942 by @anilnatha).
- 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 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).
- Fixed a pinned `checksum:` not being verified when a remote Taskfile came from
the cache (#2980 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

View File

@@ -3,6 +3,8 @@ title: Community
description:
Task community contributions, installation methods, and integrations
maintained by third parties
section: Project
docType: project
outline: deep
---

View File

@@ -3,6 +3,8 @@ title: Contributing
description:
Comprehensive guide for contributing to the Task project, including setup,
development, testing, and submitting PRs
section: Contributing
docType: contributing
outline: deep
---
@@ -126,6 +128,19 @@ 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
@@ -140,14 +155,17 @@ for fields in the docs and the schema should match.
#### Documentation channels
The docs and the blog exist in two copies, so that taskfile.dev never announces
a feature that is not in the released binary yet:
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.
@@ -253,9 +271,9 @@ If you have questions, feel free to ask them in the `#help` forum channel on our
[discord-server]: https://discord.gg/6TY36E39UK
[discussion]: https://github.com/go-task/task/discussions
[conventional-commits]: https://www.conventionalcommits.org
[experiments]: ./experiments/
[experiments-workflow]: ./experiments/#workflow
[styleguide]: ./styleguide
[cli-reference]: ./reference/cli
[schema-reference]: ./reference/schema
[usage-guide]: ./guide
[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

View File

@@ -1,6 +1,8 @@
---
title: 'Completion Scripts'
description: Deprecation of direct completion scripts in Task’s Git directory
section: Project
docType: project
outline: deep
---
@@ -21,5 +23,5 @@ 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]: /docs/installation#setup-completions
[completions]: ../installation.md#setup-completions
[task]: https://github.com/go-task/task

View File

@@ -3,6 +3,8 @@ title: Deprecations
description:
Guide to deprecated features in Task and how to migrate to the new
alternatives
section: Project
docType: project
outline: deep
---

View File

@@ -3,6 +3,8 @@ title: 'Template Functions'
description:
Deprecation of some templating functions in Task, with guidance on their
replacements.
section: Project
docType: project
outline: deep
---

View File

@@ -1,6 +1,8 @@
---
title: 'Version 2 Schema (#1197)'
description: Deprecation of Taskfile schema version 2 and migration to version 3
section: Project
docType: project
outline: deep
---

View File

@@ -2,6 +2,8 @@
title: 'Env Precedence (#1038)'
description:
Experiment to change the precedence of environment variables in Task
section: Project
docType: project
outline: deep
---

View File

@@ -1,6 +1,8 @@
---
title: 'Gentle Force (#1200)'
description: Experiment to modify the behavior of the --force flag in Task
section: Project
docType: project
outline: deep
---

View File

@@ -1,6 +1,8 @@
---
title: Experiments
description: Guide to Task’s experimental features and how to use them
section: Project
docType: project
outline: deep
---

View File

@@ -1,5 +1,8 @@
---
title: Remote Taskfiles (#1317)
description: Experimentation for using Taskfiles stored in remote locations
section: Project
docType: project
outline: deep
---
@@ -9,6 +12,6 @@ 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#v3511---2026-05-16
[changelog]: ../changelog.md#v3-51-1-2026-05-16
[remote-taskfile-docs]: ../remote-taskfiles.md
[blog-post]: ../../blog/remote-taskfiles
[blog-post]: ../../blog/remote-taskfiles.md

View File

@@ -1,5 +1,6 @@
---
title: '--- Template ---'
description: Template for documenting a new experiment.
---
# \{Name of Experiment\} (#\{Issue\})
@@ -33,4 +34,4 @@ information.
\{Short explanation of how users should migrate to the new behavior\}
[enabling-experiments]: /docs/experiments/#enabling-experiments
[enabling-experiments]: ./index.md#enabling-experiments

View File

@@ -3,6 +3,8 @@ title: FAQ
description:
Frequently asked questions about Task, including ETAs, shell limitations, and
Windows compatibility
section: Project
docType: project
outline: deep
---
@@ -104,7 +106,7 @@ 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`](/docs/reference/environment#task-core-utils)
with the [`TASK_CORE_UTILS`](./reference/environment.md#task-core-utils)
environment variable:
```bash

View File

@@ -1,14 +1,17 @@
---
title: Getting Started
title: Quick Start
description: Guide for getting started with Task
section: Getting Started
docType: guide
outline: deep
---
# Getting Started
# 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).
haven't installed Task yet, head over to our
[installation guide](./installation.md).
## Creating your first Taskfile
@@ -72,9 +75,9 @@ 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](/docs/guide#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.
[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`
@@ -131,5 +134,6 @@ 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](/docs/guide) next. Alternatively, you can check out our reference
docs for the [Taskfile schema](reference/schema) and [CLI](reference/cli).
[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).

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,140 @@
---
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
```

View File

@@ -0,0 +1,186 @@
---
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.
:::

View File

@@ -0,0 +1,229 @@
---
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.

View File

@@ -0,0 +1,266 @@
---
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

View File

@@ -0,0 +1,142 @@
---
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).

View File

@@ -0,0 +1,97 @@
---
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`.

View File

@@ -0,0 +1,247 @@
---
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.
:::

View File

@@ -0,0 +1,68 @@
---
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.

View File

@@ -0,0 +1,275 @@
---
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.

View File

@@ -0,0 +1,214 @@
---
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.
:::

View File

@@ -0,0 +1,129 @@
---
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`.

View File

@@ -0,0 +1,170 @@
---
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.
:::

View File

@@ -0,0 +1,150 @@
---
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.

View File

@@ -0,0 +1,104 @@
---
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.

View File

@@ -0,0 +1,236 @@
---
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.

View File

@@ -0,0 +1,343 @@
---
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

View File

@@ -0,0 +1,80 @@
---
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).

View File

@@ -0,0 +1,69 @@
---
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).

View File

@@ -1,244 +1,444 @@
---
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
Task offers many installation methods. Check out the available methods below.
Choose a package manager for your system, or install Task from a binary.
## Official Package Managers
<InstallationMethods>
These installation methods are maintained by the Task team and are always
up-to-date.
<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>
:::info Package Repository Hosting
## Official packages {#official-package-managers}
[![Hosted By: Cloudsmith](https://img.shields.io/badge/OSS%20hosting%20by-cloudsmith-blue?logo=cloudsmith&style=for-the-badge)](https://cloudsmith.com)
Maintained by the Task team and kept up-to-date.
Package repository hosting for deb/rpm/apk is graciously provided by [Cloudsmith](https://cloudsmith.com).
Cloudsmith is the only fully hosted, cloud-native, universal package management solution, that
enables your organization to create, store and share packages in any format, to any place, with total
confidence.
<InstallationMethod platforms="macos" platform-label="macOS">
:::
<template v-slot:heading>
### [dnf](https://docs.fedoraproject.org/en-US/quick-docs/dnf) ![Fedora](https://img.shields.io/badge/Fedora-51A2DA?logo=fedora&logoColor=fff) ![CentOS](https://img.shields.io/badge/CentOS-002260?logo=centos&logoColor=F0F0F0) ![Fedora](https://img.shields.io/badge/Red_Hat-EE0000?logo=redhat&logoColor=white) {#dnf}
### [Homebrew](https://brew.sh) {#homebrew}
[[package](https://cloudsmith.io/~task/repos/task/packages/?sort=-format&q=format%3Arpm)]
</template>
If you Set up the repository by running :
<template v-slot:links>
```shell
curl -1sLf 'https://dl.cloudsmith.io/public/task/task/setup.rpm.sh' | sudo -E bash
```
[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)
Then you can install Task with:
```shell
dnf install task
```
### [apt](https://doc.ubuntu-fr.org/apt) ![Ubuntu](https://img.shields.io/badge/Ubuntu-E95420?logo=Ubuntu&logoColor=white) ![Debian](https://img.shields.io/badge/debian-red?logo=debian&logoColor=orange&color=darkred) ![Linux Mint](https://img.shields.io/badge/Linux%20Mint-87CF3E?logo=linuxmint&logoColor=fff) {#apt}
[[package](https://cloudsmith.io/~task/repos/task/packages/?sort=-format&q=format%3Adeb)]
If you Set up the repository by running:
```shell
curl -1sLf 'https://dl.cloudsmith.io/public/task/task/setup.deb.sh' | sudo -E bash
```
Then you can install Task with:
```shell
apt install task
```
### [apk](https://wiki.alpinelinux.org/wiki/Alpine_Package_Keeper) ![Alpine Linux](https://img.shields.io/badge/Alpine_Linux-0D597F?logo=alpinelinux&logoColor=fff) {#apk}
[[package](https://cloudsmith.io/~task/repos/task/packages/?sort=-format&q=format%3Aalpine)]
Set up the repository by running:
```shell
curl -1sLf 'https://dl.cloudsmith.io/public/task/task/setup.alpine.sh' | sudo -E bash
```
Then you can install Task with:
```shell
apk add task
```
### [Homebrew](https://brew.sh) ![macOS](https://img.shields.io/badge/MacOS-000000?logo=apple&logoColor=F0F0F0) {#homebrew}
Task is available via our official Homebrew tap
[[source](https://github.com/go-task/homebrew-tap/blob/main/Casks/go-task.rb)]:
</template>
```shell
brew install go-task/tap/go-task
```
Alternatively it can be installed from the official Homebrew repository
[[package](https://formulae.brew.sh/formula/go-task)]
[[source](https://github.com/Homebrew/homebrew-core/blob/master/Formula/g/go-task.rb)]
by running:
Or use the Homebrew core formula:
```shell
brew install go-task
```
### [Snap](https://snapcraft.io/task) ![macOS](https://img.shields.io/badge/MacOS-000000?logo=apple&logoColor=F0F0F0) ![Linux](https://img.shields.io/badge/Linux-FCC624?logo=linux&logoColor=black) {#snap}
</InstallationMethod>
Task is available on [Snapcraft](https://snapcraft.io/task)
[[source](https://github.com/go-task/snap/blob/main/snap/snapcraft.yaml)], but
keep in mind that your Linux distribution should allow classic confinement for
Snaps to Task work correctly:
<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
```
### [npm](https://www.npmjs.com) ![macOS](https://img.shields.io/badge/MacOS-000000?logo=apple&logoColor=F0F0F0) ![Linux](https://img.shields.io/badge/Linux-FCC624?logo=linux&logoColor=black) ![Windows](https://custom-icon-badges.demolab.com/badge/Windows-0078D6?logo=windows11&logoColor=white) {#npm}
Requires a Linux distribution with classic confinement support.
Npm can be used as cross-platform way to install Task globally or as a
dependency of your project
[[package](https://www.npmjs.com/package/@go-task/cli)]
[[source](https://github.com/go-task/task/blob/main/package.json)]:
</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 -g @go-task/cli
```
### [WinGet](https://github.com/microsoft/winget-cli) ![Windows](https://custom-icon-badges.demolab.com/badge/Windows-0078D6?logo=windows11&logoColor=white) {#winget}
Task is also available as a project dependency.
Task is available via the
[community repository](https://github.com/microsoft/winget-pkgs)
[[source](https://github.com/microsoft/winget-pkgs/tree/master/manifests/t/Task/Task)]:
</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
```
## Community-Maintained Package Managers
Available through the
[WinGet community repository](https://github.com/microsoft/winget-pkgs).
::: warning Community Maintained
</InstallationMethod>
These installation methods are maintained by the community and may not always be
up-to-date with the latest Task version. The Task team does not directly control
these packages.
<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}
### [Mise](https://mise.jdx.dev/) ![macOS](https://img.shields.io/badge/MacOS-000000?logo=apple&logoColor=F0F0F0) ![Linux](https://img.shields.io/badge/Linux-FCC624?logo=linux&logoColor=black) ![Windows](https://custom-icon-badges.demolab.com/badge/Windows-0078D6?logo=windows11&logoColor=white) {#mise}
Maintained by the community, outside the Task team's control. These packages may
lag behind the latest release.
Mise is a cross-platform package manager that acts as a "frontend" to a variety
of other package managers "backends" such as `asdf`, `aqua` and `ubi`.
<InstallationMethod platforms="macos linux windows" platform-label="macOS · Linux · Windows">
If using Mise, we recommend using the `aqua` or `ubi` backends to install Task
as these install directly from our GitHub releases.
<template v-slot:heading>
::: code-group
### [Mise](https://mise.jdx.dev/) {#mise}
```shell [aqua]
mise use -g aqua:go-task/task@latest
mise install
</template>
<template v-slot:links>
[View package](https://mise-tools.jdx.dev/tools/task)
</template>
```shell
mise use -g task
```
```shell [ubi]
mise use -g ubi:go-task/task
mise install
```
For a project-local installation, use `mise use task` instead. This adds Task to
your project's `mise.toml`.
:::
</InstallationMethod>
### [Macports](https://macports.org) ![macOS](https://img.shields.io/badge/MacOS-000000?logo=apple&logoColor=F0F0F0) {#macports}
<InstallationMethod platforms="macos" platform-label="macOS">
Task repository is tracked by Macports
[[package](https://ports.macports.org/port/go-task/details/)]
[[source](https://github.com/macports/macports-ports/blob/master/devel/go-task/Portfile)]:
<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
```
### [pip](https://pip.pypa.io) ![macOS](https://img.shields.io/badge/MacOS-000000?logo=apple&logoColor=F0F0F0) ![Linux](https://img.shields.io/badge/Linux-FCC624?logo=linux&logoColor=black) ![Windows](https://custom-icon-badges.demolab.com/badge/Windows-0078D6?logo=windows11&logoColor=white) {#pip}
</InstallationMethod>
Like npm, pip can be used as a cross-platform way to install Task
[[package](https://pypi.org/project/go-task-bin)]
[[source](https://github.com/Bing-su/pip-binary-factory/tree/main/task)]:
<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
```
### [Chocolatey](https://chocolatey.org) ![Windows](https://custom-icon-badges.demolab.com/badge/Windows-0078D6?logo=windows11&logoColor=white) {#chocolatey}
</InstallationMethod>
[[package](https://community.chocolatey.org/packages/go-task)]
[[source](https://github.com/Starz0r/ChocolateyPackagingScripts/blob/master/src/go-task_gh_build.py)]
<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
```
### [Scoop](https://scoop.sh) ![Windows](https://custom-icon-badges.demolab.com/badge/Windows-0078D6?logo=windows11&logoColor=white) {#scoop}
</InstallationMethod>
[[source](https://github.com/ScoopInstaller/Main/blob/master/bucket/task.json)]
<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
```
### Arch ([pacman](https://wiki.archlinux.org/title/Pacman)) ![Arch Linux](https://img.shields.io/badge/Arch%20Linux-1793D1?logo=arch-linux&logoColor=fff) {#arch}
</InstallationMethod>
[[package](https://archlinux.org/packages/extra/x86_64/go-task/)]
[[source](https://gitlab.archlinux.org/archlinux/packaging/packages/go-task)]
<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
```
### Fedora ([dnf](https://docs.fedoraproject.org/en-US/quick-docs/dnf)) ![Fedora](https://img.shields.io/badge/Fedora-51A2DA?logo=fedora&logoColor=fff) {#fedora-community}
</InstallationMethod>
[[package](https://packages.fedoraproject.org/pkgs/golang-github-task/go-task/)]
[[source](https://src.fedoraproject.org/rpms/golang-github-task)]
<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
```
### FreeBSD ([Ports](https://ports.freebsd.org/cgi/ports.cgi)) ![FreeBSD](https://img.shields.io/badge/FreeBSD-990000?logo=freebsd&logoColor=fff) {#freebsd}
</InstallationMethod>
[[package](https://cgit.freebsd.org/ports/tree/devel/task)]
[[source](https://cgit.freebsd.org/ports/tree/devel/task/Makefile)]
<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
```
### [Nix](https://nixos.org) ![Nix](https://img.shields.io/badge/Nix-5277C3?logo=nixos&logoColor=fff) ![NixOS](https://img.shields.io/badge/NixOS-5277C3?logo=nixos&logoColor=fff) ![Linux](https://img.shields.io/badge/Linux-FCC624?logo=linux&logoColor=black) ![macOS](https://img.shields.io/badge/MacOS-000000?logo=apple&logoColor=F0F0F0) {#nix}
</InstallationMethod>
[[source](https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/go/go-task/package.nix)]
<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
```
### [pacstall](https://github.com/pacstall/pacstall) ![Debian](https://img.shields.io/badge/Debian-A81D33?logo=debian&logoColor=fff) ![Ubuntu](https://img.shields.io/badge/Ubuntu-E95420?logo=ubuntu&logoColor=fff) {#pacstall}
</InstallationMethod>
[[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)]
<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
```
### [pkgx](https://pkgx.sh) ![macOS](https://img.shields.io/badge/MacOS-000000?logo=apple&logoColor=F0F0F0) ![Linux](https://img.shields.io/badge/Linux-FCC624?logo=linux&logoColor=black) {#pkgx}
</InstallationMethod>
[[package](https://pkgx.dev/pkgs/taskfile.dev)]
[[source](https://github.com/pkgxdev/pantry/blob/main/projects/taskfile.dev/package.yml)]
<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
@@ -250,75 +450,88 @@ or, if you have pkgx integration enabled:
task
```
## Get The Binary
</InstallationMethod>
### Binary
</InstallationMethods>
You can download the binary from the
[releases page on GitHub](https://github.com/go-task/task/releases) and add to
your `$PATH`.
## Binaries & CI {#get-the-binary}
DEB, RPM and APK packages are also available.
Install Task without a package manager: download a binary, use the install
script, or add the setup action to your GitHub workflow.
The `task_checksums.txt` file contains the SHA-256 checksum for each file.
### Download a binary {#binary}
### Install Script
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`.
We also have an
[install script](https://github.com/go-task/task/blob/main/install-task.sh)
which is very useful in scenarios like CI. Many thanks to
[GoDownloader](https://github.com/goreleaser/godownloader) for enabling the easy
generation of this script.
Each release also includes DEB, RPM and APK packages, plus `task_checksums.txt`
with SHA-256 checksums for the release files.
By default, it installs on the `./bin` directory relative to the working
directory:
### Install with a script {#install-script}
```shell
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
```
It is possible to override the installation directory with the `-b` parameter.
On Linux, common choices are `~/.local/bin` and `~/bin` to install for the
current user or `/usr/local/bin` to install for all users:
```shell
```shell [Custom directory]
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b ~/.local/bin
```
::: warning
On macOS and Windows, `~/.local/bin` and `~/bin` are not added to `$PATH` by
default.
:::
By default, it installs the latest version available. You can also specify a tag
(available in [releases](https://github.com/go-task/task/releases)) to install a
specific version:
```shell
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d v3.36.0
```shell [Pinned version]
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d v3.42.1
```
Parameters are order specific, to set both installation directory and version:
```shell
```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
We have an [official GitHub Action](https://github.com/go-task/setup-task) to
install Task in your GitHub workflows. This repository is forked from the
fantastic project by the Arduino team. Check out the repository for more
examples and configuration.
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@v1
uses: go-task/setup-task@v2
- name: Verify Task
run: task --version
```
## Build From Source
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
@@ -364,20 +577,39 @@ demand before calling it.
go tool task {arguments...}
```
## Setup completions
## 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. There are a couple of ways these completions can be added to your shell
config:
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.
always up-to-date. If your executable isn’t named task, set the `TASK_EXE`
environment variable before running eval.
::: code-group
@@ -446,9 +678,10 @@ task --completion nu | save --force ($nu.data-dir | path join "vendor/autoload/t
### 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):
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
@@ -465,24 +698,25 @@ zstyle ':completion:*:*:task:*' show-aliases false
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 — the refreshed completions are picked
up by the next shell. With option 2, re-run the command after upgrading Task.
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.
The completions are attached to an `extern "task"` declaration, which Nushell
requires to be static. Three consequences are worth knowing:
- The experimental flags (`--force-all`, `--download`, `--offline`, …) are always
offered, even when the corresponding experiment is disabled. Their description
is prefixed with the experiment name, and `task --experiments` lists the ones
that are enabled.
- Passing a value to a boolean flag with `=` does not work: Nushell forwards
`--color=false` as two arguments, so Task reads `false` as a task name. Use
`NO_COLOR=1`, or bypass the declaration with `^task --color=false`.
- `TASK_EXE` selects the executable that is run, but not the command name the
completions are attached to, which is always `task`. For a renamed executable,
alias it instead:
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
use ($nu.data-dir | path join "vendor/autoload/task-completions.nu") *
alias go-task = task
$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).

View File

@@ -3,6 +3,8 @@ title: Integrations
description:
Official and community integrations for Task, including VS Code, JSON schemas,
and other tools
section: Getting Started
docType: guide
outline: deep
---

View File

@@ -2,6 +2,8 @@
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
---
@@ -457,6 +459,10 @@ Task uses specific exit codes to indicate different types of errors:
- **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)
@@ -468,6 +474,7 @@ Task uses specific exit codes to indicate different types of errors:
- **205** - Task cancelled by user
- **206** - Missing required variables
- **207** - Variable has incorrect value
- **208** - Task timed out
::: info

View File

@@ -2,6 +2,8 @@
title: Configuration Reference
description: Complete reference for the Task config files and env vars
permalink: /reference/config/
section: Reference
docType: reference
outline: deep
---
@@ -85,7 +87,7 @@ experiments:
- **Type**: `boolean`
- **Default**: `false`
- **Description**: Enable verbose output for all tasks
- **CLI equivalent**: [`-v, --verbose`](./cli.md#-v---verbose)
- **CLI equivalent**: [`-v, --verbose`](./cli.md#v-verbose)
- **Environment variable**: [`TASK_VERBOSE`](./environment.md#task-verbose)
```yaml
@@ -97,7 +99,7 @@ verbose: true
- **Type**: `boolean`
- **Default**: `false`
- **Description**: Disables echoing of commands
- **CLI equivalent**: [`-s, --silent`](./cli.md#-s---silent)
- **CLI equivalent**: [`-s, --silent`](./cli.md#s-silent)
- **Environment variable**: [`TASK_SILENT`](./environment.md#task-silent)
```yaml
@@ -110,7 +112,7 @@ silent: true
- **Default**: `true`
- **Description**: Enable colored output. Colors are automatically enabled in CI
environments (`CI=true`).
- **CLI equivalent**: [`-c, --color`](./cli.md#-c---color)
- **CLI equivalent**: [`-c, --color`](./cli.md#c-color)
- **Environment variable**: [`TASK_COLOR`](./environment.md#task-color)
```yaml
@@ -123,7 +125,7 @@ color: false
- **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)
- **CLI equivalent**: [`--disable-fuzzy`](./cli.md#disable-fuzzy)
- **Environment variable**:
[`TASK_DISABLE_FUZZY`](./environment.md#task-disable-fuzzy)
@@ -136,7 +138,7 @@ disable-fuzzy: true
- **Type**: `integer`
- **Minimum**: `1`
- **Description**: Number of concurrent tasks to run
- **CLI equivalent**: [`-C, --concurrency`](./cli.md#-c---concurrency-number)
- **CLI equivalent**: [`-C, --concurrency`](./cli.md#c-concurrency-number)
- **Environment variable**:
[`TASK_CONCURRENCY`](./environment.md#task-concurrency)
@@ -149,7 +151,7 @@ concurrency: 4
- **Type**: `boolean`
- **Default**: `false`
- **Description**: Stop executing dependencies as soon as one of them fail
- **CLI equivalent**: [`-F, --failfast`](./cli.md#-f---failfast)
- **CLI equivalent**: [`-F, --failfast`](./cli.md#f-failfast)
- **Environment variable**: [`TASK_FAILFAST`](./environment.md#task-failfast)
```yaml
@@ -164,7 +166,7 @@ failfast: true
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)
- **CLI equivalent**: [`--interactive`](./cli.md#interactive)
```yaml
interactive: true
@@ -300,6 +302,81 @@ task --trusted-hosts github.com,gitlab.com -t https://github.com/user/repo.git//
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`
@@ -354,6 +431,10 @@ remote:
trusted-hosts:
- github.com
- gitlab.com
headers:
- host: gitlab.com
headers:
PRIVATE-TOKEN: '{{env "GITLAB_TOKEN"}}'
cacert: ''
cert: ''
cert-key: ''

View File

@@ -1,6 +1,8 @@
---
title: Environment Reference
description: A reference for the Taskfile environment variables
section: Reference
docType: reference
outline: deep
---
@@ -87,7 +89,7 @@ files > defaults.
- **Type**: `string` (`interleaved`, `group`, `prefixed`)
- **Description**: Sets the output style
- **CLI equivalent**: [`--output`](./cli.md#--output-string)
- **CLI equivalent**: [`--output`](./cli.md#o-output-mode)
### `TASK_OUTPUT_GROUP_BEGIN`
@@ -95,7 +97,7 @@ files > defaults.
- **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)
[`--output-group-begin`](./cli.md#output-group-begin-template)
### `TASK_OUTPUT_GROUP_END`
@@ -103,7 +105,7 @@ files > defaults.
- **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)
[`--output-group-end`](./cli.md#output-group-end-template)
### `TASK_OUTPUT_GROUP_ERROR_ONLY`
@@ -112,7 +114,7 @@ files > defaults.
- **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)
[`--output-group-error-only`](./cli.md#output-group-error-only)
### `TASK_TEMP_DIR`

View File

@@ -1,6 +1,8 @@
---
title: Package API Reference
description: A reference for Task's Golang package API
section: Reference
docType: reference
---
# Package API Reference

View File

@@ -1,6 +1,8 @@
---
title: Taskfile Schema Reference
description: A reference for the Taskfile schema
section: Reference
docType: reference
outline: deep
---
@@ -420,7 +422,7 @@ value.
For complete documentation on secret variables, including security
considerations and best practices, see the
[Secret variables](/docs/guide#secret-variables) section in the Guide.
[Secret variables](../guide/secret-variables.md) section in the Guide.
:::
@@ -786,7 +788,8 @@ tasks:
# …
```
See [Prompting for missing variables interactively](/docs/guide#prompting-for-missing-variables-interactively)
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`
@@ -983,7 +986,7 @@ 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`](/docs/reference/templating#exit_code)
timed-out command reports [`EXIT_CODE`](./templating.md#exit-code)
`124`, following the convention of `timeout(1)`.
A dependency takes the same key:

View File

@@ -3,6 +3,8 @@ 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
---
@@ -334,7 +336,7 @@ tasks:
- **Type**: `int`
- **Description**: Failed command exit code (only in `defer`, only when
non-zero). A command killed by its [`timeout`](/docs/reference/schema#command)
non-zero). A command killed by its [`timeout`](./schema.md#command)
is reported as `124`, following the convention of `timeout(1)`.
```yaml

View File

@@ -3,6 +3,8 @@ title: Releasing
description:
Task release process including GoReleaser, Homebrew, npm, Snapcraft, winget,
and other package managers
section: Contributing
docType: contributing
outline: deep
---
@@ -16,20 +18,38 @@ of the Taskfile.
artifacts automatically when a new Git tag is pushed to `main` branch (raw
executables and DEB and RPM packages).
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.
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
`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:
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
@@ -40,24 +60,19 @@ task website:deploy:prod
GoReleaser will automatically publish the release to most package managers:
* Cloudsmith (DEB and RPM repositories)
* Homebrew
* npm
* winget
- Cloudsmith (DEB and RPM repositories)
- Homebrew
- npm
- Snapcraft
- winget
A single package manager still require manual steps:
* Snapcraft:
* Update the `version:` field on [snapcraft.yaml][snapcraftyaml]
* Trigger a new build on [Snapcraft -> Builds][snapcraftbuilds]
* Once finished, move the new build to "stable" on [Snapcraft -> Releases][snapcraftreleases]
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)
- [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/
[snapcraftyaml]: https://github.com/go-task/snap/blob/main/snap/snapcraft.yaml#L2
[snapcraftbuilds]: https://snapcraft.io/task/builds
[snapcraftreleases]: https://snapcraft.io/task/releases

View File

@@ -1,57 +1,129 @@
---
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
Never run remote Taskfiles from sources that you do not trust.
Only run remote Taskfiles from sources you trust. Their commands execute on your
machine, just like commands from a local Taskfile.
:::
Task allows you to use Taskfiles which are stored in remote locations. This
applies to both the root Taskfile (aka. Entrypoint) and also when including
Taskfiles.
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.
Task uses "nodes" to reference remote Taskfiles. There are a few different types
of node which you can use:
## 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
```text [HTTP/HTTPS]
https://raw.githubusercontent.com/go-task/task/main/website/src/public/Taskfile.yml
```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!
```
```text [Git over HTTP]
https://github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main
```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!
```
```text [Git over SSH]
git@github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main
```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!
```
:::
## Node Types
## 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`
This is the most basic type of remote node and works by downloading the file
from the specified 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.
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`
This type of node works by downloading the file from a Git 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.
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.
@@ -63,9 +135,9 @@ This is the same URL that you would use to clone the repo over HTTP.
`git@github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main`
This type of node works by downloading the file from a Git repository over SSH.
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.
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.
@@ -76,119 +148,24 @@ SSH keys added so that they can be used during authentication.
`?ref=<ref>` to the end of the URL. If you omit a reference, the default
branch will be used.
Task has an example remote Taskfile in our repository that you can use for
testing and that we will use throughout this document:
## Locate files and directories {#special-variables}
```yaml
version: '3'
tasks:
default:
cmds:
- task: hello
hello:
cmds:
- echo "Hello Task!"
```
## Specifying a remote entrypoint
By default, Task will look for one of the supported file names on your local
filesystem. If you want to use a remote file instead, you can pass its URI into
the `--taskfile`/`-t` flag just like you would to specify a different local
file. For example:
::: 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!
```
:::
## Including remote Taskfiles
Including a remote file works exactly the same way that including a local file
does. You just need to replace the local path with a remote URI. Any tasks in
the remote Taskfile will be available to run from your main Taskfile.
::: code-group
```yaml [HTTP/HTTPS]
version: '3'
includes:
my-remote-namespace: https://raw.githubusercontent.com/go-task/task/main/website/src/public/Taskfile.yml
```
```yaml [Git over HTTP]
version: '3'
includes:
my-remote-namespace: https://github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main
```
```yaml [Git over SSH]
version: '3'
includes:
my-remote-namespace: git@github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main
```
:::
```shell
$ task my-remote-namespace:hello
task: [hello] echo "Hello Task!"
Hello Task!
```
### 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:
my-remote-namespace: https://{{.TOKEN}}@raw.githubusercontent.com/my-org/my-repo/main/Taskfile.yml
```
## Special Variables
The file-path [special variables](../docs/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:
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 |
| `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.
## Security
## Review trust and changes {#security}
### Automatic checksums
### 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
@@ -221,7 +198,7 @@ in Task. You can also configure trusted hosts in your
containing a commit hash) to prevent Task from automatically accepting a
prompt that says a remote Taskfile has changed.
### Manual checksum pinning
### 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:
@@ -231,14 +208,15 @@ version: '3'
includes:
included:
taskfile: https://taskfile.dev
checksum: c153e97e0b3a998a7ed2e61064c6ddaddd0de0c525feefd6bba8569827d8efe9
taskfile: https://raw.githubusercontent.com/go-task/task/main/website/src/public/Taskfile.yml
checksum: '<sha256-of-reviewed-file>'
```
This will disable 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:
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
@@ -251,7 +229,7 @@ checksum. There are a couple of ways you can obtain this:
will report the incorrect expected checksum and the actual checksum. You can
copy the actual checksum and replace your temporary random value.
### TLS
### 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
@@ -260,7 +238,7 @@ 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.
#### Custom Certificates
#### 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
@@ -293,7 +271,17 @@ openssl rsa -in encrypted.key -out decrypted.key
These options can also be configured in the
[configuration file](#configuration).
## Caching & Running Offline
## 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
@@ -306,8 +294,7 @@ version. However, the cache expiry duration can be modified by setting the
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_.
This means that you should never be stuck without the ability to run your tasks
as long as you have downloaded a remote Taskfile at least once.
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
@@ -326,7 +313,7 @@ the `--download` flag.
You can use the `--clear-cache` flag to clear all cached remote files.
## Configuration
## 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

View File

@@ -1,5 +1,10 @@
---
title: Incident Response Plan
description:
Task's process for detecting, triaging, mitigating, and disclosing security
incidents
section: Project
docType: project
outline: deep
---
@@ -88,4 +93,4 @@ a "best-effort" attempt to help resolve the issue.
- Make and document any changes that can be made to prevent similar issues from
arising in the future.
[security-docs]: ../security/
[security-docs]: ./index.md

View File

@@ -1,5 +1,10 @@
---
title: Security
description:
How to report Task security vulnerabilities and how the project responds to
them
section: Project
docType: project
outline: deep
---
@@ -18,5 +23,5 @@ 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
[tm]: ./threat-model
[irp]: ./incident-response-plan.md
[tm]: ./threat-model.md

View File

@@ -1,5 +1,10 @@
---
title: Threat Model
description:
Threats, assets, trust boundaries, and mitigations for the Task project and
its release infrastructure
section: Project
docType: project
outline: deep
---
@@ -13,8 +18,8 @@ of our commitment to transparency.
### Critical Assets
- **Source Code:** The Task CLI, build scripts, and configuration files
(e.g., `Taskfile.yml`, `.goreleaser.yml`).
- **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
@@ -75,8 +80,8 @@ of our commitment to transparency.
#### Secrets Leakage
- Exposure of tokens, credentials, or signing keys in logs, error messages,
or artifacts
- 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
@@ -168,7 +173,7 @@ of our commitment to transparency.
## References
- [Task Documentation](https://taskfile.dev/)
- [Incident Response Plan](./incident-response-plan)
- [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)

View File

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

View File

@@ -3,6 +3,8 @@ 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
---

View File

@@ -4,7 +4,7 @@ description:
A new completion engine that gives every shell the same suggestions, and that
can finally complete your required variables.
author: vmaerten
date: 2026-09-29
date: 2026-10-01
tags: ['new-features', 'completion']
outline: deep
editLink: false

View File

@@ -13,7 +13,54 @@ editLink: false
::: v-pre
## v3.53.0 - 2026-08-18
## 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
@@ -21,21 +68,37 @@ editLink: false
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).
- Updated taskfile versions doc to mention when version checks were introduced
(#2184 by @jubr).
- Fixed `joinUrl` collapsing the `//` in a URL scheme (e.g. producing
`http:/localhost` instead of `http://localhost`) (#2915 by @vsaraikin).
- 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).
- 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
@@ -43,37 +106,31 @@ editLink: false
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).
- `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).
- 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).
- 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).
- Fixed pressing `Esc` at an interactive variable prompt not cancelling the run
(#2942 by @anilnatha).
- 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 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).
- Fixed a pinned `checksum:` not being verified when a remote Taskfile came from
the cache (#2980 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
@@ -1638,4 +1695,4 @@ document, since it describes in depth what changed for this version.
- Add LICENSE file
:::
:::

View File

@@ -49,6 +49,28 @@
"items": {
"type": "string"
}
},
"headers": {
"type": "array",
"description": "HTTP headers to send when downloading remote Taskfiles, per host, including authentication and custom headers.",
"items": {
"type": "object",
"properties": {
"host": {
"type": "string",
"description": "Host the headers apply to, including the port if the URL has one (e.g., 'gitlab.com', 'example.com:8080')."
},
"headers": {
"type": "object",
"description": "Headers to send. Values support templating functions, e.g. {{env \"GITLAB_TOKEN\"}}.",
"additionalProperties": {
"type": "string"
}
}
},
"required": ["host", "headers"],
"additionalProperties": false
}
}
},
"additionalProperties": false