Task (go-task)

Table of Contents

  1. How It Works
  2. Supported File Patterns
    1. Remote Includes and Discovery Errors
    2. Global Taskfile
    3. Custom Taskfile Patterns
  3. Task Execution
  4. Example Taskfile
  5. Configuration
    1. Enabling / Disabling
    2. Application Path
    3. Aliases In The Tree
  6. Wildcard Tasks
  7. CLI_ARGS Forwarding
  8. Required Variables (requires.vars)
  9. Watch Mode
  10. Troubleshooting
    1. No tasks appear in the tree view
    2. Tasks from included Taskfiles are missing
  11. Related

Task is a fast, cross-platform task runner and build tool written in Go. It is designed as a simpler, more portable alternative to Make. Tasks are defined in a Taskfile.yml file using a clean YAML syntax with support for variables, dependencies, namespacing, includes, and remote Taskfiles.

How It Works

Task discovery uses the CLI’s built-in JSON output mode rather than static YAML parsing. This correctly resolves included Taskfiles, namespaced tasks, and template variables that a static parser cannot evaluate. For each discovered Taskfile in the workspace, the extension runs:

task --taskfile <discoveryTaskfile> --list-all --no-status --json

The JSON response contains the resolved task name, description, and source location (file path and line number) for every available task. Each task is surfaced as a runnable entry in the tree view.

The task executable must be installed and accessible on your system PATH (or configured via workspaceTasks.applicationPath.task) for task discovery to work. If the executable is not found, no tasks are discovered from Taskfiles.


Supported File Patterns

The extension scans for any of the following Taskfile filenames anywhere in the workspace:

Pattern Description
**/Taskfile.yml Standard Taskfile (recommended name)
**/taskfile.yml Lowercase variant
**/Taskfile.yaml YAML extension variant
**/taskfile.yaml Lowercase YAML variant
**/Taskfile.dist.yml Distribution Taskfile (intended for version control)
**/taskfile.dist.yml Lowercase distribution variant
**/Taskfile.dist.yaml Distribution YAML variant
**/taskfile.dist.yaml Lowercase distribution YAML variant

When multiple Taskfile variants exist in the same directory (e.g. both Taskfile.yml and Taskfile.dist.yml), each distinct Taskfile path is discovered using an explicit --taskfile argument.

Global Taskfiles ($HOME/Taskfile.yml) are outside the workspace and are not discovered by default.

Remote Includes and Discovery Errors

If Task cannot list tasks (for example, an untrusted remote include, a Git clone failure, or a missing executable), Workspace Tasks adds an error to the Problems panel on the Taskfile that failed to load. The diagnostic includes the CLI error details; the Output > Workspace Tasks channel retains the log. Errors clear after successful discovery or when the Taskfile is removed or discovery is disabled.

Task’s remote trust policy is separate from VS Code Workspace Trust. The extension does not automatically trust remote hosts or bypass Task’s trust checks. Only add hosts whose remote Taskfiles you trust to your project’s .taskrc.yml or .taskrc.yaml:

remote:
  trusted-hosts:
    - github.com
  cache-dir: .task
temp-dir: .task

trusted-hosts allows Task to load remote includes from the listed hosts. The cache and temporary directory settings control Task’s downloaded-file cache and task metadata. Git includes (HTTPS or SSH) are always cloned into Task’s user-level cache (for example %LOCALAPPDATA%\task\task-git-repos on Windows), which remote.cache-dir does not relocate; a clone error mentioning that location does not by itself mean .taskrc.yml was ignored. Consider excluding .task/ from version control. trusted-hosts applies to HTTPS raw files, Git over HTTPS, and Git over SSH; repository paths, refs, and SSH credentials must still be valid.

For example, include one remote Taskfile using one of these forms:

includes:
  codeql:
    taskfile: 'git@github.com:camalot/actions.git//smells/codeql/TaskFile.yml?ref=main'
    # Or Git over HTTPS:
    # taskfile: 'https://github.com/camalot/actions.git//smells/codeql/TaskFile.yml?ref=main'
    # Or a raw HTTPS file:
    # taskfile: 'https://raw.githubusercontent.com/camalot/actions/main/smells/codeql/TaskFile.yml'
    flatten: true

Creating, editing, or deleting .taskrc.yml or .taskrc.yaml in a discovered Taskfile’s directory, a workspace root, or your home directory automatically triggers a debounced task reload, including when the previous discovery failed. Global Taskfiles use the same error reporting and configuration watching when global discovery is enabled. CLI discovery only runs in trusted VS Code workspaces.

Taskfile discovery processes are serialized across workspace and global discovery, including overlapping save-triggered and manual refreshes. Saving a Taskfile can trigger more than one refresh; running them one at a time prevents concurrent Task processes from cloning the same Git include into Task’s shared user-level clone cache. Every discovery runs in the discovered Taskfile’s directory so Task can load its local .taskrc.yml or .taskrc.yaml; the extension does not override trust or cache settings.

Tasks from remote includes may appear under External. Their source URIs retain the original ssh:// or https:// scheme, but execution uses the local Taskfile that included them and the task’s fully qualified name. For example:

task --taskfile /workspace/sample/sample-workspace-tasks/task/Taskfile.yml codeql:action:.

This also applies to aliases and local includes, preserving the including Taskfile’s namespaces, variables, and include settings. The working directory is the directory of the local discovery Taskfile, not the remote URI.

For remote tasks, Open File opens the including local Taskfile instead. Task’s CLI does not expose a command to report the cached source file path; the extension does not guess cache locations or attempt to open remote URIs as local files.

Global Taskfile

Task can discover tasks from a global Taskfile in your home directory when enabled:

{
  "workspaceTasks.taskfile.discoverGlobalTaskfile": true
}

