From 355f6ced5b84bb68554c9b8674c550d7f7db84f7 Mon Sep 17 00:00:00 2001 From: hyoshis Date: Thu, 19 Mar 2026 20:29:23 -0700 Subject: [PATCH 01/14] Update azd style guide: add user input patterns and clarify section scopes - Clarify Progress Reports as in-flight status within a command execution - Clarify Success/Error/Warning Logs as final command outcome messages - Add User Inputs section with Text Input, Yes/No Input, and List Select patterns - Document hint feature, ghost-text, and submission behavior for each input type Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../docs/style-guidelines/azd-style-guide.md | 191 +++++++++++++++++- 1 file changed, 190 insertions(+), 1 deletion(-) diff --git a/cli/azd/docs/style-guidelines/azd-style-guide.md b/cli/azd/docs/style-guidelines/azd-style-guide.md index da193e358a8..1cef90994e5 100644 --- a/cli/azd/docs/style-guidelines/azd-style-guide.md +++ b/cli/azd/docs/style-guidelines/azd-style-guide.md @@ -70,7 +70,7 @@ func (s *Service) Run(ctx context.Context) error { ### Progress Reports -Progress reports provide real-time feedback during multi-step operations. Use progress reports to: +Progress reports provide real-time feedback during a single command's execution, showing the status of individual steps as they happen. Use progress reports to: - Show status of long-running commands - Display individual service provisioning/deployment states @@ -148,6 +148,193 @@ move to root directory. (-) Skipped: [Verb] Message goes here ``` +### Success / Error / Warning Logs + +These logs represent the final outcome of a command, displayed after execution completes. Standard logs (Success, Error, Warning) use an **all-caps prefix** followed by a colon to separate the log type from the message. + +All logs should: + +- Be **succinct** +- Be **human legible** +- **Provide a path forward** when possible + +There are some specific edge cases where the log prefix is not required. + +#### Log Format + +``` +PREFIX: Message goes here. +``` + +#### Log Types + +**Success logs** — Indicate the success of a specific command or action. Success logs use the green (or bright green) color variable (`WithSuccessFormat`). +``` +SUCCESS: Message goes here. +``` + +**Error logs** — Indicate when an error occurs, or indicate overall command failure. Error logs use the red (or bright red) color variable (`WithErrorFormat`). Error logs should attempt to follow a `[Reason] [Outcome]` structure when possible. +``` +ERROR: Message goes here. +``` + +**Warning logs** — Used when a command or action has an outcome that may provide unexpected results, or when the user needs to be made aware of something potentially destructive. Warning logs use the yellow (or bright yellow) color variable (`WithWarningFormat`). +``` +WARNING: Message goes here. +``` + +**Next steps logs** — The arrow indicates the next step. Used when the command output includes follow-up actions or recommended next steps for the user. Next steps logs use the format `(->) NEXT STEPS:` followed by the message. + +``` +(->) NEXT STEPS: Message goes here. +``` + +#### Hint Text + +Hint copy can directly follow any Success, Error, or Warning log. Hint text should: + +- Provide more context to the log above +- In some cases, provide an actionable path forward (see: Actionable Hints) +- Use the white color variable (`WithHintFormat`) + +#### In-Context Examples + +**Success example:** + +``` +SUCCESS: Your Azure app has been deployed! +You can view the resources created under the resource group case-code-test-rg in Azure Portal: +https://portal.azure.com/#@/resource/subscriptions/.../resourceGroups/case-code-test-rg +``` + +**Error example:** + +``` +ERROR: 'todo-mongojs' is misspelled or missing a recognized flag. +Run azd up --help to see all available flags. +``` + +**Warning example:** + +``` +WARNING: You have already provisioned Azure resources to the (US) West US (westus) region. +You may want to run azd down to delete your existing resources before provisioning to a new region. +``` + +### User Inputs + +Certain azd commands require the user to input text, select yes/no, or select an item from a list. Examples include: + +- Inputting an environment name (text input) +- Initializing a new Git repository (y/n) +- Selecting a location to deploy to (list select) + +#### General Guidelines + +All input requests are in bold and begin with a blue `?`. This helps ensure that they stand out to users as different from other plain text logs and CLI outputs. + +#### Text Input + +Text input captures a single line of input from the user. + +**Initial state:** + +TODO: this is not shown as magenta in actual azd. confirm this. also i see that 'type' is not mentioned in azd either. +The prompt is displayed with a `[Type ? for hint]` helper in hi-magenta bold text, followed by ghost-text (secondary text color) as placeholder content. + +``` +? This captures a single line of input: [Type ? for hint] This is ghost-text +``` + +**Hint feature:** + +If the user types `?`, a hint line appears below the prompt to provide additional guidance. The hint label is displayed in magenta. + +``` +? This captures a single line of input: [Type ? for hint] This is ghost-text +Hint: This is a help message +``` + +**User input (before submitting):** + +As the user types, their input replaces the ghost-text and appears in primary text color. + +``` +? This captures a single line of input: [Type ? for hint] Input +``` + +**After submitting:** + +Once the user submits their answer: + +- The input changes from primary text to hi-blue text +- The `[Type ? for hint]` helper disappears +- If the hint line was visible, it also disappears + +``` +? This captures a single line of input: Input +``` + +#### Yes or No Input + +- Yes/no inputs include a `(Y/n)` delineator at the end of the input request (before the colon). +- Users can either input `y`/`n` or hit the return key which will select the capitalized choice in the `(Y/n)` delineator. +- Once a user has selected y or n, the result should be printed in blue text (**yes** or **no**). + +``` +? Do you want to initialize a new Git repository in this directory? (Y/n): +``` + +With input provided: + +``` +? Do you want to initialize a new Git repository in this directory? (Y/n): Yes +``` + +#### List Select + +The list select pattern presents a list of options for the user to choose from. + +**Initial state:** + +The prompt is displayed with a `Filter:` line showing ghost-text ("Type to filter list") and a footer hint ("Use arrows to move, type ? for hint"). The active selection is indicated by `>` and displayed in bold blue text. + +``` +? Select an single option: [Use arrows to move, type to filter] + + > Option 1 + Option 2 + Option 3 + Option 4 + Option 5 + Option 6 + ... +``` + +**Display rules:** + +- The list should display no more than 7 items at a time. +- When a list contains more than 7 items, ellipses (`...`) should be used to help users understand there are more items available up or down the list. +- If possible, the most commonly selected item (or the item we want to guide the user into selecting) should be highlighted by default. +- The active selection in the list should be bold and in blue text, prefixed with `>`. + +**Hint:** + +- The `[Type ? for hint]` pattern follows the same behavior as Text Input — hi-magenta in bold, with ghost-text in secondary text color. + +**After submitting:** + +Once the user makes their selection: + +- The input changes from primary text to hi-blue text +- The `[Type ? for hint]` helper disappears +- If the hint line was visible, it also disappears +- The list collapses and the selected value is printed in blue text next to the prompt + +``` +? Select an Azure location to use: (US) East US 2 (eastus2) +``` + ### Command Output Standards - **Structured output**: Support `--output json` for machine-readable output @@ -161,6 +348,8 @@ The CLI uses consistent color formatting through helper functions defined in [`c **Important**: Colors will appear differently depending on which terminal and theme (dark/light) the customer prefers. Always test output in both dark and light terminal themes. +TODO: add something about using Magenta for agentic experience + #### Standard Color Helper Functions Use these functions for consistent color formatting across the CLI: From 4e96cc3b1b487191b999db71f4275f099884d4b5 Mon Sep 17 00:00:00 2001 From: hyoshis Date: Tue, 24 Mar 2026 21:57:26 -0700 Subject: [PATCH 02/14] docs: add loading animation, braille spinner, and cancelled state sections to style guide - Add bar-fill spinner animation behavior and frame cycle documentation - Add braille spinner for multi-service concurrent operations - Add cancelled state (6th progress state) for failed sibling services - Add cancelled scenario example with multi-service deployment - Convert scenario examples to HTML with colored text for better readability Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../docs/style-guidelines/azd-style-guide.md | 137 +++++++++++++++--- 1 file changed, 116 insertions(+), 21 deletions(-) diff --git a/cli/azd/docs/style-guidelines/azd-style-guide.md b/cli/azd/docs/style-guidelines/azd-style-guide.md index 1cef90994e5..c7408010782 100644 --- a/cli/azd/docs/style-guidelines/azd-style-guide.md +++ b/cli/azd/docs/style-guidelines/azd-style-guide.md @@ -78,7 +78,7 @@ Progress reports provide real-time feedback during a single command's execution, #### Progress Report States -Items in a progress report list can be in one of five states: +Items in a progress report list can be in one of six states: 1. **Loading**: `|=== | [Verb] Message goes here` - Indicates operation in progress @@ -100,6 +100,11 @@ Items in a progress report list can be in one of five states: - Gray dash indicates intentionally skipped step - Different from failed - this is expected behavior +6. **Cancelled**: `(!) Cancelled: [Verb] Message goes here – [reason]` + - Yellow exclamation indicates the operation was cancelled due to another failure + - Includes the reason (typically which sibling operation failed) + - Used in multi-service scenarios when a failure in one service causes others to be cancelled + #### Progress Report Guidelines - **Indentation**: Progress items are always indented under the main command @@ -111,42 +116,64 @@ Items in a progress report list can be in one of five states: **Success scenario:** -``` -Provisioning Azure resources (azd provision) +
+Provisioning Azure resources (azd provision)
 Provisioning Azure resources can take some time.
 
-  (✓) Done: Creating App Service Plan: plan-r2w2adrz3rvwxu
-  (✓) Done: Creating Log Analytics workspace: log-r2w2adrz3rvwxu
-  (✓) Done: Creating Application Insights: appi-r2w2adrz3rvwxu
-  (✓) Done: Creating App Service: app-api-r2w2adrz3rvwxu
-```
+  (✓) Done: Creating App Service Plan: plan-r2w2adrz3rvwxu
+  (✓) Done: Creating Log Analytics workspace: log-r2w2adrz3rvwxu
+  (✓) Done: Creating Application Insights: appi-r2w2adrz3rvwxu
+  (✓) Done: Creating App Service: app-api-r2w2adrz3rvwxu
+
**Failure scenario:** -``` -Provisioning Azure resources (azd provision) +
+Provisioning Azure resources (azd provision)
+
+  (✓) Done: Creating App Service Plan: plan-r2w2adrz3rvwxu
+  (✓) Done: Creating Log Analytics workspace: log-r2w2adrz3rvwxu
+  (✗) Failed: Creating Cosmos DB: cosmos-r2w2adrz3rvwxu
 
-  (✓) Done: Creating App Service Plan: plan-r2w2adrz3rvwxu
-  (✓) Done: Creating Log Analytics workspace: log-r2w2adrz3rvwxu
-  (✗) Failed: Creating Cosmos DB: cosmos-r2w2adrz3rvwxu
-  
   The '{US} West US 2 (westus)' region is currently experiencing high demand
   and cannot fulfill your request. Failed to create Cosmos DB account.
 
-ERROR: Unable to complete provisioning of Azure resources, 'azd up' failed
-```
+ERROR: Unable to complete provisioning of Azure resources, 'azd up' failed
+
**Skipped scenario:** -``` +
 Note: Steps were skipped because _____ (directory, or specified service name)
 If you want to deploy all services, you can run azd deploy --all or
 move to root directory.
 
-  (✓) Done: [Verb] Message goes here
-  (✓) Done: [Verb] Message goes here
-  (-) Skipped: [Verb] Message goes here
-```
+  (✓) Done: [Verb] Message goes here
+  (✓) Done: [Verb] Message goes here
+  (-) Skipped: [Verb] Message goes here
+
+ +**Cancelled scenario (multi-service deployment with failure):** + +
+Deploying services (6)
+
+  (!) Cancelled: postgres (59s) – catalogservice failed
+  (!) Cancelled: basketcache (45s) – catalogservice failed
+  (✓) Done: basketservice (25s)
+  - Endpoint: https://basketservice-yo2mecxyj3dmw.azurewebsites.net/
+  (✓) Done: catalogdbmanager (58s)
+  (✗) Failed:  catalogservice (51s)
+  Required Azure Developer CLI dependencies are missing:
+  - git CLI version ≥ 2.0.0 (current: 1.9.0), see https://git-scm.com/downloads to install.
+  Log:  /path/to/.azure/logs/deploy/deploy-catalogservice.log
+  (✓) Done: frontend (27s)
+
+ERROR: Unable to complete deployment, 'azd concurx up' failed.
+To complete the operation, install the required dependencies and try again.
+
+ +When one service fails in a concurrent deployment, sibling services that cannot continue are **cancelled** (not failed). The cancelled message includes the reason (e.g., `– catalogservice failed`) so the user knows which service caused the cancellation. ### Success / Error / Warning Logs @@ -441,6 +468,74 @@ Note: There is a discrepancy in the naming convention between ANSI Color coding +### Loading Animation (Progress Spinner) + +`azd` uses a **bar-fill spinner** to indicate ongoing operations. The animation displays a pair of `|` border characters with `=` fill characters that bounce back and forth, alongside a status message describing the current operation. + +#### Animation Behavior + +The spinner **animates in place** on a single line by overwriting itself. The `=` fill characters grow and bounce back and forth between the `|` borders, creating a fluid loading effect: + +``` +|===== | Creating App Service: my-app-r2w2adrz3rvwxu +``` + +The full animation cycle frames are: + +``` +| | → |= | → |== | → |=== | → |==== | → |===== | → |====== | → |=======| +|=======| → | ======| → | =====| → | ====| → | ===| → | ==| → | =| → | | +``` + +These frames repeat continuously on the **same line** until the operation completes. The spinner bar is displayed in **hint-colored** text (gray) to keep focus on the status message. + +#### When to Use: Bar Spinner vs. Braille Spinner + +The **bar-fill spinner** (`|=======|`) is designed for **single-operation progress** — one task happening at a time on one line. When **multiple concurrent operations** are displayed as a list (e.g., deploying several services simultaneously), use the **braille spinner** instead. The bar spinner would be visually overwhelming when repeated across many lines. + +The braille spinner animates in place with dot patterns that fill in clockwise, then drain away: + +``` +⠁ → ⠃ → ⠇ → ⡇ → ⡏ → ⡟ → ⡿ → ⣿ → ⣾ → ⣴ → ⣠ → ⣀ → ...repeats +``` + +**Multi-service deployment example:** + +``` +Deploying 6 services + + ⠙ Deploying: postgres (5s) + ⠙ Deploying: basketcache (5s) + (•) Queued: basketservice + (•) Queued: catalogdbmanager + ⠙ Deploying: catalogservice (5s) + (•) Queued: frontend +``` + +| Scenario | Spinner Type | Reason | +| --- | --- | --- | +| Single long-running operation (provisioning, creating a resource) | **Bar-fill** (`\|=== \|`) | Clear progress indicator for one task | +| Multiple concurrent operations shown as a list | **Braille** (`⠋⠙⠹...`) | Compact — doesn't clutter multi-line lists | +| Queued / waiting items in a list | **Static dot** `(•)` | No animation needed — item hasn't started | + +#### Character Sets + +There are three spinner variants based on terminal capability: + +| Variant | Characters | When Used | +| --- | --- | --- | +| **Bar-fill** | `\|=======\|` (bouncing fill bar) | Single-operation progress in interactive terminal | +| **Braille** | `⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏` | Multi-item concurrent progress lists | +| **Short** | `.`, `..`, `...` | Non-interactive or limited terminals | +| **No Terminal** | *(empty)* | No terminal attached (e.g., piped output) | + +#### Guidelines + +- **Use the bar-fill spinner** for single in-progress operations (resource creation, provisioning) +- **Use the braille spinner** when showing a list of multiple concurrent operations +- **Use `(•)` static indicator** for queued items that haven't started yet +- **Keep status messages concise** — use the format `"ing : "` + ## Testing Standards ### Test Structure From 30a1c0a7b8ec524e5121a19e5b7f6b3846c31638 Mon Sep 17 00:00:00 2001 From: hyoshis Date: Tue, 24 Mar 2026 22:29:32 -0700 Subject: [PATCH 03/14] docs: add style guide reference and CLI UX instruction to AGENTS.md Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- cli/azd/AGENTS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cli/azd/AGENTS.md b/cli/azd/AGENTS.md index 73f4217bd09..b1c3bd8074a 100644 --- a/cli/azd/AGENTS.md +++ b/cli/azd/AGENTS.md @@ -157,6 +157,10 @@ func (a *myAction) Run(ctx context.Context) (*actions.ActionResult, error) { - **Shell-safe output**: When emitting shell commands in user-facing messages (e.g., `cd `), quote paths that may contain spaces. Use `fmt.Sprintf("cd %q", path)` or conditionally wrap in quotes - **Consistent JSON types**: When adding fields to JSON output (`--output json`), match the types used by similar fields across commands. Don't mix `*time.Time` and custom timestamp wrappers (e.g., `*RFC3339Time`) in the same API surface +### CLI UX & Style + +When designing CLI output, terminal UX, spinners, progress states, or colors, follow the guidelines in `docs/style-guidelines/azd-style-guide.md`. + ### Code Organization - **Import order**: stdlib → external → azure/azd internal → local @@ -298,6 +302,7 @@ go build Feature-specific docs are in `docs/` — refer to them as needed. Some key docs include: +- `docs/style-guidelines/azd-style-guide.md` - CLI style guide (colors, spinners, progress states, terminal UX) - `docs/style-guidelines/new-azd-command.md` - Adding new commands - `docs/extensions/extension-framework.md` - Extension development using gRPC extension framework - `docs/style-guidelines/guiding-principles.md` - Design principles From 11f6f8390826fdfa41ded931f9f502f26b0d1691 Mon Sep 17 00:00:00 2001 From: hyoshis Date: Wed, 25 Mar 2026 12:57:15 -0700 Subject: [PATCH 04/14] temp Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- after.html | 408 +++++++++++++++++++++++++++++++ before.html | 357 ++++++++++++++++++++++++++++ cli/azd/install-azd.ps1 | 396 ++++++++++++++++++++++++++++++ cli/azd/uninstall-azd.ps1 | 71 ++++++ demo.html | 489 ++++++++++++++++++++++++++++++++++++++ test.html | 295 +++++++++++++++++++++++ 6 files changed, 2016 insertions(+) create mode 100644 after.html create mode 100644 before.html create mode 100644 cli/azd/install-azd.ps1 create mode 100644 cli/azd/uninstall-azd.ps1 create mode 100644 demo.html create mode 100644 test.html diff --git a/after.html b/after.html new file mode 100644 index 00000000000..1d41afb7cb9 --- /dev/null +++ b/after.html @@ -0,0 +1,408 @@ + + + + + +AFTER — CLI With azd Style Guide Applied + + + + + + +
+ +
+ What you're looking at: The same mycloud deploy scenario from before.html, + redesigned by applying the azd style guide. Every change traces back to a specific guideline. +
+ + + + +
PS C:\Users\user\myapp> mycloud deploy --environment production + +Deploying to Azure (mycloud deploy) +Deploying application to environment: production
+ +
+ ✅ Clean bold command header with command name in parentheses § Command Header
+ ✅ No decorative banner, no emoji, no ASCII art
+ ✅ No [INFO] log-level prefixes — this is user-facing output
+ ✅ Notices removed — don't dump unrelated info before the task +
+ + + + +
? Enter a resource group name: [Type ? for hint] rg-myapp-prod +
+
? Enter a resource group name: rg-myapp-prod + +? Select an Azure location: [Use arrows to move, type to filter] + + (US) East US (eastus) + > (US) East US 2 (eastus2) + (US) West US (westus) + (US) West US 2 (westus2) + (EU) North Europe (northeurope) + (EU) West Europe (westeurope) + (APAC) Southeast Asia (southeastasia) + ...
+
? Enter a resource group name: rg-myapp-prod +? Select an Azure location: (US) East US 2 (eastus2) +? Deploy to production? (Y/n): Yes
+ +
+ ✅ Blue ? prefix on every prompt — visually distinct § User Inputs
+ ✅ Bold prompt text with [Type ? for hint] helper § Text Input
+ ✅ Ghost text as placeholder, cyan for submitted answers § Color Coding
+ ✅ Scrollable list with > cursor, max 7 visible + ... § List Select
+ ✅ Region labels with friendly names: "(US) East US 2 (eastus2)"
+ ✅ Confirmation uses standard (Y/n) with default capitalized § Yes/No Input
+ ✅ Completed prompts stay visible with selections in cyan +
+ + + + +
Provisioning Azure resources +Provisioning Azure resources can take some time. + + (✓) Done: Creating resource group: rg-myapp-prod + (✓) Done: Creating App Service Plan: plan-myapp-prod + (✓) Done: Creating SQL Database: sql-myapp-prod + (✓) Done: Creating Storage Account: stmyappprod + (✓) Done: Creating Key Vault: kv-myapp-prod + Creating Application Insights: appi-myapp-prod
+ +
+ ✅ Bar-fill spinner animates in-place — no scrolling dots § Loading Animation
+ ✅ (✓) Done: in green for each completed step § Progress States
+ ✅ Resource names included for traceability
+ ✅ Clean indentation under command header § Progress Report Guidelines +
+ +
Provisioning Azure resources +Provisioning Azure resources can take some time. + + (✓) Done: Creating resource group: rg-myapp-prod + (✓) Done: Creating App Service Plan: plan-myapp-prod + (✓) Done: Creating SQL Database: sql-myapp-prod + (✓) Done: Creating Storage Account: stmyappprod + (✓) Done: Creating Key Vault: kv-myapp-prod + (✓) Done: Creating Application Insights: appi-myapp-prod + +SUCCESS: Your application was provisioned in Azure in 4 minutes 11 seconds.
+ +
+ ✅ SUCCESS: in green with duration § Success Logs
+ ✅ All steps resolved to (✓) Done — clear at a glance +
+ + + + +
Deploying services (4) + + Deploying: api (12s) + Deploying: worker (8s) + (•) Queued: frontend + (•) Queued: migration-job
+ +
+ ✅ Braille spinner for concurrent multi-service list § Bar vs Braille Spinner
+ ✅ (•) static dot for queued items — no animation until started
+ ✅ Compact format — no verbose build logs inline
+ ✅ Service count in header: "Deploying services (4)" +
+ +
Deploying services (4) + + (✓) Done: api (52s) + - Endpoint: https://api-myapp-prod.azurewebsites.net + (✓) Done: worker (41s) + (✗) Failed: frontend (12s) + Build failed: missing "build" script in package.json. + Run npm run build locally to verify, then retry with mycloud deploy --service frontend + Log: ~/.mycloud/logs/deploy/2025-03-24/deploy-frontend.log + (!) Cancelled: migration-job – frontend failed + +ERROR: Unable to complete deployment, 1 service failed. +To retry the failed service, run mycloud deploy --service frontend
+ +
+ ✅ (✗) Failed: in red with concise error — no stack trace § Progress States
+ ✅ Actionable fix: specific command to retry § Error Logs
+ ✅ Log file path provided for debugging
+ ✅ (!) Cancelled: with reason — clear cause-and-effect § Cancelled State
+ ✅ ERROR: summary — one line, not five
+ ✅ Endpoints shown inline under successful service +
+ + + + +
Deploying services (4) + + (✓) Done: api (52s) + - Endpoint: https://api-myapp-prod.azurewebsites.net + (✓) Done: worker (41s) + (✓) Done: frontend (38s) + - Endpoint: https://frontend-myapp-prod.azurewebsites.net + (✓) Done: migration-job (18s) + +SUCCESS: Your application was deployed to Azure in 2 minutes 49 seconds. +You can view the resources created under the resource group rg-myapp-prod in Azure Portal: +https://portal.azure.com/#@/resource/subscriptions/.../resourceGroups/rg-myapp-prod + +Next steps: + Run mycloud monitor to view application logs + Run mycloud down to delete Azure resources
+ +
+ ✅ SUCCESS: with duration and portal link § Success Logs
+ ✅ Next steps: with actionable follow-up commands § Hint Text
+ ✅ No "DEPLOYMENT SUMMARY" ASCII box — status is already inline
+ ✅ No redundant "Done." at the end — SUCCESS is the clear signal +
+ + + + +
Progress states: + Loading (bar-fill — single operation) + Loading (braille — concurrent list) + (•) Queued (waiting to start) + (✓) Done: Completed successfully + (✗) Failed: Operation failed + (!) Warning: Non-blocking issue + (!) Cancelled: Stopped due to sibling failure + (-) Skipped: Intentionally skipped + +Completion messages: + SUCCESS: Positive outcome + ERROR: Failure with actionable guidance + WARNING: User should be aware + +Prompts: + ? Prompt text: user input in cyan + ? Confirm? (Y/n): Yes + ? Select from list: [Use arrows to move, type to filter] + > Selected item + Other item + +Colors: + Green — success, done, positive outcomes + Red — errors, failures + Yellow — warnings, cancelled + Cyan — user input, commands, prompts + Blue — links, URLs + Gray — secondary info, hints, skipped + Magenta — hint helpers [Type ? for hint]
+ +
+ +
after.html — Part of the azd Style Guide demo | Guided by azd-style-guide.md
+ + + diff --git a/before.html b/before.html new file mode 100644 index 00000000000..92c7f3abb12 --- /dev/null +++ b/before.html @@ -0,0 +1,357 @@ + + + + + +BEFORE — CLI Without Style Guide + + + + + + +
+ +
+ What you're looking at: A fictional CLI tool (mycloud deploy) that provisions + infrastructure and deploys services — without following any style guidelines. Each section highlights + specific problems that the azd style guide addresses. +
+ + + + +
🚀 ★★★ Welcome to MyCloud CLI v3.2.1 ★★★ 🚀 +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +NOTICE: You are using the latest version. +NOTICE: Telemetry is enabled. Set MYCLOUD_TELEMETRY=false to disable. +NOTICE: New feature: pipeline support! Try `mycloud pipeline init`. + +$ mycloud deploy --environment production + +[INFO] Starting deployment process... +[INFO] Reading configuration from mycloud.yaml +[INFO] Found 4 services to deploy +[INFO] Target environment: production +[INFO] Subscription: 0cd6095b-b140-41ec-ad1d-32f2f7493386 +[INFO] Region: eastus2 +[INFO] Authenticating... +[INFO] Token acquired successfully
+ +
+ ❌ Decorative banner with emoji — not professional CLI output
+ ❌ Multiple notices dumped before command runs — noise
+ ❌ [INFO] log-style prefixes — this is a CLI, not a log file
+ ❌ Neon magenta/yellow colors — not ANSI-standard, won't adapt to light themes
+ ❌ Subscription ID exposed without context +
+ + + + +
[INFO] Environment 'production' does not have a resource group configured. + +Enter resource group name: _ + +Enter resource group name: rg-myapp-prod + +Select a region (type number): + 1) eastus + 2) eastus2 + 3) westus + 4) westus2 + 5) northeurope + 6) westeurope + 7) southeastasia + 8) japaneast + 9) australiaeast + 10) brazilsouth + 11) canadacentral + 12) centralindia + 13) koreacentral + 14) uksouth + 15) francecentral + +Type a number [1-15]: 2 + +Confirm deployment to production? [yes/no] yes
+ +
+ ❌ No ? prefix on prompts — blends with regular output
+ ❌ Plain white text prompts — not visually distinct
+ ❌ All 15 regions shown at once — no scrollable list, no filtering
+ ❌ No [Type ? for hint] helper for guidance
+ ❌ "yes/no" instead of standard "(Y/n)" with default
+ ❌ Selected values not highlighted in cyan after submission +
+ + + + +
[INFO] Starting infrastructure provisioning... +[INFO] Creating resource group: rg-myapp-prod +[INFO] Resource group created. +[INFO] Creating App Service Plan... (this may take a few minutes) +[INFO] .......... done (45s) +[INFO] Creating SQL Database... +[INFO] .......... done (2m 12s) +[INFO] Creating Storage Account... +[INFO] .. +[INFO] .... +[INFO] ........ +[INFO] .......... done (1m 33s) +[INFO] Creating Key Vault... +[INFO] .......... done (28s) +[INFO] Creating Application Insights... +[INFO] .......... done (15s) +[INFO] Configuring network security groups... +[INFO] .......... done (8s) + +[INFO] All infrastructure resources created.
+ +
+ ❌ Dots printed as new lines instead of in-place animation — produces wall of text
+ ❌ No spinner or progress bar — just growing dots
+ ❌ No structured states (✓ Done / ✗ Failed) — just "done" text
+ ❌ Every line is [INFO] green — no visual hierarchy between steps
+ ❌ "this may take a few minutes" — vague, informal +
+ + + + +
[INFO] Deploying services... + +[INFO] --- Deploying: api --- +[INFO] Building container image... +[INFO] Pushing to registry... +[INFO] Updating App Service... +[INFO] api deployed successfully. (52s) + +[INFO] --- Deploying: worker --- +[INFO] Building container image... +[INFO] Pushing to registry... +[INFO] Updating App Service... +[INFO] worker deployed successfully. (41s) + +[INFO] --- Deploying: frontend --- +[INFO] Building container image... +[ERROR] Build failed: npm ERR! Missing script: "build" +[ERROR] Stack trace: + at ChildProcess.emit (node:events:513:28) + at Process.ChildProcess._handle.onexit (node:internal/child_process:291:12) + at ChildProcess.exithandler (node:child_process:422:5) +[ERROR] npm ERR! code ELIFECYCLE +[ERROR] npm ERR! errno 1 + +[INFO] --- Deploying: migration-job --- +[INFO] Building container image... +[INFO] Pushing to registry... +[INFO] migration-job deployed successfully. (18s)
+ +
+ ❌ Sequential deployment with full verbose build logs — overwhelming
+ ❌ Raw stack trace shown to user — should be behind --debug flag
+ ❌ No distinction between in-progress / done / failed states
+ ❌ Services deployed sequentially, not shown as concurrent list
+ ❌ Failed service doesn't affect others — no cancelled state
+ ❌ "--- Deploying: api ---" separator — not a standard pattern +
+ + + + +
[ERROR] Deployment partially failed. +[ERROR] 1 of 4 services failed to deploy. +[ERROR] Failed services: frontend +[ERROR] Check the logs at ~/.mycloud/logs/deploy-2025-03-24.log +[ERROR] Exit code: 1 + +[WARN] Some services were deployed successfully. +[WARN] You may need to redeploy the failed services. + +======================================== + DEPLOYMENT SUMMARY +======================================== + api : OK (52s) + worker : OK (41s) + frontend : FAILED (12s) + migration : OK (18s) +======================================== + Total time: 3m 42s +======================================== + +[INFO] Endpoints: +[INFO] api: https://api-myapp-prod.azurewebsites.net +[INFO] worker: (no endpoint) +[INFO] frontend: (deploy failed) + +Done.
+ +
+ ❌ Multiple redundant [ERROR] lines — one clear message is enough
+ ❌ ASCII-art summary box — not azd style
+ ❌ "OK" / "FAILED" status — should be (✓) Done / (✗) Failed
+ ❌ No actionable guidance — what should the user do next?
+ ❌ "Done." at the end is ambiguous — was it successful or not?
+ ❌ Stack trace was shown inline instead of pointing to log file
+ ❌ Warning after error creates confusion about actual state
+ ❌ Endpoints listed with [INFO] prefix instead of clean format +
+ +
+ Summary of problems: This CLI mixes log-level prefixes ([INFO], [ERROR], [WARN]) with user-facing output, + uses inconsistent color coding, dumps verbose internal details, provides no structured progress states, + shows raw stack traces, uses decorative formatting (banners, ASCII boxes), and fails to give clear + actionable guidance when things go wrong. See after.html for the azd-styled version. +
+ +
+ +
before.html — Part of the azd Style Guide demo
+ + + diff --git a/cli/azd/install-azd.ps1 b/cli/azd/install-azd.ps1 new file mode 100644 index 00000000000..a779a222e49 --- /dev/null +++ b/cli/azd/install-azd.ps1 @@ -0,0 +1,396 @@ +#!/usr/bin/env pwsh +<# +.SYNOPSIS +Download and install azd on the local machine. + +.DESCRIPTION +Downloads and installs azd on the local machine. Includes ability to configure +download and install locations. + +.PARAMETER BaseUrl +Specifies the base URL to use when downloading. Default is +https://azuresdkartifacts.z5.web.core.windows.net/azd/standalone/release + +.PARAMETER Version +Specifies the version to use. Default is `latest`. Valid values include a +SemVer version number (e.g. 1.0.0 or 1.1.0-beta.1), `latest`, `daily` + +.PARAMETER DryRun +Print the download URL and quit. Does not download or install. + +.PARAMETER InstallFolder +Location to install azd. + +.PARAMETER SymlinkFolder +(Mac/Linux only) Folder to symlink + +.PARAMETER DownloadTimeoutSeconds +Download timeout in seconds. Default is 120 (2 minutes). + +.PARAMETER SkipVerify +Skips verification of the downloaded file. + +.PARAMETER InstallShScriptUrl +(Mac/Linux only) URL to the install-azd.sh script. Default is https://aka.ms/install-azd.sh + +.EXAMPLE +powershell -ex AllSigned -c "Invoke-RestMethod 'https://aka.ms/install-azd.ps1' | Invoke-Expression" + +Install the azd CLI from a Windows shell + +The use of `-ex AllSigned` is intended to handle the scenario where a machine's +default execution policy is restricted such that modules used by +`install-azd.ps1` cannot be loaded. Because this syntax is piping output from +`Invoke-RestMethod` to `Invoke-Expression` there is no direct valication of the +`install-azd.ps1` script's signature. Validation of the script can be +accomplished by downloading the script to a file and executing the script file. + +.EXAMPLE +Invoke-RestMethod 'https://aka.ms/install-azd.ps1' -OutFile 'install-azd.ps1' +PS > ./install-azd.ps1 + +Download the installer and execute from PowerShell + +.EXAMPLE +Invoke-RestMethod 'https://aka.ms/install-azd.ps1' -OutFile 'install-azd.ps1' +PS > ./install-azd.ps1 -Version daily + +Download the installer and install the "daily" build +#> + +param( + [string] $BaseUrl = "https://azuresdkartifacts.z5.web.core.windows.net/azd/standalone/release", + [string] $Version = "stable", + [switch] $DryRun, + [string] $InstallFolder, + [string] $SymlinkFolder, + [switch] $SkipVerify, + [int] $DownloadTimeoutSeconds = 120, + [switch] $NoTelemetry, + [string] $InstallShScriptUrl = "https://aka.ms/install-azd.sh" +) + +function isLinuxOrMac { + return $IsLinux -or $IsMacOS +} + +# Does some very basic parsing of /etc/os-release to output the value present in +# the file. Since only lines that start with '#' are to be treated as comments +# according to `man os-release` there is no additional parsing of comments +# Options like: +# bash -c "set -o allexport; source /etc/os-release;set +o allexport; echo $VERSION_ID" +# were considered but it's possible that bash is not installed on the system and +# these commands would not be available. +function getOsReleaseValue($key) { + $value = $null + foreach ($line in Get-Content '/etc/os-release') { + if ($line -like "$key=*") { + # 'ID="value" -> @('ID', '"value"') + $splitLine = $line.Split('=', 2) + + # Remove surrounding whitespaces and quotes + # ` "value" ` -> `value` + # `'value'` -> `value` + $value = $splitLine[1].Trim().Trim(@("`"", "'")) + } + } + return $value +} + +function getOs { + $os = [Environment]::OSVersion.Platform.ToString() + try { + if (isLinuxOrMac) { + if ($IsLinux) { + $os = getOsReleaseValue 'ID' + } elseif ($IsMacOs) { + $os = sw_vers -productName + } + } + } catch { + Write-Error "Error getting OS name $_" + $os = "error" + } + return $os +} + +function getOsVersion { + $version = [Environment]::OSVersion.Version.ToString() + try { + if (isLinuxOrMac) { + if ($IsLinux) { + $version = getOsReleaseValue 'VERSION_ID' + } elseif ($IsMacOS) { + $version = sw_vers -productVersion + } + } + } catch { + Write-Error "Error getting OS version $_" + $version = "error" + } + return $version +} + +function isWsl { + $isWsl = $false + if ($IsLinux) { + $kernelRelease = uname --kernel-release + if ($kernelRelease -like '*wsl*') { + $isWsl = $true + } + } + return $isWsl +} + +function getTerminal { + return (Get-Process -Id $PID).ProcessName +} + +function getExecutionEnvironment { + $executionEnvironment = 'Desktop' + if ($env:GITHUB_ACTIONS) { + $executionEnvironment = 'GitHub Actions' + } elseif ($env:SYSTEM_TEAMPROJECTID) { + $executionEnvironment = 'Azure DevOps' + } + return $executionEnvironment +} + +function promptForTelemetry { + # UserInteractive may return $false if the session is not interactive + # but this does not work in 100% of cases. For example, running: + # "powershell -NonInteractive -c '[Environment]::UserInteractive'" + # results in output of "True" even though the shell is not interactive. + if (![Environment]::UserInteractive) { + return $false + } + + Write-Host "Answering 'yes' below will send data to Microsoft. To learn more about data collection see:" + Write-Host "https://go.microsoft.com/fwlink/?LinkId=521839" + Write-Host "" + Write-Host "You can also file an issue at https://github.com/Azure/azure-dev/issues/new?assignees=&labels=&template=issue_report.md&title=%5BIssue%5D" + + try { + $yes = New-Object System.Management.Automation.Host.ChoiceDescription ` + "&Yes", ` + "Sends failure report to Microsoft" + $no = New-Object System.Management.Automation.Host.ChoiceDescription ` + "&No", ` + "Exits the script without sending a failure report to Microsoft (Default)" + $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no) + $decision = $Host.UI.PromptForChoice( ` + 'Confirm issue report', ` + 'Do you want to send diagnostic data about the failure to Microsoft?', ` + $options, ` + 1 ` # Default is 'No' + ) + + # Return $true if user consents + return $decision -eq 0 + } catch { + # Failure to prompt generally indicates that the environment is not + # interactive and the default resposne can be assumed. + return $false + } +} + +function reportTelemetryIfEnabled($eventName, $reason='', $additionalProperties = @{}) { + if ($NoTelemetry -or $env:AZURE_DEV_COLLECT_TELEMETRY -eq 'no') { + Write-Verbose "Telemetry disabled. No telemetry reported." -Verbose:$Verbose + return + } + + $IKEY = 'a9e6fa10-a9ac-4525-8388-22d39336ecc2' + + $telemetryObject = @{ + iKey = $IKEY; + name = "Microsoft.ApplicationInsights.$($IKEY.Replace('-', '')).Event"; + time = (Get-Date).ToUniversalTime().ToString('o'); + data = @{ + baseType = 'EventData'; + baseData = @{ + ver = 2; + name = $eventName; + properties = @{ + installVersion = $Version; + reason = $reason; + os = getOs; + osVersion = getOsVersion; + isWsl = isWsl; + terminal = getTerminal; + executionEnvironment = getExecutionEnvironment; + }; + } + } + } + + # Add entries from $additionalProperties. These may overwrite existing + # entries in the properties field. + if ($additionalProperties -and $additionalProperties.Count) { + foreach ($entry in $additionalProperties.GetEnumerator()) { + $telemetryObject.data.baseData.properties[$entry.Name] = $entry.Value + } + } + + Write-Host "An error was encountered during install: $reason" + Write-Host "Error data collected:" + $telemetryDataTable = $telemetryObject.data.baseData.properties | Format-Table | Out-String + Write-Host $telemetryDataTable + if (!(promptForTelemetry)) { + # The user responded 'no' to the telemetry prompt or is in a + # non-interactive session. Do not send telemetry. + return + } + + try { + Invoke-RestMethod ` + -Uri 'https://centralus-2.in.applicationinsights.azure.com/v2/track' ` + -ContentType 'application/json' ` + -Method Post ` + -Body (ConvertTo-Json -InputObject $telemetryObject -Depth 100 -Compress) | Out-Null + Write-Verbose -Verbose:$Verbose "Telemetry posted" + } catch { + Write-Host $_ + Write-Verbose -Verbose:$Verbose "Telemetry post failed" + } +} + +if (isLinuxOrMac) { + if (!(Get-Command curl)) { + Write-Error "Command could not be found: curl." + exit 1 + } + if (!(Get-Command bash)) { + Write-Error "Command could not be found: bash." + exit 1 + } + + $params = @( + '--base-url', "'$BaseUrl'", + '--version', "'$Version'" + ) + + if ($InstallFolder) { + $params += '--install-folder', "'$InstallFolder'" + } + + if ($SymlinkFolder) { + $params += '--symlink-folder', "'$SymlinkFolder'" + } + + if ($SkipVerify) { + $params += '--skip-verify' + } + + if ($DryRun) { + $params += '--dry-run' + } + + if ($NoTelemetry) { + $params += '--no-telemetry' + } + + if ($VerbosePreference -eq 'Continue') { + $params += '--verbose' + } + + $bashParameters = $params -join ' ' + Write-Verbose "Running: curl -fsSL $InstallShScriptUrl | bash -s -- $bashParameters" -Verbose:$Verbose + bash -c "curl -fsSL $InstallShScriptUrl | bash -s -- $bashParameters" + exit $LASTEXITCODE +} + +try { + $packageFilename = "azd-windows-amd64.msi" + + $downloadUrl = "$BaseUrl/$packageFilename" + if ($Version) { + $downloadUrl = "$BaseUrl/$Version/$packageFilename" + } + + if ($DryRun) { + Write-Host $downloadUrl + exit 0 + } + + $tempFolder = "$([System.IO.Path]::GetTempPath())$([System.IO.Path]::GetRandomFileName())" + Write-Verbose "Creating temporary folder for downloading package: $tempFolder" + New-Item -ItemType Directory -Path $tempFolder | Out-Null + + Write-Verbose "Downloading build from $downloadUrl" -Verbose:$Verbose + $releaseArtifactFilename = Join-Path $tempFolder $packageFilename + try { + $global:LASTEXITCODE = 0 + Invoke-WebRequest -Uri $downloadUrl -OutFile $releaseArtifactFilename -TimeoutSec $DownloadTimeoutSeconds + if ($LASTEXITCODE) { + throw "Invoke-WebRequest failed with nonzero exit code: $LASTEXITCODE" + } + } catch { + Write-Error -ErrorRecord $_ + reportTelemetryIfEnabled 'InstallFailed' 'DownloadFailed' @{ downloadUrl = $downloadUrl } + exit 1 + } + + + try { + if (!$SkipVerify) { + try { + Write-Verbose "Verifying signature of $releaseArtifactFilename" -Verbose:$Verbose + $signature = Get-AuthenticodeSignature $releaseArtifactFilename + if ($signature.Status -ne 'Valid') { + Write-Error "Signature of $releaseArtifactFilename is not valid" + reportTelemetryIfEnabled 'InstallFailed' 'SignatureVerificationFailed' + exit 1 + } + } catch { + Write-Error -ErrorRecord $_ + reportTelemetryIfEnabled 'InstallFailed' 'SignatureVerificationFailed' + exit 1 + } + } + + Write-Verbose "Installing MSI" -Verbose:$Verbose + $MSIEXEC = "${env:SystemRoot}\System32\msiexec.exe" + $installProcess = Start-Process $MSIEXEC ` + -ArgumentList @("/i", "`"$releaseArtifactFilename`"", "/qn", "INSTALLDIR=`"$InstallFolder`"", "INSTALLEDBY=`"install-azd.ps1`"") ` + -PassThru ` + -Wait + + if ($installProcess.ExitCode) { + if ($installProcess.ExitCode -eq 1603) { + Write-Host "A later version of Azure Developer CLI may already be installed. Use 'Add or remove programs' to uninstall that version and try again." + } + + Write-Error "Could not install MSI at $releaseArtifactFilename. msiexec.exe returned exit code: $($installProcess.ExitCode)" + + reportTelemetryIfEnabled 'InstallFailed' 'MsiFailure' @{ msiExitCode = $installProcess.ExitCode } + exit 1 + } + } catch { + Write-Error -ErrorRecord $_ + reportTelemetryIfEnabled 'InstallFailed' 'GeneralInstallFailure' + exit 1 + } + + Write-Verbose "Cleaning temporary install directory: $tempFolder" -Verbose:$Verbose + Remove-Item $tempFolder -Recurse -Force | Out-Null + + if (!(isLinuxOrMac)) { + # Installed on Windows + Write-Host "Successfully installed azd" + Write-Host "Azure Developer CLI (azd) installed successfully. You may need to restart running programs for installation to take effect." + Write-Host "- For Windows Terminal, start a new Windows Terminal instance." + Write-Host "- For VSCode, close all instances of VSCode and then restart it." + } + Write-Host "" + Write-Host "The Azure Developer CLI collects usage data and sends that usage data to Microsoft in order to help us improve your experience." + Write-Host "You can opt-out of telemetry by setting the AZURE_DEV_COLLECT_TELEMETRY environment variable to 'no' in the shell you use." + Write-Host "" + Write-Host "Read more about Azure Developer CLI telemetry: https://github.com/Azure/azure-dev#data-collection" + + exit 0 +} catch { + Write-Error -ErrorRecord $_ + reportTelemetryIfEnabled 'InstallFailed' 'UnhandledError' @{ exceptionName = $_.Exception.GetType().Name; } + exit 1 +} diff --git a/cli/azd/uninstall-azd.ps1 b/cli/azd/uninstall-azd.ps1 new file mode 100644 index 00000000000..685c6645d4f --- /dev/null +++ b/cli/azd/uninstall-azd.ps1 @@ -0,0 +1,71 @@ +#!/usr/bin/env pwsh +param( + [string] $InstallFolder = "", + [string] $UninstallShScriptUrl = 'https://aka.ms/uninstall-azd.sh' +) + +if ($IsLinux -or $IsMacOS) { + Write-Verbose "Running: curl -fsSL $UninstallShScriptUrl | bash " + curl -fsSL $UninstallShScriptUrl | bash +} else { + # Uninstall azd from Windows for versions of azd which predate 0.5.0-beta.1 + if (!$InstallFolder) { + $InstallFolder = "$($env:LocalAppData)\Programs\Azure Dev CLI" + } + if (Test-Path $InstallFolder) { + Write-Host "Remove Install folder: $InstallFolder" + Remove-Item $InstallFolder -Recurse -Force + } else { + Write-Host "azd is not installed at $InstallFolder. To install run:" + Write-Host "powershell -ex AllSigned -c `"Invoke-RestMethod 'https://aka.ms/install-azd.ps1' | Invoke-Expression`"`n" + } + + # $env:Path, [Environment]::GetEnvironmentVariable('PATH'), Get-ItemProperty, + # and setx all expand variables (e.g. %JAVA_HOME%) in the value. Writing the + # expanded paths back into the environment would be destructive so instead, read + # the PATH entry directly from the registry with the DoNotExpandEnvironmentNames + # option and update the PATH entry in the registry. + try { + . { + # Wrap the Microsoft.Win32.Registry calls in a script block to + # prevent the type intializer from attempting to initialize those + # objects in non-Windows environments. + $registryKey = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey('Environment', $true) + $originalPath = $registryKey.GetValue(` + 'PATH', ` + '', ` + [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames ` + ) + $originalValueKind = $registryKey.GetValueKind('PATH') + } + $pathParts = $originalPath -split ';' + + if ($pathParts -contains $InstallFolder) { + Write-Host "Removing $InstallFolder from PATH" + $newPathParts = $pathParts.Where({ $_ -ne $InstallFolder }) + $newPath = $newPathParts -join ';' + + $registryKey.SetValue( ` + 'PATH', ` + $newPath, ` + $originalValueKind ` + ) + + # Calling this method ensures that a WM_SETTINGCHANGE message is + # sent to top level windows without having to pinvoke from + # PowerShell. Setting to $null deletes the variable if it exists. + [Environment]::SetEnvironmentVariable( ` + 'AZD_INSTALLER_NOOP', ` + $null, ` + [EnvironmentVariableTarget]::User ` + ) + } else { + Write-Host "Could not find an entry for $InstallFolder in PATH" + } + } finally { + if ($registryKey) { + $registryKey.Close() + } + } +} + diff --git a/demo.html b/demo.html new file mode 100644 index 00000000000..e909ff6e80f --- /dev/null +++ b/demo.html @@ -0,0 +1,489 @@ + + + + + +azd Style Guide — Before / After Demo + + + + + + +
+ + + + +
① Command Start & User Prompts
+ + +
+
+ Before +

Without style guide

+
+ +
🚀 ★★★ Welcome to MyCloud CLI v3.2.1 ★★★ 🚀 +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +NOTICE: Telemetry is enabled. +NOTICE: New feature available! + +$ mycloud deploy --env production + +[INFO] Starting deployment... +[INFO] Reading mycloud.yaml +[INFO] Found 4 services +[INFO] Authenticating... done + +Enter resource group name: rg-myapp + +Select a region (type number): + 1) eastus 6) westeurope + 2) eastus2 7) southeastasia + 3) westus 8) japaneast + 4) westus2 9) australiaeast + 5) northeurope 10) brazilsouth +Type a number [1-10]: 2 + +Confirm deploy to production? [yes/no] yes
+ +
+ ❌ Decorative emoji banner + ❌ Notices dumped before command + ❌ [INFO] log-level prefixes + ❌ Plain text prompts — no ? prefix + ❌ All regions shown at once + ❌ "yes/no" not standard "(Y/n)" + ❌ No selected value highlighting +
+
+ + +
+
+ After +

