---
title: 'Scoped Taskfiles'
description:
Experiment for variable isolation and env namespace in included Taskfiles
outline: 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](./index.md#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 | `` |
| `{{.env.MY_ENV}}` | - | Works |
| `{{.PATH}}` (OS) | Works | `` |
| `{{.env.PATH}}` (OS) | - | Works |
| `{{.TASK}}` (special) | Works | Works (stays at root) |
### Example
```yaml
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
```yaml
# Taskfile.yml
version: '3'
vars:
ROOT_VAR: from_root
includes:
api: ./api
web: ./web
```
```yaml
# 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}}"
```
```yaml
# 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.
```yaml
version: '3'
tasks:
greet:
vars:
NAME: from_task
cmds:
- echo "Hello {{.NAME}}"
```
```bash
# 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.