Azure Developer CLI (azd) - Agent Instructions
January 30, 2026 · View on GitHub
Instructions for AI coding agents working with the Azure Developer CLI.
Overview
Azure Developer CLI (azd) is a Go-based CLI for Azure application development and deployment. It handles infrastructure provisioning with Bicep/Terraform, app deployment, environment management, project and service lifecycle hooks, and features a gRPC-based extension framework.
Directory Structure
cli/azd/
├── main.go # Entry point
├── cmd/ # Commands (ActionDescriptor pattern)
│ ├── root.go # Command tree registration
│ ├── container.go # IoC service registration
│ ├── actions/ # Action framework
│ └── middleware/ # Cross-cutting concerns (telemetry, hooks, extensions)
├── pkg/ # Reusable public packages
│ ├── ioc/ # Dependency injection container
│ ├── project/ # Project configuration (azure.yaml), service targets, framework services
│ └── infra/ # Infrastructure providers (Bicep, Terraform)
│ ├── azapi/ # Azure APIs
│ └── tools/ # External tools
├── internal/ # Internal packages (telemetry, tracing)
├── test/ # Test utilities
├── extensions/ # First-party extensions
└── docs/ # Documentation
Entry points: main.go → cmd/root.go (command tree) → cmd/container.go (IoC registration)
Tip: Service registration in cmd/container.go shows all major components. To find where a feature is implemented, start with the command in cmd/, follow to the action, then trace service dependencies.
Development
Commands assume you are in cli/azd.
Build
go build
Test
Note: In CI environments like inside a GitHub coding agent session, run go build first as the automatic build is skipped and the azd binary must exist for tests that spawn the CLI process. This applies to snapshot tests and functional tests in test/functional/.
# Specific test
go test ./pkg/project/... -run TestProjectConfig
# Update command snapshots (whenever command help text changes or new commands are added)
UPDATE_SNAPSHOTS=true go test ./cmd -run 'TestFigSpec|TestUsage'
# Unit tests only (can take up to 10 min)
go test ./... -short
# Full suite including E2E (can take 10+ min)
go test ./...
Test file patterns:
- Unit tests:
*_test.goalongside source files - Functional tests:
test/functional/ - Shared mocks:
test/mocks/
When writing tests, prefer table-driven tests. Use testify/mock for mocking.
Pre-Commit Checklist
gofmt -s -w .
golangci-lint run ./...
cspell lint "**/*.go" --relative --config ./.vscode/cspell.yaml --no-progress
../../eng/scripts/copyright-check.sh . --fix
- Line length: 125 chars max for Go (enforced by
llllinter); no limit for Markdown - Spelling: Add technical terms to
cli/azd/.vscode/cspell.yamloverrides - Copyright: All Go files need the Microsoft header (handled by copyright-check.sh)
Avoiding Unrelated go.mod/go.sum Changes
When running tools like CodeQL or go mod tidy, go.mod and go.sum files may be modified across multiple Go modules. Only commit go.mod/go.sum changes that are relevant to the task.
- azd core changes (
cli/azd/excludingextensions/): Only commitcli/azd/go.modandcli/azd/go.sum. Do NOT commit anygo.mod/go.sumfiles incli/azd/extensions/. - Extension changes (
cli/azd/extensions/<extension-name>/): Only commitgo.mod/go.sumfor the specific extension being modified.
If unrelated go.mod/go.sum files are staged, unstage them before committing.
Key Patterns
IoC Container (Dependency Injection)
Always use IoC for service registration—never instantiate services directly (see cli/azd/cmd/container.go):
ioc.RegisterSingleton(container, func() *MyService {
return &MyService{dep: ioc.Get[*Dependency](container)}
})
Action-Based Commands
Commands implement the actions.Action interface, not traditional Cobra handlers:
type myAction struct {
svc *SomeService
}
func newMyAction(svc *SomeService) actions.Action {
return &myAction{svc: svc}
}
func (a *myAction) Run(ctx context.Context) (*actions.ActionResult, error) {
return &actions.ActionResult{
Message: &actions.ResultMessage{Header: "Success"},
}, nil
}
Output Formatting
- Commands can support multiple output formats via
--outputflag likejsonandtable - Use structured output for machine consumption
Code Organization
- Import order: stdlib → external → azure/azd internal → local
- Complex packages: Consider using
types.gofor shared type definitions (3+ types) - Context propagation: Pass
ctx context.Contextas the first parameter to functions that do I/O or may need cancellation
Error Handling
- Wrap errors with
fmt.Errorf("context: %w", err)to preserve the error chain - Consider using
internal.ErrorWithSuggestionfor straightforward, deterministic user-fixable issues - Handle context cancellations appropriately
Documentation Standards
- Public functions and types must have Go doc comments
- Comments should start with the function/type name
- Document non-obvious dependencies or assumptions
Modern Go
This project uses Go 1.25. Use modern standard library features:
slices,maps,cmppackages: Use for searching, sorting, cloning, and iterating—avoid manual loops- Iterators: Use
rangeover functions/iterators (e.g.,maps.Keys(),slices.All()) - Built-ins: Use
min(),max(),clear()directly - Range over integers:
for i := range 10 { }
MCP Tools
Tools follow server.ServerTool interface from github.com/mark3labs/mcp-go/server:
- Constructor:
NewXXXTool() server.ServerTool - Handler:
handleXXX(ctx, request) (*mcp.CallToolResult, error) - Snake_case names (e.g.,
azd_plan_init)
Extensions
First-party azd extensions live in cli/azd/extensions/.
To build:
cd cli/azd/extensions/<extension-name>
# Build using developer extension (for local development)
azd x build
# Or build using Go directly
go build
Documentation
Feature-specific docs are in docs/ — refer to them as needed. Some key docs include:
docs/style-guidelines/new-azd-command.md- Adding new commandsdocs/extensions/extension-framework.md- Extension development using gRPC extension frameworkdocs/style-guidelines/guiding-principles.md- Design principlesdocs/tracing-in-azd.md- Tracing/telemetry guidelines