With azd style guide

+
+ +
PS C:\Users\user\myapp> mycloud deploy --env production + +Deploying to Azure (mycloud deploy) + +? Enter a resource group name: rg-myapp + +? Select an Azure location: + (US) East US (eastus) + > (US) East US 2 (eastus2) + (US) West US (westus) + (US) West US 2 (westus2) + (EU) North Europe (northeurope) + (EU) West Europe (westeurope) + (APAC) Southeast Asia (southeastasia) + ... + +? Select an Azure location: (US) East US 2 (eastus2) + +? Deploy to production? (Y/n): Yes
+ +
+ ✅ Clean bold header with (command name) + ✅ No banner, no notices, no [INFO] + ✅ ? prefix on all prompts + ✅ Scrollable list with > cursor, max 7 + ✅ Standard (Y/n) with default + ✅ Selections shown in cyan +
+
+ + + + +
② Provisioning Progress
+ + +
+
+ Before +

Dot-based progress

+
+ +
[INFO] Provisioning infrastructure... +[INFO] Creating resource group... +[INFO] Resource group created. +[INFO] Creating App Service Plan... +[INFO] .......... done (45s) +[INFO] Creating SQL Database... +[INFO] .. +[INFO] .... +[INFO] ........ +[INFO] .......... done (2m 12s) +[INFO] Creating Storage Account... +[INFO] .......... done (1m 33s) +[INFO] Creating Key Vault... +[INFO] .......... done (28s) + +[INFO] All resources created.
+ +
+ ❌ Growing dots on new lines — wall of text + ❌ No in-place animation + ❌ No ✓/✗ status indicators + ❌ Everything is green [INFO] + ❌ "done" is just text, no visual state +
+
+ + +
+
+ After +

