Tasks
Tasks are the core unit in qp: every executable workflow (linting, testing, builds, deploys, checks) is a task.
Task Anatomy
Every task needs:
desc(required)- Exactly one execution mode:
cmdfor one shell commandstepsfor a pipeline of named tasks or inline shell commandsrunfor expression DAG execution
tasks:
lint:
desc: Lint the repo
cmd: golangci-lint run
check:
desc: Quality gate
steps: [lint, test]
release:
desc: Branch-aware publish flow
run: when(branch() == "main", publish)Command Tasks
Basic command task
tasks:
test:
desc: Run all tests
cmd: go test ./...Command task with env, dir, shell
defaults:
dir: .
tasks:
ui-test:
desc: Run web tests in strict bash mode
cmd: npm test -- --runInBand
dir: web
shell: /bin/bash
shell_args: [-euo, pipefail, -c]
env:
CI: "1"
NODE_ENV: testdir overrides defaults.dir for that task. shell and shell_args let you opt into strict shell behavior when needed.
qp help <task> output
$ qp help ui-test
Task: ui-test
Description: Run web tests in strict bash mode
Usage: qp ui-test [--var name=value] [--profile name] [--dry-run] [--verbose] [--quiet] [--no-cache] [--allow-unsafe] [--events] [--json]
Type: cmd
Dir: web
Shell: /bin/bash -euo pipefail -c
Safety: safe
Working Directory Rules
Use top-level defaults.dir for consistent repo-relative execution, and override per task only when needed.
defaults:
dir: services/api
tasks:
lint:
desc: Lint API service
cmd: golangci-lint run ./...
docs:
desc: Build docs site from repo root
dir: .
cmd: quarto render manualEnvironment Variables
Environment values can come from:
- Your process environment
- Top-level
env_file - Task
env - CLI overlays (
--var, profiles, params, etc.) that interpolate into task values
env_file: .env
tasks:
smoke:
desc: Hit API health endpoint
cmd: curl -fsS "$BASE_URL/healthz"
env:
BASE_URL: https://staging.internal.exampleqp smokeSafety Levels
Safety labels help humans and agents decide what is safe to run automatically.
| Safety | Typical usage | Requires --allow-unsafe |
|---|---|---|
safe |
Read-only checks (go test, linters, static analysis) |
No |
idempotent |
Repeatable mutations (terraform plan, sync jobs) |
No |
destructive |
Repo/data mutation (rm, schema drops, force rewrites) |
Yes |
external |
Outside-repo side effects (deploys, releases, notifications) | Yes |
tasks:
deploy:
desc: Deploy API to production
cmd: ./scripts/deploy-prod.sh
safety: externalqp deploy
# task "deploy" is marked external; rerun with --allow-unsafe ...
qp deploy --allow-unsafe--dry-run still works without --allow-unsafe, which is useful for validating intent before execution.
Agent Visibility, Silent, Defer, Timeout
tasks:
compose-up:
desc: Start local stack
cmd: docker compose up -d
defer: docker compose down
timeout: 5m
silent: false
agent: falseagent: falsehides risky or noisy tasks from autonomous agent defaults.deferalways runs after the main command (pass or fail), commonly used for cleanup.timeoutuses Go duration syntax (30s,5m,1h).- timeout exits with code
124and statustimeout.
Error Formats
If a task emits stable diagnostics, set error_format so --json output includes parsed errors.
Supported values: go_test, pytest, tsc, eslint, generic.
tasks:
unit:
desc: Run Go tests with structured diagnostics
cmd: go test ./...
error_format: go_testqp unit --jsonqp still streams raw stderr/stdout, and adds structured parse data when possible.
Dependencies With needs
Use needs when prerequisites should run before a command task, while keeping that task’s own command separate.
tasks:
lint:
desc: Lint code
cmd: golangci-lint run
test:
desc: Run tests
cmd: go test ./...
build:
desc: Build binary after quality checks
needs: [lint, test]
cmd: go build ./cmd/qpDifference from steps:
needs= prerequisite tasks run first, then this task’s command runssteps= this task is itself a pipeline definition
Default Task
Set a top-level default for the common command:
default: checkNow plain qp runs check.
Next Step
For a deep dive on parameter passing and validation rules, continue to Tasks and Params.