This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch v3-0-test
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/v3-0-test by this push:
     new 6a95e10823b [v3-0-test] Add new `breeze run` command for 
non-interactive command execution (#52370) (#52373)
6a95e10823b is described below

commit 6a95e10823be64e9cf1bebdcb17ed8469c8edc79
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Sat Jun 28 13:00:48 2025 +0200

    [v3-0-test] Add new `breeze run` command for non-interactive command 
execution (#52370) (#52373)
    
    Add a new `breeze run` command that allows running commands in the Breeze
    environment without entering an interactive shell. This is useful for
    automated testing, and one-off command execution which is useful for AI too.
    (cherry picked from commit bb041b3e1ac4afe962faf273c7798d819b5d5351)
    
    Co-authored-by: Kaxil Naik <[email protected]>
---
 dev/breeze/doc/03_developer_tasks.rst              |  50 +++++
 dev/breeze/doc/images/output-commands.svg          |  54 ++---
 dev/breeze/doc/images/output_run.svg               | 240 +++++++++++++++++++++
 dev/breeze/doc/images/output_run.txt               |   1 +
 .../output_setup_check-all-params-in-groups.svg    |   2 +-
 .../output_setup_check-all-params-in-groups.txt    |   2 +-
 .../output_setup_regenerate-command-images.svg     |   2 +-
 .../output_setup_regenerate-command-images.txt     |   2 +-
 .../airflow_breeze/commands/developer_commands.py  | 137 ++++++++++++
 .../commands/developer_commands_config.py          |  37 ++++
 .../src/airflow_breeze/commands/setup_commands.py  |   1 +
 11 files changed, 499 insertions(+), 29 deletions(-)

diff --git a/dev/breeze/doc/03_developer_tasks.rst 
b/dev/breeze/doc/03_developer_tasks.rst
index 9bc70819903..3a425469283 100644
--- a/dev/breeze/doc/03_developer_tasks.rst
+++ b/dev/breeze/doc/03_developer_tasks.rst
@@ -494,6 +494,56 @@ Those are all available flags of ``shell`` command:
   :width: 100%
   :alt: Breeze shell
 
+Running commands without interactive shell
+------------------------------------------
+
+For automated testing, and one-off command execution, you can use the ``breeze 
run`` command
+to execute commands in the Breeze environment without entering the interactive 
shell. This command is
+particularly useful when you want to run a specific command and exit 
immediately, without the overhead
+of an interactive session.
+
+The ``breeze run`` command creates a fresh container that is automatically 
cleaned up after the command
+completes, and each run uses a unique project name to avoid conflicts with 
other instances.
+
+Here are some common examples:
+
+Running a specific test:
+
+.. code-block:: bash
+
+    breeze run pytest 
providers/google/tests/unit/google/cloud/operators/test_dataflow.py -v
+
+Running Python commands:
+
+.. code-block:: bash
+
+    breeze run python -c "from airflow.providers.google.version_compat import 
AIRFLOW_V_3_0_PLUS; print(AIRFLOW_V_3_0_PLUS)"
+
+Running bash commands:
+
+.. code-block:: bash
+
+    breeze run bash -c "cd /opt/airflow && python -m pytest 
providers/google/tests/"
+
+Running with different Python version:
+
+.. code-block:: bash
+
+    breeze run --python 3.11 pytest 
providers/standard/tests/unit/operators/test_bash.py
+
+Running with PostgreSQL backend:
+
+.. code-block:: bash
+
+    breeze run --backend postgres pytest providers/postgres/tests/
+
+Those are all available flags of ``run`` command:
+
+.. image:: ./images/output_run.svg
+  :target: 
https://raw.githubusercontent.com/apache/airflow/main/dev/breeze/images/output_run.svg
+  :width: 100%
+  :alt: Breeze run
+
 Running Breeze with Metrics
 ---------------------------
 
diff --git a/dev/breeze/doc/images/output-commands.svg 
b/dev/breeze/doc/images/output-commands.svg
index 234bfa5ee81..3589844031e 100644
--- a/dev/breeze/doc/images/output-commands.svg
+++ b/dev/breeze/doc/images/output-commands.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 2172.7999999999997" 
xmlns="http://www.w3.org/2000/svg";>
+<svg class="rich-terminal" viewBox="0 0 1482 2197.2" 
xmlns="http://www.w3.org/2000/svg";>
     <!-- Generated with Rich https://www.textualize.io -->
     <style>
 
@@ -43,7 +43,7 @@
 
     <defs>
     <clipPath id="breeze-help-clip-terminal">
-      <rect x="0" y="0" width="1463.0" height="2121.7999999999997" />
+      <rect x="0" y="0" width="1463.0" height="2146.2" />
     </clipPath>
     <clipPath id="breeze-help-line-0">
     <rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -303,9 +303,12 @@
 <clipPath id="breeze-help-line-85">
     <rect x="0" y="2075.5" width="1464" height="24.65"/>
             </clipPath>
+<clipPath id="breeze-help-line-86">
+    <rect x="0" y="2099.9" width="1464" height="24.65"/>
+            </clipPath>
     </defs>
 
-    <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" 
x="1" y="1" width="1480" height="2170.8" rx="8"/><text 
class="breeze-help-title" fill="#c5c8c6" text-anchor="middle" x="740" 
y="27">Breeze&#160;commands</text>
+    <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" 
x="1" y="1" width="1480" height="2195.2" rx="8"/><text 
class="breeze-help-title" fill="#c5c8c6" text-anchor="middle" x="740" 
y="27">Breeze&#160;commands</text>
             <g transform="translate(26,22)">
             <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
             <circle cx="22" cy="0" r="7" fill="#febc2e"/>
@@ -380,28 +383,29 @@
 </text><text class="breeze-help-r5" x="0" y="1532.8" textLength="12.2" 
clip-path="url(#breeze-help-line-62)">│</text><text class="breeze-help-r4" 
x="24.4" y="1532.8" textLength="280.6" 
clip-path="url(#breeze-help-line-62)">down&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="329.4" y="1532.8" textLength="1110.2" 
clip-path="url(#breeze-help-line-62)">Stop&#160;running&#160;breeze&#160;e [...]
 </text><text class="breeze-help-r5" x="0" y="1557.2" textLength="12.2" 
clip-path="url(#breeze-help-line-63)">│</text><text class="breeze-help-r4" 
x="24.4" y="1557.2" textLength="280.6" 
clip-path="url(#breeze-help-line-63)">shell&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="329.4" y="1557.2" textLength="1110.2" 
clip-path="url(#breeze-help-line-63)">Enter&#160;breeze&#160;environment.&#160; 
[...]
 </text><text class="breeze-help-r5" x="0" y="1581.6" textLength="12.2" 
clip-path="url(#breeze-help-line-64)">│</text><text class="breeze-help-r4" 
x="24.4" y="1581.6" textLength="280.6" 
clip-path="url(#breeze-help-line-64)">exec&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="329.4" y="1581.6" textLength="1110.2" 
clip-path="url(#breeze-help-line-64)">Joins&#160;the&#160;interactive&#160 [...]
-</text><text class="breeze-help-r5" x="0" y="1606" textLength="12.2" 
clip-path="url(#breeze-help-line-65)">│</text><text class="breeze-help-r4" 
x="24.4" y="1606" textLength="280.6" 
clip-path="url(#breeze-help-line-65)">compile-ui-assets&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="329.4" y="1606" textLength="1110.2" 
clip-path="url(#breeze-help-line-65)">Compiles&#160;ui&#160;assets.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
-</text><text class="breeze-help-r5" x="0" y="1630.4" textLength="12.2" 
clip-path="url(#breeze-help-line-66)">│</text><text class="breeze-help-r4" 
x="24.4" y="1630.4" textLength="280.6" 
clip-path="url(#breeze-help-line-66)">cleanup&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="329.4" y="1630.4" textLength="1110.2" 
clip-path="url(#breeze-help-line-66)">Cleans&#160;the&#160;cache&#160;of&#160;parameters,
 [...]
-</text><text class="breeze-help-r5" x="0" y="1654.8" textLength="12.2" 
clip-path="url(#breeze-help-line-67)">│</text><text class="breeze-help-r4" 
x="24.4" y="1654.8" textLength="280.6" 
clip-path="url(#breeze-help-line-67)">generate-migration-file</text><text 
class="breeze-help-r1" x="329.4" y="1654.8" textLength="1110.2" 
clip-path="url(#breeze-help-line-67)">Autogenerate&#160;the&#160;alembic&#160;migration&#160;file&#160;for&#160;the&#160;ORM&#160;changes.&#160;&#160;&#160;&#160;&#160;&
 [...]
-</text><text class="breeze-help-r5" x="0" y="1679.2" textLength="12.2" 
clip-path="url(#breeze-help-line-68)">│</text><text class="breeze-help-r4" 
x="24.4" y="1679.2" textLength="280.6" 
clip-path="url(#breeze-help-line-68)">doctor&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="329.4" y="1679.2" textLength="1110.2" 
clip-path="url(#breeze-help-line-68)">Auto-healing&#160;of&#160;breeze&#160;&#160;&#
 [...]
-</text><text class="breeze-help-r5" x="0" y="1703.6" textLength="1464" 
clip-path="url(#breeze-help-line-69)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-help-r1" x="1464" y="1703.6" textLength="12.2" 
clip-path="url(#breeze-help-line-69)">
-</text><text class="breeze-help-r5" x="0" y="1728" textLength="24.4" 
clip-path="url(#breeze-help-line-70)">╭─</text><text class="breeze-help-r5" 
x="24.4" y="1728" textLength="219.6" 
clip-path="url(#breeze-help-line-70)">&#160;Testing&#160;commands&#160;</text><text
 class="breeze-help-r5" x="244" y="1728" textLength="1195.6" 
clip-path="url(#breeze-help-line-70)">──────────────────────────────────────────────────────────────────────────────────────────────────</text><text
 class="breeze-hel [...]
-</text><text class="breeze-help-r5" x="0" y="1752.4" textLength="12.2" 
clip-path="url(#breeze-help-line-71)">│</text><text class="breeze-help-r4" 
x="24.4" y="1752.4" textLength="183" 
clip-path="url(#breeze-help-line-71)">testing&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="231.8" y="1752.4" textLength="1207.8" 
clip-path="url(#breeze-help-line-71)">Tools&#160;that&#160;developers&#160;can&#160;use&#160;to&#160;run&#160;tests&#160;&#160;&#160;&#160;
 [...]
-</text><text class="breeze-help-r5" x="0" y="1776.8" textLength="12.2" 
clip-path="url(#breeze-help-line-72)">│</text><text class="breeze-help-r4" 
x="24.4" y="1776.8" textLength="183" 
clip-path="url(#breeze-help-line-72)">k8s&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="231.8" y="1776.8" textLength="1207.8" 
clip-path="url(#breeze-help-line-72)">Tools&#160;that&#160;developers&#160;use&#160;to&#160;run&#160;Kubernetes&#160;te
 [...]
-</text><text class="breeze-help-r5" x="0" y="1801.2" textLength="1464" 
clip-path="url(#breeze-help-line-73)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-help-r1" x="1464" y="1801.2" textLength="12.2" 
clip-path="url(#breeze-help-line-73)">
-</text><text class="breeze-help-r5" x="0" y="1825.6" textLength="24.4" 
clip-path="url(#breeze-help-line-74)">╭─</text><text class="breeze-help-r5" 
x="24.4" y="1825.6" textLength="195.2" 
clip-path="url(#breeze-help-line-74)">&#160;Image&#160;commands&#160;</text><text
 class="breeze-help-r5" x="219.6" y="1825.6" textLength="1220" 
clip-path="url(#breeze-help-line-74)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text
 class="bree [...]
-</text><text class="breeze-help-r5" x="0" y="1850" textLength="12.2" 
clip-path="url(#breeze-help-line-75)">│</text><text class="breeze-help-r4" 
x="24.4" y="1850" textLength="207.4" 
clip-path="url(#breeze-help-line-75)">ci-image&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="256.2" y="1850" textLength="1183.4" 
clip-path="url(#breeze-help-line-75)">Tools&#160;that&#160;developers&#160;can&#160;use&#160;to&#160;manually&#160;manage&#160;CI&#160;i
 [...]
-</text><text class="breeze-help-r5" x="0" y="1874.4" textLength="12.2" 
clip-path="url(#breeze-help-line-76)">│</text><text class="breeze-help-r4" 
x="24.4" y="1874.4" textLength="207.4" 
clip-path="url(#breeze-help-line-76)">prod-image&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="256.2" y="1874.4" textLength="1183.4" 
clip-path="url(#breeze-help-line-76)">Tools&#160;that&#160;developers&#160;can&#160;use&#160;to&#160;manually&#160;manage&#160;PROD&#160;ima
 [...]
-</text><text class="breeze-help-r5" x="0" y="1898.8" textLength="1464" 
clip-path="url(#breeze-help-line-77)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-help-r1" x="1464" y="1898.8" textLength="12.2" 
clip-path="url(#breeze-help-line-77)">
-</text><text class="breeze-help-r5" x="0" y="1923.2" textLength="24.4" 
clip-path="url(#breeze-help-line-78)">╭─</text><text class="breeze-help-r5" 
x="24.4" y="1923.2" textLength="353.8" 
clip-path="url(#breeze-help-line-78)">&#160;Release&#160;management&#160;commands&#160;</text><text
 class="breeze-help-r5" x="378.2" y="1923.2" textLength="1061.4" 
clip-path="url(#breeze-help-line-78)">───────────────────────────────────────────────────────────────────────────────────────</text><text
 clas [...]
-</text><text class="breeze-help-r5" x="0" y="1947.6" textLength="12.2" 
clip-path="url(#breeze-help-line-79)">│</text><text class="breeze-help-r4" 
x="24.4" y="1947.6" textLength="280.6" 
clip-path="url(#breeze-help-line-79)">release-management&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="329.4" y="1947.6" textLength="1110.2" 
clip-path="url(#breeze-help-line-79)">Tools&#160;that&#160;release&#160;managers&#160;can&#160;use&#160;to&#160;prepare&#160;and&#160;manage&#16
 [...]
-</text><text class="breeze-help-r5" x="0" y="1972" textLength="12.2" 
clip-path="url(#breeze-help-line-80)">│</text><text class="breeze-help-r4" 
x="24.4" y="1972" textLength="280.6" 
clip-path="url(#breeze-help-line-80)">sbom&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="329.4" y="1972" textLength="1110.2" 
clip-path="url(#breeze-help-line-80)">Tools&#160;that&#160;release&#160;managers
 [...]
-</text><text class="breeze-help-r5" x="0" y="1996.4" textLength="12.2" 
clip-path="url(#breeze-help-line-81)">│</text><text class="breeze-help-r4" 
x="24.4" y="1996.4" textLength="280.6" 
clip-path="url(#breeze-help-line-81)">workflow-run&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="329.4" y="1996.4" textLength="1110.2" 
clip-path="url(#breeze-help-line-81)">Tools&#160;to&#160;manage&#160;Airflow&#160;repository&#160;workflows&#160;&
 [...]
-</text><text class="breeze-help-r5" x="0" y="2020.8" textLength="1464" 
clip-path="url(#breeze-help-line-82)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-help-r1" x="1464" y="2020.8" textLength="12.2" 
clip-path="url(#breeze-help-line-82)">
-</text><text class="breeze-help-r5" x="0" y="2045.2" textLength="24.4" 
clip-path="url(#breeze-help-line-83)">╭─</text><text class="breeze-help-r5" 
x="24.4" y="2045.2" textLength="195.2" 
clip-path="url(#breeze-help-line-83)">&#160;Other&#160;commands&#160;</text><text
 class="breeze-help-r5" x="219.6" y="2045.2" textLength="1220" 
clip-path="url(#breeze-help-line-83)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text
 class="bree [...]
-</text><text class="breeze-help-r5" x="0" y="2069.6" textLength="12.2" 
clip-path="url(#breeze-help-line-84)">│</text><text class="breeze-help-r4" 
x="24.4" y="2069.6" textLength="122" 
clip-path="url(#breeze-help-line-84)">setup&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="170.8" y="2069.6" textLength="1268.8" 
clip-path="url(#breeze-help-line-84)">Tools&#160;that&#160;developers&#160;can&#160;use&#160;to&#160;configure&#160;Breeze&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
-</text><text class="breeze-help-r5" x="0" y="2094" textLength="12.2" 
clip-path="url(#breeze-help-line-85)">│</text><text class="breeze-help-r4" 
x="24.4" y="2094" textLength="122" 
clip-path="url(#breeze-help-line-85)">ci&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="170.8" y="2094" textLength="1268.8" 
clip-path="url(#breeze-help-line-85)">Tools&#160;that&#160;CI&#160;workflows&#160;use&#160;to&#160;cleanup/manage&#160;CI&#160;environment&#160;&#160;
 [...]
-</text><text class="breeze-help-r5" x="0" y="2118.4" textLength="1464" 
clip-path="url(#breeze-help-line-86)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-help-r1" x="1464" y="2118.4" textLength="12.2" 
clip-path="url(#breeze-help-line-86)">
+</text><text class="breeze-help-r5" x="0" y="1606" textLength="12.2" 
clip-path="url(#breeze-help-line-65)">│</text><text class="breeze-help-r4" 
x="24.4" y="1606" textLength="280.6" 
clip-path="url(#breeze-help-line-65)">run&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="329.4" y="1606" textLength="1110.2" 
clip-path="url(#breeze-help-line-65)">Run&#160;a&#160;command&#160;in&#160; 
[...]
+</text><text class="breeze-help-r5" x="0" y="1630.4" textLength="12.2" 
clip-path="url(#breeze-help-line-66)">│</text><text class="breeze-help-r4" 
x="24.4" y="1630.4" textLength="280.6" 
clip-path="url(#breeze-help-line-66)">compile-ui-assets&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="329.4" y="1630.4" textLength="1110.2" 
clip-path="url(#breeze-help-line-66)">Compiles&#160;ui&#160;assets.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
+</text><text class="breeze-help-r5" x="0" y="1654.8" textLength="12.2" 
clip-path="url(#breeze-help-line-67)">│</text><text class="breeze-help-r4" 
x="24.4" y="1654.8" textLength="280.6" 
clip-path="url(#breeze-help-line-67)">cleanup&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="329.4" y="1654.8" textLength="1110.2" 
clip-path="url(#breeze-help-line-67)">Cleans&#160;the&#160;cache&#160;of&#160;parameters,
 [...]
+</text><text class="breeze-help-r5" x="0" y="1679.2" textLength="12.2" 
clip-path="url(#breeze-help-line-68)">│</text><text class="breeze-help-r4" 
x="24.4" y="1679.2" textLength="280.6" 
clip-path="url(#breeze-help-line-68)">generate-migration-file</text><text 
class="breeze-help-r1" x="329.4" y="1679.2" textLength="1110.2" 
clip-path="url(#breeze-help-line-68)">Autogenerate&#160;the&#160;alembic&#160;migration&#160;file&#160;for&#160;the&#160;ORM&#160;changes.&#160;&#160;&#160;&#160;&#160;&
 [...]
+</text><text class="breeze-help-r5" x="0" y="1703.6" textLength="12.2" 
clip-path="url(#breeze-help-line-69)">│</text><text class="breeze-help-r4" 
x="24.4" y="1703.6" textLength="280.6" 
clip-path="url(#breeze-help-line-69)">doctor&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="329.4" y="1703.6" textLength="1110.2" 
clip-path="url(#breeze-help-line-69)">Auto-healing&#160;of&#160;breeze&#160;&#160;&#
 [...]
+</text><text class="breeze-help-r5" x="0" y="1728" textLength="1464" 
clip-path="url(#breeze-help-line-70)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-help-r1" x="1464" y="1728" textLength="12.2" 
clip-path="url(#breeze-help-line-70)">
+</text><text class="breeze-help-r5" x="0" y="1752.4" textLength="24.4" 
clip-path="url(#breeze-help-line-71)">╭─</text><text class="breeze-help-r5" 
x="24.4" y="1752.4" textLength="219.6" 
clip-path="url(#breeze-help-line-71)">&#160;Testing&#160;commands&#160;</text><text
 class="breeze-help-r5" x="244" y="1752.4" textLength="1195.6" 
clip-path="url(#breeze-help-line-71)">──────────────────────────────────────────────────────────────────────────────────────────────────</text><text
 class="bree [...]
+</text><text class="breeze-help-r5" x="0" y="1776.8" textLength="12.2" 
clip-path="url(#breeze-help-line-72)">│</text><text class="breeze-help-r4" 
x="24.4" y="1776.8" textLength="183" 
clip-path="url(#breeze-help-line-72)">testing&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="231.8" y="1776.8" textLength="1207.8" 
clip-path="url(#breeze-help-line-72)">Tools&#160;that&#160;developers&#160;can&#160;use&#160;to&#160;run&#160;tests&#160;&#160;&#160;&#160;
 [...]
+</text><text class="breeze-help-r5" x="0" y="1801.2" textLength="12.2" 
clip-path="url(#breeze-help-line-73)">│</text><text class="breeze-help-r4" 
x="24.4" y="1801.2" textLength="183" 
clip-path="url(#breeze-help-line-73)">k8s&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="231.8" y="1801.2" textLength="1207.8" 
clip-path="url(#breeze-help-line-73)">Tools&#160;that&#160;developers&#160;use&#160;to&#160;run&#160;Kubernetes&#160;te
 [...]
+</text><text class="breeze-help-r5" x="0" y="1825.6" textLength="1464" 
clip-path="url(#breeze-help-line-74)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-help-r1" x="1464" y="1825.6" textLength="12.2" 
clip-path="url(#breeze-help-line-74)">
+</text><text class="breeze-help-r5" x="0" y="1850" textLength="24.4" 
clip-path="url(#breeze-help-line-75)">╭─</text><text class="breeze-help-r5" 
x="24.4" y="1850" textLength="195.2" 
clip-path="url(#breeze-help-line-75)">&#160;Image&#160;commands&#160;</text><text
 class="breeze-help-r5" x="219.6" y="1850" textLength="1220" 
clip-path="url(#breeze-help-line-75)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text
 class="breeze-hel [...]
+</text><text class="breeze-help-r5" x="0" y="1874.4" textLength="12.2" 
clip-path="url(#breeze-help-line-76)">│</text><text class="breeze-help-r4" 
x="24.4" y="1874.4" textLength="207.4" 
clip-path="url(#breeze-help-line-76)">ci-image&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="256.2" y="1874.4" textLength="1183.4" 
clip-path="url(#breeze-help-line-76)">Tools&#160;that&#160;developers&#160;can&#160;use&#160;to&#160;manually&#160;manage&#160;CI&
 [...]
+</text><text class="breeze-help-r5" x="0" y="1898.8" textLength="12.2" 
clip-path="url(#breeze-help-line-77)">│</text><text class="breeze-help-r4" 
x="24.4" y="1898.8" textLength="207.4" 
clip-path="url(#breeze-help-line-77)">prod-image&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="256.2" y="1898.8" textLength="1183.4" 
clip-path="url(#breeze-help-line-77)">Tools&#160;that&#160;developers&#160;can&#160;use&#160;to&#160;manually&#160;manage&#160;PROD&#160;ima
 [...]
+</text><text class="breeze-help-r5" x="0" y="1923.2" textLength="1464" 
clip-path="url(#breeze-help-line-78)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-help-r1" x="1464" y="1923.2" textLength="12.2" 
clip-path="url(#breeze-help-line-78)">
+</text><text class="breeze-help-r5" x="0" y="1947.6" textLength="24.4" 
clip-path="url(#breeze-help-line-79)">╭─</text><text class="breeze-help-r5" 
x="24.4" y="1947.6" textLength="353.8" 
clip-path="url(#breeze-help-line-79)">&#160;Release&#160;management&#160;commands&#160;</text><text
 class="breeze-help-r5" x="378.2" y="1947.6" textLength="1061.4" 
clip-path="url(#breeze-help-line-79)">───────────────────────────────────────────────────────────────────────────────────────</text><text
 clas [...]
+</text><text class="breeze-help-r5" x="0" y="1972" textLength="12.2" 
clip-path="url(#breeze-help-line-80)">│</text><text class="breeze-help-r4" 
x="24.4" y="1972" textLength="280.6" 
clip-path="url(#breeze-help-line-80)">release-management&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="329.4" y="1972" textLength="1110.2" 
clip-path="url(#breeze-help-line-80)">Tools&#160;that&#160;release&#160;managers&#160;can&#160;use&#160;to&#160;prepare&#160;and&#160;manage&#160;Airf
 [...]
+</text><text class="breeze-help-r5" x="0" y="1996.4" textLength="12.2" 
clip-path="url(#breeze-help-line-81)">│</text><text class="breeze-help-r4" 
x="24.4" y="1996.4" textLength="280.6" 
clip-path="url(#breeze-help-line-81)">sbom&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="329.4" y="1996.4" textLength="1110.2" 
clip-path="url(#breeze-help-line-81)">Tools&#160;that&#160;release&#160;ma [...]
+</text><text class="breeze-help-r5" x="0" y="2020.8" textLength="12.2" 
clip-path="url(#breeze-help-line-82)">│</text><text class="breeze-help-r4" 
x="24.4" y="2020.8" textLength="280.6" 
clip-path="url(#breeze-help-line-82)">workflow-run&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="329.4" y="2020.8" textLength="1110.2" 
clip-path="url(#breeze-help-line-82)">Tools&#160;to&#160;manage&#160;Airflow&#160;repository&#160;workflows&#160;&
 [...]
+</text><text class="breeze-help-r5" x="0" y="2045.2" textLength="1464" 
clip-path="url(#breeze-help-line-83)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-help-r1" x="1464" y="2045.2" textLength="12.2" 
clip-path="url(#breeze-help-line-83)">
+</text><text class="breeze-help-r5" x="0" y="2069.6" textLength="24.4" 
clip-path="url(#breeze-help-line-84)">╭─</text><text class="breeze-help-r5" 
x="24.4" y="2069.6" textLength="195.2" 
clip-path="url(#breeze-help-line-84)">&#160;Other&#160;commands&#160;</text><text
 class="breeze-help-r5" x="219.6" y="2069.6" textLength="1220" 
clip-path="url(#breeze-help-line-84)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text
 class="bree [...]
+</text><text class="breeze-help-r5" x="0" y="2094" textLength="12.2" 
clip-path="url(#breeze-help-line-85)">│</text><text class="breeze-help-r4" 
x="24.4" y="2094" textLength="122" 
clip-path="url(#breeze-help-line-85)">setup&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="170.8" y="2094" textLength="1268.8" 
clip-path="url(#breeze-help-line-85)">Tools&#160;that&#160;developers&#160;can&#160;use&#160;to&#160;configure&#160;Breeze&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
+</text><text class="breeze-help-r5" x="0" y="2118.4" textLength="12.2" 
clip-path="url(#breeze-help-line-86)">│</text><text class="breeze-help-r4" 
x="24.4" y="2118.4" textLength="122" 
clip-path="url(#breeze-help-line-86)">ci&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="170.8" y="2118.4" textLength="1268.8" 
clip-path="url(#breeze-help-line-86)">Tools&#160;that&#160;CI&#160;workflows&#160;use&#160;to&#160;cleanup/manage&#160;CI&#160;environment&#160;
 [...]
+</text><text class="breeze-help-r5" x="0" y="2142.8" textLength="1464" 
clip-path="url(#breeze-help-line-87)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-help-r1" x="1464" y="2142.8" textLength="12.2" 
clip-path="url(#breeze-help-line-87)">
 </text>
     </g>
     </g>
diff --git a/dev/breeze/doc/images/output_run.svg 
b/dev/breeze/doc/images/output_run.svg
new file mode 100644
index 00000000000..b672a174b29
--- /dev/null
+++ b/dev/breeze/doc/images/output_run.svg
@@ -0,0 +1,240 @@
+<svg class="rich-terminal" viewBox="0 0 1482 1148.0" 
xmlns="http://www.w3.org/2000/svg";>
+    <!-- Generated with Rich https://www.textualize.io -->
+    <style>
+
+    @font-face {
+        font-family: "Fira Code";
+        src: local("FiraCode-Regular"),
+                
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2";)
 format("woff2"),
+                
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff";)
 format("woff");
+        font-style: normal;
+        font-weight: 400;
+    }
+    @font-face {
+        font-family: "Fira Code";
+        src: local("FiraCode-Bold"),
+                
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2";)
 format("woff2"),
+                
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff";)
 format("woff");
+        font-style: bold;
+        font-weight: 700;
+    }
+
+    .breeze-run-matrix {
+        font-family: Fira Code, monospace;
+        font-size: 20px;
+        line-height: 24.4px;
+        font-variant-east-asian: full-width;
+    }
+
+    .breeze-run-title {
+        font-size: 18px;
+        font-weight: bold;
+        font-family: arial;
+    }
+
+    .breeze-run-r1 { fill: #c5c8c6 }
+.breeze-run-r2 { fill: #d0b344 }
+.breeze-run-r3 { fill: #c5c8c6;font-weight: bold }
+.breeze-run-r4 { fill: #68a0b3;font-weight: bold }
+.breeze-run-r5 { fill: #868887 }
+.breeze-run-r6 { fill: #98a84b;font-weight: bold }
+.breeze-run-r7 { fill: #8d7b39 }
+    </style>
+
+    <defs>
+    <clipPath id="breeze-run-clip-terminal">
+      <rect x="0" y="0" width="1463.0" height="1097.0" />
+    </clipPath>
+    <clipPath id="breeze-run-line-0">
+    <rect x="0" y="1.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-1">
+    <rect x="0" y="25.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-2">
+    <rect x="0" y="50.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-3">
+    <rect x="0" y="74.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-4">
+    <rect x="0" y="99.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-5">
+    <rect x="0" y="123.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-6">
+    <rect x="0" y="147.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-7">
+    <rect x="0" y="172.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-8">
+    <rect x="0" y="196.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-9">
+    <rect x="0" y="221.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-10">
+    <rect x="0" y="245.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-11">
+    <rect x="0" y="269.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-12">
+    <rect x="0" y="294.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-13">
+    <rect x="0" y="318.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-14">
+    <rect x="0" y="343.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-15">
+    <rect x="0" y="367.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-16">
+    <rect x="0" y="391.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-17">
+    <rect x="0" y="416.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-18">
+    <rect x="0" y="440.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-19">
+    <rect x="0" y="465.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-20">
+    <rect x="0" y="489.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-21">
+    <rect x="0" y="513.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-22">
+    <rect x="0" y="538.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-23">
+    <rect x="0" y="562.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-24">
+    <rect x="0" y="587.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-25">
+    <rect x="0" y="611.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-26">
+    <rect x="0" y="635.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-27">
+    <rect x="0" y="660.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-28">
+    <rect x="0" y="684.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-29">
+    <rect x="0" y="709.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-30">
+    <rect x="0" y="733.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-31">
+    <rect x="0" y="757.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-32">
+    <rect x="0" y="782.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-33">
+    <rect x="0" y="806.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-34">
+    <rect x="0" y="831.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-35">
+    <rect x="0" y="855.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-36">
+    <rect x="0" y="879.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-37">
+    <rect x="0" y="904.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-38">
+    <rect x="0" y="928.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-39">
+    <rect x="0" y="953.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-40">
+    <rect x="0" y="977.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-41">
+    <rect x="0" y="1001.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-42">
+    <rect x="0" y="1026.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-run-line-43">
+    <rect x="0" y="1050.7" width="1464" height="24.65"/>
+            </clipPath>
+    </defs>
+
+    <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" 
x="1" y="1" width="1480" height="1146" rx="8"/><text class="breeze-run-title" 
fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command:&#160;run</text>
+            <g transform="translate(26,22)">
+            <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
+            <circle cx="22" cy="0" r="7" fill="#febc2e"/>
+            <circle cx="44" cy="0" r="7" fill="#28c840"/>
+            </g>
+        
+    <g transform="translate(9, 41)" clip-path="url(#breeze-run-clip-terminal)">
+    
+    <g class="breeze-run-matrix">
+    <text class="breeze-run-r1" x="1464" y="20" textLength="12.2" 
clip-path="url(#breeze-run-line-0)">
+</text><text class="breeze-run-r2" x="12.2" y="44.4" textLength="73.2" 
clip-path="url(#breeze-run-line-1)">Usage:</text><text class="breeze-run-r3" 
x="97.6" y="44.4" textLength="122" 
clip-path="url(#breeze-run-line-1)">breeze&#160;run</text><text 
class="breeze-run-r1" x="231.8" y="44.4" textLength="12.2" 
clip-path="url(#breeze-run-line-1)">[</text><text class="breeze-run-r4" x="244" 
y="44.4" textLength="85.4" 
clip-path="url(#breeze-run-line-1)">OPTIONS</text><text class="breeze-run-r1" x 
[...]
+</text><text class="breeze-run-r1" x="1464" y="68.8" textLength="12.2" 
clip-path="url(#breeze-run-line-2)">
+</text><text class="breeze-run-r1" x="12.2" y="93.2" textLength="963.8" 
clip-path="url(#breeze-run-line-3)">Run&#160;a&#160;command&#160;in&#160;the&#160;Breeze&#160;environment&#160;without&#160;entering&#160;the&#160;interactive&#160;shell.</text><text
 class="breeze-run-r1" x="1464" y="93.2" textLength="12.2" 
clip-path="url(#breeze-run-line-3)">
+</text><text class="breeze-run-r1" x="1464" y="117.6" textLength="12.2" 
clip-path="url(#breeze-run-line-4)">
+</text><text class="breeze-run-r5" x="0" y="142" textLength="24.4" 
clip-path="url(#breeze-run-line-5)">╭─</text><text class="breeze-run-r5" 
x="24.4" y="142" textLength="231.8" 
clip-path="url(#breeze-run-line-5)">&#160;Command&#160;execution&#160;</text><text
 class="breeze-run-r5" x="256.2" y="142" textLength="1183.4" 
clip-path="url(#breeze-run-line-5)">─────────────────────────────────────────────────────────────────────────────────────────────────</text><text
 class="breeze-run-r5" x="14 [...]
+</text><text class="breeze-run-r5" x="0" y="166.4" textLength="12.2" 
clip-path="url(#breeze-run-line-6)">│</text><text class="breeze-run-r4" 
x="24.4" y="166.4" textLength="97.6" 
clip-path="url(#breeze-run-line-6)">--python</text><text class="breeze-run-r6" 
x="268.4" y="166.4" textLength="24.4" 
clip-path="url(#breeze-run-line-6)">-p</text><text class="breeze-run-r1" 
x="317.2" y="166.4" textLength="732" 
clip-path="url(#breeze-run-line-6)">Python&#160;major/minor&#160;version&#160;used&#160
 [...]
+</text><text class="breeze-run-r5" x="0" y="190.8" textLength="12.2" 
clip-path="url(#breeze-run-line-7)">│</text><text class="breeze-run-r5" 
x="317.2" y="190.8" textLength="732" 
clip-path="url(#breeze-run-line-7)">[default:&#160;3.10]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
+</text><text class="breeze-run-r5" x="0" y="215.2" textLength="12.2" 
clip-path="url(#breeze-run-line-8)">│</text><text class="breeze-run-r4" 
x="24.4" y="215.2" textLength="109.8" 
clip-path="url(#breeze-run-line-8)">--backend</text><text class="breeze-run-r6" 
x="268.4" y="215.2" textLength="24.4" 
clip-path="url(#breeze-run-line-8)">-b</text><text class="breeze-run-r1" 
x="317.2" y="215.2" textLength="1122.4" 
clip-path="url(#breeze-run-line-8)">Database&#160;backend&#160;to&#160;use.&#160;I
 [...]
+</text><text class="breeze-run-r5" x="0" y="239.6" textLength="12.2" 
clip-path="url(#breeze-run-line-9)">│</text><text class="breeze-run-r1" 
x="317.2" y="239.6" textLength="1122.4" 
clip-path="url(#breeze-run-line-9)">configuration,&#160;meaning&#160;there&#160;will&#160;be&#160;no&#160;database&#160;available,&#160;and&#160;any&#160;attempts&#160;to&#160;connect&#160;to&#160;&#160;</text><text
 class="breeze-run-r5" x="1451.8" y="239.6" textLength="12.2" 
clip-path="url(#breeze-run-line-9) [...]
+</text><text class="breeze-run-r5" x="0" y="264" textLength="12.2" 
clip-path="url(#breeze-run-line-10)">│</text><text class="breeze-run-r1" 
x="317.2" y="264" textLength="1122.4" 
clip-path="url(#breeze-run-line-10)">the&#160;Airflow&#160;database&#160;will&#160;fail.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
+</text><text class="breeze-run-r5" x="0" y="288.4" textLength="12.2" 
clip-path="url(#breeze-run-line-11)">│</text><text class="breeze-run-r7" 
x="317.2" y="288.4" textLength="1122.4" 
clip-path="url(#breeze-run-line-11)">(&gt;sqlite&lt;&#160;|&#160;mysql&#160;|&#160;postgres&#160;|&#160;none)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
+</text><text class="breeze-run-r5" x="0" y="312.8" textLength="12.2" 
clip-path="url(#breeze-run-line-12)">│</text><text class="breeze-run-r5" 
x="317.2" y="312.8" textLength="1122.4" 
clip-path="url(#breeze-run-line-12)">[default:&#160;sqlite]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
+</text><text class="breeze-run-r5" x="0" y="337.2" textLength="12.2" 
clip-path="url(#breeze-run-line-13)">│</text><text class="breeze-run-r4" 
x="24.4" y="337.2" textLength="219.6" 
clip-path="url(#breeze-run-line-13)">--postgres-version</text><text 
class="breeze-run-r6" x="268.4" y="337.2" textLength="24.4" 
clip-path="url(#breeze-run-line-13)">-P</text><text class="breeze-run-r1" 
x="317.2" y="337.2" textLength="305" 
clip-path="url(#breeze-run-line-13)">Version&#160;of&#160;Postgres&#160;u [...]
+</text><text class="breeze-run-r5" x="0" y="361.6" textLength="12.2" 
clip-path="url(#breeze-run-line-14)">│</text><text class="breeze-run-r4" 
x="24.4" y="361.6" textLength="183" 
clip-path="url(#breeze-run-line-14)">--mysql-version</text><text 
class="breeze-run-r6" x="268.4" y="361.6" textLength="24.4" 
clip-path="url(#breeze-run-line-14)">-M</text><text class="breeze-run-r1" 
x="317.2" y="361.6" textLength="268.4" 
clip-path="url(#breeze-run-line-14)">Version&#160;of&#160;MySQL&#160;used.</ 
[...]
+</text><text class="breeze-run-r5" x="0" y="386" textLength="1464" 
clip-path="url(#breeze-run-line-15)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-run-r1" x="1464" y="386" textLength="12.2" 
clip-path="url(#breeze-run-line-15)">
+</text><text class="breeze-run-r5" x="0" y="410.4" textLength="24.4" 
clip-path="url(#breeze-run-line-16)">╭─</text><text class="breeze-run-r5" 
x="24.4" y="410.4" textLength="500.2" 
clip-path="url(#breeze-run-line-16)">&#160;Build&#160;CI&#160;image&#160;(before&#160;running&#160;command)&#160;</text><text
 class="breeze-run-r5" x="524.6" y="410.4" textLength="915" 
clip-path="url(#breeze-run-line-16)">───────────────────────────────────────────────────────────────────────────</text><text
 c [...]
+</text><text class="breeze-run-r5" x="0" y="434.8" textLength="12.2" 
clip-path="url(#breeze-run-line-17)">│</text><text class="breeze-run-r4" 
x="24.4" y="434.8" textLength="158.6" 
clip-path="url(#breeze-run-line-17)">--force-build</text><text 
class="breeze-run-r1" x="341.6" y="434.8" textLength="707.6" 
clip-path="url(#breeze-run-line-17)">Force&#160;image&#160;build&#160;no&#160;matter&#160;if&#160;it&#160;is&#160;determined&#160;as&#160;needed.</text><text
 class="breeze-run-r5" x="1451. [...]
+</text><text class="breeze-run-r5" x="0" y="459.2" textLength="12.2" 
clip-path="url(#breeze-run-line-18)">│</text><text class="breeze-run-r4" 
x="24.4" y="459.2" textLength="122" 
clip-path="url(#breeze-run-line-18)">--platform</text><text 
class="breeze-run-r1" x="341.6" y="459.2" textLength="329.4" 
clip-path="url(#breeze-run-line-18)">Platform&#160;for&#160;Airflow&#160;image.</text><text
 class="breeze-run-r7" x="683.2" y="459.2" textLength="707.6" 
clip-path="url(#breeze-run-line-18)">(li [...]
+</text><text class="breeze-run-r5" x="0" y="483.6" textLength="12.2" 
clip-path="url(#breeze-run-line-19)">│</text><text class="breeze-run-r4" 
x="24.4" y="483.6" textLength="231.8" 
clip-path="url(#breeze-run-line-19)">--github-repository</text><text 
class="breeze-run-r6" x="292.8" y="483.6" textLength="24.4" 
clip-path="url(#breeze-run-line-19)">-g</text><text class="breeze-run-r1" 
x="341.6" y="483.6" textLength="585.6" 
clip-path="url(#breeze-run-line-19)">GitHub&#160;repository&#160;used& [...]
+</text><text class="breeze-run-r5" x="0" y="508" textLength="12.2" 
clip-path="url(#breeze-run-line-20)">│</text><text class="breeze-run-r4" 
x="24.4" y="508" textLength="109.8" 
clip-path="url(#breeze-run-line-20)">--builder</text><text 
class="breeze-run-r1" x="341.6" y="508" textLength="756.4" 
clip-path="url(#breeze-run-line-20)">Buildx&#160;builder&#160;used&#160;to&#160;perform&#160;`docker&#160;buildx&#160;build`&#160;commands.</text><text
 class="breeze-run-r7" x="1110.2" y="508" textL [...]
+</text><text class="breeze-run-r5" x="0" y="532.4" textLength="12.2" 
clip-path="url(#breeze-run-line-21)">│</text><text class="breeze-run-r5" 
x="341.6" y="532.4" textLength="756.4" 
clip-path="url(#breeze-run-line-21)">[default:&#160;autodetect]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</
 [...]
+</text><text class="breeze-run-r5" x="0" y="556.8" textLength="12.2" 
clip-path="url(#breeze-run-line-22)">│</text><text class="breeze-run-r4" 
x="24.4" y="556.8" textLength="97.6" 
clip-path="url(#breeze-run-line-22)">--use-uv</text><text class="breeze-run-r1" 
x="122" y="556.8" textLength="12.2" 
clip-path="url(#breeze-run-line-22)">/</text><text class="breeze-run-r4" 
x="134.2" y="556.8" textLength="134.2" 
clip-path="url(#breeze-run-line-22)">--no-use-uv</text><text 
class="breeze-run-r1" x= [...]
+</text><text class="breeze-run-r5" x="0" y="581.2" textLength="12.2" 
clip-path="url(#breeze-run-line-23)">│</text><text class="breeze-run-r4" 
x="24.4" y="581.2" textLength="207.4" 
clip-path="url(#breeze-run-line-23)">--uv-http-timeout</text><text 
class="breeze-run-r1" x="341.6" y="581.2" textLength="829.6" 
clip-path="url(#breeze-run-line-23)">Timeout&#160;for&#160;requests&#160;that&#160;UV&#160;makes&#160;(only&#160;used&#160;in&#160;case&#160;of&#160;UV&#160;builds).</text><text
 class= [...]
+</text><text class="breeze-run-r5" x="0" y="605.6" textLength="12.2" 
clip-path="url(#breeze-run-line-24)">│</text><text class="breeze-run-r5" 
x="341.6" y="605.6" textLength="829.6" 
clip-path="url(#breeze-run-line-24)">[default:&#160;300;&#160;x&gt;=1]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
+</text><text class="breeze-run-r5" x="0" y="630" textLength="1464" 
clip-path="url(#breeze-run-line-25)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-run-r1" x="1464" y="630" textLength="12.2" 
clip-path="url(#breeze-run-line-25)">
+</text><text class="breeze-run-r5" x="0" y="654.4" textLength="24.4" 
clip-path="url(#breeze-run-line-26)">╭─</text><text class="breeze-run-r5" 
x="24.4" y="654.4" textLength="427" 
clip-path="url(#breeze-run-line-26)">&#160;Docker&#160;Compose&#160;project&#160;management&#160;</text><text
 class="breeze-run-r5" x="451.4" y="654.4" textLength="988.2" 
clip-path="url(#breeze-run-line-26)">─────────────────────────────────────────────────────────────────────────────────</text><text
 class="bree [...]
+</text><text class="breeze-run-r5" x="0" y="678.8" textLength="12.2" 
clip-path="url(#breeze-run-line-27)">│</text><text class="breeze-run-r4" 
x="24.4" y="678.8" textLength="170.8" 
clip-path="url(#breeze-run-line-27)">--project-name</text><text 
class="breeze-run-r1" x="244" y="678.8" textLength="1195.6" 
clip-path="url(#breeze-run-line-27)">Name&#160;of&#160;the&#160;docker-compose&#160;project&#160;to&#160;bring&#160;down.&#160;The&#160;`docker-compose`&#160;is&#160;for&#160;legacy&#160;b
 [...]
+</text><text class="breeze-run-r5" x="0" y="703.2" textLength="12.2" 
clip-path="url(#breeze-run-line-28)">│</text><text class="breeze-run-r1" 
x="244" y="703.2" textLength="512.4" 
clip-path="url(#breeze-run-line-28)">project&#160;name&#160;and&#160;you&#160;can&#160;use&#160;`breeze&#160;down&#160;</text><text
 class="breeze-run-r4" x="756.4" y="703.2" textLength="170.8" 
clip-path="url(#breeze-run-line-28)">--project-name</text><text 
class="breeze-run-r1" x="927.2" y="703.2" textLength="51 [...]
+</text><text class="breeze-run-r5" x="0" y="727.6" textLength="12.2" 
clip-path="url(#breeze-run-line-29)">│</text><text class="breeze-run-r1" 
x="244" y="727.6" textLength="1195.6" 
clip-path="url(#breeze-run-line-29)">belonging&#160;to&#160;it.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
+</text><text class="breeze-run-r5" x="0" y="752" textLength="12.2" 
clip-path="url(#breeze-run-line-30)">│</text><text class="breeze-run-r7" 
x="244" y="752" textLength="1195.6" 
clip-path="url(#breeze-run-line-30)">(breeze&#160;|&#160;pre-commit&#160;|&#160;docker-compose)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
+</text><text class="breeze-run-r5" x="0" y="776.4" textLength="12.2" 
clip-path="url(#breeze-run-line-31)">│</text><text class="breeze-run-r5" 
x="244" y="776.4" textLength="1195.6" 
clip-path="url(#breeze-run-line-31)">[default:&#160;breeze]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
+</text><text class="breeze-run-r5" x="0" y="800.8" textLength="12.2" 
clip-path="url(#breeze-run-line-32)">│</text><text class="breeze-run-r4" 
x="24.4" y="800.8" textLength="158.6" 
clip-path="url(#breeze-run-line-32)">--docker-host</text><text 
class="breeze-run-r1" x="244" y="800.8" textLength="915" 
clip-path="url(#breeze-run-line-32)">Optional&#160;-&#160;docker&#160;host&#160;to&#160;use&#160;when&#160;running&#160;docker&#160;commands.&#160;When&#160;set,&#160;the&#160;`</text><text
 cl [...]
+</text><text class="breeze-run-r5" x="0" y="825.2" textLength="12.2" 
clip-path="url(#breeze-run-line-33)">│</text><text class="breeze-run-r1" 
x="244" y="825.2" textLength="1195.6" 
clip-path="url(#breeze-run-line-33)">ignored&#160;when&#160;building&#160;images.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
+</text><text class="breeze-run-r5" x="0" y="849.6" textLength="12.2" 
clip-path="url(#breeze-run-line-34)">│</text><text class="breeze-run-r7" 
x="244" y="849.6" textLength="1195.6" 
clip-path="url(#breeze-run-line-34)">(TEXT)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
+</text><text class="breeze-run-r5" x="0" y="874" textLength="1464" 
clip-path="url(#breeze-run-line-35)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-run-r1" x="1464" y="874" textLength="12.2" 
clip-path="url(#breeze-run-line-35)">
+</text><text class="breeze-run-r5" x="0" y="898.4" textLength="24.4" 
clip-path="url(#breeze-run-line-36)">╭─</text><text class="breeze-run-r5" 
x="24.4" y="898.4" textLength="183" 
clip-path="url(#breeze-run-line-36)">&#160;Other&#160;options&#160;</text><text 
class="breeze-run-r5" x="207.4" y="898.4" textLength="1232.2" 
clip-path="url(#breeze-run-line-36)">─────────────────────────────────────────────────────────────────────────────────────────────────────</text><text
 class="breeze-run-r5 [...]
+</text><text class="breeze-run-r5" x="0" y="922.8" textLength="12.2" 
clip-path="url(#breeze-run-line-37)">│</text><text class="breeze-run-r4" 
x="24.4" y="922.8" textLength="256.2" 
clip-path="url(#breeze-run-line-37)">--forward-credentials</text><text 
class="breeze-run-r6" x="366" y="922.8" textLength="24.4" 
clip-path="url(#breeze-run-line-37)">-f</text><text class="breeze-run-r1" 
x="414.8" y="922.8" textLength="634.4" 
clip-path="url(#breeze-run-line-37)">Forward&#160;local&#160;credentia [...]
+</text><text class="breeze-run-r5" x="0" y="947.2" textLength="12.2" 
clip-path="url(#breeze-run-line-38)">│</text><text class="breeze-run-r4" 
x="24.4" y="947.2" textLength="317.2" 
clip-path="url(#breeze-run-line-38)">--skip-image-upgrade-check</text><text 
class="breeze-run-r1" x="414.8" y="947.2" textLength="536.8" 
clip-path="url(#breeze-run-line-38)">Skip&#160;checking&#160;if&#160;the&#160;CI&#160;image&#160;is&#160;up&#160;to&#160;date.</text><text
 class="breeze-run-r5" x="1451.8" y=" [...]
+</text><text class="breeze-run-r5" x="0" y="971.6" textLength="1464" 
clip-path="url(#breeze-run-line-39)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-run-r1" x="1464" y="971.6" textLength="12.2" 
clip-path="url(#breeze-run-line-39)">
+</text><text class="breeze-run-r5" x="0" y="996" textLength="24.4" 
clip-path="url(#breeze-run-line-40)">╭─</text><text class="breeze-run-r5" 
x="24.4" y="996" textLength="195.2" 
clip-path="url(#breeze-run-line-40)">&#160;Common&#160;options&#160;</text><text
 class="breeze-run-r5" x="219.6" y="996" textLength="1220" 
clip-path="url(#breeze-run-line-40)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text
 class="breeze-run-r5" x="1 [...]
+</text><text class="breeze-run-r5" x="0" y="1020.4" textLength="12.2" 
clip-path="url(#breeze-run-line-41)">│</text><text class="breeze-run-r4" 
x="24.4" y="1020.4" textLength="109.8" 
clip-path="url(#breeze-run-line-41)">--dry-run</text><text 
class="breeze-run-r6" x="158.6" y="1020.4" textLength="24.4" 
clip-path="url(#breeze-run-line-41)">-D</text><text class="breeze-run-r1" 
x="207.4" y="1020.4" textLength="719.8" 
clip-path="url(#breeze-run-line-41)">If&#160;dry-run&#160;is&#160;set,&#160; 
[...]
+</text><text class="breeze-run-r5" x="0" y="1044.8" textLength="12.2" 
clip-path="url(#breeze-run-line-42)">│</text><text class="breeze-run-r4" 
x="24.4" y="1044.8" textLength="109.8" 
clip-path="url(#breeze-run-line-42)">--verbose</text><text 
class="breeze-run-r6" x="158.6" y="1044.8" textLength="24.4" 
clip-path="url(#breeze-run-line-42)">-v</text><text class="breeze-run-r1" 
x="207.4" y="1044.8" textLength="585.6" 
clip-path="url(#breeze-run-line-42)">Print&#160;verbose&#160;information&#16 
[...]
+</text><text class="breeze-run-r5" x="0" y="1069.2" textLength="12.2" 
clip-path="url(#breeze-run-line-43)">│</text><text class="breeze-run-r4" 
x="24.4" y="1069.2" textLength="73.2" 
clip-path="url(#breeze-run-line-43)">--help</text><text class="breeze-run-r6" 
x="158.6" y="1069.2" textLength="24.4" 
clip-path="url(#breeze-run-line-43)">-h</text><text class="breeze-run-r1" 
x="207.4" y="1069.2" textLength="329.4" 
clip-path="url(#breeze-run-line-43)">Show&#160;this&#160;message&#160;and&#160;e
 [...]
+</text><text class="breeze-run-r5" x="0" y="1093.6" textLength="1464" 
clip-path="url(#breeze-run-line-44)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-run-r1" x="1464" y="1093.6" textLength="12.2" 
clip-path="url(#breeze-run-line-44)">
+</text>
+    </g>
+    </g>
+</svg>
diff --git a/dev/breeze/doc/images/output_run.txt 
b/dev/breeze/doc/images/output_run.txt
new file mode 100644
index 00000000000..53c445f3e15
--- /dev/null
+++ b/dev/breeze/doc/images/output_run.txt
@@ -0,0 +1 @@
+820a829e6ae777a8625862d010f8e693
diff --git a/dev/breeze/doc/images/output_setup_check-all-params-in-groups.svg 
b/dev/breeze/doc/images/output_setup_check-all-params-in-groups.svg
index dd7f6cd19f2..0603451c7d5 100644
--- a/dev/breeze/doc/images/output_setup_check-all-params-in-groups.svg
+++ b/dev/breeze/doc/images/output_setup_check-all-params-in-groups.svg
@@ -208,7 +208,7 @@
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="630" 
textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-25)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="630" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-25)">release-management:publish-docs-to-s3&#160;|&#160;release-management:release-prod-images&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#
 [...]
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="654.4" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-26)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="654.4" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-26)">release-management:start-rc-process&#160;|&#160;release-management:start-release&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="678.8" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-27)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="678.8" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-27)">release-management:tag-providers&#160;|&#160;release-management:update-constraints&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="703.2" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="703.2" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">release-management:verify-provider-distributions&#160;|&#160;sbom&#160;|&#160;sbom:build-all-airflow-images&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="703.2" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="703.2" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">release-management:verify-provider-distributions&#160;|&#160;run&#160;|&#160;sbom&#160;|&#160;sbom:build-all-airflow-images&#160;|&#160;&#160;&#160;&#160;&#160
 [...]
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="727.6" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="727.6" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">sbom:export-dependency-information&#160;|&#160;sbom:generate-providers-requirements&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="752" 
textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="752" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">sbom:update-sbom-information&#160;|&#160;setup&#160;|&#160;setup:autocomplete&#160;|&#160;setup:check-all-params-in-groups&#160;|&#160;&#160;&#160;&#160;&#160;&#16
 [...]
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="776.4" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="776.4" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">setup:config&#160;|&#160;setup:regenerate-command-images&#160;|&#160;setup:self-upgrade&#160;|&#160;setup:synchronize-local-mounts&#160;|&#160;</text><text
 cla [...]
diff --git a/dev/breeze/doc/images/output_setup_check-all-params-in-groups.txt 
b/dev/breeze/doc/images/output_setup_check-all-params-in-groups.txt
index c712a698cd5..6afbc1c4b9a 100644
--- a/dev/breeze/doc/images/output_setup_check-all-params-in-groups.txt
+++ b/dev/breeze/doc/images/output_setup_check-all-params-in-groups.txt
@@ -1 +1 @@
-990975cc123e19cc0e094e129dcac59b
+b1c66655acd75f4f7c65b2d35552f54e
diff --git a/dev/breeze/doc/images/output_setup_regenerate-command-images.svg 
b/dev/breeze/doc/images/output_setup_regenerate-command-images.svg
index 9304f343dbc..91345750033 100644
--- a/dev/breeze/doc/images/output_setup_regenerate-command-images.svg
+++ b/dev/breeze/doc/images/output_setup_regenerate-command-images.svg
@@ -229,7 +229,7 @@
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="703.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-28)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="703.2" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-28)">release-management:publish-docs-to-s3&#160;|&#160;release-management:release-prod-images&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#
 [...]
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="727.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-29)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="727.6" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-29)">release-management:start-rc-process&#160;|&#160;release-management:start-release&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="752" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-30)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="752" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-30)">release-management:tag-providers&#160;|&#160;release-management:update-constraints&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="776.4" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-31)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="776.4" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-31)">release-management:verify-provider-distributions&#160;|&#160;sbom&#160;|&#160;sbom:build-all-airflow-images&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="776.4" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-31)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="776.4" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-31)">release-management:verify-provider-distributions&#160;|&#160;run&#160;|&#160;sbom&#160;|&#160;sbom:build-all-airflow-images&#160;|&#160;&#160;&#160;&#160;&#160;</t
 [...]
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="800.8" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-32)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="800.8" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-32)">sbom:export-dependency-information&#160;|&#160;sbom:generate-providers-requirements&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="825.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-33)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="825.2" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-33)">sbom:update-sbom-information&#160;|&#160;setup&#160;|&#160;setup:autocomplete&#160;|&#160;setup:check-all-params-in-groups&#160;|&#160;&#160;&#160;&#160;&#160;&#16
 [...]
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="849.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-34)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="849.6" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-34)">setup:config&#160;|&#160;setup:regenerate-command-images&#160;|&#160;setup:self-upgrade&#160;|&#160;setup:synchronize-local-mounts</text><text
 class="breeze-setup- [...]
diff --git a/dev/breeze/doc/images/output_setup_regenerate-command-images.txt 
b/dev/breeze/doc/images/output_setup_regenerate-command-images.txt
index 4fd763c19df..e1261a22897 100644
--- a/dev/breeze/doc/images/output_setup_regenerate-command-images.txt
+++ b/dev/breeze/doc/images/output_setup_regenerate-command-images.txt
@@ -1 +1 @@
-dd551b481de86089ffc562db65a88f2c
+d112f32bf3ac63a45cafb3cd1248d728
diff --git a/dev/breeze/src/airflow_breeze/commands/developer_commands.py 
b/dev/breeze/src/airflow_breeze/commands/developer_commands.py
index e4f032108fd..0a6ad967909 100644
--- a/dev/breeze/src/airflow_breeze/commands/developer_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/developer_commands.py
@@ -1075,6 +1075,9 @@ def exec(exec_args: tuple):
         if not process:
             sys.exit(1)
         sys.exit(process.returncode)
+    else:
+        get_console().print("[error]No airflow containers are running[/]")
+        sys.exit(1)
 
 
 def stop_exec_on_error(returncode: int):
@@ -1197,3 +1200,137 @@ def doctor(ctx):
         ctx.forward(cleanup)
     elif given_answer == Answer.QUIT:
         sys.exit(0)
+
+
[email protected](
+    name="run",
+    help="Run a command in the Breeze environment without entering the 
interactive shell.",
+    context_settings={"ignore_unknown_options": True, "allow_extra_args": 
True},
+)
[email protected]("command", required=True)
[email protected]("command_args", nargs=-1, type=click.UNPROCESSED)
+@option_backend
+@option_builder
+@option_docker_host
+@option_dry_run
+@option_force_build
+@option_forward_credentials
+@option_github_repository
+@option_mysql_version
+@option_platform_single
+@option_postgres_version
+@option_project_name
+@option_python
+@option_skip_image_upgrade_check
+@option_use_uv
+@option_uv_http_timeout
+@option_verbose
+def run(
+    command: str,
+    command_args: tuple,
+    backend: str,
+    builder: str,
+    docker_host: str | None,
+    force_build: bool,
+    forward_credentials: bool,
+    github_repository: str,
+    mysql_version: str,
+    platform: str | None,
+    postgres_version: str,
+    project_name: str,
+    python: str,
+    skip_image_upgrade_check: bool,
+    use_uv: bool,
+    uv_http_timeout: int,
+):
+    """
+    Run a command in the Breeze environment without entering the interactive 
shell.
+
+    This is useful for automated testing, CI workflows, and one-off command 
execution.
+    The command will be executed in a fresh container that is automatically 
cleaned up.
+    Each run uses a unique project name to avoid conflicts with other 
instances.
+
+    Examples:
+        # Run a specific test
+        breeze run pytest 
providers/google/tests/unit/google/cloud/operators/test_dataflow.py -v
+
+        # Check version compatibility
+        breeze run python -c "from airflow.providers.google.version_compat 
import AIRFLOW_V_3_0_PLUS; print(AIRFLOW_V_3_0_PLUS)"
+
+        # Run bash commands
+        breeze run bash -c "cd /opt/airflow && python -m pytest 
providers/google/tests/"
+
+        # Run with different Python version
+        breeze run --python 3.11 pytest 
providers/standard/tests/unit/operators/test_bash.py
+
+        # Run with PostgreSQL backend
+        breeze run --backend postgres pytest providers/postgres/tests/
+    """
+    import uuid
+
+    from airflow_breeze.commands.ci_image_commands import 
rebuild_or_pull_ci_image_if_needed
+    from airflow_breeze.params.shell_params import ShellParams
+    from airflow_breeze.utils.ci_group import ci_group
+    from airflow_breeze.utils.docker_command_utils import 
execute_command_in_shell
+    from airflow_breeze.utils.platforms import get_normalized_platform
+
+    # Generate a unique project name to avoid conflicts with other running 
instances
+    unique_project_name = f"{project_name}-run-{uuid.uuid4().hex[:8]}"
+
+    # Build the full command string with proper escaping
+    import shlex
+
+    if command_args:
+        # Use shlex.join to properly escape arguments
+        full_command = f"{command} {shlex.join(command_args)}"
+    else:
+        full_command = command
+
+    platform = get_normalized_platform(platform)
+
+    # Create shell parameters optimized for non-interactive command execution
+    shell_params = ShellParams(
+        backend=backend,
+        builder=builder,
+        docker_host=docker_host,
+        force_build=force_build,
+        forward_credentials=forward_credentials,
+        github_repository=github_repository,
+        mysql_version=mysql_version,
+        platform=platform,
+        postgres_version=postgres_version,
+        project_name=unique_project_name,
+        python=python,
+        skip_image_upgrade_check=skip_image_upgrade_check,
+        use_uv=use_uv,
+        uv_http_timeout=uv_http_timeout,
+        # Optimizations for non-interactive execution
+        quiet=True,
+        skip_environment_initialization=True,
+        tty="disabled",
+        # Set extra_args to empty tuple since we'll pass the command directly
+        extra_args=(),
+    )
+
+    if get_verbose():
+        get_console().print(f"[info]Running command in Breeze: 
{full_command}[/]")
+        get_console().print(f"[info]Using project name: 
{unique_project_name}[/]")
+
+    # Build or pull the CI image if needed
+    rebuild_or_pull_ci_image_if_needed(command_params=shell_params)
+
+    # Execute the command in the shell
+    with ci_group(f"Running command: {command}"):
+        result = execute_command_in_shell(
+            shell_params=shell_params,
+            project_name=unique_project_name,
+            command=full_command,
+        )
+
+    # Clean up ownership
+    from airflow_breeze.utils.docker_command_utils import 
fix_ownership_using_docker
+
+    fix_ownership_using_docker()
+
+    # Exit with the same code as the command
+    sys.exit(result.returncode)
diff --git 
a/dev/breeze/src/airflow_breeze/commands/developer_commands_config.py 
b/dev/breeze/src/airflow_breeze/commands/developer_commands_config.py
index bb5e449d038..eae6e0cb862 100644
--- a/dev/breeze/src/airflow_breeze/commands/developer_commands_config.py
+++ b/dev/breeze/src/airflow_breeze/commands/developer_commands_config.py
@@ -25,6 +25,7 @@ DEVELOPER_COMMANDS: dict[str, str | list[str]] = {
         "down",
         "shell",
         "exec",
+        "run",
         "compile-ui-assets",
         "cleanup",
         "generate-migration-file",
@@ -295,6 +296,42 @@ DEVELOPER_PARAMETERS: dict[str, list[dict[str, str | 
list[str]]]] = {
     "breeze exec": [
         {"name": "Drops in the interactive shell of active airflow container"},
     ],
+    "breeze run": [
+        {
+            "name": "Command execution",
+            "options": [
+                "--python",
+                "--backend",
+                "--postgres-version",
+                "--mysql-version",
+            ],
+        },
+        {
+            "name": "Build CI image (before running command)",
+            "options": [
+                "--force-build",
+                "--platform",
+                "--github-repository",
+                "--builder",
+                "--use-uv",
+                "--uv-http-timeout",
+            ],
+        },
+        {
+            "name": "Docker Compose project management",
+            "options": [
+                "--project-name",
+                "--docker-host",
+            ],
+        },
+        {
+            "name": "Other options",
+            "options": [
+                "--forward-credentials",
+                "--skip-image-upgrade-check",
+            ],
+        },
+    ],
     "breeze down": [
         {
             "name": "Down flags",
diff --git a/dev/breeze/src/airflow_breeze/commands/setup_commands.py 
b/dev/breeze/src/airflow_breeze/commands/setup_commands.py
index 1429a6b13f4..68954529007 100644
--- a/dev/breeze/src/airflow_breeze/commands/setup_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/setup_commands.py
@@ -562,6 +562,7 @@ DEVELOPER_COMMANDS = [
     "down",
     "exec",
     "shell",
+    "run",
     "compile-ui-assets",
     "cleanup",
     "generate-migration-file",

Reply via email to