Bar-fill spinner + states

+
+ +
Provisioning Azure resources +Provisioning Azure resources can take some time. + + (✓) Done: Creating resource group: rg-myapp + (✓) Done: Creating App Service Plan: plan-myapp + (✓) Done: Creating SQL Database: sql-myapp + (✓) Done: Creating Storage Account: stmyapp + (✓) Done: Creating Key Vault: kv-myapp + Creating App Insights: appi-myapp + +
+ +
+ ✅ Bar-fill spinner animates in-place + ✅ (✓) Done: green for completed + ✅ Resource names for traceability + ✅ Clear visual hierarchy + ✅ No log-level prefixes +
+
+ + + + +
③ Multi-Service Deployment & Failure Handling
+ + +
+
+ Before +

Sequential verbose output

+
+ +
[INFO] Deploying services... + +[INFO] --- Deploying: api --- +[INFO] Building image... pushing... +[INFO] api deployed OK. (52s) + +[INFO] --- Deploying: worker --- +[INFO] Building image... pushing... +[INFO] worker deployed OK. (41s) + +[INFO] --- Deploying: frontend --- +[INFO] Building image... +[ERROR] npm ERR! Missing script: "build" +[ERROR] Stack trace: + at ChildProcess.emit (node:events:513) + at Process._handle.onexit (:291:12) +[ERROR] npm ERR! code ELIFECYCLE + +[INFO] --- Deploying: migration --- +[INFO] migration deployed OK. (18s)
+ +
+ ❌ Sequential — no concurrent view + ❌ Raw stack trace shown to user + ❌ No queued/cancelled states + ❌ Failed service doesn't affect others + ❌ "--- Deploying ---" separators + ❌ "OK" instead of structured state +
+
+ + +
+
+ After +

Braille spinners + all states

+
+ +
Deploying services (4) + + Deploying: api (12s) + Deploying: worker (8s) + (•) Queued: frontend + (•) Queued: migration +
+ +
Deploying services (4) + + (✓) Done: api (52s) + - Endpoint: https://api-myapp.azurewebsites.net + (✓) Done: worker (41s) + (✗) Failed: frontend (12s) + Missing "build" script in package.json. + Run npm run build locally, then mycloud deploy --service frontend + (!) Cancelled: migration – frontend failed
+ +
+ ✅ Braille spinners for concurrent list + ✅ (•) queued state for waiting items + ✅ (✗) Failed with concise error + ✅ (!) Cancelled with reason + ✅ No stack trace — log path instead + ✅ Actionable retry command +
+
+ + + + +
④ Completion & Error Output
+ + +
+
+ Before +

ASCII box summary

+
+ +
[ERROR] Deployment partially failed. +[ERROR] 1 of 4 services failed. +[ERROR] Failed: frontend +[ERROR] Check logs. +[ERROR] Exit code: 1 + +[WARN] Some services deployed OK. +[WARN] Redeploy failed services. + +════════════════════════════════════ + DEPLOYMENT SUMMARY +════════════════════════════════════ + api : OK (52s) + worker : OK (41s) + frontend : FAILED (12s) + migration : OK (18s) +════════════════════════════════════ + +Done.
+ +
+ ❌ Five redundant [ERROR] lines + ❌ [WARN] after [ERROR] — confusing + ❌ ASCII-art summary box + ❌ "OK" / "FAILED" — not structured + ❌ No actionable fix commands + ❌ "Done." — ambiguous outcome +
+
+ + +
+
+ After +

Clear ERROR + actionable fix

+
+ +
ERROR: Unable to complete deployment, 1 service failed. +Run mycloud deploy --service frontend to retry. + +View detailed logs at: +~/.mycloud/logs/deploy/2025-03-24
+ +
+ +
— And when everything succeeds: — + +SUCCESS: Your app was deployed to Azure in 2 minutes 49 seconds. + +You can view resources in Azure Portal: +https://portal.azure.com/...rg-myapp + +Next steps: + Run mycloud monitor to view logs + Run mycloud down to delete resources
+ +
+ ✅ One ERROR: line — concise + ✅ Actionable retry command + ✅ Log path for debugging + ✅ SUCCESS: with duration + ✅ Portal link for resources + ✅ Next steps with commands +
+
+ +
+ +
demo.html — azd Style Guide before/after comparison | cli/azd/docs/style-guidelines/azd-style-guide.md
+ + + diff --git a/test.html b/test.html new file mode 100644 index 00000000000..8e40e38a08d --- /dev/null +++ b/test.html @@ -0,0 +1,295 @@ + + + + + +Qoder CLI – azd Style Redesign + + + + +
+ +

Qoder CLI → azd Style Redesign

+ + +✗ BEFORE — Original Qoder CLI + +
┌──────────────────────────────────────────────────────┐ + ✦ Welcome to Qoder CLI! + + cwd: /Users/leon/qoder +└──────────────────────────────────────────────────────┘ + +Tips for getting started: +1. Ask questions, edit files, or run commands. +2. Be specific for the best results. +3. Type /help for more information. + +> Build a cryptocurrency price tracking H5 app with Go that displays the real-time price of Bitcoin. + + task-executor (Create crypto tracker H5 app) + + ... +3 messages (ctrl+r to expand) + + Let me check the current directory to understand the project structure better. + + Bash (command: pwd && ls -la, background: false) + └ /Users/leon/qoder + total 0 + drwxr-xr-x@ 3 leon staff 96 10 13 20:48 . + drwxr-x---+ 99 leon staff 3168 10 13 19:14 .. + drwxr-xr-x@ 3 leon staff 96 10 13 20:48 .qoder + ... +2 lines (ctrl+r to expand) + + I see we're in an empty directory. Let me create the necessary files... + + Bash (command: go mod init crypto-tracker, background: false) + go: creating new go.mod: module crypto-tracker
+ +
+ Issues: Decorative box banner, green dot bullets (●), exposed bash commands & raw output, + freeform narrative text, no structured progress states, no clear completion message. +
+ +
+ + +✓ AFTER — azd Style + +
Qoder CLI +cwd: /Users/leon/qoder + +Tips for getting started: + 1. Ask questions, edit files, or run commands. + 2. Be specific for the best results. + 3. Type /help for more information. + +? What would you like to do: Build a cryptocurrency price tracking H5 app with Go + +Creating crypto tracker H5 app + + (✓) Done: Checked project structure + (✓) Done: Initialized Go module (crypto-tracker) + (✓) Done: Created main.go + (✓) Done: Created templates/index.html + (✓) Done: Installed dependencies (3 packages) + +SUCCESS: Crypto tracker H5 app created. + +Files created: + go.mod + main.go + templates/index.html + +Next steps: + Run go run main.go to start the app + Open http://localhost:8080 in your browser
+ +
+ + +

