Azure Developer CLI hooks support multiple executor types — Bash, PowerShell, Python (and future JavaScript, TypeScript, .NET). Every hook follows the same unified lifecycle regardless of its executor: Prepare → Execute → Cleanup.
| Executor | kind value |
File extension | Status |
|---|---|---|---|
| Bash | sh |
.sh |
✅ Stable |
| PowerShell | pwsh |
.ps1 |
✅ Stable |
| Python | python |
.py |
✅ Phase 1 |
| JavaScript | js |
.js |
✅ Phase 2 |
| TypeScript | ts |
.ts |
✅ Phase 3 |
| .NET (C#) | dotnet |
.cs |
🔜 Planned |
Hooks are configured in azure.yaml under the hooks section at the
project or service level. Two optional fields are available:
Specifies the executor type for the hook. Allowed values:
sh, pwsh, js, ts, python, dotnet.
When omitted, the executor is auto-detected from the file extension of the
run path. For example, run: ./hooks/seed.py automatically selects the
Python executor.
The working directory (cwd) for hook execution. Used as the project context
for dependency installation (e.g. pip install from requirements.txt) and
builds.
Automatically inferred from the directory containing the script referenced
by run. For example, run: hooks/preprovision/main.py infers the working
directory as hooks/preprovision/. Only set dir as an override when the
project root differs from the script's directory (e.g. the entry point lives
in a src/ subdirectory but requirements.txt is in the parent).
Relative paths are resolved from the project or service root.
The simplest way to use a Python hook. The executor is inferred from the .py
extension, and the working directory is auto-inferred from the script's location.
Dependencies are installed automatically if a requirements.txt or
pyproject.toml is found in the script's directory.
hooks:
postprovision:
run: ./hooks/seed-database.pyWhen the script lives in a subdirectory, the dir is automatically set to that
directory. No explicit dir field is needed:
hooks:
preprovision:
run: hooks/preprovision/main.py
# dir is auto-inferred as hooks/preprovision/When auto-detection is not desired or the file extension is ambiguous, set
the kind field explicitly to select the Python executor:
hooks:
postprovision:
run: ./hooks/setup.py
kind: pythonWhen the script lives in a subdirectory but dependencies (requirements.txt)
are at the parent level, use dir to override the auto-inferred working
directory:
hooks:
postprovision:
run: ./tools/scripts/seed.py
dir: ./tools # override: requirements.txt is in ./tools, not ./tools/scriptsUse windows and posix overrides to provide platform-specific hooks:
hooks:
postprovision:
windows:
run: ./hooks/setup.ps1
shell: pwsh
posix:
run: ./hooks/setup.py
kind: pythonHooks support the secrets field for resolving Azure Key Vault references,
regardless of executor type:
hooks:
postprovision:
run: ./hooks/seed-database.py
secrets:
DB_CONNECTION_STRING: DATABASE_URLThe simplest way to use a JavaScript hook. The executor is inferred from the .js
extension. Dependencies are installed automatically if a package.json is found
in the script's directory (or a parent directory up to the project root).
hooks:
postprovision:
run: ./hooks/seed-database.jsWhen a package.json exists near the script, npm install runs automatically
before execution.
hooks:
postprovision:
run: ./hooks/seed-database.js
# package.json in ./hooks/ → npm install runs automaticallyhooks:
postprovision:
run: ./hooks/setup
kind: jshooks:
postprovision:
run: ./tools/scripts/seed.js
dir: ./tools # package.json is in ./tools, not ./tools/scriptshooks:
postprovision:
windows:
run: ./hooks/setup.ps1
shell: pwsh
posix:
run: ./hooks/setup.js
kind: jsTypeScript hooks use npx tsx for zero-config execution. tsx handles
TypeScript natively without requiring a separate compilation step, and
supports both ESM and CommonJS modules automatically.
hooks:
postprovision:
run: ./hooks/seed-database.tsWhen a package.json is found, dependencies are installed before execution.
If tsx is listed as a dependency, the local version is used; otherwise
npx downloads it on demand.
hooks:
postprovision:
run: ./hooks/seed-database.ts
# package.json with tsx dependency → uses local tsxhooks:
postprovision:
run: ./hooks/setup
kind: tsBash hooks continue to work exactly as before. The kind field is
optional and defaults to the appropriate shell type:
hooks:
preprovision:
run: echo "Provisioning starting..."
shell: shEvery hook follows the unified Prepare → Execute → Cleanup lifecycle:
- Prepare — The executor validates prerequisites and performs any
setup. This includes:
- Kind detection from the explicit
kindfield, theshellfield, or the file extension of therunpath. - Runtime validation — verifying the required runtime is
installed (e.g. Python 3 for
.pyhooks, pwsh for.ps1). - Project discovery — walking up the directory tree from the
script to find project files (
requirements.txt,pyproject.toml,package.json,*.*proj). The search stops at the project/service root boundary. - Dependency installation — creating a virtual environment (for Python) and installing dependencies from the discovered project file.
- Temp file creation — for inline scripts (Bash/PowerShell only), writing the script content to a temporary file.
- Kind detection from the explicit
- Execute — The executor runs the hook using the appropriate
runtime (e.g.
python,bash,pwsh). - Cleanup — The executor removes any temporary resources created during Prepare (e.g. inline script temp files). This runs regardless of whether Execute succeeded or failed.
- Inline scripts are only supported for Bash and PowerShell hooks. All other executor types must reference a file path.
- Phase 1 supports Python as a non-shell executor. Phase 2 adds JavaScript and Phase 3 adds TypeScript. .NET support is planned for a future phase.
- Virtual environments (Python) are created in the project directory alongside
the dependency file, following the naming convention
{dirName}_env. - TypeScript hooks require Node.js 18+ and use
npx tsxfor execution. Iftsxis not installed locally,npxwill download it automatically. - Package manager for JS/TS hooks currently uses npm for dependency installation. Support for pnpm and yarn may be added in a future release.