name: sayt-ide description: > How to write .vscode/tasks.json — build/test task schema, dependsOn chains, per-language examples (Gradle, Go, Node/pnpm, Python, Zig). Use when creating build tasks, test tasks, or fixing compilation/test failures. user-invocable: false
build / test — VS Code Tasks via vscode-task-runner
sayt build and sayt test delegate to vscode-task-runner (vtr), which reads .vscode/tasks.json and runs the tasks labeled "build" and "test" respectively.
How It Works
sayt buildrunsvtr buildwhich finds the task with"label": "build"in.vscode/tasks.jsonsayt testrunsvtr testwhich finds the task with"label": "test"- vtr resolves
dependsOnchains and runs prerequisite tasks first - The commands execute as shell commands in the project directory
vtr is installed via uvx (Python) and is cached after sayt setup for offline use.
.vscode/tasks.json Schema
Every tasks.json must have:
"version": "2.0.0"- A
tasksarray with at minimum a"build"and"test"task
Required Task Structure
{
"label": "build", // MUST be exactly "build" or "test"
"type": "shell", // MUST be "shell" for sayt compatibility
"command": "...", // The executable to run
"args": ["..."], // Arguments (optional)
"group": {
"kind": "build", // "build" or "test"
"isDefault": true // Mark as default for the group
},
"problemMatcher": [], // VS Code error matching (can be empty)
"dependsOn": ["..."] // Prerequisite tasks (optional)
}
Windows Support
Add a windows override for cross-platform commands:
{
"label": "build",
"type": "shell",
"command": "./gradlew",
"windows": { "command": ".\\gradlew.bat" },
"args": ["assemble"]
}
Task Dependencies
Use dependsOn to run prerequisite tasks:
{
"label": "build",
"type": "shell",
"command": "go",
"args": ["build", "-o", "app"],
"dependsOn": ["sqlc-generate", "buf-generate"]
}
Dependency tasks don't need isDefault: true but should still be in the tasks array.
Per-Language Examples
Kotlin/Java (Gradle)
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"type": "shell",
"command": "./gradlew",
"windows": { "command": ".\\gradlew.bat" },
"args": ["assemble"],
"problemMatcher": [],
"group": { "kind": "build", "isDefault": true }
},
{
"label": "test",
"type": "shell",
"command": "./gradlew",
"windows": { "command": ".\\gradlew.bat" },
"args": ["test"],
"group": { "kind": "test", "isDefault": true },
"problemMatcher": []
}
]
}
Go
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"type": "shell",
"command": "go",
"args": ["build", "-o", "app"],
"group": { "kind": "build", "isDefault": true },
"dependsOn": ["sqlc-generate", "buf-generate"],
"problemMatcher": []
},
{
"label": "sqlc-generate",
"type": "shell",
"command": "sqlc",
"args": ["generate"],
"group": { "kind": "build" },
"problemMatcher": []
},
{
"label": "buf-generate",
"type": "shell",
"command": "buf",
"args": ["generate", "../../libraries/xproto", "--template", "../../libraries/xproto/buf.go.gen.yaml", "-o", "../../libraries/xproto"],
"group": { "kind": "build" },
"problemMatcher": []
},
{
"label": "test",
"type": "shell",
"command": "go",
"args": ["run", "gotest.tools/gotestsum@v1.12.0", "-f", "github-actions", "--", "./...", "-tags=unit_test"],
"group": { "kind": "test", "isDefault": true },
"problemMatcher": []
}
]
}
Node.js / pnpm (monorepo with Turbo)
{
"version": "2.0.0",
"tasks": [
{
"label": "install",
"type": "shell",
"command": "pnpm install --frozen-lockfile"
},
{
"label": "build",
"type": "shell",
"command": "pnpm -C ../.. exec turbo --filter ./guis/web assemble",
"problemMatcher": ["$tsc"],
"group": { "kind": "build", "isDefault": true },
"dependsOn": ["install"]
},
{
"label": "test",
"type": "shell",
"command": "pnpm -C ../.. exec turbo --filter ./guis/web test",
"group": { "kind": "test", "isDefault": true },
"problemMatcher": ["$tsc"],
"dependsOn": ["install"]
}
]
}
Node.js / pnpm (standalone)
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"type": "shell",
"command": "pnpm",
"args": ["build"],
"group": { "kind": "build", "isDefault": true },
"problemMatcher": ["$tsc"]
},
{
"label": "test",
"type": "shell",
"command": "pnpm",
"args": ["test"],
"group": { "kind": "test", "isDefault": true },
"problemMatcher": []
}
]
}
Python
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"type": "shell",
"command": "python",
"args": ["-m", "build"],
"group": { "kind": "build", "isDefault": true },
"problemMatcher": []
},
{
"label": "test",
"type": "shell",
"command": "pytest",
"group": { "kind": "test", "isDefault": true },
"problemMatcher": []
}
]
}
Zig
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"type": "shell",
"command": "zig",
"args": ["build"],
"group": { "kind": "build", "isDefault": true },
"problemMatcher": []
},
{
"label": "test",
"type": "shell",
"command": "zig",
"args": ["build", "test"],
"group": { "kind": "test", "isDefault": true },
"problemMatcher": []
}
]
}
Writing Good Tasks
- Label exactly "build" and "test" — vtr looks for these exact labels
- Use
"type": "shell"— Required for sayt/vtr compatibility - Set
isDefault: true— Mark one build and one test task as default - Use
dependsOn— For code generation or install steps that must run first - Add
problemMatcher— Helps VS Code parse errors (use["$tsc"]for TypeScript,[]otherwise) - Add
windowsoverrides — If the command differs on Windows (e.g.,gradlewvsgradlew.bat) - Keep it simple — The task should run the same command you'd type in the terminal
Interpreting Results
- Build success: The underlying compiler/bundler exited 0
- Build failure: Read the compiler output — fix the source code
- Test success: All unit tests passed
- Test failure: Read test output for assertion failures and stack traces
- "command not found: vtr": Run
pipx install vscode-task-runnerorsayt setup
Current flags
!sayt help build 2>&1 || true
!sayt help test 2>&1 || true