Repository navigation
Azure Functions CLI (v5) Bug Bash
Quick Reference:
- CLI docs: https://aka.ms/func-cli
- File an issue: https://aka.ms/func-cli/file-an-issue
The install script should do this for you with the -BugBash | BUGBASH=true flag being passed, but this is just FYI
# bash / zsh
export FUNC_CLI_WORKLOADS_SOURCE="https://pkgs.dev.azure.com/azfunc/public/_packaging/pre-release/nuget/v3/index.json"
export FUNC_CLI_QUICKSTART_MANIFEST_URL="https://raw.githubusercontent.com/Azure/azure-functions-templates/dev/Functions.Templates/Template-Manifest/manifest.json"
export FUNC_CLI_WORKLOADS_PRERELEASE="true"
# PowerShell
$env:FUNC_CLI_WORKLOADS_SOURCE = "https://pkgs.dev.azure.com/azfunc/public/_packaging/pre-release/nuget/v3/index.json"
$env:FUNC_CLI_QUICKSTART_MANIFEST_URL = "https://raw.githubusercontent.com/Azure/azure-functions-templates/dev/Functions.Templates/Template-Manifest/manifest.json"
$env:FUNC_CLI_WORKLOADS_PRERELEASE = "true"Welcome! This document walks you through installing the new func CLI (v5),
poking at every command surface, and running an end-to-end "init → new → run →
pack" flow for each supported stack (Go, Node, Python, .NET).
The v5 CLI is a ground-up rebuild on .NET 10 with a workload-based
extensibility model. v4 is still the way to package and publish today, so the
E2E flow uses v5 for init / new / run and v4 for func pack.
Scope. Test what's documented here. If you find something weird outside the scripted flows, even better, log it!
Install whichever of these you need for the flows you plan to test:
| Tool | Why | Notes |
|---|---|---|
| .NET 10 SDK | dotnet stack | See global.json for the exact pinned version. |
| Node.js 20+ | node stack | LTS is fine. |
| Python 3.11+ | python stack | A venv-capable install. |
| Go 1.22+ | go stack | Only needed if you're testing the Go flow. |
| PowerShell 7+ or bash/zsh | Install scripts | One of them; the installer supports both. |
You'll also want a clean working directory you don't mind throwing away. Suggested:
mkdir -p ~/func-bug-bash && cd ~/func-bug-bashThe installer auto-detects OS / arch, downloads the latest 5.x release from
GitHub, drops it in ~/.azure-functions, and adds that to PATH. It will also set the
required environment variables for you.
& ([scriptblock]::Create((irm https://aka.ms/func-cli/install.ps1))) -Source jviau/azure-functions-core-tools -Prerelease -BugBashcurl -sSL https://aka.ms/func-cli/install.sh | PRERELEASE=true SOURCE=jviau/azure-functions-core-tools BUGBASH=true bash
source ~/.bashrc # or ~/.zshrc, depending on your shellfunc --version # prints just the version
func --verbose # prints version + runtime + install details
func help # full command treeThe install script should do this for you with the -BugBash | BUGBASH=true flag being passed, but this is just FYI
# bash / zsh
export FUNC_CLI_WORKLOADS_SOURCE="https://pkgs.dev.azure.com/azfunc/public/_packaging/pre-release/nuget/v3/index.json"
export FUNC_CLI_QUICKSTART_MANIFEST_URL="https://raw.githubusercontent.com/Azure/azure-functions-templates/dev/Functions.Templates/Template-Manifest/manifest.json"
export FUNC_CLI_WORKLOADS_PRERELEASE="true"
# PowerShell
$env:FUNC_CLI_WORKLOADS_SOURCE = "https://pkgs.dev.azure.com/azfunc/public/_packaging/pre-release/nuget/v3/index.json"
$env:FUNC_CLI_QUICKSTART_MANIFEST_URL = "https://raw.githubusercontent.com/Azure/azure-functions-templates/dev/Functions.Templates/Template-Manifest/manifest.json"
$env:FUNC_CLI_WORKLOADS_PRERELEASE = "true"For every command, run it with no args, with --help, with a bad value, and
with Ctrl+C mid-flight. We care about:
- Help text is accurate and matches what the command actually does.
- Errors are actionable: they tell you what to do next.
-
Ctrl+Cexits cleanly (no stack trace, non-zero exit code). - Colors / icons render correctly. Try
NO_COLOR=1 func ...and a non-TTY pipe (func help | cat).
| Command | Try |
|---|---|
func |
No args, should show help. |
func help [command] |
func help, func help workload, func help bogus. |
func --version / func --verbose
|
Both forms. |
func version |
Same output as --version. |
func setup prepares the local machine: host, extension bundle, and (since
5.0.0) the matching stack workload for your project.
func setup --help
func setup # interactive, detects from local.settings.json
func setup --features node
func setup --features python,host
func setup --features python,node,go
func setup --features runtime
func setup --non-interactive --yes
func setup --profile <profile-name>func profile list
func profile show <profile>
func profile set <profile>The full lifecycle of installable language workloads and tooling.
func workload search
func workload search dotnet
func workload list # what's installed
func workload install <id>
func workload install ./path/to/local.nupkg
func workload install <id> --version <semver>
func workload install <id> --exact
func workload install <id> --force
func workload update <id>
func workload uninstall <id>
func workload prune # remove inactive side-by-side installsAliases to try as <id>: dotnet, node, python, go.
Edge cases worth pushing on:
- Install something, then install the same alias again, expect "already installed" rather than a duplicate.
- Install with
--forceafter a successful install. -
func workload uninstallon something not installed. -
func workload install bogus-package(resolution failure). -
func workload install <id> --source ./does-not-exist.
These are the project-level commands. They require a stack workload to be installed first (see §7).
func init --help
func new --help
func run --help # also aliased as `func start`Path argument variations — each of these commands accepts an optional
positional [path]. Test both forms:
# With an explicit path (created if it doesn't exist)
func init MyApp
func new MyApp --template "HTTP trigger" --name hello
func run MyApp
# Without a path (uses the current working directory)
mkdir MyApp && cd MyApp
func init
func new --template "HTTP trigger" --name hello
func runThings to push on:
-
func init MyAppandfunc initin./MyAppshould produce identical layouts. - Relative (
./MyApp), absolute (/tmp/MyApporC:\temp\MyApp), and bare (MyApp) paths all work. - Path with spaces (
"My App") is handled correctly. - Passing a path to
func new/func runthat wasn't initialized produces a clear error, not a stack trace. -
func run MyAppandcd MyApp && func runboot the same project.
mkdir quickstart
func quickstart --help
func quickstart list # browse available templates
func quickstart list --stack python
func quickstart info <template-id> # details for one template
func quickstart [path] # interactive, prompts for choices
func quickstart --template <template-id> ./my-app # skip all prompts
func quickstart --stack python --resource http
func quickstart --iac bicep
func quickstart --search mcp
func quickstart --fetch git # force git instead of http (default is git too)
func run <path to host.json>
cd [path]
azd upThings to push on:
- Run with no installed stack workload, expect a clear "install a stack first" hint.
-
--templatewith an unknown id errors clearly. - Scaffolding into a non-empty directory: expected behaviour vs
--force. - Filters combine sanely (
--stack,--resource,--iac,--search). - After scaffolding, the project should be runnable end-to-end (see §7).
These apply to every command:
| Area | How to test |
|---|---|
| Cancellation | Start a long-running command (func setup, func workload install ...), hit Ctrl+C. Expect a graceful exit (no stack trace, non-zero exit code). |
| Colors / themes | Run with NO_COLOR=1. Pipe through cat. Both should produce readable, unstyled output. |
| Non-TTY | Run any interactive prompt with stdin redirected from /dev/null, expect a clear "non-interactive, please pass --xyz" error, not a hang. |
| Telemetry opt-out | Set FUNC_CLI_TELEMETRY_OPTOUT=1 (or the legacy FUNCTIONS_CORE_TOOLS_TELEMETRY_OPTOUT=1) and run any command. Nothing should change in the user-facing output, but telemetry should be off. |
| Help discoverability | For every subcommand, --help describes every option, and func help <command> matches it. |
| Error text | Errors should say what to do next. "Run func workload install node" is good; a bare exception message is a bug. |
func run --output <mode> supports three modes. Test all three:
func run --output compact # default: interactive TUI
func run --output plain # line-based, for CI / non-TTY
func run --output json # one JSON event per lineFor json, validate with:
func run --output json | jq -c . # every line parses as JSONThe pattern for each stack is identical:
- Install the v5 stack workload.
-
func inita new project. -
func newto add an HTTP trigger. -
func runto boot it locally and curl the trigger.
Open a fresh directory per stack so they don't tangle:
cd ~/func-bug-bash
mkdir node-app python-app dotnet-app go-appfunc workload install node
cd ~/func-bug-bash/node-app
func init --stack node --language javascript # try variations such as typescript, ts, js
func new --template "HTTP trigger" --name hello
func run
# In another shell:
curl http://localhost:7071/api/helloRepeat with --language typescript in a sibling directory.
func workload install python
cd ~/func-bug-bash/python-app
python -m venv .venv && source .venv/bin/activate
func init --stack python
func new --template "HTTP trigger" --name hello
func run
curl http://localhost:7071/api/hellofunc workload install dotnet
cd ~/func-bug-bash/dotnet-app
func init --stack dotnet --language C#
func new --template "HTTP trigger" --name Hello
func run
curl http://localhost:7071/api/HelloAlso try --language F# in a sibling directory.
func workload install go
cd ~/func-bug-bash/go-app
func init --stack go
func new --template "HTTP trigger" --name hello
func run
curl http://localhost:7071/api/hello-
func initcreates a sensible project layout. Files match what a real developer would expect for that stack. -
func init --forceon a non-empty directory wipes it (except.git) and re-initializes cleanly. -
func newlists templates when run without--template, and the chosen template scaffolds without errors. -
func runboots the host, the trigger responds athttp://localhost:7071/..., andCtrl+Cshuts it down cleanly. -
func run --port 0picks a free port;--port 7071errors clearly if the port is taken.
Please file everything as a GitHub issue. Bugs, papercuts, confusing output, missing features, doc gaps, naming nits, all of it. We'll triage incoming issues throughout the bug bash and fix as many as we can before the next drop, so the faster you file, the better the chance it lands.
File at https://github.com/Azure/azure-functions-core-tools/issues with
the v5 label (and bug / enhancement / documentation as
appropriate).
For each report, include:
-
func --verboseoutput (version + RID). - Exact command line and full output. For colored output, copy with
NO_COLOR=1. - OS, shell, and (for stack-specific bugs) the runtime version of the stack.
- Repro steps minimised to the smallest sequence that triggers the issue.
- For crashes, attach the stack trace and, if possible, re-run with
--verboseand include that output.
Don't sit on a "maybe it's just me" issue, file it. Duplicates are easy to close; missing reports are not.
When you're done:
# Uninstall installed workloads
func workload list # see what's there
func workload uninstall dotnet
func workload uninstall node
func workload uninstall python
func workload uninstall go
func workload prune
# Remove the v5 install entirely
rm -rf ~/.azure-functions
# Clean up the bug-bash sandbox
rm -rf ~/func-bug-bash
If you edited your shell profile via the installer, also remove the
`export PATH="$HOME/.azure-functions:$PATH"` line it appended to
`~/.bashrc` / `~/.zshrc`.
---
Thanks for bug-bashing! 🐛🔨
# Troubleshooting
## Error: Package 'foo' is not a func CLI workload (missing package type 'FuncCliWorkload' in its .nuspec)
The workload source isn't set, so the CLI is resolving from nuget.org instead of the bug bash feed. Set it for your shell:
```Bash
# bash / zsh
export FUNC_CLI_WORKLOADS_SOURCE="https://pkgs.dev.azure.com/azfunc/public/_packaging/pre-release/nuget/v3/index.json"
export FUNC_CLI_WORKLOADS_PRERELEASE = "true"
# PowerShell
$env:FUNC_CLI_WORKLOADS_SOURCE = "https://pkgs.dev.azure.com/azfunc/public/_packaging/pre-release/nuget/v3/index.json"
$env:FUNC_CLI_WORKLOADS_PRERELEASE = "true"Re-run the command. To make this stick across sessions, add the line to your shell profile (~/.zshrc, ~/.bashrc, or $PROFILE).
The quickstart manifest CDN isn't updated yet, point the CLI at the dev manifest:
# bash / zsh
export FUNC_CLI_QUICKSTART_MANIFEST_URL="https://raw.githubusercontent.com/Azure/azure-functions-templates/dev/Functions.Templates/Template-Manifest/manifest.json"
# PowerShell
$env:FUNC_CLI_QUICKSTART_MANIFEST_URL = "https://raw.githubusercontent.com/Azure/azure-functions-templates/dev/Functions.Templates/Template-Manifest/manifest.json"Clear the cached manifest so the new URL is picked up:
# macOS / Linux
rm -rf ~/.azure-functions/quickstart
# Windows (PowerShell)
Remove-Item -Recurse -Force "$env:USERPROFILE\.azure-functions\quickstart"Then re-run func quickstart.