When enabled, Workspace Tasks checks standard Taskfile variants in $HOME and uses the first one found by Task precedence. These files are watched for create/change/delete events, and global tasks are refreshed automatically when they change.

Custom Taskfile Patterns

Deprecated in favor of workspaceTasks.additionalFilePatterns.taskfile.

If your project uses non-standard Taskfile names, add custom glob patterns to discover them:

{
  "workspaceTasks.taskfile.additionalFilePatterns": [
    "**/Taskfile.ci.yml",
    "**/backend/MyTasks.yml"
  ]
}

Executions automatically include --taskfile <absolute path> to ensure the selected Taskfile is used consistently regardless of current working directory.


Task Execution

When you run a Task task, the extension invokes:

task --taskfile <discoveryTaskfile> <taskName> [args]

The working directory is set to the directory containing the discovery Taskfile. This ensures task resolves the correct Taskfile, local includes, and relative paths.

Run with arguments example:

task --taskfile /workspace/project/Taskfile.yml deploy --force

Example Taskfile

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

version: '3'

vars:
  APP_NAME: my-app

tasks:
  default:
    desc: Print a greeting message
    cmds:
      - echo "Hello from Task!"
    silent: true

  build:
    desc: Build the application
    cmds:
      - echo "Building ..."

  test:
    desc: Run the test suite
    cmds:
      - echo "Running tests for ..."

  ci:
    desc: Run the full CI pipeline
    deps: [build, test]

Configuration

Enabling / Disabling

Task support is enabled by default. To disable it, add the following to your VS Code settings:

{
  "workspaceTasks.enabledTaskTypes": {
    "taskfile": false
  }
}

Application Path

If task is not on your system PATH, or you want to use a specific version, configure the executable path:

{
  "workspaceTasks.applicationPath.taskfile": "/usr/local/bin/task"
}

On Windows, if the path ends with task (without .exe), the .exe extension is appended automatically. The ~/ prefix is expanded to your home directory on all platforms.

See Application Paths for the full reference.

Aliases In The Tree

Task supports aliases (alternative names for the same task). When workspaceTasks.taskfile.showAliases is enabled (default: true), tasks with aliases appear as expandable tree items and each alias is shown as a child item.

Running an alias child executes:

task <alias>

Disable alias child items in the tree with:

{
  "workspaceTasks.taskfile.showAliases": false
}

Wildcard Tasks

Task supports task names that contain * as a wildcard β€” for example:

tasks:
  build:*:
    desc: Build a component
    cmds:
      - echo "Building "

When you run a wildcard task from the tree view (or via a command), the extension detects the * in the task name and prompts you to supply a value for each wildcard segment before executing.

For example, running build:* opens an input box:

Enter value for wildcard 1 of 1 in "build:*"

Type the value (e.g. frontend) and press Enter. The extension then runs:

task build:frontend

If the task name contains multiple wildcards (e.g. deploy:*:*), you are prompted once for each * in sequence. Pressing Escape at any prompt cancels the operation.

Wildcard tasks are indicated in the tree view with a [*] suffix on their tooltip to help you identify them at a glance.


CLI_ARGS Forwarding

Task’s `` template variable forwards any command-line arguments that follow -- directly to the task. The extension detects this pattern at discovery time and automatically inserts -- before any arguments you supply when running such a task with Run with Args.

For example, given:

tasks:
  test:
    desc: Run tests
    cmds:
      - go test ./... 

Running this task with args -v -run TestFoo produces:

task test -- -v -run TestFoo

Without ``, arguments are appended directly (no -- separator).


Required Variables (requires.vars)

Taskfile supports required variables via requires.vars.

Workspace Tasks treats these as a Taskfile-specific guided argument flow:

  • Run Task prompts only for required variables that are not already predefined in Taskfile vars.
  • Run with Args always prompts for all required variables, and uses predefined values as defaults when available.

For enum-based required variables, the extension shows a pick list. For plain variables, it shows an input box. Values are passed to task as VAR='value' assignments and are inserted before any -- separator.

Example:

tasks:
  prompt:
    vars:
      APP_NAME: my-app
    requires:
      vars:
        - name: APP_NAME
        - name: ENVIRONMENT
          enum: [dev, staging, prod]

In this example:

  • Run Task prompts only for ENVIRONMENT (because APP_NAME is already defined).
  • Run with Args prompts for both APP_NAME and ENVIRONMENT, with APP_NAME pre-filled to my-app.

This guided flow is controlled by the workspaceTasks.task.guidedArgInput setting (default: true). If the setting is false, the required-variables prompt is skipped and the task runs without collecting variable values.


Watch Mode

Task supports a watch mode (task --watch) that re-runs a task whenever its source files change. To start a task in watch mode, click the Watch ($(eye)) button that appears next to a task item in the tree view, or right-click and select Watch Task.

Watch mode opens a new integrated terminal named task watch: <taskName>. Close the terminal to stop watching.

To disable the Watch button on task items:

{
  "workspaceTasks.taskfile.enableWatchMode": false
}

Troubleshooting

No tasks appear in the tree view

  1. Check that task is installed. Run task --version in a terminal to verify.
  2. Check the application path setting. If task is not on your PATH, set workspaceTasks.applicationPath.task to the full path of the executable.
  3. Check that task is enabled. Verify workspaceTasks.enabledTaskTypes.task is true (it is true by default).
  4. Reload the workspace. Use the Workspace Tasks: Refresh command (Ctrl+Shift+P β†’ Workspace Tasks: Refresh).

Tasks from included Taskfiles are missing

Task automatically resolves includes when --list-all --json is invoked. If included Taskfiles reference paths that do not exist, task may print an error to stderr instead of returning JSON. Check the extension output channel (Workspace Tasks in the Output panel) for warning messages from the task discovery process.