Live Animation: Progress States

+ +

These show how the spinner animations look during execution:

+ +

Bar-fill spinner (single operation)

+
Provisioning Azure resources +Provisioning Azure resources can take some time. + + (✓) Done: Creating App Service Plan: plan-r2w2adrz3rvwxu + (✓) Done: Creating Log Analytics workspace: log-r2w2adrz3rvwxu + Creating Application Insights: appi-r2w2adrz3rvwxu
+ +

Braille spinner (multi-service deployment)

+
Deploying 4 services + + Deploying: api (12s) + Deploying: worker (8s) + (•) Queued: frontend + (•) Queued: database-migration
+ +

Completed with mixed states

+
Deploying 4 services + + (✓) Done: api (32s) + - Endpoint: https://api-yo2mecxyj3dmw.azurewebsites.net/ + (✓) Done: worker (28s) + (✗) Failed: frontend (15s) + Missing build output directory. Run 'npm run build' before deploying. + (!) Cancelled: database-migration – frontend failed + +ERROR: Unable to complete deployment, 1 service failed. +Run azd deploy --service frontend to retry the failed service.
+ +
+ + +

azd Style Reference

+ +
Status indicators: + (✓) Done: Operation completed successfully + (✗) Failed: Operation failed + (!) Warning: Non-blocking issue + (!) Cancelled: Cancelled due to sibling failure + (-) Skipped: Intentionally skipped + (•) Queued / waiting + +Spinners: + Bar-fill — single long-running operation + Braille — concurrent multi-item lists + +Prompt: + ? Interactive prompt: user input in cyan + +Completion: + SUCCESS: Positive outcome message + ERROR: Failure with actionable guidance
+ +
+ + + From 0a41d3d93aea2f3a87b53637ce6471c76567ff65 Mon Sep 17 00:00:00 2001 From: hyoshis Date: Fri, 27 Mar 2026 14:54:00 -0700 Subject: [PATCH 05/14] docs: add agentic flow UX section and fix hint color in style guide - Add Agentic Flow UX section covering spinner, display layers, hints, and status messages - Add magenta for agentic experiences note in CLI Color Standards - Fix hint text color from hi-magenta to hi-blue to match actual code - Remove resolved TODO Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../docs/style-guidelines/azd-style-guide.md | 115 +++++++++++++++++- 1 file changed, 112 insertions(+), 3 deletions(-) diff --git a/cli/azd/docs/style-guidelines/azd-style-guide.md b/cli/azd/docs/style-guidelines/azd-style-guide.md index c7408010782..a6378fe439e 100644 --- a/cli/azd/docs/style-guidelines/azd-style-guide.md +++ b/cli/azd/docs/style-guidelines/azd-style-guide.md @@ -266,8 +266,7 @@ Text input captures a single line of input from the user. **Initial state:** -TODO: this is not shown as magenta in actual azd. confirm this. also i see that 'type' is not mentioned in azd either. -The prompt is displayed with a `[Type ? for hint]` helper in hi-magenta bold text, followed by ghost-text (secondary text color) as placeholder content. +The prompt is displayed with a `[Type ? for hint]` helper in hi-blue bold text (via `WithHighLightFormat`), followed by ghost-text (secondary text color) as placeholder content. ``` ? This captures a single line of input: [Type ? for hint] This is ghost-text @@ -375,7 +374,7 @@ The CLI uses consistent color formatting through helper functions defined in [`c **Important**: Colors will appear differently depending on which terminal and theme (dark/light) the customer prefers. Always test output in both dark and light terminal themes. -TODO: add something about using Magenta for agentic experience +**Magenta for agentic experiences**: Agentic flows use magenta as their primary accent color (see [Agentic Flow UX](#agentic-flow-ux) below). Use `color.MagentaString()` for tool names, agent labels, status messages, and spinner characters in agent mode. Use `color.HiMagentaString()` for the agent badge (`🤖 [azd] Agent`), subagent names, and next-steps headers. #### Standard Color Helper Functions @@ -536,6 +535,116 @@ There are three spinner variants based on terminal capability: - **Use `(•)` static indicator** for queued items that haven't started yet - **Keep status messages concise** — use the format `"ing : "` +### Agentic Flow UX + +Any command or flow that involves **AI-driven or agentic operations** — such as `azd init` → "Use agent mode", `azd ai agent` commands, or future agentic features — should follow the UX patterns in this section. These patterns visually differentiate AI-driven operations from standard CLI output and should be applied consistently across all agentic experiences. + +#### When Agentic Flow Applies + +| Entry Point | Description | +| --- | --- | +| `azd init` → "Use agent mode" | Initializes a project using Copilot agent | +| `azd ai agent *` commands | All agent subcommands follow agentic UX | + +#### Agentic Spinner + +The agentic spinner uses the **same default character set** as the standard spinner (`|`, `/`, `-`, `\`) rendered in **magenta** via `WithHintFormat()`, cycling at 250ms intervals. This is different from the bar-fill spinner (`|=======|`) used for standard provisioning/deployment progress. + +**Animation frames:** + +``` +| → / → - → \ → (repeats) +``` + +The spinner characters appear in **magenta** while the accompanying text describes the current operation: + +
+/ Thinking...
+
+ +
+- Running powershell azd env list... (5s)
+
+ +| Scenario | Spinner Type | Reason | +| --- | --- | --- | +| Standard single operation (provisioning, creating a resource) | **Bar-fill** (`\|=== \|`) | Clear progress for deterministic operations | +| Agentic flow (agent thinking, tool execution) | **Character rotation** (`\| / - \`) | Lightweight indicator for non-deterministic AI operations | +| Multiple concurrent operations in a list | **Braille** (`⠋⠙⠹...`) | Compact for multi-line lists | + +#### Agentic Display Layers + +The agentic display uses a canvas with multiple visual layers rendered together: + +1. **Reasoning display** — Shows the last ~5 lines of the agent's reasoning in **gray** text above the spinner +2. **Spinner** — The rotating `| / - \` character in **magenta** with a status message +3. **Sub-detail lines** — Optional tree-structured lines below the spinner showing command arguments or file paths, using ASCII connectors (`├`, `└`) +4. **Cancel hint** — A `Press Ctrl+C to cancel` message at the bottom + +**Example — agent thinking:** + +
+/ Thinking...
+
+ +**Example — tool execution with elapsed time:** + +
+\ Running powershell npm install... (12s)
+
+ +**Example — tool completion:** + +
+✔︎ Ran powershell npm install
+
+ +**Example — tool failure:** + +
+ powershell npm install
+  └ Error: ENOENT: no such file or directory
+
+ +#### Agentic Hint Text + +The hint mechanism (`?` key) works the same way in agentic flow as in standard flow — pressing `?` reveals help text, pressing `Escape` dismisses it. In both cases, the hint label and message are rendered in **magenta** via `WithHintFormat()`: + +
+? Enter your environment name: [Type ? for hint] my-env
+Hint: The environment name is used to create a resource group and identify resources in Azure.
+
+ +#### Agentic Status Messages + +Key status messages in agentic flow use magenta to reinforce the agentic context: + +
+Preparing application for Azure deployment...
+
+ +
+(->) Next steps: Run azd up to provision and deploy your application.
+
+ +#### Color Summary for Agentic Flow + +| Element | Color | Function | +| --- | --- | --- | +| Spinner character (`\| / - \`) | Magenta | `WithHintFormat()` | +| Tool names in spinner text | Magenta | `color.MagentaString()` | +| Hint label and text | Magenta | `WithHintFormat()` | +| Status messages (e.g., "Preparing...") | Magenta | `color.MagentaString()` | +| Next-steps header | Hi-Magenta | `color.HiMagentaString()` | +| Reasoning text | Gray | `color.HiBlackString()` | +| Elapsed time / secondary info | Gray | `color.HiBlackString()` | +| Tool success checkmark | Green | `color.GreenString()` | +| Tool failure X | Red | `color.RedString()` | + +#### Implementation Reference + +The agentic display is implemented in [`internal/agent/display.go`](../../internal/agent/display.go) via the `AgentDisplay` struct, which subscribes to Copilot SDK session events and manages a multi-layer canvas for rendering. + ## Testing Standards ### Test Structure From 0de9a8f52c2696b1d974ea70dba5eda434d20079 Mon Sep 17 00:00:00 2001 From: hyoshis Date: Fri, 27 Mar 2026 14:59:07 -0700 Subject: [PATCH 06/14] revert: remove install-azd.ps1 and uninstall-azd.ps1 from cli/azd/ These files were accidentally added in the temp commit. The canonical location is cli/installer/. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- cli/azd/install-azd.ps1 | 396 -------------------------------------- cli/azd/uninstall-azd.ps1 | 71 ------- 2 files changed, 467 deletions(-) delete mode 100644 cli/azd/install-azd.ps1 delete mode 100644 cli/azd/uninstall-azd.ps1 diff --git a/cli/azd/install-azd.ps1 b/cli/azd/install-azd.ps1 deleted file mode 100644 index a779a222e49..00000000000 --- a/cli/azd/install-azd.ps1 +++ /dev/null @@ -1,396 +0,0 @@ -#!/usr/bin/env pwsh -<# -.SYNOPSIS -Download and install azd on the local machine. - -.DESCRIPTION -Downloads and installs azd on the local machine. Includes ability to configure -download and install locations. - -.PARAMETER BaseUrl -Specifies the base URL to use when downloading. Default is -https://azuresdkartifacts.z5.web.core.windows.net/azd/standalone/release - -.PARAMETER Version -Specifies the version to use. Default is `latest`. Valid values include a -SemVer version number (e.g. 1.0.0 or 1.1.0-beta.1), `latest`, `daily` - -.PARAMETER DryRun -Print the download URL and quit. Does not download or install. - -.PARAMETER InstallFolder -Location to install azd. - -.PARAMETER SymlinkFolder -(Mac/Linux only) Folder to symlink - -.PARAMETER DownloadTimeoutSeconds -Download timeout in seconds. Default is 120 (2 minutes). - -.PARAMETER SkipVerify -Skips verification of the downloaded file. - -.PARAMETER InstallShScriptUrl -(Mac/Linux only) URL to the install-azd.sh script. Default is https://aka.ms/install-azd.sh - -.EXAMPLE -powershell -ex AllSigned -c "Invoke-RestMethod 'https://aka.ms/install-azd.ps1' | Invoke-Expression" - -Install the azd CLI from a Windows shell - -The use of `-ex AllSigned` is intended to handle the scenario where a machine's -default execution policy is restricted such that modules used by -`install-azd.ps1` cannot be loaded. Because this syntax is piping output from -`Invoke-RestMethod` to `Invoke-Expression` there is no direct valication of the -`install-azd.ps1` script's signature. Validation of the script can be -accomplished by downloading the script to a file and executing the script file. - -.EXAMPLE -Invoke-RestMethod 'https://aka.ms/install-azd.ps1' -OutFile 'install-azd.ps1' -PS > ./install-azd.ps1 - -Download the installer and execute from PowerShell - -.EXAMPLE -Invoke-RestMethod 'https://aka.ms/install-azd.ps1' -OutFile 'install-azd.ps1' -PS > ./install-azd.ps1 -Version daily - -Download the installer and install the "daily" build -#> - -param( - [string] $BaseUrl = "https://azuresdkartifacts.z5.web.core.windows.net/azd/standalone/release", - [string] $Version = "stable", - [switch] $DryRun, - [string] $InstallFolder, - [string] $SymlinkFolder, - [switch] $SkipVerify, - [int] $DownloadTimeoutSeconds = 120, - [switch] $NoTelemetry, - [string] $InstallShScriptUrl = "https://aka.ms/install-azd.sh" -) - -function isLinuxOrMac { - return $IsLinux -or $IsMacOS -} - -# Does some very basic parsing of /etc/os-release to output the value present in -# the file. Since only lines that start with '#' are to be treated as comments -# according to `man os-release` there is no additional parsing of comments -# Options like: -# bash -c "set -o allexport; source /etc/os-release;set +o allexport; echo $VERSION_ID" -# were considered but it's possible that bash is not installed on the system and -# these commands would not be available. -function getOsReleaseValue($key) { - $value = $null - foreach ($line in Get-Content '/etc/os-release') { - if ($line -like "$key=*") { - # 'ID="value" -> @('ID', '"value"') - $splitLine = $line.Split('=', 2) - - # Remove surrounding whitespaces and quotes - # ` "value" ` -> `value` - # `'value'` -> `value` - $value = $splitLine[1].Trim().Trim(@("`"", "'")) - } - } - return $value -} - -function getOs { - $os = [Environment]::OSVersion.Platform.ToString() - try { - if (isLinuxOrMac) { - if ($IsLinux) { - $os = getOsReleaseValue 'ID' - } elseif ($IsMacOs) { - $os = sw_vers -productName - } - } - } catch { - Write-Error "Error getting OS name $_" - $os = "error" - } - return $os -} - -function getOsVersion { - $version = [Environment]::OSVersion.Version.ToString() - try { - if (isLinuxOrMac) { - if ($IsLinux) { - $version = getOsReleaseValue 'VERSION_ID' - } elseif ($IsMacOS) { - $version = sw_vers -productVersion - } - } - } catch { - Write-Error "Error getting OS version $_" - $version = "error" - } - return $version -} - -function isWsl { - $isWsl = $false - if ($IsLinux) { - $kernelRelease = uname --kernel-release - if ($kernelRelease -like '*wsl*') { - $isWsl = $true - } - } - return $isWsl -} - -function getTerminal { - return (Get-Process -Id $PID).ProcessName -} - -function getExecutionEnvironment { - $executionEnvironment = 'Desktop' - if ($env:GITHUB_ACTIONS) { - $executionEnvironment = 'GitHub Actions' - } elseif ($env:SYSTEM_TEAMPROJECTID) { - $executionEnvironment = 'Azure DevOps' - } - return $executionEnvironment -} - -function promptForTelemetry { - # UserInteractive may return $false if the session is not interactive - # but this does not work in 100% of cases. For example, running: - # "powershell -NonInteractive -c '[Environment]::UserInteractive'" - # results in output of "True" even though the shell is not interactive. - if (![Environment]::UserInteractive) { - return $false - } - - Write-Host "Answering 'yes' below will send data to Microsoft. To learn more about data collection see:" - Write-Host "https://go.microsoft.com/fwlink/?LinkId=521839" - Write-Host "" - Write-Host "You can also file an issue at https://github.com/Azure/azure-dev/issues/new?assignees=&labels=&template=issue_report.md&title=%5BIssue%5D" - - try { - $yes = New-Object System.Management.Automation.Host.ChoiceDescription ` - "&Yes", ` - "Sends failure report to Microsoft" - $no = New-Object System.Management.Automation.Host.ChoiceDescription ` - "&No", ` - "Exits the script without sending a failure report to Microsoft (Default)" - $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no) - $decision = $Host.UI.PromptForChoice( ` - 'Confirm issue report', ` - 'Do you want to send diagnostic data about the failure to Microsoft?', ` - $options, ` - 1 ` # Default is 'No' - ) - - # Return $true if user consents - return $decision -eq 0 - } catch { - # Failure to prompt generally indicates that the environment is not - # interactive and the default resposne can be assumed. - return $false - } -} - -function reportTelemetryIfEnabled($eventName, $reason='', $additionalProperties = @{}) { - if ($NoTelemetry -or $env:AZURE_DEV_COLLECT_TELEMETRY -eq 'no') { - Write-Verbose "Telemetry disabled. No telemetry reported." -Verbose:$Verbose - return - } - - $IKEY = 'a9e6fa10-a9ac-4525-8388-22d39336ecc2' - - $telemetryObject = @{ - iKey = $IKEY; - name = "Microsoft.ApplicationInsights.$($IKEY.Replace('-', '')).Event"; - time = (Get-Date).ToUniversalTime().ToString('o'); - data = @{ - baseType = 'EventData'; - baseData = @{ - ver = 2; - name = $eventName; - properties = @{ - installVersion = $Version; - reason = $reason; - os = getOs; - osVersion = getOsVersion; - isWsl = isWsl; - terminal = getTerminal; - executionEnvironment = getExecutionEnvironment; - }; - } - } - } - - # Add entries from $additionalProperties. These may overwrite existing - # entries in the properties field. - if ($additionalProperties -and $additionalProperties.Count) { - foreach ($entry in $additionalProperties.GetEnumerator()) { - $telemetryObject.data.baseData.properties[$entry.Name] = $entry.Value - } - } - - Write-Host "An error was encountered during install: $reason" - Write-Host "Error data collected:" - $telemetryDataTable = $telemetryObject.data.baseData.properties | Format-Table | Out-String - Write-Host $telemetryDataTable - if (!(promptForTelemetry)) { - # The user responded 'no' to the telemetry prompt or is in a - # non-interactive session. Do not send telemetry. - return - } - - try { - Invoke-RestMethod ` - -Uri 'https://centralus-2.in.applicationinsights.azure.com/v2/track' ` - -ContentType 'application/json' ` - -Method Post ` - -Body (ConvertTo-Json -InputObject $telemetryObject -Depth 100 -Compress) | Out-Null - Write-Verbose -Verbose:$Verbose "Telemetry posted" - } catch { - Write-Host $_ - Write-Verbose -Verbose:$Verbose "Telemetry post failed" - } -} - -if (isLinuxOrMac) { - if (!(Get-Command curl)) { - Write-Error "Command could not be found: curl." - exit 1 - } - if (!(Get-Command bash)) { - Write-Error "Command could not be found: bash." - exit 1 - } - - $params = @( - '--base-url', "'$BaseUrl'", - '--version', "'$Version'" - ) - - if ($InstallFolder) { - $params += '--install-folder', "'$InstallFolder'" - } - - if ($SymlinkFolder) { - $params += '--symlink-folder', "'$SymlinkFolder'" - } - - if ($SkipVerify) { - $params += '--skip-verify' - } - - if ($DryRun) { - $params += '--dry-run' - } - - if ($NoTelemetry) { - $params += '--no-telemetry' - } - - if ($VerbosePreference -eq 'Continue') { - $params += '--verbose' - } - - $bashParameters = $params -join ' ' - Write-Verbose "Running: curl -fsSL $InstallShScriptUrl | bash -s -- $bashParameters" -Verbose:$Verbose - bash -c "curl -fsSL $InstallShScriptUrl | bash -s -- $bashParameters" - exit $LASTEXITCODE -} - -try { - $packageFilename = "azd-windows-amd64.msi" - - $downloadUrl = "$BaseUrl/$packageFilename" - if ($Version) { - $downloadUrl = "$BaseUrl/$Version/$packageFilename" - } - - if ($DryRun) { - Write-Host $downloadUrl - exit 0 - } - - $tempFolder = "$([System.IO.Path]::GetTempPath())$([System.IO.Path]::GetRandomFileName())" - Write-Verbose "Creating temporary folder for downloading package: $tempFolder" - New-Item -ItemType Directory -Path $tempFolder | Out-Null - - Write-Verbose "Downloading build from $downloadUrl" -Verbose:$Verbose - $releaseArtifactFilename = Join-Path $tempFolder $packageFilename - try { - $global:LASTEXITCODE = 0 - Invoke-WebRequest -Uri $downloadUrl -OutFile $releaseArtifactFilename -TimeoutSec $DownloadTimeoutSeconds - if ($LASTEXITCODE) { - throw "Invoke-WebRequest failed with nonzero exit code: $LASTEXITCODE" - } - } catch { - Write-Error -ErrorRecord $_ - reportTelemetryIfEnabled 'InstallFailed' 'DownloadFailed' @{ downloadUrl = $downloadUrl } - exit 1 - } - - - try { - if (!$SkipVerify) { - try { - Write-Verbose "Verifying signature of $releaseArtifactFilename" -Verbose:$Verbose - $signature = Get-AuthenticodeSignature $releaseArtifactFilename - if ($signature.Status -ne 'Valid') { - Write-Error "Signature of $releaseArtifactFilename is not valid" - reportTelemetryIfEnabled 'InstallFailed' 'SignatureVerificationFailed' - exit 1 - } - } catch { - Write-Error -ErrorRecord $_ - reportTelemetryIfEnabled 'InstallFailed' 'SignatureVerificationFailed' - exit 1 - } - } - - Write-Verbose "Installing MSI" -Verbose:$Verbose - $MSIEXEC = "${env:SystemRoot}\System32\msiexec.exe" - $installProcess = Start-Process $MSIEXEC ` - -ArgumentList @("/i", "`"$releaseArtifactFilename`"", "/qn", "INSTALLDIR=`"$InstallFolder`"", "INSTALLEDBY=`"install-azd.ps1`"") ` - -PassThru ` - -Wait - - if ($installProcess.ExitCode) { - if ($installProcess.ExitCode -eq 1603) { - Write-Host "A later version of Azure Developer CLI may already be installed. Use 'Add or remove programs' to uninstall that version and try again." - } - - Write-Error "Could not install MSI at $releaseArtifactFilename. msiexec.exe returned exit code: $($installProcess.ExitCode)" - - reportTelemetryIfEnabled 'InstallFailed' 'MsiFailure' @{ msiExitCode = $installProcess.ExitCode } - exit 1 - } - } catch { - Write-Error -ErrorRecord $_ - reportTelemetryIfEnabled 'InstallFailed' 'GeneralInstallFailure' - exit 1 - } - - Write-Verbose "Cleaning temporary install directory: $tempFolder" -Verbose:$Verbose - Remove-Item $tempFolder -Recurse -Force | Out-Null - - if (!(isLinuxOrMac)) { - # Installed on Windows - Write-Host "Successfully installed azd" - Write-Host "Azure Developer CLI (azd) installed successfully. You may need to restart running programs for installation to take effect." - Write-Host "- For Windows Terminal, start a new Windows Terminal instance." - Write-Host "- For VSCode, close all instances of VSCode and then restart it." - } - Write-Host "" - Write-Host "The Azure Developer CLI collects usage data and sends that usage data to Microsoft in order to help us improve your experience." - Write-Host "You can opt-out of telemetry by setting the AZURE_DEV_COLLECT_TELEMETRY environment variable to 'no' in the shell you use." - Write-Host "" - Write-Host "Read more about Azure Developer CLI telemetry: https://github.com/Azure/azure-dev#data-collection" - - exit 0 -} catch { - Write-Error -ErrorRecord $_ - reportTelemetryIfEnabled 'InstallFailed' 'UnhandledError' @{ exceptionName = $_.Exception.GetType().Name; } - exit 1 -} diff --git a/cli/azd/uninstall-azd.ps1 b/cli/azd/uninstall-azd.ps1 deleted file mode 100644 index 685c6645d4f..00000000000 --- a/cli/azd/uninstall-azd.ps1 +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env pwsh -param( - [string] $InstallFolder = "", - [string] $UninstallShScriptUrl = 'https://aka.ms/uninstall-azd.sh' -) - -if ($IsLinux -or $IsMacOS) { - Write-Verbose "Running: curl -fsSL $UninstallShScriptUrl | bash " - curl -fsSL $UninstallShScriptUrl | bash -} else { - # Uninstall azd from Windows for versions of azd which predate 0.5.0-beta.1 - if (!$InstallFolder) { - $InstallFolder = "$($env:LocalAppData)\Programs\Azure Dev CLI" - } - if (Test-Path $InstallFolder) { - Write-Host "Remove Install folder: $InstallFolder" - Remove-Item $InstallFolder -Recurse -Force - } else { - Write-Host "azd is not installed at $InstallFolder. To install run:" - Write-Host "powershell -ex AllSigned -c `"Invoke-RestMethod 'https://aka.ms/install-azd.ps1' | Invoke-Expression`"`n" - } - - # $env:Path, [Environment]::GetEnvironmentVariable('PATH'), Get-ItemProperty, - # and setx all expand variables (e.g. %JAVA_HOME%) in the value. Writing the - # expanded paths back into the environment would be destructive so instead, read - # the PATH entry directly from the registry with the DoNotExpandEnvironmentNames - # option and update the PATH entry in the registry. - try { - . { - # Wrap the Microsoft.Win32.Registry calls in a script block to - # prevent the type intializer from attempting to initialize those - # objects in non-Windows environments. - $registryKey = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey('Environment', $true) - $originalPath = $registryKey.GetValue(` - 'PATH', ` - '', ` - [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames ` - ) - $originalValueKind = $registryKey.GetValueKind('PATH') - } - $pathParts = $originalPath -split ';' - - if ($pathParts -contains $InstallFolder) { - Write-Host "Removing $InstallFolder from PATH" - $newPathParts = $pathParts.Where({ $_ -ne $InstallFolder }) - $newPath = $newPathParts -join ';' - - $registryKey.SetValue( ` - 'PATH', ` - $newPath, ` - $originalValueKind ` - ) - - # Calling this method ensures that a WM_SETTINGCHANGE message is - # sent to top level windows without having to pinvoke from - # PowerShell. Setting to $null deletes the variable if it exists. - [Environment]::SetEnvironmentVariable( ` - 'AZD_INSTALLER_NOOP', ` - $null, ` - [EnvironmentVariableTarget]::User ` - ) - } else { - Write-Host "Could not find an entry for $InstallFolder in PATH" - } - } finally { - if ($registryKey) { - $registryKey.Close() - } - } -} - From 5331a5948f822df5c624a3578c724ef809a53bf7 Mon Sep 17 00:00:00 2001 From: hyoshis Date: Fri, 27 Mar 2026 15:00:30 -0700 Subject: [PATCH 07/14] revert: remove temp HTML files Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- after.html | 408 ------------------------------------------- before.html | 357 -------------------------------------- demo.html | 489 ---------------------------------------------------- test.html | 295 ------------------------------- 4 files changed, 1549 deletions(-) delete mode 100644 after.html delete mode 100644 before.html delete mode 100644 demo.html delete mode 100644 test.html diff --git a/after.html b/after.html deleted file mode 100644 index 1d41afb7cb9..00000000000 --- a/after.html +++ /dev/null @@ -1,408 +0,0 @@ - - - - - -AFTER — CLI With azd Style Guide Applied - - - - - - -
- -
- What you're looking at: The same mycloud deploy scenario from before.html, - redesigned by applying the azd style guide. Every change traces back to a specific guideline. -
- - - - -
PS C:\Users\user\myapp> mycloud deploy --environment production - -Deploying to Azure (mycloud deploy) -Deploying application to environment: production
- -
- ✅ Clean bold command header with command name in parentheses § Command Header
- ✅ No decorative banner, no emoji, no ASCII art
- ✅ No [INFO] log-level prefixes — this is user-facing output
- ✅ Notices removed — don't dump unrelated info before the task -
- - - - -
? Enter a resource group name: [Type ? for hint] rg-myapp-prod -
-
? Enter a resource group name: rg-myapp-prod - -? Select an Azure location: [Use arrows to move, type to filter] - - (US) East US (eastus) - > (US) East US 2 (eastus2) - (US) West US (westus) - (US) West US 2 (westus2) - (EU) North Europe (northeurope) - (EU) West Europe (westeurope) - (APAC) Southeast Asia (southeastasia) - ...
-
? Enter a resource group name: rg-myapp-prod -? Select an Azure location: (US) East US 2 (eastus2) -? Deploy to production? (Y/n): Yes
- -
- ✅ Blue ? prefix on every prompt — visually distinct § User Inputs
- ✅ Bold prompt text with [Type ? for hint] helper § Text Input
- ✅ Ghost text as placeholder, cyan for submitted answers § Color Coding
- ✅ Scrollable list with > cursor, max 7 visible + ... § List Select
- ✅ Region labels with friendly names: "(US) East US 2 (eastus2)"
- ✅ Confirmation uses standard (Y/n) with default capitalized § Yes/No Input
- ✅ Completed prompts stay visible with selections in cyan -
- - - - -
Provisioning Azure resources -Provisioning Azure resources can take some time. - - (✓) Done: Creating resource group: rg-myapp-prod - (✓) Done: Creating App Service Plan: plan-myapp-prod - (✓) Done: Creating SQL Database: sql-myapp-prod - (✓) Done: Creating Storage Account: stmyappprod - (✓) Done: Creating Key Vault: kv-myapp-prod - Creating Application Insights: appi-myapp-prod
- -
- ✅ Bar-fill spinner animates in-place — no scrolling dots § Loading Animation
- ✅ (✓) Done: in green for each completed step § Progress States
- ✅ Resource names included for traceability
- ✅ Clean indentation under command header § Progress Report Guidelines -
- -
Provisioning Azure resources -Provisioning Azure resources can take some time. - - (✓) Done: Creating resource group: rg-myapp-prod - (✓) Done: Creating App Service Plan: plan-myapp-prod - (✓) Done: Creating SQL Database: sql-myapp-prod - (✓) Done: Creating Storage Account: stmyappprod - (✓) Done: Creating Key Vault: kv-myapp-prod - (✓) Done: Creating Application Insights: appi-myapp-prod - -SUCCESS: Your application was provisioned in Azure in 4 minutes 11 seconds.
- -
- ✅ SUCCESS: in green with duration § Success Logs
- ✅ All steps resolved to (✓) Done — clear at a glance -
- - - - -
Deploying services (4) - - Deploying: api (12s) - Deploying: worker (8s) - (•) Queued: frontend - (•) Queued: migration-job
- -
- ✅ Braille spinner for concurrent multi-service list § Bar vs Braille Spinner
- ✅ (•) static dot for queued items — no animation until started
- ✅ Compact format — no verbose build logs inline
- ✅ Service count in header: "Deploying services (4)" -
- -
Deploying services (4) - - (✓) Done: api (52s) - - Endpoint: https://api-myapp-prod.azurewebsites.net - (✓) Done: worker (41s) - (✗) Failed: frontend (12s) - Build failed: missing "build" script in package.json. - Run npm run build locally to verify, then retry with mycloud deploy --service frontend - Log: ~/.mycloud/logs/deploy/2025-03-24/deploy-frontend.log - (!) Cancelled: migration-job – frontend failed - -ERROR: Unable to complete deployment, 1 service failed. -To retry the failed service, run mycloud deploy --service frontend
- -
- ✅ (✗) Failed: in red with concise error — no stack trace § Progress States
- ✅ Actionable fix: specific command to retry § Error Logs
- ✅ Log file path provided for debugging
- ✅ (!) Cancelled: with reason — clear cause-and-effect § Cancelled State
- ✅ ERROR: summary — one line, not five
- ✅ Endpoints shown inline under successful service -
- - - - -
Deploying services (4) - - (✓) Done: api (52s) - - Endpoint: https://api-myapp-prod.azurewebsites.net - (✓) Done: worker (41s) - (✓) Done: frontend (38s) - - Endpoint: https://frontend-myapp-prod.azurewebsites.net - (✓) Done: migration-job (18s) - -SUCCESS: Your application was deployed to Azure in 2 minutes 49 seconds. -You can view the resources created under the resource group rg-myapp-prod in Azure Portal: -https://portal.azure.com/#@/resource/subscriptions/.../resourceGroups/rg-myapp-prod - -Next steps: - Run mycloud monitor to view application logs - Run mycloud down to delete Azure resources
- -
- ✅ SUCCESS: with duration and portal link § Success Logs
- ✅ Next steps: with actionable follow-up commands § Hint Text
- ✅ No "DEPLOYMENT SUMMARY" ASCII box — status is already inline
- ✅ No redundant "Done." at the end — SUCCESS is the clear signal -
- - - - -
Progress states: - Loading (bar-fill — single operation) - Loading (braille — concurrent list) - (•) Queued (waiting to start) - (✓) Done: Completed successfully - (✗) Failed: Operation failed - (!) Warning: Non-blocking issue - (!) Cancelled: Stopped due to sibling failure - (-) Skipped: Intentionally skipped - -Completion messages: - SUCCESS: Positive outcome - ERROR: Failure with actionable guidance - WARNING: User should be aware - -Prompts: - ? Prompt text: user input in cyan - ? Confirm? (Y/n): Yes - ? Select from list: [Use arrows to move, type to filter] - > Selected item - Other item - -Colors: - Green — success, done, positive outcomes - Red — errors, failures - Yellow — warnings, cancelled - Cyan — user input, commands, prompts - Blue — links, URLs - Gray — secondary info, hints, skipped - Magenta — hint helpers [Type ? for hint]
- -
- -
after.html — Part of the azd Style Guide demo | Guided by azd-style-guide.md
- - - diff --git a/before.html b/before.html deleted file mode 100644 index 92c7f3abb12..00000000000 --- a/before.html +++ /dev/null @@ -1,357 +0,0 @@ - - - - - -BEFORE — CLI Without Style Guide - - - - - - -
- -
- What you're looking at: A fictional CLI tool (mycloud deploy) that provisions - infrastructure and deploys services — without following any style guidelines. Each section highlights - specific problems that the azd style guide addresses. -
- - - - -
🚀 ★★★ Welcome to MyCloud CLI v3.2.1 ★★★ 🚀 -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -NOTICE: You are using the latest version. -NOTICE: Telemetry is enabled. Set MYCLOUD_TELEMETRY=false to disable. -NOTICE: New feature: pipeline support! Try `mycloud pipeline init`. - -$ mycloud deploy --environment production - -[INFO] Starting deployment process... -[INFO] Reading configuration from mycloud.yaml -[INFO] Found 4 services to deploy -[INFO] Target environment: production -[INFO] Subscription: 0cd6095b-b140-41ec-ad1d-32f2f7493386 -[INFO] Region: eastus2 -[INFO] Authenticating... -[INFO] Token acquired successfully
- -
- ❌ Decorative banner with emoji — not professional CLI output
- ❌ Multiple notices dumped before command runs — noise
- ❌ [INFO] log-style prefixes — this is a CLI, not a log file
- ❌ Neon magenta/yellow colors — not ANSI-standard, won't adapt to light themes
- ❌ Subscription ID exposed without context -
- - - - -
[INFO] Environment 'production' does not have a resource group configured. - -Enter resource group name: _ - -Enter resource group name: rg-myapp-prod - -Select a region (type number): - 1) eastus - 2) eastus2 - 3) westus - 4) westus2 - 5) northeurope - 6) westeurope - 7) southeastasia - 8) japaneast - 9) australiaeast - 10) brazilsouth - 11) canadacentral - 12) centralindia - 13) koreacentral - 14) uksouth - 15) francecentral - -Type a number [1-15]: 2 - -Confirm deployment to production? [yes/no] yes
- -
- ❌ No ? prefix on prompts — blends with regular output
- ❌ Plain white text prompts — not visually distinct
- ❌ All 15 regions shown at once — no scrollable list, no filtering
- ❌ No [Type ? for hint] helper for guidance
- ❌ "yes/no" instead of standard "(Y/n)" with default
- ❌ Selected values not highlighted in cyan after submission -
- - - - -
[INFO] Starting infrastructure provisioning... -[INFO] Creating resource group: rg-myapp-prod -[INFO] Resource group created. -[INFO] Creating App Service Plan... (this may take a few minutes) -[INFO] .......... done (45s) -[INFO] Creating SQL Database... -[INFO] .......... done (2m 12s) -[INFO] Creating Storage Account... -[INFO] .. -[INFO] .... -[INFO] ........ -[INFO] .......... done (1m 33s) -[INFO] Creating Key Vault... -[INFO] .......... done (28s) -[INFO] Creating Application Insights... -[INFO] .......... done (15s) -[INFO] Configuring network security groups... -[INFO] .......... done (8s) - -[INFO] All infrastructure resources created.
- -
- ❌ Dots printed as new lines instead of in-place animation — produces wall of text
- ❌ No spinner or progress bar — just growing dots
- ❌ No structured states (✓ Done / ✗ Failed) — just "done" text
- ❌ Every line is [INFO] green — no visual hierarchy between steps
- ❌ "this may take a few minutes" — vague, informal -
- - - - -
[INFO] Deploying services... - -[INFO] --- Deploying: api --- -[INFO] Building container image... -[INFO] Pushing to registry... -[INFO] Updating App Service... -[INFO] api deployed successfully. (52s) - -[INFO] --- Deploying: worker --- -[INFO] Building container image... -[INFO] Pushing to registry... -[INFO] Updating App Service... -[INFO] worker deployed successfully. (41s) - -[INFO] --- Deploying: frontend --- -[INFO] Building container image... -[ERROR] Build failed: npm ERR! Missing script: "build" -[ERROR] Stack trace: - at ChildProcess.emit (node:events:513:28) - at Process.ChildProcess._handle.onexit (node:internal/child_process:291:12) - at ChildProcess.exithandler (node:child_process:422:5) -[ERROR] npm ERR! code ELIFECYCLE -[ERROR] npm ERR! errno 1 - -[INFO] --- Deploying: migration-job --- -[INFO] Building container image... -[INFO] Pushing to registry... -[INFO] migration-job deployed successfully. (18s)
- -
- ❌ Sequential deployment with full verbose build logs — overwhelming
- ❌ Raw stack trace shown to user — should be behind --debug flag
- ❌ No distinction between in-progress / done / failed states
- ❌ Services deployed sequentially, not shown as concurrent list
- ❌ Failed service doesn't affect others — no cancelled state
- ❌ "--- Deploying: api ---" separator — not a standard pattern -
- - - - -
[ERROR] Deployment partially failed. -[ERROR] 1 of 4 services failed to deploy. -[ERROR] Failed services: frontend -[ERROR] Check the logs at ~/.mycloud/logs/deploy-2025-03-24.log -[ERROR] Exit code: 1 - -[WARN] Some services were deployed successfully. -[WARN] You may need to redeploy the failed services. - -======================================== - DEPLOYMENT SUMMARY -======================================== - api : OK (52s) - worker : OK (41s) - frontend : FAILED (12s) - migration : OK (18s) -======================================== - Total time: 3m 42s -======================================== - -[INFO] Endpoints: -[INFO] api: https://api-myapp-prod.azurewebsites.net -[INFO] worker: (no endpoint) -[INFO] frontend: (deploy failed) - -Done.
- -
- ❌ Multiple redundant [ERROR] lines — one clear message is enough
- ❌ ASCII-art summary box — not azd style
- ❌ "OK" / "FAILED" status — should be (✓) Done / (✗) Failed
- ❌ No actionable guidance — what should the user do next?
- ❌ "Done." at the end is ambiguous — was it successful or not?
- ❌ Stack trace was shown inline instead of pointing to log file
- ❌ Warning after error creates confusion about actual state
- ❌ Endpoints listed with [INFO] prefix instead of clean format -
- -
- Summary of problems: This CLI mixes log-level prefixes ([INFO], [ERROR], [WARN]) with user-facing output, - uses inconsistent color coding, dumps verbose internal details, provides no structured progress states, - shows raw stack traces, uses decorative formatting (banners, ASCII boxes), and fails to give clear - actionable guidance when things go wrong. See after.html for the azd-styled version. -
- -
- -
before.html — Part of the azd Style Guide demo
- - - diff --git a/demo.html b/demo.html deleted file mode 100644 index e909ff6e80f..00000000000 --- a/demo.html +++ /dev/null @@ -1,489 +0,0 @@ - - - - - -azd Style Guide — Before / After Demo - - - - - - -
- - - - -
① Command Start & User Prompts
- - -
-
- Before -

