diff --git a/website/.vitepress/config.ts b/website/.vitepress/config.ts
index 24c675f1..db44f510 100644
--- a/website/.vitepress/config.ts
+++ b/website/.vitepress/config.ts
@@ -302,6 +302,10 @@ export default defineConfig({
{
text: 'Remote Taskfiles (#1317)',
link: '/docs/experiments/remote-taskfiles'
+ },
+ {
+ text: 'Scoped Taskfiles',
+ link: '/docs/experiments/scoped-taskfiles'
}
]
},
diff --git a/website/src/docs/experiments/scoped-taskfiles.md b/website/src/docs/experiments/scoped-taskfiles.md
new file mode 100644
index 00000000..7cee72e8
--- /dev/null
+++ b/website/src/docs/experiments/scoped-taskfiles.md
@@ -0,0 +1,201 @@
+---
+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.