[EPIC] Enhance CLI interactivity for LLM/automation scenarios
- Dominant language
- Go
- Stars
- 569
- Forks
- 364
- Avg merge
- 2d 19h
- Merged PRs (30d)
- 136
Description
## Problem Statement
LLMs (GitHub Copilot, Claude, etc.) and automation tools running azd commands like `init`, `up`, `provision` encounter interactive prompts that block execution. The current `--no-prompt` flag only uses default values or fails when no default exists—it does not allow callers to **provide answers** programmatically.
### Current Limitations
When an LLM runs `azd init` or `azd provision`:
1. **Prompts block execution** - The CLI waits for user input that LLMs cannot provide through normal terminal interaction
2. **`--no-prompt` is insufficient** - It only accepts defaults or fails; there is no mechanism to supply specific answers
3. **External prompt service is complex** - The `AZD_UI_PROMPT_ENDPOINT` mechanism requires setting up an HTTP server, which is impractical for simple LLM automation
### Affected Commands
- `azd init` - Template selection, environment naming, service configuration
- `azd provision` - Subscription selection, location selection, parameter inputs
- `azd up` - Combines init + provision prompts
- `azd down` - Confirmation prompts (partially addressed by `--force`)
- Any command with IaC parameter prompts
## Proposed Solution
Implement complementary mechanisms for LLM-friendly interactivity:
### 1. JSON Prompt Mode (`--json-prompts`)
When enabled, prompts output structured JSON to stdout and read JSON responses from stdin, enabling real-time LLM interaction:
**Prompt Output (stdout):**
```json
{
"type": "prompt",
"prompt": {
"id": "subscription",
"kind": "select",
"message": "Select an Azure subscription",
"choices": [
{"value": "sub-123", "detail": "My Subscription 1"},
{"value": "sub-456", "detail": "My Subscription 2"}
],
"defaultValue": "sub-123"
}
}
```
**Response Input (stdin):**
```json
{"id": "subscription", "value": "sub-456"}
```
### 2. Upfront Answers Flag (`--answers`)
Accept pre-defined answers as JSON, allowing all inputs to be provided before execution:
```bash
# Inline JSON
azd init --answers '{"template":"todo-nodejs-mongo","environment":"dev"}'
# File reference
azd provision --answers @./answers.json
```
### 3. Input Introspection (`--describe-inputs`) [Future]
List all possible prompts a command might ask before running:
```bash
azd init --describe-inputs --output json
```
## Benefits
- **LLM Compatibility**: Enables GitHub Copilot, Claude, and other LLMs to run azd commands interactively
- **CI/CD Flexibility**: Provides more control than `--no-prompt` for complex automation scenarios
- **Backwards Compatible**: Additive changes that do not affect existing `--no-prompt` behavior
- **Aligned with Existing Patterns**: JSON format matches the existing external prompt API specification
## Technical Notes
- Implementation builds on existing `Console` abstraction in `pkg/input/console.go`
- JSON schema compatible with `AZD_UI_PROMPT_ENDPOINT` external prompt API
- Prompt types supported: `string`, `password`, `select`, `multiSelect`, `confirm`, `directory`
## Related
- External prompting documentation: `cli/azd/docs/external-prompting.md`
- MCP server support: `cli/azd/internal/mcp/`
Contributor guide
Assessment
This issue has not been assessed yet.