Without style guide

-
- -
🚀 ★★★ Welcome to MyCloud CLI v3.2.1 ★★★ 🚀 -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -NOTICE: Telemetry is enabled. -NOTICE: New feature available! - -$ mycloud deploy --env production - -[INFO] Starting deployment... -[INFO] Reading mycloud.yaml -[INFO] Found 4 services -[INFO] Authenticating... done - -Enter resource group name: rg-myapp - -Select a region (type number): - 1) eastus 6) westeurope - 2) eastus2 7) southeastasia - 3) westus 8) japaneast - 4) westus2 9) australiaeast - 5) northeurope 10) brazilsouth -Type a number [1-10]: 2 - -Confirm deploy to production? [yes/no] yes
- -
- ❌ Decorative emoji banner - ❌ Notices dumped before command - ❌ [INFO] log-level prefixes - ❌ Plain text prompts — no ? prefix - ❌ All regions shown at once - ❌ "yes/no" not standard "(Y/n)" - ❌ No selected value highlighting -
-
- - -
-
- After -

With azd style guide

-
- -
PS C:\Users\user\myapp> mycloud deploy --env production - -Deploying to Azure (mycloud deploy) - -? Enter a resource group name: rg-myapp - -? Select an Azure location: - (US) East US (eastus) - > (US) East US 2 (eastus2) - (US) West US (westus) - (US) West US 2 (westus2) - (EU) North Europe (northeurope) - (EU) West Europe (westeurope) - (APAC) Southeast Asia (southeastasia) - ... - -? Select an Azure location: (US) East US 2 (eastus2) - -? Deploy to production? (Y/n): Yes
- -
- ✅ Clean bold header with (command name) - ✅ No banner, no notices, no [INFO] - ✅ ? prefix on all prompts - ✅ Scrollable list with > cursor, max 7 - ✅ Standard (Y/n) with default - ✅ Selections shown in cyan -
-
- - - - -
② Provisioning Progress
- - -
-
- Before -

