This guide walks through adding a new command to the Azure Developer CLI.
azd uses an ActionDescriptor pattern to define commands. Each command consists of:
- ActionDescriptor — Declares the command's metadata, flags, and output formats
- Action — Implements
Run(ctx context.Context) (*ActionResult, error) - Flags struct — Defines command-line flags with a
Bind()method - IoC registration — Wires the action and flags into the dependency injection container
Create cli/azd/cmd/<command_name>.go:
package cmd
import (
"context"
"github.com/azure/azure-dev/cli/azd/cmd/actions"
"github.com/azure/azure-dev/cli/azd/internal"
"github.com/spf13/pflag"
)
type myCommandFlags struct {
name string
}
func (f *myCommandFlags) Bind(local *pflag.FlagSet, global *internal.GlobalCommandOptions) {
local.StringVar(&f.name, "name", "", "Resource name")
}
type myCommandAction struct {
flags *myCommandFlags
svc *SomeService
}
func newMyCommandAction(flags *myCommandFlags, svc *SomeService) actions.Action {
return &myCommandAction{flags: flags, svc: svc}
}
func (a *myCommandAction) Run(ctx context.Context) (*actions.ActionResult, error) {
// Command logic here
return &actions.ActionResult{
Message: &actions.ResultMessage{Header: "Done!"},
}, nil
}Add to the command tree in cli/azd/cmd/root.go:
root.Add("mycommand", &actions.ActionDescriptorOptions{
Command: newMyCommandCmd(),
ActionResolver: newMyCommandAction,
FlagsResolver: newMyCommandFlags,
})If the command produces structured output, add format support in the descriptor and inject output.Formatter in your action:
root.Add("mycommand", &actions.ActionDescriptorOptions{
Command: newMyCommandCmd(),
ActionResolver: newMyCommandAction,
FlagsResolver: newMyCommandFlags,
OutputFormats: []output.Format{output.JsonFormat, output.TableFormat},
})Note:
OutputFormatsonly registers the--outputand--queryflags. Your action must also injectoutput.Formatteras a dependency and callformatter.Format()to emit structured output.
After adding the command, regenerate CLI snapshots:
UPDATE_SNAPSHOTS=true go test ./cmd -run 'TestFigSpec|TestUsage'- Verb-first structure: Use simple verbs (
up,add,deploy) with minimal nesting - Build on existing categories: Extend existing command groups rather than creating new ones
- Progressive disclosure: Basic usage should be simple; advanced features discoverable when needed
- Consistent parameters: Reuse established flag patterns (
--subscription,--name,--output)
For the full implementation guide including middleware, telemetry integration, and advanced patterns, see: