Files
go-task/website/src/docs/experiments/scoped-taskfiles.md
Valentin Maerten 5ef7313e95 docs(experiments): add SCOPED_TASKFILES documentation
Document the new experiment with:
- Environment namespace ({{.env.XXX}}) explanation
- Variable scoping between includes
- CLI variables priority
- Migration guide from legacy mode
- Comparison table between legacy and scoped modes
2026-01-25 19:54:04 +01:00

5.2 KiB

title, description, outline
title description outline
Scoped Taskfiles Experiment for variable isolation and env namespace in included Taskfiles deep

Scoped Taskfiles

::: warning

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

:::

::: danger

This experiment breaks the following functionality:

  • Environment variables are no longer available at root level in templates
    • Before: {{.PATH}}, {{.MY_ENV}}
    • After: {{.env.PATH}}, {{.env.MY_ENV}}
  • Variables from sibling includes are no longer visible
    • Include A cannot access variables defined in Include B
    • Each include only sees: root vars + its own vars + parent vars

:::

::: info

To enable this experiment, set the environment variable: TASK_X_SCOPED_TASKFILES=1. Check out our guide to enabling experiments for more information.

:::

This experiment introduces two major changes to how variables work in Task:

  1. Environment namespace: Environment variables (both OS and Taskfile env: sections) are moved to a dedicated {{.env.XXX}} namespace, separating them from regular variables
  2. Variable scoping: Variables defined in included Taskfiles are isolated - sibling includes cannot see each other's variables

Environment Namespace

With this experiment enabled, environment variables are no longer mixed with regular variables at the template root level. Instead, they are accessible through the {{.env.XXX}} namespace.

Comparison Table

Template Legacy SCOPED_TASKFILES
{{.MY_VAR}} (from vars:) Works Works
{{.MY_ENV}} (from env:) Works <no value>
{{.env.MY_ENV}} - Works
{{.PATH}} (OS) Works <no value>
{{.env.PATH}} (OS) - Works
{{.TASK}} (special) Works Works (stays at root)

Example

version: '3'

env:
  DB_HOST: localhost

vars:
  DB_NAME: mydb

tasks:
  show:
    cmds:
      # Access Taskfile env: section
      - echo "Host: {{.env.DB_HOST}}"

      # Access regular vars (unchanged)
      - echo "Name: {{.DB_NAME}}"

      # Access OS environment variables
      - echo "Path: {{.env.PATH}}"

      # Special variables stay at root level
      - echo "Task: {{.TASK}}"

Variable Scoping

Variables defined in included Taskfiles are now isolated from each other. Sibling includes cannot access each other's variables, but child includes can still inherit variables from their parent.

Example

# Taskfile.yml
version: '3'

vars:
  ROOT_VAR: from_root

includes:
  api: ./api
  web: ./web
# api/Taskfile.yml
version: '3'

vars:
  API_VAR: from_api

tasks:
  show:
    cmds:
      # Inherited from root - works
      - echo "ROOT_VAR={{.ROOT_VAR}}"

      # Own variable - works
      - echo "API_VAR={{.API_VAR}}"

      # From sibling include - NOT visible
      - echo "WEB_VAR={{.WEB_VAR}}"
# web/Taskfile.yml
version: '3'

vars:
  WEB_VAR: from_web

tasks:
  show:
    cmds:
      # Inherited from root - works
      - echo "ROOT_VAR={{.ROOT_VAR}}"

      # Own variable - works
      - echo "WEB_VAR={{.WEB_VAR}}"

      # From sibling include - NOT visible
      - echo "API_VAR={{.API_VAR}}"

CLI Variables Priority

With this experiment, CLI variables (passed as task foo VAR=value) have the highest priority and will override task-level variables.

version: '3'

tasks:
  greet:
    vars:
      NAME: from_task
    cmds:
      - echo "Hello {{.NAME}}"
# CLI vars now override task vars
TASK_X_SCOPED_TASKFILES=1 task greet NAME=cli
# Output: Hello cli

Migration Guide

To migrate your Taskfiles to use this experiment:

  1. Update environment variable references in your templates:

    • {{.PATH}} becomes {{.env.PATH}}
    • {{.HOME}} becomes {{.env.HOME}}
    • {{.MY_TASKFILE_ENV}} becomes {{.env.MY_TASKFILE_ENV}}
  2. Variables in vars: sections remain unchanged:

    • {{.MY_VAR}} still works the same way
  3. Special variables stay at root level:

    • {{.TASK}}, {{.ROOT_DIR}}, {{.TASKFILE}}, {{.TASKFILE_DIR}}, etc.
  4. Review cross-include variable dependencies:

    • If your included Taskfiles rely on variables from sibling includes, you'll need to either move those variables to the root Taskfile or pass them explicitly via the vars: attribute in the includes: section.