Dot-based progress

-
- -
[INFO] Provisioning infrastructure... -[INFO] Creating resource group... -[INFO] Resource group created. -[INFO] Creating App Service Plan... -[INFO] .......... done (45s) -[INFO] Creating SQL Database... -[INFO] .. -[INFO] .... -[INFO] ........ -[INFO] .......... done (2m 12s) -[INFO] Creating Storage Account... -[INFO] .......... done (1m 33s) -[INFO] Creating Key Vault... -[INFO] .......... done (28s) - -[INFO] All resources created.
- -
- ❌ Growing dots on new lines — wall of text - ❌ No in-place animation - ❌ No ✓/✗ status indicators - ❌ Everything is green [INFO] - ❌ "done" is just text, no visual state -
-
- - -
-
- After -

Bar-fill spinner + states

-
- -
Provisioning Azure resources -Provisioning Azure resources can take some time. - - (✓) Done: Creating resource group: rg-myapp - (✓) Done: Creating App Service Plan: plan-myapp - (✓) Done: Creating SQL Database: sql-myapp - (✓) Done: Creating Storage Account: stmyapp - (✓) Done: Creating Key Vault: kv-myapp - Creating App Insights: appi-myapp - -
- -
- ✅ Bar-fill spinner animates in-place - ✅ (✓) Done: green for completed - ✅ Resource names for traceability - ✅ Clear visual hierarchy - ✅ No log-level prefixes -
-
- - - - -
③ Multi-Service Deployment & Failure Handling
- - -
-
- Before -

Sequential verbose output

-
- -
[INFO] Deploying services... - -[INFO] --- Deploying: api --- -[INFO] Building image... pushing... -[INFO] api deployed OK. (52s) - -[INFO] --- Deploying: worker --- -[INFO] Building image... pushing... -[INFO] worker deployed OK. (41s) - -[INFO] --- Deploying: frontend --- -[INFO] Building image... -[ERROR] npm ERR! Missing script: "build" -[ERROR] Stack trace: - at ChildProcess.emit (node:events:513) - at Process._handle.onexit (:291:12) -[ERROR] npm ERR! code ELIFECYCLE - -[INFO] --- Deploying: migration --- -[INFO] migration deployed OK. (18s)
- -
- ❌ Sequential — no concurrent view - ❌ Raw stack trace shown to user - ❌ No queued/cancelled states - ❌ Failed service doesn't affect others - ❌ "--- Deploying ---" separators - ❌ "OK" instead of structured state -
-
- - -
-
- After -

Braille spinners + all states

-
- -
Deploying services (4) - - Deploying: api (12s) - Deploying: worker (8s) - (•) Queued: frontend - (•) Queued: migration -
- -
Deploying services (4) - - (✓) Done: api (52s) - - Endpoint: https://api-myapp.azurewebsites.net - (✓) Done: worker (41s) - (✗) Failed: frontend (12s) - Missing "build" script in package.json. - Run npm run build locally, then mycloud deploy --service frontend - (!) Cancelled: migration – frontend failed
- -
- ✅ Braille spinners for concurrent list - ✅ (•) queued state for waiting items - ✅ (✗) Failed with concise error - ✅ (!) Cancelled with reason - ✅ No stack trace — log path instead - ✅ Actionable retry command -
-
- - - - -
④ Completion & Error Output
- - -
-
- Before -

ASCII box summary

-
- -
[ERROR] Deployment partially failed. -[ERROR] 1 of 4 services failed. -[ERROR] Failed: frontend -[ERROR] Check logs. -[ERROR] Exit code: 1 - -[WARN] Some services deployed OK. -[WARN] Redeploy failed services. - -════════════════════════════════════ - DEPLOYMENT SUMMARY -════════════════════════════════════ - api : OK (52s) - worker : OK (41s) - frontend : FAILED (12s) - migration : OK (18s) -════════════════════════════════════ - -Done.
- -
- ❌ Five redundant [ERROR] lines - ❌ [WARN] after [ERROR] — confusing - ❌ ASCII-art summary box - ❌ "OK" / "FAILED" — not structured - ❌ No actionable fix commands - ❌ "Done." — ambiguous outcome -
-
- - -
-
- After -

Clear ERROR + actionable fix

-
- -
ERROR: Unable to complete deployment, 1 service failed. -Run mycloud deploy --service frontend to retry. - -View detailed logs at: -~/.mycloud/logs/deploy/2025-03-24
- -
- -
— And when everything succeeds: — - -SUCCESS: Your app was deployed to Azure in 2 minutes 49 seconds. - -You can view resources in Azure Portal: -https://portal.azure.com/...rg-myapp - -Next steps: - Run mycloud monitor to view logs - Run mycloud down to delete resources
- -
- ✅ One ERROR: line — concise - ✅ Actionable retry command - ✅ Log path for debugging - ✅ SUCCESS: with duration - ✅ Portal link for resources - ✅ Next steps with commands -
-
- -
- -
demo.html — azd Style Guide before/after comparison | cli/azd/docs/style-guidelines/azd-style-guide.md
- - - diff --git a/test.html b/test.html deleted file mode 100644 index 8e40e38a08d..00000000000 --- a/test.html +++ /dev/null @@ -1,295 +0,0 @@ - - - - - -Qoder CLI – azd Style Redesign - - - - -
- -

Qoder CLI → azd Style Redesign

- - -✗ BEFORE — Original Qoder CLI - -
┌──────────────────────────────────────────────────────┐ - ✦ Welcome to Qoder CLI! - - cwd: /Users/leon/qoder -└──────────────────────────────────────────────────────┘ - -Tips for getting started: -1. Ask questions, edit files, or run commands. -2. Be specific for the best results. -3. Type /help for more information. - -> Build a cryptocurrency price tracking H5 app with Go that displays the real-time price of Bitcoin. - - task-executor (Create crypto tracker H5 app) - - ... +3 messages (ctrl+r to expand) - - Let me check the current directory to understand the project structure better. - - Bash (command: pwd && ls -la, background: false) - └ /Users/leon/qoder - total 0 - drwxr-xr-x@ 3 leon staff 96 10 13 20:48 . - drwxr-x---+ 99 leon staff 3168 10 13 19:14 .. - drwxr-xr-x@ 3 leon staff 96 10 13 20:48 .qoder - ... +2 lines (ctrl+r to expand) - - I see we're in an empty directory. Let me create the necessary files... - - Bash (command: go mod init crypto-tracker, background: false) - go: creating new go.mod: module crypto-tracker
- -
- Issues: Decorative box banner, green dot bullets (●), exposed bash commands & raw output, - freeform narrative text, no structured progress states, no clear completion message. -
- -
- - -✓ AFTER — azd Style - -
Qoder CLI -cwd: /Users/leon/qoder - -Tips for getting started: - 1. Ask questions, edit files, or run commands. - 2. Be specific for the best results. - 3. Type /help for more information. - -? What would you like to do: Build a cryptocurrency price tracking H5 app with Go - -Creating crypto tracker H5 app - - (✓) Done: Checked project structure - (✓) Done: Initialized Go module (crypto-tracker) - (✓) Done: Created main.go - (✓) Done: Created templates/index.html - (✓) Done: Installed dependencies (3 packages) - -SUCCESS: Crypto tracker H5 app created. - -Files created: - go.mod - main.go - templates/index.html - -Next steps: - Run go run main.go to start the app - Open http://localhost:8080 in your browser
- -
- - -

Live Animation: Progress States

- -

These show how the spinner animations look during execution:

- -

Bar-fill spinner (single operation)

-
Provisioning Azure resources -Provisioning Azure resources can take some time. - - (✓) Done: Creating App Service Plan: plan-r2w2adrz3rvwxu - (✓) Done: Creating Log Analytics workspace: log-r2w2adrz3rvwxu - Creating Application Insights: appi-r2w2adrz3rvwxu
- -

Braille spinner (multi-service deployment)

-
Deploying 4 services - - Deploying: api (12s) - Deploying: worker (8s) - (•) Queued: frontend - (•) Queued: database-migration
- -

Completed with mixed states

-
Deploying 4 services - - (✓) Done: api (32s) - - Endpoint: https://api-yo2mecxyj3dmw.azurewebsites.net/ - (✓) Done: worker (28s) - (✗) Failed: frontend (15s) - Missing build output directory. Run 'npm run build' before deploying. - (!) Cancelled: database-migration – frontend failed - -ERROR: Unable to complete deployment, 1 service failed. -Run azd deploy --service frontend to retry the failed service.
- -
- - -

azd Style Reference

- -
Status indicators: - (✓) Done: Operation completed successfully - (✗) Failed: Operation failed - (!) Warning: Non-blocking issue - (!) Cancelled: Cancelled due to sibling failure - (-) Skipped: Intentionally skipped - (•) Queued / waiting - -Spinners: - Bar-fill — single long-running operation - Braille — concurrent multi-item lists - -Prompt: - ? Interactive prompt: user input in cyan - -Completion: - SUCCESS: Positive outcome message - ERROR: Failure with actionable guidance
- -
- - - From ca3a73f56dc9e940719d40358b00021b39d0cc03 Mon Sep 17 00:00:00 2001 From: hyoshis Date: Fri, 27 Mar 2026 17:17:14 -0700 Subject: [PATCH 08/14] docs: add color to all style guide examples Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../docs/style-guidelines/azd-style-guide.md | 115 +++++++++--------- 1 file changed, 59 insertions(+), 56 deletions(-) diff --git a/cli/azd/docs/style-guidelines/azd-style-guide.md b/cli/azd/docs/style-guidelines/azd-style-guide.md index a6378fe439e..ba810bd30f7 100644 --- a/cli/azd/docs/style-guidelines/azd-style-guide.md +++ b/cli/azd/docs/style-guidelines/azd-style-guide.md @@ -80,27 +80,27 @@ Progress reports provide real-time feedback during a single command's execution, Items in a progress report list can be in one of six states: -1. **Loading**: `|=== | [Verb] Message goes here` +1. **Loading**: |=== | [Verb] Message goes here - Indicates operation in progress - Shows loading bar animation -2. **Done**: `(✓) Done: [Verb] Message goes here` +2. **Done**: (✓) Done: [Verb] Message goes here - Green checkmark indicates successful completion - Past tense verb -3. **Failed**: `(✗) Failed: [Verb] Message goes here` +3. **Failed**: (✗) Failed: [Verb] Message goes here - Red X indicates error - Include specific error message below -4. **Warning**: `(!) Warning: [Verb] Message goes here` +4. **Warning**: (!) Warning: [Verb] Message goes here - Yellow exclamation for non-blocking issues - Command continues but user should be aware -5. **Skipped**: `(-) Skipped: [Verb] Message goes here` +5. **Skipped**: (-) Skipped: [Verb] Message goes here - Gray dash indicates intentionally skipped step - Different from failed - this is expected behavior -6. **Cancelled**: `(!) Cancelled: [Verb] Message goes here – [reason]` +6. **Cancelled**: (!) Cancelled: [Verb] Message goes here – [reason] - Yellow exclamation indicates the operation was cancelled due to another failure - Includes the reason (typically which sibling operation failed) - Used in multi-service scenarios when a failure in one service causes others to be cancelled @@ -196,25 +196,28 @@ PREFIX: Message goes here. #### Log Types **Success logs** — Indicate the success of a specific command or action. Success logs use the green (or bright green) color variable (`WithSuccessFormat`). -``` -SUCCESS: Message goes here. -``` + +
+SUCCESS: Message goes here.
+
**Error logs** — Indicate when an error occurs, or indicate overall command failure. Error logs use the red (or bright red) color variable (`WithErrorFormat`). Error logs should attempt to follow a `[Reason] [Outcome]` structure when possible. -``` -ERROR: Message goes here. -``` + +
+ERROR: Message goes here.
+
**Warning logs** — Used when a command or action has an outcome that may provide unexpected results, or when the user needs to be made aware of something potentially destructive. Warning logs use the yellow (or bright yellow) color variable (`WithWarningFormat`). -``` -WARNING: Message goes here. -``` + +
+WARNING: Message goes here.
+
**Next steps logs** — The arrow indicates the next step. Used when the command output includes follow-up actions or recommended next steps for the user. Next steps logs use the format `(->) NEXT STEPS:` followed by the message. -``` +
 (->) NEXT STEPS: Message goes here.
-```
+
#### Hint Text @@ -228,25 +231,25 @@ Hint copy can directly follow any Success, Error, or Warning log. Hint text shou **Success example:** -``` -SUCCESS: Your Azure app has been deployed! +
+SUCCESS: Your Azure app has been deployed!
 You can view the resources created under the resource group case-code-test-rg in Azure Portal:
-https://portal.azure.com/#@/resource/subscriptions/.../resourceGroups/case-code-test-rg
-```
+https://portal.azure.com/#@/resource/subscriptions/.../resourceGroups/case-code-test-rg
+
**Error example:** -``` -ERROR: 'todo-mongojs' is misspelled or missing a recognized flag. -Run azd up --help to see all available flags. -``` +
+ERROR: 'todo-mongojs' is misspelled or missing a recognized flag.
+Run azd up --help to see all available flags.
+
**Warning example:** -``` -WARNING: You have already provisioned Azure resources to the (US) West US (westus) region. -You may want to run azd down to delete your existing resources before provisioning to a new region. -``` +
+WARNING: You have already provisioned Azure resources to the (US) West US (westus) region.
+You may want to run azd down to delete your existing resources before provisioning to a new region.
+
### User Inputs @@ -268,26 +271,26 @@ Text input captures a single line of input from the user. The prompt is displayed with a `[Type ? for hint]` helper in hi-blue bold text (via `WithHighLightFormat`), followed by ghost-text (secondary text color) as placeholder content. -``` -? This captures a single line of input: [Type ? for hint] This is ghost-text -``` +
+? This captures a single line of input: [Type ? for hint] This is ghost-text
+
**Hint feature:** If the user types `?`, a hint line appears below the prompt to provide additional guidance. The hint label is displayed in magenta. -``` -? This captures a single line of input: [Type ? for hint] This is ghost-text -Hint: This is a help message -``` +
+? This captures a single line of input: [Type ? for hint] This is ghost-text
+Hint: This is a help message
+
**User input (before submitting):** As the user types, their input replaces the ghost-text and appears in primary text color. -``` -? This captures a single line of input: [Type ? for hint] Input -``` +
+? This captures a single line of input: [Type ? for hint] Input
+
**After submitting:** @@ -297,9 +300,9 @@ Once the user submits their answer: - The `[Type ? for hint]` helper disappears - If the hint line was visible, it also disappears -``` -? This captures a single line of input: Input -``` +
+? This captures a single line of input: Input
+
#### Yes or No Input @@ -307,15 +310,15 @@ Once the user submits their answer: - Users can either input `y`/`n` or hit the return key which will select the capitalized choice in the `(Y/n)` delineator. - Once a user has selected y or n, the result should be printed in blue text (**yes** or **no**). -``` -? Do you want to initialize a new Git repository in this directory? (Y/n): -``` +
+? Do you want to initialize a new Git repository in this directory? (Y/n):
+
With input provided: -``` -? Do you want to initialize a new Git repository in this directory? (Y/n): Yes -``` +
+? Do you want to initialize a new Git repository in this directory? (Y/n): Yes
+
#### List Select @@ -325,17 +328,17 @@ The list select pattern presents a list of options for the user to choose from. The prompt is displayed with a `Filter:` line showing ghost-text ("Type to filter list") and a footer hint ("Use arrows to move, type ? for hint"). The active selection is indicated by `>` and displayed in bold blue text. -``` -? Select an single option: [Use arrows to move, type to filter] +
+? Select an single option:  [Use arrows to move, type to filter]
 
