---
url: /docs/contributing.md
description: >-
  Comprehensive guide for contributing to the Task project, including setup,
  development, testing, and submitting PRs
---

# Contributing

Thank you for your interest in contributing to Task! We welcome and appreciate
all forms of contributions, but we kindly ask that you read this document first.
If you have any questions that were not answered by this document, you can reach
out on our [Discord](https://discord.gg/6TY36E39UK) or by opening a discussion
on GitHub. If you want to help, but you're not sure where to start, you can
check out our list of
[good first issues](https://github.com/go-task/task/contribute).

::: info

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

:::

## AI Usage Policy

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

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

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

## Before you start

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

## 1. Setup

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

```shell
mise install
```

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

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

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

## 2. Making changes

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

### Running your changes

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

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

### Updating documentation

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

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

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

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

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

#### Documentation channels

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

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

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

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

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

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

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

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

### Writing tests

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

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

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

## 3. Committing your code

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

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

## 4. Submitting a PR

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

## FAQ

> I want to contribute, where do I start?

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

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

> I'm stuck, where can I get help?

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

***

[task]: https://github.com/go-task/task

[vscode-task]: https://github.com/go-task/vscode-task

[go]: https://go.dev

[gofumpt]: https://github.com/mvdan/gofumpt

[gci]: https://github.com/daixiang0/gci

[golangci-lint]: https://golangci-lint.run

[golangci-lint-docs]: https://golangci-lint.run/welcome/integrations/

[prettier]: https://prettier.io

[nodejs]: https://nodejs.org/en/

[pnpm]: https://pnpm.io/

[mise]: https://mise.jdx.dev

[vitepress]: https://vitepress.dev

[json-schema]: https://github.com/go-task/task/blob/main/website/src/public/schema.json

[task-open-issues]: https://github.com/go-task/task/issues

[vscode-task-open-issues]: https://github.com/go-task/vscode-task/issues

[good-first-issue]: https://github.com/go-task/task/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22

[discord-server]: https://discord.gg/6TY36E39UK

[discussion]: https://github.com/go-task/task/discussions

[conventional-commits]: https://www.conventionalcommits.org

[experiments]: /docs/experiments.md

[experiments-workflow]: /docs/experiments.md#workflow

[styleguide]: /docs/styleguide.md

[cli-reference]: /docs/reference/cli.md

[schema-reference]: /docs/reference/schema.md

[usage-guide]: /docs/guide.md