-  > Option 1
+  > Option 1
     Option 2
     Option 3
     Option 4
     Option 5
     Option 6
     ...
-```
+
**Display rules:** @@ -346,7 +349,7 @@ The prompt is displayed with a `Filter:` line showing ghost-text ("Type to filte **Hint:** -- The `[Type ? for hint]` pattern follows the same behavior as Text Input — hi-magenta in bold, with ghost-text in secondary text color. +- The `[Type ? for hint]` pattern follows the same behavior as Text Input — hi-blue in bold (via `WithHighLightFormat`), with ghost-text in secondary text color. **After submitting:** @@ -357,9 +360,9 @@ Once the user makes their selection: - If the hint line was visible, it also disappears - The list collapses and the selected value is printed in blue text next to the prompt -``` -? Select an Azure location to use: (US) East US 2 (eastus2) -``` +
+? Select an Azure location to use: (US) East US 2 (eastus2)
+
### Command Output Standards From 59a5e9b8877a2afefff15e7b860b1f174ef75ace Mon Sep 17 00:00:00 2001 From: hyoshis Date: Tue, 31 Mar 2026 18:12:25 -0700 Subject: [PATCH 09/14] Refine CLI style guide and AGENTS.md style reference - Expand AGENTS.md CLI UX & Style section with detailed pointers to the style guide and list of covered patterns - Add scope note clarifying guide covers core azd flows only - Streamline azd-style-guide.md: remove cancelled state, simplify progress report examples, and tighten formatting Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- cli/azd/AGENTS.md | 13 +- .../docs/style-guidelines/azd-style-guide.md | 266 ++---------------- 2 files changed, 33 insertions(+), 246 deletions(-) diff --git a/cli/azd/AGENTS.md b/cli/azd/AGENTS.md index b1c3bd8074a..c64e71c564a 100644 --- a/cli/azd/AGENTS.md +++ b/cli/azd/AGENTS.md @@ -159,7 +159,18 @@ func (a *myAction) Run(ctx context.Context) (*actions.ActionResult, error) { ### CLI UX & Style -When designing CLI output, terminal UX, spinners, progress states, or colors, follow the guidelines in `docs/style-guidelines/azd-style-guide.md`. +When working on CLI output, terminal UX, spinners, progress states, colors, or prompts for **core azd flows**, you **MUST read** the style guide before making any changes or recommendations: + +📄 **`cli/azd/docs/style-guidelines/azd-style-guide.md`** (full path from repo root) + +This file is the authoritative reference for core azd terminal UX patterns including: +- Progress report states (`(✓) Done`, `(✗) Failed`, `(!) Warning`, `(-) Skipped`) +- Spinner type (bar-fill `|=======|`) +- Color conventions (`WithSuccessFormat`, `WithErrorFormat`, `WithHighLightFormat`, etc.) +- User input patterns (text input, list select, yes/no confirm) +- Prompt styling (`?` marker in bold blue, `[Type ? for hint]`, post-submit states) + +> **Note**: This style guide covers **core azd flows only**. Separate guidelines for agentic flows and extension-specific UX will be provided in dedicated files in the future. Do not apply core azd patterns to agentic or extension flows without a dedicated style reference. ### Code Organization diff --git a/cli/azd/docs/style-guidelines/azd-style-guide.md b/cli/azd/docs/style-guidelines/azd-style-guide.md index ba810bd30f7..4a4909b6b1e 100644 --- a/cli/azd/docs/style-guidelines/azd-style-guide.md +++ b/cli/azd/docs/style-guidelines/azd-style-guide.md @@ -4,6 +4,8 @@ This style guide establishes standards for code, user experience, testing, and documentation across the Azure Developer CLI project. Following these guidelines ensures consistency, maintainability, and a high-quality user experience. +> **Scope**: This guide covers **core azd flows** only. Separate guidelines for agentic flows and extension-specific UX will be provided in dedicated files in the future. + ## Code Style Guidelines ### Go Conventions @@ -100,15 +102,9 @@ Items in a progress report list can be in one of six states: - Gray dash indicates intentionally skipped step - Different from failed - this is expected behavior -6. **Cancelled**: (!) Cancelled: [Verb] Message goes here – [reason] - - Yellow exclamation indicates the operation was cancelled due to another failure - - Includes the reason (typically which sibling operation failed) - - Used in multi-service scenarios when a failure in one service causes others to be cancelled - #### Progress Report Guidelines - **Indentation**: Progress items are always indented under the main command -- **Hierarchy**: Sub-steps appear indented under parent steps - **Verb consistency**: Use present progressive for loading, past tense for completed - **Contextual information**: Include resource names, identifiers when relevant @@ -134,9 +130,7 @@ Provisioning Azure resources can take some time. (✓) Done: Creating App Service Plan: plan-r2w2adrz3rvwxu (✓) Done: Creating Log Analytics workspace: log-r2w2adrz3rvwxu (✗) Failed: Creating Cosmos DB: cosmos-r2w2adrz3rvwxu - - The '{US} West US 2 (westus)' region is currently experiencing high demand - and cannot fulfill your request. Failed to create Cosmos DB account. + The '{US} West US 2 (westus)' region is currently experiencing high demand and cannot fulfill your request. Failed to create Cosmos DB account. ERROR: Unable to complete provisioning of Azure resources, 'azd up' failed @@ -144,37 +138,11 @@ Provisioning Azure resources can take some time. **Skipped scenario:**
-Note: Steps were skipped because _____ (directory, or specified service name)
-If you want to deploy all services, you can run azd deploy --all or
-move to root directory.
-
   (✓) Done: [Verb] Message goes here
   (✓) Done: [Verb] Message goes here
   (-) Skipped: [Verb] Message goes here
 
-**Cancelled scenario (multi-service deployment with failure):** - -
-Deploying services (6)
-
-  (!) Cancelled: postgres (59s) – catalogservice failed
-  (!) Cancelled: basketcache (45s) – catalogservice failed
-  (✓) Done: basketservice (25s)
-  - Endpoint: https://basketservice-yo2mecxyj3dmw.azurewebsites.net/
-  (✓) Done: catalogdbmanager (58s)
-  (✗) Failed:  catalogservice (51s)
-  Required Azure Developer CLI dependencies are missing:
-  - git CLI version ≥ 2.0.0 (current: 1.9.0), see https://git-scm.com/downloads to install.
-  Log:  /path/to/.azure/logs/deploy/deploy-catalogservice.log
-  (✓) Done: frontend (27s)
-
-ERROR: Unable to complete deployment, 'azd concurx up' failed.
-To complete the operation, install the required dependencies and try again.
-
- -When one service fails in a concurrent deployment, sibling services that cannot continue are **cancelled** (not failed). The cancelled message includes the reason (e.g., `– catalogservice failed`) so the user knows which service caused the cancellation. - ### Success / Error / Warning Logs These logs represent the final outcome of a command, displayed after execution completes. Standard logs (Success, Error, Warning) use an **all-caps prefix** followed by a colon to separate the log type from the message. @@ -219,14 +187,6 @@ PREFIX: Message goes here. (->) NEXT STEPS: Message goes here. -#### Hint Text - -Hint copy can directly follow any Success, Error, or Warning log. Hint text should: - -- Provide more context to the log above -- In some cases, provide an actionable path forward (see: Actionable Hints) -- Use the white color variable (`WithHintFormat`) - #### In-Context Examples **Success example:** @@ -241,14 +201,14 @@ You can view the resources created under the resource group case-code-test-rg in
 ERROR: 'todo-mongojs' is misspelled or missing a recognized flag.
-Run azd up --help to see all available flags.
+Run azd up --help to see all available flags.
 
**Warning example:**
 WARNING: You have already provisioned Azure resources to the (US) West US (westus) region.
-You may want to run azd down to delete your existing resources before provisioning to a new region.
+You may want to run azd down to delete your existing resources before provisioning to a new region.
 
### User Inputs @@ -269,55 +229,28 @@ Text input captures a single line of input from the user. **Initial state:** -The prompt is displayed with a `[Type ? for hint]` helper in hi-blue bold text (via `WithHighLightFormat`), followed by ghost-text (secondary text color) as placeholder content. +The prompt is displayed with a `[Type ? for hint]` helper in **hi-blue bold text** via `WithHighLightFormat` (Bright Blue, ANSI 94), followed by ghost-text (secondary text color) as placeholder content.
-? This captures a single line of input: [Type ? for hint] This is ghost-text
+? This captures a single line of input: [Type ? for hint]
 
**Hint feature:** -If the user types `?`, a hint line appears below the prompt to provide additional guidance. The hint label is displayed in magenta. - -
-? This captures a single line of input: [Type ? for hint] This is ghost-text
-Hint: This is a help message
-
- -**User input (before submitting):** - -As the user types, their input replaces the ghost-text and appears in primary text color. - -
-? This captures a single line of input: [Type ? for hint] Input
-
- -**After submitting:** - -Once the user submits their answer: - -- The input changes from primary text to hi-blue text -- The `[Type ? for hint]` helper disappears -- If the hint line was visible, it also disappears +If the user types `?`, a hint line appears below the prompt to provide additional guidance.
-? This captures a single line of input: Input
+? This captures a single line of input: [Type ? for hint]
+Hint: This is a help message
 
#### Yes or No Input - Yes/no inputs include a `(Y/n)` delineator at the end of the input request (before the colon). - Users can either input `y`/`n` or hit the return key which will select the capitalized choice in the `(Y/n)` delineator. -- Once a user has selected y or n, the result should be printed in blue text (**yes** or **no**).
-? Do you want to initialize a new Git repository in this directory? (Y/n):
-
- -With input provided: - -
-? Do you want to initialize a new Git repository in this directory? (Y/n): Yes
+? Do you want to initialize a new Git repository in this directory? (Y/n):
 
#### List Select @@ -326,12 +259,12 @@ The list select pattern presents a list of options for the user to choose from. **Initial state:** -The prompt is displayed with a `Filter:` line showing ghost-text ("Type to filter list") and a footer hint ("Use arrows to move, type ? for hint"). The active selection is indicated by `>` and displayed in bold blue text. +The prompt is displayed with a `Filter:` line showing ghost-text ("Type to filter list") and a footer hint in **hi-blue text** via `WithHighLightFormat` (Bright Blue, ANSI 94). The active selection is indicated by `>` and displayed in bold blue text.
-? Select an single option:  [Use arrows to move, type to filter]
+? Select a single option:  [Use arrows to move, type to filter]
 
-  > Option 1
+  > Option 1
     Option 2
     Option 3
     Option 4
@@ -349,7 +282,7 @@ The prompt is displayed with a `Filter:` line showing ghost-text ("Type to filte
 
 **Hint:**
 
-- The `[Type ? for hint]` pattern follows the same behavior as Text Input — hi-blue in bold (via `WithHighLightFormat`), with ghost-text in secondary text color.
+- The `[Type ? for hint]` pattern follows the same behavior as Text Input — **hi-blue bold** via `WithHighLightFormat` (Bright Blue, ANSI 94).
 
 **After submitting:**
 
@@ -361,24 +294,15 @@ Once the user makes their selection:
 - The list collapses and the selected value is printed in blue text next to the prompt
 
 
-? Select an Azure location to use: (US) East US 2 (eastus2)
+? Select an Azure location to use: (US) East US 2 (eastus2)
 
-### Command Output Standards - -- **Structured output**: Support `--output json` for machine-readable output -- **Progress indicators**: Use spinners and progress bars for long operations -- **Colorization**: Use consistent colors (green=success, red=error, yellow=warning) -- **URLs**: Always include relevant portal/console URLs for created resources - ### CLI Color Standards The CLI uses consistent color formatting through helper functions defined in [`cli/azd/pkg/output/colors.go`](../../pkg/output/colors.go). **Always use these helper functions** instead of writing raw ANSI escape codes. **Important**: Colors will appear differently depending on which terminal and theme (dark/light) the customer prefers. Always test output in both dark and light terminal themes. -**Magenta for agentic experiences**: Agentic flows use magenta as their primary accent color (see [Agentic Flow UX](#agentic-flow-ux) below). Use `color.MagentaString()` for tool names, agent labels, status messages, and spinner characters in agent mode. Use `color.HiMagentaString()` for the agent badge (`🤖 [azd] Agent`), subagent names, and next-steps headers. - #### Standard Color Helper Functions Use these functions for consistent color formatting across the CLI: @@ -491,163 +415,15 @@ The full animation cycle frames are: These frames repeat continuously on the **same line** until the operation completes. The spinner bar is displayed in **hint-colored** text (gray) to keep focus on the status message. -#### When to Use: Bar Spinner vs. Braille Spinner - -The **bar-fill spinner** (`|=======|`) is designed for **single-operation progress** — one task happening at a time on one line. When **multiple concurrent operations** are displayed as a list (e.g., deploying several services simultaneously), use the **braille spinner** instead. The bar spinner would be visually overwhelming when repeated across many lines. - -The braille spinner animates in place with dot patterns that fill in clockwise, then drain away: - -``` -⠁ → ⠃ → ⠇ → ⡇ → ⡏ → ⡟ → ⡿ → ⣿ → ⣾ → ⣴ → ⣠ → ⣀ → ...repeats -``` - -**Multi-service deployment example:** - -``` -Deploying 6 services - - ⠙ Deploying: postgres (5s) - ⠙ Deploying: basketcache (5s) - (•) Queued: basketservice - (•) Queued: catalogdbmanager - ⠙ Deploying: catalogservice (5s) - (•) Queued: frontend -``` - -| Scenario | Spinner Type | Reason | -| --- | --- | --- | -| Single long-running operation (provisioning, creating a resource) | **Bar-fill** (`\|=== \|`) | Clear progress indicator for one task | -| Multiple concurrent operations shown as a list | **Braille** (`⠋⠙⠹...`) | Compact — doesn't clutter multi-line lists | -| Queued / waiting items in a list | **Static dot** `(•)` | No animation needed — item hasn't started | - -#### Character Sets - -There are three spinner variants based on terminal capability: - -| Variant | Characters | When Used | -| --- | --- | --- | -| **Bar-fill** | `\|=======\|` (bouncing fill bar) | Single-operation progress in interactive terminal | -| **Braille** | `⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏` | Multi-item concurrent progress lists | -| **Short** | `.`, `..`, `...` | Non-interactive or limited terminals | -| **No Terminal** | *(empty)* | No terminal attached (e.g., piped output) | - -#### Guidelines - -- **Use the bar-fill spinner** for single in-progress operations (resource creation, provisioning) -- **Use the braille spinner** when showing a list of multiple concurrent operations -- **Use `(•)` static indicator** for queued items that haven't started yet -- **Keep status messages concise** — use the format `"ing : "` - -### Agentic Flow UX +#### Implementation -Any command or flow that involves **AI-driven or agentic operations** — such as `azd init` → "Use agent mode", `azd ai agent` commands, or future agentic features — should follow the UX patterns in this section. These patterns visually differentiate AI-driven operations from standard CLI output and should be applied consistently across all agentic experiences. +Use `console.ShowSpinner()` and `console.StopSpinner()` from [`pkg/input/console.go`](../../pkg/input/console.go) to display the bar-fill spinner. These are the standard functions used across all azd commands. -#### When Agentic Flow Applies - -| Entry Point | Description | -| --- | --- | -| `azd init` → "Use agent mode" | Initializes a project using Copilot agent | -| `azd ai agent *` commands | All agent subcommands follow agentic UX | - -#### Agentic Spinner - -The agentic spinner uses the **same default character set** as the standard spinner (`|`, `/`, `-`, `\`) rendered in **magenta** via `WithHintFormat()`, cycling at 250ms intervals. This is different from the bar-fill spinner (`|=======|`) used for standard provisioning/deployment progress. - -**Animation frames:** - -``` -| → / → - → \ → (repeats) +```go +// Start or update spinner +console.ShowSpinner(ctx, "Creating App Service: my-app-r2w2adrz3rvwxu", input.Step) ``` -The spinner characters appear in **magenta** while the accompanying text describes the current operation: - -
-/ Thinking...
-
- -
-- Running powershell azd env list... (5s)
-
- -| Scenario | Spinner Type | Reason | -| --- | --- | --- | -| Standard single operation (provisioning, creating a resource) | **Bar-fill** (`\|=== \|`) | Clear progress for deterministic operations | -| Agentic flow (agent thinking, tool execution) | **Character rotation** (`\| / - \`) | Lightweight indicator for non-deterministic AI operations | -| Multiple concurrent operations in a list | **Braille** (`⠋⠙⠹...`) | Compact for multi-line lists | - -#### Agentic Display Layers - -The agentic display uses a canvas with multiple visual layers rendered together: - -1. **Reasoning display** — Shows the last ~5 lines of the agent's reasoning in **gray** text above the spinner -2. **Spinner** — The rotating `| / - \` character in **magenta** with a status message -3. **Sub-detail lines** — Optional tree-structured lines below the spinner showing command arguments or file paths, using ASCII connectors (`├`, `└`) -4. **Cancel hint** — A `Press Ctrl+C to cancel` message at the bottom - -**Example — agent thinking:** - -
-/ Thinking...
-
- -**Example — tool execution with elapsed time:** - -
-\ Running powershell npm install... (12s)
-
- -**Example — tool completion:** - -
-✔︎ Ran powershell npm install
-
- -**Example — tool failure:** - -
- powershell npm install
-  └ Error: ENOENT: no such file or directory
-
- -#### Agentic Hint Text - -The hint mechanism (`?` key) works the same way in agentic flow as in standard flow — pressing `?` reveals help text, pressing `Escape` dismisses it. In both cases, the hint label and message are rendered in **magenta** via `WithHintFormat()`: - -
-? Enter your environment name: [Type ? for hint] my-env
-Hint: The environment name is used to create a resource group and identify resources in Azure.
-
- -#### Agentic Status Messages - -Key status messages in agentic flow use magenta to reinforce the agentic context: - -
-Preparing application for Azure deployment...
-
- -
-(->) Next steps: Run azd up to provision and deploy your application.
-
- -#### Color Summary for Agentic Flow - -| Element | Color | Function | -| --- | --- | --- | -| Spinner character (`\| / - \`) | Magenta | `WithHintFormat()` | -| Tool names in spinner text | Magenta | `color.MagentaString()` | -| Hint label and text | Magenta | `WithHintFormat()` | -| Status messages (e.g., "Preparing...") | Magenta | `color.MagentaString()` | -| Next-steps header | Hi-Magenta | `color.HiMagentaString()` | -| Reasoning text | Gray | `color.HiBlackString()` | -| Elapsed time / secondary info | Gray | `color.HiBlackString()` | -| Tool success checkmark | Green | `color.GreenString()` | -| Tool failure X | Red | `color.RedString()` | - -#### Implementation Reference - -The agentic display is implemented in [`internal/agent/display.go`](../../internal/agent/display.go) via the `AgentDisplay` struct, which subscribes to Copilot SDK session events and manages a multi-layer canvas for rendering. - ## Testing Standards ### Test Structure From 8ed061b92b08f085e2d60b86647cde853f579a6e Mon Sep 17 00:00:00 2001 From: Hiyo Shin Date: Wed, 1 Apr 2026 13:19:31 -0700 Subject: [PATCH 10/14] Update cli/azd/AGENTS.md Co-authored-by: Jon Gallant <2163001+jongio@users.noreply.github.com> --- cli/azd/AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/azd/AGENTS.md b/cli/azd/AGENTS.md index 7984353e166..0807174d8d0 100644 --- a/cli/azd/AGENTS.md +++ b/cli/azd/AGENTS.md @@ -164,7 +164,7 @@ When working on CLI output, terminal UX, spinners, progress states, colors, or p 📄 **`cli/azd/docs/style-guidelines/azd-style-guide.md`** (full path from repo root) This file is the authoritative reference for core azd terminal UX patterns including: -- Progress report states (`(✓) Done`, `(✗) Failed`, `(!) Warning`, `(-) Skipped`) +- Progress report states (`(✓) Done`, `(x) Failed`, `(!) Warning`, `(-) Skipped`) - Spinner type (bar-fill `|=======|`) - Color conventions (`WithSuccessFormat`, `WithErrorFormat`, `WithHighLightFormat`, etc.) - User input patterns (text input, list select, yes/no confirm) From 2055a167ad810f8ff690d6a9fc999143e29460dd Mon Sep 17 00:00:00 2001 From: Hiyo Shin Date: Wed, 1 Apr 2026 13:21:04 -0700 Subject: [PATCH 11/14] Update cli/azd/docs/style-guidelines/azd-style-guide.md Co-authored-by: Jon Gallant <2163001+jongio@users.noreply.github.com> --- cli/azd/docs/style-guidelines/azd-style-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/azd/docs/style-guidelines/azd-style-guide.md b/cli/azd/docs/style-guidelines/azd-style-guide.md index 4a4909b6b1e..78ba5bd1a53 100644 --- a/cli/azd/docs/style-guidelines/azd-style-guide.md +++ b/cli/azd/docs/style-guidelines/azd-style-guide.md @@ -80,7 +80,7 @@ Progress reports provide real-time feedback during a single command's execution, #### Progress Report States -Items in a progress report list can be in one of six states: +Items in a progress report list can be in one of five states: 1. **Loading**: |=== | [Verb] Message goes here - Indicates operation in progress From e9a4064114e47053ad9271dc93f51f4631e37ae5 Mon Sep 17 00:00:00 2001 From: hyoshis Date: Wed, 1 Apr 2026 13:57:22 -0700 Subject: [PATCH 12/14] docs: improve style guide for AI readability and GH-markdown rendering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace all
/ HTML blocks with fenced code blocks
  (GitHub-flavored Markdown strips inline styles)
- Fix (✗) to (x) for Failed prefix to match codebase (console.go, uxitem.go)
- Fix spinner color description: 'hint-colored' to 'gray via WithGrayFormat'
- Add quick-reference lookup tables for states and log types
- Add 'When to Use Each Log Type' guidance (SUCCESS vs ERROR vs WARNING)
- Add Common Mistakes DO/DON'T table
- Move color annotations from inline to blockquotes below code blocks
- Trim redundant examples (keep failure scenario + error in-context example)
- Remove Next Steps log references

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
 .../docs/style-guidelines/azd-style-guide.md  | 209 +++++++++---------
 1 file changed, 107 insertions(+), 102 deletions(-)

diff --git a/cli/azd/docs/style-guidelines/azd-style-guide.md b/cli/azd/docs/style-guidelines/azd-style-guide.md
index 78ba5bd1a53..3789fb9ee84 100644
--- a/cli/azd/docs/style-guidelines/azd-style-guide.md
+++ b/cli/azd/docs/style-guidelines/azd-style-guide.md
@@ -82,66 +82,64 @@ Progress reports provide real-time feedback during a single command's execution,
 
 Items in a progress report list can be in one of five states:
 
-1. **Loading**: |===    | [Verb] Message goes here
-   - Indicates operation in progress
-   - Shows loading bar animation
+1. **Loading**: `|===    | [Verb] Message goes here`
+   - Indicates operation in progress; animated bar-fill spinner in gray (`WithGrayFormat`)
 
-2. **Done**: (✓) Done: [Verb] Message goes here
-   - Green checkmark indicates successful completion
-   - Past tense verb
+2. **Done**: `(✓) Done: [Verb] Message goes here`
+   - Green checkmark via `WithSuccessFormat`; use past tense verb
 
-3. **Failed**: (✗) Failed: [Verb] Message goes here
-   - Red X indicates error
-   - Include specific error message below
+3. **Failed**: `(x) Failed: [Verb] Message goes here`
+   - Red `x` via `WithErrorFormat`; include specific error message below
 
-4. **Warning**: (!) Warning: [Verb] Message goes here
-   - Yellow exclamation for non-blocking issues
-   - Command continues but user should be aware
+4. **Warning**: `(!) Warning: [Verb] Message goes here`
+   - Yellow exclamation via `WithWarningFormat`; non-blocking, command continues
 
-5. **Skipped**: (-) Skipped: [Verb] Message goes here
-   - Gray dash indicates intentionally skipped step
-   - Different from failed - this is expected behavior
+5. **Skipped**: `(-) Skipped: [Verb] Message goes here`
+   - Gray dash via `WithGrayFormat`; intentionally skipped (not a failure)
 
-#### Progress Report Guidelines
+#### Quick Reference
 
-- **Indentation**: Progress items are always indented under the main command
-- **Verb consistency**: Use present progressive for loading, past tense for completed
-- **Contextual information**: Include resource names, identifiers when relevant
+**Progress report state → prefix → color function:**
 
-#### Examples
+| State    | Prefix         | Color Function      | Notes                     |
+| -------- | -------------- | ------------------- | ------------------------- |
+| Loading  | `\|===    \|`  | `WithGrayFormat`    | Animated bar-fill spinner |
+| Done     | `(✓) Done:`    | `WithSuccessFormat` | Past tense verb           |
+| Failed   | `(x) Failed:`  | `WithErrorFormat`   | Follow with error detail  |
+| Warning  | `(!) Warning:` | `WithWarningFormat` | Non-blocking issue        |
+| Skipped  | `(-) Skipped:` | `WithGrayFormat`    | Expected, not a failure   |
+
+**Log type → prefix → color function:**
 
-**Success scenario:**
+| Log Type   | Prefix            | Color Function      | When to use                                |
+| ---------- | ----------------- | ------------------- | ------------------------------------------ |
+| Success    | `SUCCESS:`        | `WithSuccessFormat` | Command completed its primary goal         |
+| Error      | `ERROR:`          | `WithErrorFormat`   | Command failed; top-level failure message  |
+| Warning    | `WARNING:`        | `WithWarningFormat` | Non-fatal issue the user should know about |
 
-
-Provisioning Azure resources (azd provision)
-Provisioning Azure resources can take some time.
+#### Progress Report Guidelines
 
-  (✓) Done: Creating App Service Plan: plan-r2w2adrz3rvwxu
-  (✓) Done: Creating Log Analytics workspace: log-r2w2adrz3rvwxu
-  (✓) Done: Creating Application Insights: appi-r2w2adrz3rvwxu
-  (✓) Done: Creating App Service: app-api-r2w2adrz3rvwxu
-
+- **Indentation**: Progress items are always indented under the main command +- **Verb consistency**: Use present progressive for loading, past tense for completed +- **Contextual information**: Include resource names, identifiers when relevant -**Failure scenario:** +#### Example -
-Provisioning Azure resources (azd provision)
+**Failure scenario** (shows how multiple states compose with error detail):
 
-  (✓) Done: Creating App Service Plan: plan-r2w2adrz3rvwxu
-  (✓) Done: Creating Log Analytics workspace: log-r2w2adrz3rvwxu
-  (✗) Failed: Creating Cosmos DB: cosmos-r2w2adrz3rvwxu
-  The '{US} West US 2 (westus)' region is currently experiencing high demand and cannot fulfill your request. Failed to create Cosmos DB account.
+```
+Provisioning Azure resources (azd provision)
 
-ERROR: Unable to complete provisioning of Azure resources, 'azd up' failed
-
+ (✓) Done: Creating App Service Plan: plan-r2w2adrz3rvwxu + (✓) Done: Creating Log Analytics workspace: log-r2w2adrz3rvwxu + (x) Failed: Creating Cosmos DB: cosmos-r2w2adrz3rvwxu + The '{US} West US 2 (westus)' region is currently experiencing high demand + and cannot fulfill your request. Failed to create Cosmos DB account. -**Skipped scenario:** +ERROR: Unable to complete provisioning of Azure resources, 'azd up' failed +``` -
-  (✓) Done: [Verb] Message goes here
-  (✓) Done: [Verb] Message goes here
-  (-) Skipped: [Verb] Message goes here
-
+> Colors: Title → `WithBold`. `(✓) Done:` → `WithSuccessFormat`. `(x) Failed:` and error detail → `WithErrorFormat`. `ERROR:` line → `WithErrorFormat`. ### Success / Error / Warning Logs @@ -155,6 +153,12 @@ All logs should: There are some specific edge cases where the log prefix is not required. +#### When to Use Each Log Type + +- **SUCCESS**: The command achieved its primary goal. Use after deployments, provisioning, or any command that completes a user-requested action. +- **ERROR**: The command failed and cannot continue. Always include the reason and, when possible, a suggested fix. Only use for top-level command failures, not internal retries. +- **WARNING**: The command succeeded (or will proceed), but something unexpected happened that the user should know about. Examples: deprecated flags, region capacity concerns, overwriting existing resources. + #### Log Format ``` @@ -163,53 +167,34 @@ PREFIX: Message goes here. #### Log Types -**Success logs** — Indicate the success of a specific command or action. Success logs use the green (or bright green) color variable (`WithSuccessFormat`). - -
-SUCCESS: Message goes here.
-
- -**Error logs** — Indicate when an error occurs, or indicate overall command failure. Error logs use the red (or bright red) color variable (`WithErrorFormat`). Error logs should attempt to follow a `[Reason] [Outcome]` structure when possible. - -
-ERROR: Message goes here.
-
- -**Warning logs** — Used when a command or action has an outcome that may provide unexpected results, or when the user needs to be made aware of something potentially destructive. Warning logs use the yellow (or bright yellow) color variable (`WithWarningFormat`). +**Success logs** — Use `WithSuccessFormat` (green/bright green). -
-WARNING: Message goes here.
-
- -**Next steps logs** — The arrow indicates the next step. Used when the command output includes follow-up actions or recommended next steps for the user. Next steps logs use the format `(->) NEXT STEPS:` followed by the message. +``` +SUCCESS: Message goes here. +``` -
-(->) NEXT STEPS: Message goes here.
-
+**Error logs** — Use `WithErrorFormat` (red/bright red). Follow a `[Reason] [Outcome]` structure when possible. -#### In-Context Examples +``` +ERROR: Message goes here. +``` -**Success example:** +**Warning logs** — Use `WithWarningFormat` (yellow/bright yellow). -
-SUCCESS: Your Azure app has been deployed!
-You can view the resources created under the resource group case-code-test-rg in Azure Portal:
-https://portal.azure.com/#@/resource/subscriptions/.../resourceGroups/case-code-test-rg
-
+``` +WARNING: Message goes here. +``` -**Error example:** +#### In-Context Example -
-ERROR: 'todo-mongojs' is misspelled or missing a recognized flag.
-Run azd up --help to see all available flags.
-
+**Error with suggested command** (shows multi-line composition with inline highlights): -**Warning example:** +``` +ERROR: 'todo-mongojs' is misspelled or missing a recognized flag. +Run azd up --help to see all available flags. +``` -
-WARNING: You have already provisioned Azure resources to the (US) West US (westus) region.
-You may want to run azd down to delete your existing resources before provisioning to a new region.
-
+> Colors: `ERROR:` line → `WithErrorFormat`. `azd up --help` → `WithHighLightFormat`. ### User Inputs @@ -231,27 +216,33 @@ Text input captures a single line of input from the user. The prompt is displayed with a `[Type ? for hint]` helper in **hi-blue bold text** via `WithHighLightFormat` (Bright Blue, ANSI 94), followed by ghost-text (secondary text color) as placeholder content. -
-? This captures a single line of input: [Type ? for hint]
-
+``` +? This captures a single line of input: [Type ? for hint] +``` + +> Colors: `?` → `WithHighLightFormat` + `WithBold`. `[Type ? for hint]` → `WithHighLightFormat` + `WithBold`. **Hint feature:** -If the user types `?`, a hint line appears below the prompt to provide additional guidance. +If the user types `?`, a hint line appears below the prompt to provide additional guidance. -
-? This captures a single line of input: [Type ? for hint]
-Hint: This is a help message
-
+``` +? This captures a single line of input: [Type ? for hint] +Hint: This is a help message +``` + +> Colors: `?` and `[Type ? for hint]` → `WithHighLightFormat` + `WithBold`. Hint line → `WithHintFormat` + `WithBold`. #### Yes or No Input - Yes/no inputs include a `(Y/n)` delineator at the end of the input request (before the colon). - Users can either input `y`/`n` or hit the return key which will select the capitalized choice in the `(Y/n)` delineator. -
-? Do you want to initialize a new Git repository in this directory? (Y/n):
-
+``` +? Do you want to initialize a new Git repository in this directory? (Y/n): +``` + +> Colors: `?` → `WithHighLightFormat` + `WithBold`. #### List Select @@ -261,17 +252,19 @@ The list select pattern presents a list of options for the user to choose from. The prompt is displayed with a `Filter:` line showing ghost-text ("Type to filter list") and a footer hint in **hi-blue text** via `WithHighLightFormat` (Bright Blue, ANSI 94). The active selection is indicated by `>` and displayed in bold blue text. -
-? Select a single option:  [Use arrows to move, type to filter]
+```
+? Select a single option:  [Use arrows to move, type to filter]
 
-  > Option 1
+  > Option 1
     Option 2
     Option 3
     Option 4
     Option 5
     Option 6
     ...
-
+``` + +> Colors: `?` → `WithHighLightFormat` + `WithBold`. `[Use arrows to move, type to filter]` → `WithHighLightFormat` + `WithBold`. `> Option 1` (selected item) → `WithHighLightFormat` + `WithBold`. **Display rules:** @@ -293,9 +286,11 @@ Once the user makes their selection: - If the hint line was visible, it also disappears - The list collapses and the selected value is printed in blue text next to the prompt -
-? Select an Azure location to use: (US) East US 2 (eastus2)
-
+``` +? Select an Azure location to use: (US) East US 2 (eastus2) +``` + +> Colors: `?` → `WithHighLightFormat` + `WithBold`. `(US) East US 2 (eastus2)` (selected value) → `WithHighLightFormat`. ### CLI Color Standards @@ -329,7 +324,7 @@ fmt.Println(output.WithSuccessFormat("(✓) Done:") + " Creating resource") fmt.Println(output.WithWarningFormat("(!) Warning:") + " Configuration may need update") // Error message -fmt.Println(output.WithErrorFormat("(✗) Failed:") + " Unable to connect") +fmt.Println(output.WithErrorFormat("(x) Failed:") + " Unable to connect") // Hyperlink fmt.Printf("View in portal: %s\n", output.WithLinkFormat(url)) @@ -346,6 +341,16 @@ fmt.Printf("Run %s to deploy\n", output.WithHighLightFormat("azd deploy")) - **Theme support**: Test in both light and dark terminal themes - **Fallback**: Ensure output remains readable if colors are disabled +#### Common Mistakes + +| ❌ Don't | ✅ Do | Why | +| --- | --- | --- | +| `Error: something went wrong` | `ERROR: something went wrong.` | All-caps prefix is required | +| `Done: Created resource` | `(✓) Done: Created resource` | Include icon prefix for progress states | +| `color.Red("ERROR")` | `output.WithErrorFormat("ERROR:")` | Always use helper functions | +| Print bare success text | `SUCCESS: Your app has been deployed!` | Always include the `SUCCESS:` prefix | +| `(✗) Failed:` (Unicode ballot X) | `(x) Failed:` (lowercase letter x) | Match the codebase symbol | +
📚 Learn more about ANSI color codes (optional reference) @@ -413,7 +418,7 @@ The full animation cycle frames are: |=======| → | ======| → | =====| → | ====| → | ===| → | ==| → | =| → | | ``` -These frames repeat continuously on the **same line** until the operation completes. The spinner bar is displayed in **hint-colored** text (gray) to keep focus on the status message. +These frames repeat continuously on the **same line** until the operation completes. The spinner bar is displayed in **gray text** via `WithGrayFormat` to keep focus on the status message. #### Implementation From 17d49f83ab8f806d2c02c2719325f2c20046ce46 Mon Sep 17 00:00:00 2001 From: hyoshis Date: Wed, 1 Apr 2026 13:58:53 -0700 Subject: [PATCH 13/14] docs: remove WithHintFormat from style guide pending context review Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- cli/azd/docs/style-guidelines/azd-style-guide.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cli/azd/docs/style-guidelines/azd-style-guide.md b/cli/azd/docs/style-guidelines/azd-style-guide.md index 3789fb9ee84..f25fe042647 100644 --- a/cli/azd/docs/style-guidelines/azd-style-guide.md +++ b/cli/azd/docs/style-guidelines/azd-style-guide.md @@ -231,7 +231,7 @@ If the user types `?`, a hint line appears below the prompt to provide additiona Hint: This is a help message ``` -> Colors: `?` and `[Type ? for hint]` → `WithHighLightFormat` + `WithBold`. Hint line → `WithHintFormat` + `WithBold`. +> Colors: `?` and `[Type ? for hint]` → `WithHighLightFormat` + `WithBold`. Hint line → bold, color TBD. #### Yes or No Input @@ -310,7 +310,6 @@ Use these functions for consistent color formatting across the CLI: | **Warning** | `WithWarningFormat(text string)` | Warning messages, non-critical issues | | **Error** | `WithErrorFormat(text string)` | Error messages, failures | | **Gray text** | `WithGrayFormat(text string)` | Secondary information, muted text | -| **Hint text** | `WithHintFormat(text string)` | Helpful suggestions, tips | | **Bold text** | `WithBold(text string)` | Emphasis, headers | | **Underline** | `WithUnderline(text string)` | Emphasis (use sparingly) | From 36325fa443cd95fa265fa9df2e3409f42a502a56 Mon Sep 17 00:00:00 2001 From: hyoshis Date: Wed, 1 Apr 2026 14:00:55 -0700 Subject: [PATCH 14/14] docs: remove TBD hint line color annotation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- cli/azd/docs/style-guidelines/azd-style-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/azd/docs/style-guidelines/azd-style-guide.md b/cli/azd/docs/style-guidelines/azd-style-guide.md index f25fe042647..e7de0497819 100644 --- a/cli/azd/docs/style-guidelines/azd-style-guide.md +++ b/cli/azd/docs/style-guidelines/azd-style-guide.md @@ -231,7 +231,7 @@ If the user types `?`, a hint line appears below the prompt to provide additiona Hint: This is a help message ``` -> Colors: `?` and `[Type ? for hint]` → `WithHighLightFormat` + `WithBold`. Hint line → bold, color TBD. +> Colors: `?` and `[Type ? for hint]` → `WithHighLightFormat` + `WithBold`. #### Yes or No Input