diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 60f3e3f67966e..9b02fc34461da 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -378,9 +378,9 @@ jobs:
           FORCE_COLOR: 2
 
 
-  test-openapi-client-generation:
+  test-openapi-client:
     timeout-minutes: 10
-    name: "Test OpenAPI client generation"
+    name: "Test OpenAPI client"
     runs-on: ${{fromJSON(needs.build-info.outputs.runs-on)}}
     needs: [build-info]
     if: needs.build-info.outputs.needs-api-codegen == 'true'
@@ -392,8 +392,67 @@ jobs:
         with:
           fetch-depth: 2
           persist-credentials: false
-      - name: "Generate client codegen diff"
-        run: ./scripts/ci/openapi/client_codegen_diff.sh
+      - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
+        uses: actions/checkout@v4
+        with:
+          repository: "apache/airflow-client-python"
+          fetch-depth: 1
+          persist-credentials: false
+          path: ./airflow-client-python
+      - name: "Install Breeze"
+        uses: ./.github/actions/breeze
+      - name: "Generate client with breeze"
+        run: >
+          breeze release-management prepare-python-client --package-format both
+          --version-suffix-for-pypi dev0 --python-client-repo ./airflow-client-python
+      - name: "Show diff"
+        run: git diff --color HEAD
+        working-directory: ./airflow-client-python
+      - name: Install hatch
+        run: |
+          python -m pip install --upgrade pipx
+          pipx install hatch
+      - name: Run tests
+        run: hatch run run-coverage
+        env:
+          HATCH_ENV: "test"
+        working-directory: ./clients/python
+      - name: "Install Airflow in editable mode with fab for webserver tests"
+        run: pip install -e ".[fab]"
+      - name: "Install Python client"
+        run: pip install ./dist/apache_airflow_client-*.whl
+      - name: "Initialize Airflow DB and start webserver"
+        run: |
+          airflow db init
+          # Let scheduler runs a few loops and get all DAG files from example DAGs serialized to DB
+          airflow scheduler --num-runs 100
+          airflow users create --username admin --password admin --firstname Admin --lastname Admin \
+             --role Admin --email admin@example.org
+          killall python || true  # just in case there is a webserver running in the background
+          nohup airflow webserver --port 8080 &
+          echo "Started webserver"
+        env:
+          AIRFLOW__API__AUTH_BACKENDS: airflow.api.auth.backend.session,airflow.api.auth.backend.basic_auth
+          AIRFLOW__WEBSERVER__EXPOSE_CONFIG: "True"
+          AIRFLOW__CORE__LOAD_EXAMPLES: "True"
+      - name: "Waiting for the webserver to be available"
+        run: |
+          timeout 30 bash -c 'until nc -z $0 $1; do echo "sleeping"; sleep 1; done' localhost 8080
+          sleep 5
+      - name: "Run test python client"
+        run: python ./clients/python/test_python_client.py
+        env:
+          FORCE_COLOR: "standard"
+      - name: "Stop running webserver"
+        run: killall python || true  # just in case there is a webserver running in the background
+        if: always()
+      - name: "Upload python client packages"
+        uses: actions/upload-artifact@v3
+        with:
+          name: python-client-packages
+          path: ./dist/apache_airflow_client-*
+          retention-days: 7
+          if-no-files-found: error
 
   test-git-clone-on-windows:
     timeout-minutes: 5
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 4fe395776743f..676e8b0e4f0a3 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -94,6 +94,16 @@ repos:
           - --license-filepath
           - scripts/ci/license-templates/LICENSE.txt
           - --fuzzy-match-generates-todo
+      - id: insert-license
+        name: Add license for all toml files
+        exclude: ^\.github/.*$|^.*/.*_vendor/|^dev/breeze/autocomplete/.*$
+        files: \.toml$
+        args:
+          - --comment-style
+          - "|#|"
+          - --license-filepath
+          - scripts/ci/license-templates/LICENSE.txt
+          - --fuzzy-match-generates-todo
       - id: insert-license
         name: Add license for all Python files
         exclude: ^\.github/.*$|^.*/.*_vendor/
@@ -1107,7 +1117,7 @@ repos:
         language: python
         entry: ./scripts/ci/pre_commit/pre_commit_mypy.py --namespace-packages
         files: \.py$
-        exclude: ^.*/.*_vendor/|^airflow/migrations|^airflow/providers|^dev|^scripts|^docs|^provider_packages|^tests/providers|^tests/system/providers|^tests/dags/test_imports.py
+        exclude: ^.*/.*_vendor/|^airflow/migrations|^airflow/providers|^dev|^scripts|^docs|^provider_packages|^tests/providers|^tests/system/providers|^tests/dags/test_imports.py|^clients/python/test_.*\.py
         require_serial: true
         additional_dependencies: ['rich>=12.4.4']
       - id: mypy-airflow
diff --git a/.rat-excludes b/.rat-excludes
index 6464d827d5626..f7e492374a6e9 100644
--- a/.rat-excludes
+++ b/.rat-excludes
@@ -152,3 +152,7 @@ PKG-INFO
 
 # checksum files
 .*\.md5sum
+
+# Openapi files
+.openapi-generator-ignore
+version.txt
diff --git a/BREEZE.rst b/BREEZE.rst
index e5a12a8ac9454..6311463765391 100644
--- a/BREEZE.rst
+++ b/BREEZE.rst
@@ -2049,6 +2049,28 @@ When we prepare final release, we automate some of the steps we need to do.
   :width: 100%
   :alt: Breeze release-management start-rc-process
 
+
+Preparing Python Clients
+""""""""""""""""""""""""
+
+The **Python client** source code can be generated and Python client packages could be built. For that you
+need to have python client's repository checked out
+
+
+.. code-block:: bash
+
+     breeze release-management prepare-python-client --python-client-repo ~/code/airflow-client-python
+
+You can also generate python client with custom security schemes.
+
+These are all of the available flags for the command:
+
+.. image:: ./images/breeze/output_release-management_prepare-python-client.svg
+  :target: https://raw.githubusercontent.com/apache/airflow/main/images/breeze/output_release-management_prepare-python-client.svg
+  :width: 100%
+  :alt: Breeze release management prepare Python client
+
+
 Releasing Production images
 """""""""""""""""""""""""""
 
diff --git a/STATIC_CODE_CHECKS.rst b/STATIC_CODE_CHECKS.rst
index 4a357984f46af..b03b14332120e 100644
--- a/STATIC_CODE_CHECKS.rst
+++ b/STATIC_CODE_CHECKS.rst
@@ -320,6 +320,7 @@ require Breeze Docker image to be built locally.
 |                                                           | * Add license for all CSS/JS/JSX/PUML/TS/TSX files           |         |
 |                                                           | * Add license for all JINJA template files                   |         |
 |                                                           | * Add license for all Shell files                            |         |
+|                                                           | * Add license for all toml files                             |         |
 |                                                           | * Add license for all Python files                           |         |
 |                                                           | * Add license for all XML files                              |         |
 |                                                           | * Add license for all Helm template files                    |         |
diff --git a/clients/README.md b/clients/README.md
index 6a665f67e0756..dba7bbe7009be 100644
--- a/clients/README.md
+++ b/clients/README.md
@@ -19,20 +19,30 @@
 
 # Airflow OpenAPI clients
 
+This directory contains definition of Airflow OpenAPI client packages.
+
 Supported languages:
 
-* [Golang](https://github.com/apache/airflow-client-go) generated through `./gen/go.sh`.
 * [Python](https://github.com/apache/airflow-client-python) generated through `./gen/python.sh`.
 
-## Dependencies
+## Generating client code
 
-All client generation scripts use [pre-commit](https://pre-commit.com/#install)
-to prepend license header to generated code.
+To generate the client code using dockerized breeze environment, run (at the Airflow source root directory):
 
-## Usage
+```bash
+breeze release-management prepare-python-client --package-format both
+```
 
-To generate Go client, run:
+The client source code generation uses OpenAPI generator image, generation of packages is done using Hatch.
+By default, packages are generated in a dockerized Hatch environment, but you can also use a local one by
+setting `--use-local-hatch` flag.
 
+```bash
+breeze release-management prepare-python-client --package-format both --use-local-hatch
 ```
-bash ./gen/go.sh ../airflow/api_connexion/openapi/v1.yaml AIRFLOW_CLIENT_GO_REPO_PATH/airflow
-```
+
+## Browsing the generated source code
+
+The generated source code is not committed to Airflow repository, but when releasing the package, Airflow
+team also stores generated client code in the
+[Airflow Client Python repository](https://github.com/apache/airflow-client-python).
diff --git a/clients/gen/common.sh b/clients/gen/common.sh
deleted file mode 100755
index 0437028351589..0000000000000
--- a/clients/gen/common.sh
+++ /dev/null
@@ -1,91 +0,0 @@
-#!/bin/bash
-
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-OPENAPI_GENERATOR_CLI_VER=5.4.0
-readonly OPENAPI_GENERATOR_CLI_VER
-
-GIT_USER=${GIT_USER:-apache}
-readonly GIT_USER
-
-function validate_input {
-    if [ "$#" -ne 2 ]; then
-        echo "USAGE: $0 SPEC_PATH OUTPUT_DIR"
-        exit 1
-    fi
-
-    if ! [ -x "$(command -v realpath)" ]; then
-      echo 'Error: realpath is not installed.' >&2
-      exit 1
-    fi
-
-    SPEC_PATH=$(realpath "$1")
-    readonly SPEC_PATH
-
-    if [ ! -d "$2" ]; then
-        echo "$2 is not a valid directory or does not exist."
-        exit 1
-    fi
-
-    OUTPUT_DIR=$(realpath "$2")
-    readonly OUTPUT_DIR
-
-    # cleanup the existing generated code, otherwise generator would skip them
-    for dir in "${CLEANUP_DIRS[@]}"
-    do
-        local dirToClean="${OUTPUT_DIR}/${dir}"
-        echo "Cleaning up ${dirToClean}"
-        rm -rf "${dirToClean:?}"
-    done
-
-    # create openapi ignore file to keep generated code clean
-    cat <<EOF > "${OUTPUT_DIR}/.openapi-generator-ignore"
-.travis.yml
-git_push.sh
-.gitlab-ci.yml
-requirements.txt
-pyproject.toml
-test-requirements.txt
-tox.ini
-EOF
-}
-
-function run_pre_commit {
-    cd "${OUTPUT_DIR}"
-
-    # prepend license headers
-    pre-commit run --all-files || true
-    echo "Output above might state Failed: 'Some sources were modified by the hook' - This is expected as the hook is used to add the licences."
-}
-
-function gen_client {
-    lang=$1
-    shift
-    set -ex
-    IFS=','
-    docker run --rm \
-        -u "$(id -u):$(id -g)" \
-        -v "${SPEC_PATH}:/spec" \
-        -v "${OUTPUT_DIR}:/output" \
-        openapitools/openapi-generator-cli:v${OPENAPI_GENERATOR_CLI_VER} \
-        generate \
-        --input-spec "/spec" \
-        --generator-name "${lang}" \
-        --git-user-id "${GIT_USER}" \
-        --output "/output" "$@"
-}
diff --git a/clients/gen/go.sh b/clients/gen/go.sh
deleted file mode 100755
index a38fc87ad0cd8..0000000000000
--- a/clients/gen/go.sh
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/bin/bash
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-CLIENTS_GEN_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
-readonly CLIENTS_GEN_DIR
-
-CLEANUP_DIRS=(api docs)
-readonly CLEANUP_DIRS
-
-# shellcheck source=./clients/gen/common.sh
-source "${CLIENTS_GEN_DIR}/common.sh"
-
-VERSION=2.5.0
-readonly VERSION
-
-go_config=(
-    "packageVersion=${VERSION}"
-    "enumClassPrefix=true"
-    "structPrefix=true"
-)
-
-validate_input "$@"
-
-# additional-properties key value tuples need to be separated by comma, not space
-IFS=,
-gen_client go \
-    --package-name airflow \
-    --git-repo-id airflow-client-go/airflow \
-    --additional-properties "${go_config[*]}"
-
-# fix client content type validation regexp:
-# https://github.com/OpenAPITools/openapi-generator/issues/4890
-sed -i "s/(?:vnd\\\.\[^;\]+\\\+)?json/(?:(?:vnd\\\.\[^;\]+\\\+)|(?:problem\\\+))?json/g" "${OUTPUT_DIR}/client.go"
-sed -i "s/(?i:(?:application|text)\/xml/(?i:(?:application|text)\/(?:problem\\\+)?xml/g" "${OUTPUT_DIR}/client.go"
-
-run_pre_commit
-echo "Generation successful"
diff --git a/clients/gen/python.sh b/clients/gen/python.sh
deleted file mode 100755
index c3d9e5766a49d..0000000000000
--- a/clients/gen/python.sh
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/bin/bash
-set -ueo pipefail
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-CLIENTS_GEN_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
-readonly CLIENTS_GEN_DIR
-
-CLEANUP_DIRS=(client docs test README.md)
-readonly CLEANUP_DIRS
-
-# shellcheck source=./clients/gen/common.sh
-source "${CLIENTS_GEN_DIR}/common.sh"
-
-VERSION=2.5.1
-readonly VERSION
-
-python_config=(
-    "packageVersion=${VERSION}"
-)
-
-validate_input "$@"
-
-gen_client python \
-    --package-name client \
-    --git-repo-id airflow-client-python \
-    --additional-properties "${python_config[*]}"
-
-echo "--- Patching generated code..."
-
-# Post-processing of the generated Python wrapper.
-
-INPLACE_ARG=("-i")
-if [[ "$OSTYPE" == "darwin"* ]]; then
-    INPLACE_ARG=(-i '')
-fi
-
-touch "${OUTPUT_DIR}/__init__.py"
-find "${OUTPUT_DIR}/test" -type f -name \*.py -exec sed "${INPLACE_ARG[@]}" -e 's/client/airflow_client.client/g' {} +
-find "${OUTPUT_DIR}" -type f -a -name \*.md -exec sed "${INPLACE_ARG[@]}" -e 's/# client/# Apache Airflow Python Client/g' {} +
-find "${OUTPUT_DIR}" -type f -a -name \*.md -exec sed "${INPLACE_ARG[@]}" -e 's/import client/import airflow_client.client/g' {} +
-find "${OUTPUT_DIR}" -type f -a -name \*.md -exec sed "${INPLACE_ARG[@]}" -e 's/from client/from airflow_client.client/g' {} +
-find "${OUTPUT_DIR}" -type f -a -name \*.md -exec sed "${INPLACE_ARG[@]}" -e 's/getattr(client\.models/getattr(airflow_client.client.models/g' {} +
-
-# fix imports
-find "${OUTPUT_DIR}/client/" -type f -name \*.py -exec sed "${INPLACE_ARG[@]}" -e 's/import client\./import airflow_client.client./g' {} +
-find "${OUTPUT_DIR}/client/" -type f -name \*.py -exec sed "${INPLACE_ARG[@]}" -e 's/from client/from airflow_client.client/g' {} +
-find "${OUTPUT_DIR}/client/" -type f -name \*.py -exec sed "${INPLACE_ARG[@]}" -e 's/getattr(client\.models/getattr(airflow_client.client.models/g' {} +
-
-run_pre_commit
-echo "Generation successful"
diff --git a/clients/python/.gitignore b/clients/python/.gitignore
new file mode 100644
index 0000000000000..7bf956fe5584b
--- /dev/null
+++ b/clients/python/.gitignore
@@ -0,0 +1,9 @@
+/airflow_client
+/docs
+/dist
+/test
+/tmp
+/v1.yaml
+/.coverage
+/apache_airflow_client.egg-info/
+/.idea
diff --git a/clients/python/.openapi-generator-ignore b/clients/python/.openapi-generator-ignore
new file mode 100644
index 0000000000000..36151b881984f
--- /dev/null
+++ b/clients/python/.openapi-generator-ignore
@@ -0,0 +1,8 @@
+.travis.yml
+git_push.sh
+.gitlab-ci.yml
+requirements.txt
+setup.cfg
+setup.py
+test-requirements.txt
+tox.ini
diff --git a/clients/python/CHANGELOG.md b/clients/python/CHANGELOG.md
new file mode 100644
index 0000000000000..259cc063b0601
--- /dev/null
+++ b/clients/python/CHANGELOG.md
@@ -0,0 +1,248 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ -->
+
+# v2.8.0
+
+## Major changes:
+
+  - Allow filtering event logs by attributes ([#34417](https://github.com/apache/airflow/pull/34417))
+  - Add extra fields to plugins endpoint ([#34913](https://github.com/apache/airflow/pull/34913))
+  - Let auth managers provide their own API endpoints ([#34349](https://github.com/apache/airflow/pull/34349))
+  - Enable pools to consider deferred tasks ([#32709](https://github.com/apache/airflow/pull/32709))
+  - Add dag_run_ids and task_ids filter for the batch task instance API endpoint ([#32705](https://github.com/apache/airflow/pull/32705))
+
+## Major Fixes
+
+  - Add DagModel attributes before dumping DagDetailSchema for get_dag_details API endpoint ([#34947](https://github.com/apache/airflow/pull/34947))
+  - Add TriggerRule missing value in rest API ([#35194](https://github.com/apache/airflow/pull/35194))
+  - Fix wrong plugin schema ([#34858](https://github.com/apache/airflow/pull/34858))
+  - Make dry run optional for patch task instance ([#34568](https://github.com/apache/airflow/pull/34568))
+  - OpenAPI Spec fix nullable alongside $ref ([#32887](https://github.com/apache/airflow/pull/32887))
+  - Clarify new_state in OpenAPI spec ([#34056](https://github.com/apache/airflow/pull/34056))
+
+## NEW API supported
+
+  - NA
+
+# v2.7.3
+
+## Major changes:
+
+ - NA
+
+## Major Fixes
+
+ - Add TriggerRule missing value in rest API ([#35194](https://github.com/apache/airflow/pull/35194))
+ - Fix wrong plugin schema ([#34858](https://github.com/apache/airflow/pull/34858))
+
+# v2.7.2
+
+ Apache Airflow API version: 2.7.2
+
+## Major changes:
+
+ - NA
+
+## Major Fixes
+
+- Fix: make dry run optional for patch task instance  ([#34568](https://github.com/apache/airflow/pull/34568))
+
+## NEW API supported
+
+ - NA
+
+# v2.7.0
+
+Apache Airflow API version: 2.7.0
+
+## Major changes:
+
+ - Enable pools to consider deferred tasks ([#32709](https://github.com/apache/airflow/pull/32709))
+ - add dag_run_ids and task_ids filter for the batch task instance API endpoint ([#32705](https://github.com/apache/airflow/pull/32705))
+ - Add xcom map_index as a filter to xcom endpoint ([#32453](https://github.com/apache/airflow/pull/32453))
+ - Updates health check endpoint to include dag_processor status. ([#32382](https://github.com/apache/airflow/pull/32382))
+ - Add TriggererStatus to OpenAPI spec ([#31579](https://github.com/apache/airflow/pull/31579))
+
+## Major Fixes
+
+ - OpenAPI Spec fix nullable alongside $ref ([#32887](https://github.com/apache/airflow/pull/32887))
+ - Fix incorrect default on readonly property in our API ([#32510](https://github.com/apache/airflow/pull/32510))
+ - Fix broken links in openapi/v1.yaml ([#31619](https://github.com/apache/airflow/pull/31619))
+ - Update Dag trigger API and command docs ([#32696](https://github.com/apache/airflow/pull/32696))
+
+## NEW API supported
+
+ - NA
+
+# v2.6.2
+
+Apache Airflow API version: 2.6.2
+
+## Major changes:
+
+ - Add TriggererStatus to OpenAPI spec ([#31579](https://github.com/apache/airflow/pull/31579))
+
+## Major Fixes
+
+ - Fixing broken links in openapi/v1.yaml ([#31619](https://github.com/apache/airflow/pull/31619))
+
+## NEW API supported
+
+ - NA
+
+# v2.6.1
+
+Apache Airflow API version: 2.6.1
+
+## Major changes:
+
+ - NA
+
+## Major Fixes
+
+ - Fix Pool schema OpenAPI spec ([#30973](https://github.com/apache/airflow/pull/30973))
+
+## NEW API supported
+
+ - NA
+
+# v2.6.0
+
+Apache Airflow API version: 2.6.0
+
+## Major changes:
+
+ - Minimum Python version is 3.7
+ - DAGRun dag_id parameter is properly validated as read-only and setting it might result in an error:
+   "`dag_id` is a read-only attribute" This might break some workflows that used examples from the documentation.
+
+## Major Fixes
+
+ - Move read only property in order to fix Dagrun API docs ([#30149](https://github.com/apache/airflow/pull/30149))
+ - Fix clear dag run openapi spec responses by adding additional return type ([#29600](https://github.com/apache/airflow/pull/29600))
+ - Fix Rest API update user output ([#29409](https://github.com/apache/airflow/pull/29409))
+ - Add a param for get_dags endpoint to list only unpaused dags
+([#28713](https://github.com/apache/airflow/pull/28713))
+ - Expose updated_at filter for dag run and task instance endpoints ([#28636](https://github.com/apache/airflow/pull/28636))
+
+## NEW API supported
+
+ - NA
+
+# v2.5.1
+
+Apache Airflow API version: 2.5.1
+
+## Major changes:
+
+- NA
+
+## Major fixes:
+
+- Fix authentication issues by regenerating the client with proper security schemas
+
+## New API supported:
+
+- NA
+
+# v2.5.0
+
+Apache Airflow API version: 2.5.x
+
+## Major changes:
+
+- NA
+
+## Major fixes:
+
+- NA
+
+## New API supported:
+
+- GET /datasets/events | Get dataset events
+- GET /datasets | Get datasets
+- GET /datasets/{id} | Get a dataset
+- POST /dags/{dag_id}/dagRuns/{dag_run_id}/clear | Clear a dagrun endpoint
+- GET /dags/{dag_id}/dagRuns/{dag_run_id}/upstreamDatasetEvents | Get dataset events for a DAG run
+
+# v2.3.0
+
+Apache Airflow API version: 2.3.x
+
+## Major changes:
+
+- NA
+
+## Major fixes:
+
+- NA
+
+## New API supported:
+
+- PATCH /dags | Update DAGs
+- GET /dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/{map_index} | Get a mapped task instance
+- GET /dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/listMapped | List mapped task instances
+
+# v2.2.0
+
+Apache Airflow API version: 2.2.x
+
+## Major changes:
+
+- Client code is generated using OpenApi's 5.3.0 generator CLI
+
+## Major fixes:
+
+- NA
+
+## New API supported:
+
+- POST /connections/test | Test a connection
+- DELETE /dags/{dag_id} | Delete a DAG
+- PATCH /dags/{dag_id}/dagRuns/{dag_run_id} | Modify a DAG run
+- DELETE /users/{username} | Delete a user
+- PATCH /users/{username} | Update a user
+- POST /users | Create a user
+
+# v2.1.0
+
+Apache Airflow API version: 2.1.x
+
+## Major changes:
+
+ - Client code is generated using OpenApi's 5.1.1 generator CLI
+
+## Major fixes:
+
+ - Fixed the iteration issue on array items caused by unsupported class 'object'.
+   Issue [#15](https://github.com/apache/airflow-client-python/issues/15)
+
+## New API supported:
+
+ - Permissions
+ - Plugins
+ - Providers
+ - Roles
+ - Users
+
+# v2.0.0
+
+Apache Airflow API version: 2.0.x
+
+Initial version of the Python client.
diff --git a/clients/python/INSTALL b/clients/python/INSTALL
new file mode 100644
index 0000000000000..edf1a74823548
--- /dev/null
+++ b/clients/python/INSTALL
@@ -0,0 +1,26 @@
+# INSTALL / BUILD instructions for Apache Airflow Python Client
+
+This ia a generic installation method that requires a number of dependencies to be installed.
+
+Depending on your system you might need different prerequisites, but the Python3.6 or above is a must.
+
+# [required] fetch the tarball and untar the source move into the directory that was untarred.
+
+# [optional] run Apache RAT (release audit tool) to validate license headers
+# RAT docs here: https://creadur.apache.org/rat/. Requires Java and Apache Rat
+java -jar apache-rat.jar -E ./.rat-excludes -d .
+
+# [optional] You may want to install the client into a virtual env to keep the
+# dependencies separated from the system wide versions
+
+python3 -m venv PATH_TO_YOUR_VENV
+source PATH_TO_YOUR_VENV/bin/activate
+
+# [required] building and installing by pip (the package can also be built with any other modern tools
+# that can build Python packages, e.g. setuptools, but pip is the recommended way)
+
+pip install .
+
+# We also recommend hatch to convert the client to packages
+
+hatch build -c -t wheel -t sdist
diff --git a/clients/python/LICENSE b/clients/python/LICENSE
new file mode 100644
index 0000000000000..b83a80d26d245
--- /dev/null
+++ b/clients/python/LICENSE
@@ -0,0 +1,253 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+============================================================================
+   APACHE AIRFLOW SUBCOMPONENTS:
+
+   The Apache Airflow project contains subcomponents with separate copyright
+   notices and license terms. Your use of the source code for the these
+   subcomponents is subject to the terms and conditions of the following
+   licenses.
+
+
+========================================================================
+Third party Apache 2.0 licenses
+========================================================================
+
+The following components are provided under the Apache 2.0 License.
+See project link for details. The text of each license is also included
+at licenses/LICENSE-[project].txt.
+
+    (ALv2 License) hue v4.3.0 (https://github.com/cloudera/hue/)
+    (ALv2 License) jqclock v2.3.0 (https://github.com/JohnRDOrazio/jQuery-Clock-Plugin)
+    (ALv2 License) bootstrap3-typeahead v4.0.2 (https://github.com/bassjobsen/Bootstrap-3-Typeahead)
+    (ALv2 License) connexion v2.7.0 (https://github.com/zalando/connexion)
+
+========================================================================
+MIT licenses
+========================================================================
+
+The following components are provided under the MIT License. See project link for details.
+The text of each license is also included at licenses/LICENSE-[project].txt.
+
+    (MIT License) jquery v3.5.1 (https://jquery.org/license/)
+    (MIT License) dagre-d3 v0.6.4 (https://github.com/cpettitt/dagre-d3)
+    (MIT License) bootstrap v3.4.1 (https://github.com/twbs/bootstrap/)
+    (MIT License) d3-tip v0.9.1 (https://github.com/Caged/d3-tip)
+    (MIT License) dataTables v1.10.25 (https://datatables.net)
+    (MIT License) normalize.css v3.0.2 (http://necolas.github.io/normalize.css/)
+    (MIT License) ElasticMock v1.3.2 (https://github.com/vrcmarcos/elasticmock)
+    (MIT License) MomentJS v2.24.0 (http://momentjs.com/)
+    (MIT License) eonasdan-bootstrap-datetimepicker v4.17.49 (https://github.com/eonasdan/bootstrap-datetimepicker/)
+
+========================================================================
+BSD 3-Clause licenses
+========================================================================
+The following components are provided under the BSD 3-Clause license. See project links for details.
+The text of each license is also included at licenses/LICENSE-[project].txt.
+
+    (BSD 3 License) d3 v5.16.0 (https://d3js.org)
+    (BSD 3 License) d3-shape v2.1.0 (https://github.com/d3/d3-shape)
+    (BSD 3 License) cgroupspy 0.2.1 (https://github.com/cloudsigma/cgroupspy)
+
+========================================================================
+See licenses/LICENSES-ui.txt for packages used in `/airflow/www`
diff --git a/clients/python/NOTICE b/clients/python/NOTICE
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clients/python/README.md b/clients/python/README.md
new file mode 100644
index 0000000000000..dc8fd402ae2bb
--- /dev/null
+++ b/clients/python/README.md
@@ -0,0 +1,610 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ -->
+
+# Apache Airflow Python Client
+
+# Overview
+
+To facilitate management, Apache Airflow supports a range of REST API endpoints across its
+objects.
+This section provides an overview of the API design, methods, and supported use cases.
+
+Most of the endpoints accept `JSON` as input and return `JSON` responses.
+This means that you must usually add the following headers to your request:
+
+```
+Content-type: application/json
+Accept: application/json
+```
+
+## Resources
+
+The term `resource` refers to a single type of object in the Airflow metadata. An API is broken up by its
+endpoint's corresponding resource.
+The name of a resource is typically plural and expressed in camelCase. Example: `dagRuns`.
+
+Resource names are used as part of endpoint URLs, as well as in API parameters and responses.
+
+## CRUD Operations
+
+The platform supports **Create**, **Read**, **Update**, and **Delete** operations on most resources.
+You can review the standards for these operations and their standard parameters below.
+
+Some endpoints have special behavior as exceptions.
+
+### Create
+
+To create a resource, you typically submit an HTTP `POST` request with the resource's required metadata
+in the request body.
+The response returns a `201 Created` response code upon success with the resource's metadata, including
+its internal `id`, in the response body.
+
+### Read
+
+The HTTP `GET` request can be used to read a resource or to list a number of resources.
+
+A resource's `id` can be submitted in the request parameters to read a specific resource.
+The response usually returns a `200 OK` response code upon success, with the resource's metadata in
+the response body.
+
+If a `GET` request does not include a specific resource `id`, it is treated as a list request.
+The response usually returns a `200 OK` response code upon success, with an object containing a list
+of resources' metadata in the response body.
+
+When reading resources, some common query parameters are usually available. e.g.:
+
+```
+v1/connections?limit=25&offset=25
+```
+
+|Query Parameter|Type|Description|
+|---------------|----|-----------|
+|limit|integer|Maximum number of objects to fetch. Usually 25 by default|
+|offset|integer|Offset after which to start returning objects. For use with limit query parameter.|
+
+### Update
+
+Updating a resource requires the resource `id`, and is typically done using an HTTP `PATCH` request,
+with the fields to modify in the request body.
+The response usually returns a `200 OK` response code upon success, with information about the modified
+resource in the response body.
+
+### Delete
+
+Deleting a resource requires the resource `id` and is typically executing via an HTTP `DELETE` request.
+The response usually returns a `204 No Content` response code upon success.
+
+## Conventions
+
+- Resource names are plural and expressed in camelCase.
+- Names are consistent between URL parameter name and field name.
+
+- Field names are in snake_case.
+
+```json
+{
+    \"name\": \"string\",
+    \"slots\": 0,
+    \"occupied_slots\": 0,
+    \"used_slots\": 0,
+    \"queued_slots\": 0,
+    \"open_slots\": 0
+}
+```
+
+### Update Mask
+
+Update mask is available as a query parameter in patch endpoints. It is used to notify the
+API which fields you want to update. Using `update_mask` makes it easier to update objects
+by helping the server know which fields to update in an object instead of updating all fields.
+The update request ignores any fields that aren't specified in the field mask, leaving them with
+their current values.
+
+Example:
+
+```python
+import requests
+
+resource = requests.get("/resource/my-id").json()
+resource["my_field"] = "new-value"
+requests.patch("/resource/my-id?update_mask=my_field", data=json.dumps(resource))
+```
+
+## Versioning and Endpoint Lifecycle
+
+- API versioning is not synchronized to specific releases of the Apache Airflow.
+- APIs are designed to be backward compatible.
+- Any changes to the API will first go through a deprecation phase.
+
+# Trying the API
+
+You can use a third party client, such as [curl](https://curl.haxx.se/), [HTTPie](https://httpie.org/),
+[Postman](https://www.postman.com/) or [the Insomnia rest client](https://insomnia.rest/) to test
+the Apache Airflow API.
+
+Note that you will need to pass credentials data.
+
+For e.g., here is how to pause a DAG with [curl](https://curl.haxx.se/), when basic authorization is used:
+
+```bash
+curl -X PATCH 'https://example.com/api/v1/dags/{dag_id}?update_mask=is_paused' \\
+-H 'Content-Type: application/json' \\
+--user \"username:password\" \\
+-d '{
+    \"is_paused\": true
+}'
+```
+
+Using a graphical tool such as [Postman](https://www.postman.com/) or [Insomnia](https://insomnia.rest/),
+it is possible to import the API specifications directly:
+
+1. Download the API specification by clicking the **Download** button at top of this document.
+2. Import the JSON specification in the graphical tool of your choice.
+
+  - In *Postman*, you can click the **import** button at the top
+  - With *Insomnia*, you can just drag-and-drop the file on the UI
+
+Note that with *Postman*, you can also generate code snippets by selecting a request and clicking on
+the **Code** button.
+
+## Enabling CORS
+
+[Cross-origin resource sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)
+is a browser security feature that restricts HTTP requests that are
+initiated from scripts running in the browser.
+
+For details on enabling/configuring CORS, see
+[Enabling CORS](https://airflow.apache.org/docs/apache-airflow/stable/security/api.html).
+
+# Authentication
+
+To be able to meet the requirements of many organizations, Airflow supports many authentication methods,
+and it is even possible to add your own method.
+
+If you want to check which auth backend is currently set, you can use
+`airflow config get-value api auth_backends` command as in the example below.
+
+```bash
+$ airflow config get-value api auth_backends
+airflow.api.auth.backend.basic_auth
+```
+
+The default is to deny all requests.
+
+For details on configuring the authentication, see
+[API Authorization](https://airflow.apache.org/docs/apache-airflow/stable/security/api.html).
+
+# Errors
+
+We follow the error response format proposed in [RFC 7807](https://tools.ietf.org/html/rfc7807)
+also known as Problem Details for HTTP APIs. As with our normal API responses,
+your client must be prepared to gracefully handle additional members of the response.
+
+## Unauthenticated
+
+This indicates that the request has not been applied because it lacks valid authentication
+credentials for the target resource. Please check that you have valid credentials.
+
+## PermissionDenied
+
+This response means that the server understood the request but refuses to authorize
+it because it lacks sufficient rights to the resource. It happens when you do not have the
+necessary permission to execute the action you performed. You need to get the appropriate
+permissions in other to resolve this error.
+
+## BadRequest
+
+This response means that the server cannot or will not process the request due to something
+that is perceived to be a client error (e.g., malformed request syntax, invalid request message
+framing, or deceptive request routing). To resolve this, please ensure that your syntax is correct.
+
+## NotFound
+
+This client error response indicates that the server cannot find the requested resource.
+
+## MethodNotAllowed
+
+Indicates that the request method is known by the server but is not supported by the target resource.
+
+## NotAcceptable
+
+The target resource does not have a current representation that would be acceptable to the user
+agent, according to the proactive negotiation header fields received in the request, and the
+server is unwilling to supply a default representation.
+
+## AlreadyExists
+
+The request could not be completed due to a conflict with the current state of the target
+resource, e.g. the resource it tries to create already exists.
+
+## Unknown
+
+This means that the server encountered an unexpected condition that prevented it from
+fulfilling the request.
+
+This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
+
+- API version: 2.8.0
+- Package version: 2.8.0
+- Build package: org.openapitools.codegen.languages.PythonClientCodegen
+For more information, please visit [https://airflow.apache.org](https://airflow.apache.org)
+
+## Requirements.
+
+Python >=3.8
+
+## Installation & Usage
+
+### pip install
+
+You can install the client using standard Python installation tools. It is hosted
+in PyPI with `apache-airflow-client` package id so the easiest way to get the latest
+version is to run:
+
+```bash
+pip install apache-airflow-client
+```
+
+If the python package is hosted on a repository, you can install directly using:
+
+```bash
+pip install git+https://github.com/apache/airflow-client-python.git
+```
+
+### Import check
+
+Then import the package:
+
+```python
+import airflow_client.client
+```
+
+## Getting Started
+
+Please follow the [installation procedure](#installation--usage) and then run the following:
+
+```python
+import time
+import airflow_client.client
+from pprint import pprint
+from airflow_client.client.api import config_api
+from airflow_client.client.model.config import Config
+from airflow_client.client.model.error import Error
+
+# Defining the host is optional and defaults to /api/v1
+# See configuration.py for a list of all supported configuration parameters.
+configuration = client.Configuration(host="/api/v1")
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure HTTP basic authorization: Basic
+configuration = client.Configuration(username="YOUR_USERNAME", password="YOUR_PASSWORD")
+
+
+# Enter a context with an instance of the API client
+with client.ApiClient(configuration) as api_client:
+    # Create an instance of the API class
+    api_instance = config_api.ConfigApi(api_client)
+
+    try:
+        # Get current configuration
+        api_response = api_instance.get_config()
+        pprint(api_response)
+    except client.ApiException as e:
+        print("Exception when calling ConfigApi->get_config: %s\n" % e)
+```
+
+## Documentation for API Endpoints
+
+All URIs are relative to */api/v1*
+
+Class | Method | HTTP request | Description
+------------ | ------------- | ------------- | -------------
+*ConfigApi* | [**get_config**](docs/ConfigApi.md#get_config) | **GET** /config | Get current configuration
+*ConnectionApi* | [**delete_connection**](docs/ConnectionApi.md#delete_connection) | **DELETE** /connections/{connection_id} | Delete a connection
+*ConnectionApi* | [**get_connection**](docs/ConnectionApi.md#get_connection) | **GET** /connections/{connection_id} | Get a connection
+*ConnectionApi* | [**get_connections**](docs/ConnectionApi.md#get_connections) | **GET** /connections | List connections
+*ConnectionApi* | [**patch_connection**](docs/ConnectionApi.md#patch_connection) | **PATCH** /connections/{connection_id} | Update a connection
+*ConnectionApi* | [**post_connection**](docs/ConnectionApi.md#post_connection) | **POST** /connections | Create a connection
+*ConnectionApi* | [**test_connection**](docs/ConnectionApi.md#test_connection) | **POST** /connections/test | Test a connection
+*DAGApi* | [**delete_dag**](docs/DAGApi.md#delete_dag) | **DELETE** /dags/{dag_id} | Delete a DAG
+*DAGApi* | [**get_dag**](docs/DAGApi.md#get_dag) | **GET** /dags/{dag_id} | Get basic information about a DAG
+*DAGApi* | [**get_dag_details**](docs/DAGApi.md#get_dag_details) | **GET** /dags/{dag_id}/details | Get a simplified representation of DAG
+*DAGApi* | [**get_dag_source**](docs/DAGApi.md#get_dag_source) | **GET** /dagSources/{file_token} | Get a source code
+*DAGApi* | [**get_dags**](docs/DAGApi.md#get_dags) | **GET** /dags | List DAGs
+*DAGApi* | [**get_task**](docs/DAGApi.md#get_task) | **GET** /dags/{dag_id}/tasks/{task_id} | Get simplified representation of a task
+*DAGApi* | [**get_tasks**](docs/DAGApi.md#get_tasks) | **GET** /dags/{dag_id}/tasks | Get tasks for DAG
+*DAGApi* | [**patch_dag**](docs/DAGApi.md#patch_dag) | **PATCH** /dags/{dag_id} | Update a DAG
+*DAGApi* | [**patch_dags**](docs/DAGApi.md#patch_dags) | **PATCH** /dags | Update DAGs
+*DAGApi* | [**post_clear_task_instances**](docs/DAGApi.md#post_clear_task_instances) | **POST** /dags/{dag_id}/clearTaskInstances | Clear a set of task instances
+*DAGApi* | [**post_set_task_instances_state**](docs/DAGApi.md#post_set_task_instances_state) | **POST** /dags/{dag_id}/updateTaskInstancesState | Set a state of task instances
+*DAGRunApi* | [**clear_dag_run**](docs/DAGRunApi.md#clear_dag_run) | **POST** /dags/{dag_id}/dagRuns/{dag_run_id}/clear | Clear a DAG run
+*DAGRunApi* | [**delete_dag_run**](docs/DAGRunApi.md#delete_dag_run) | **DELETE** /dags/{dag_id}/dagRuns/{dag_run_id} | Delete a DAG run
+*DAGRunApi* | [**get_dag_run**](docs/DAGRunApi.md#get_dag_run) | **GET** /dags/{dag_id}/dagRuns/{dag_run_id} | Get a DAG run
+*DAGRunApi* | [**get_dag_runs**](docs/DAGRunApi.md#get_dag_runs) | **GET** /dags/{dag_id}/dagRuns | List DAG runs
+*DAGRunApi* | [**get_dag_runs_batch**](docs/DAGRunApi.md#get_dag_runs_batch) | **POST** /dags/~/dagRuns/list | List DAG runs (batch)
+*DAGRunApi* | [**get_upstream_dataset_events**](docs/DAGRunApi.md#get_upstream_dataset_events) | **GET** /dags/{dag_id}/dagRuns/{dag_run_id}/upstreamDatasetEvents | Get dataset events for a DAG run
+*DAGRunApi* | [**post_dag_run**](docs/DAGRunApi.md#post_dag_run) | **POST** /dags/{dag_id}/dagRuns | Trigger a new DAG run
+*DAGRunApi* | [**set_dag_run_note**](docs/DAGRunApi.md#set_dag_run_note) | **PATCH** /dags/{dag_id}/dagRuns/{dag_run_id}/setNote | Update the DagRun note.
+*DAGRunApi* | [**update_dag_run_state**](docs/DAGRunApi.md#update_dag_run_state) | **PATCH** /dags/{dag_id}/dagRuns/{dag_run_id} | Modify a DAG run
+*DagWarningApi* | [**get_dag_warnings**](docs/DagWarningApi.md#get_dag_warnings) | **GET** /dagWarnings | List dag warnings
+*DatasetApi* | [**get_dataset**](docs/DatasetApi.md#get_dataset) | **GET** /datasets/{uri} | Get a dataset
+*DatasetApi* | [**get_dataset_events**](docs/DatasetApi.md#get_dataset_events) | **GET** /datasets/events | Get dataset events
+*DatasetApi* | [**get_datasets**](docs/DatasetApi.md#get_datasets) | **GET** /datasets | List datasets
+*DatasetApi* | [**get_upstream_dataset_events**](docs/DatasetApi.md#get_upstream_dataset_events) | **GET** /dags/{dag_id}/dagRuns/{dag_run_id}/upstreamDatasetEvents | Get dataset events for a DAG run
+*EventLogApi* | [**get_event_log**](docs/EventLogApi.md#get_event_log) | **GET** /eventLogs/{event_log_id} | Get a log entry
+*EventLogApi* | [**get_event_logs**](docs/EventLogApi.md#get_event_logs) | **GET** /eventLogs | List log entries
+*ImportErrorApi* | [**get_import_error**](docs/ImportErrorApi.md#get_import_error) | **GET** /importErrors/{import_error_id} | Get an import error
+*ImportErrorApi* | [**get_import_errors**](docs/ImportErrorApi.md#get_import_errors) | **GET** /importErrors | List import errors
+*MonitoringApi* | [**get_health**](docs/MonitoringApi.md#get_health) | **GET** /health | Get instance status
+*MonitoringApi* | [**get_version**](docs/MonitoringApi.md#get_version) | **GET** /version | Get version information
+*PermissionApi* | [**get_permissions**](docs/PermissionApi.md#get_permissions) | **GET** /permissions | List permissions
+*PluginApi* | [**get_plugins**](docs/PluginApi.md#get_plugins) | **GET** /plugins | Get a list of loaded plugins
+*PoolApi* | [**delete_pool**](docs/PoolApi.md#delete_pool) | **DELETE** /pools/{pool_name} | Delete a pool
+*PoolApi* | [**get_pool**](docs/PoolApi.md#get_pool) | **GET** /pools/{pool_name} | Get a pool
+*PoolApi* | [**get_pools**](docs/PoolApi.md#get_pools) | **GET** /pools | List pools
+*PoolApi* | [**patch_pool**](docs/PoolApi.md#patch_pool) | **PATCH** /pools/{pool_name} | Update a pool
+*PoolApi* | [**post_pool**](docs/PoolApi.md#post_pool) | **POST** /pools | Create a pool
+*ProviderApi* | [**get_providers**](docs/ProviderApi.md#get_providers) | **GET** /providers | List providers
+*RoleApi* | [**delete_role**](docs/RoleApi.md#delete_role) | **DELETE** /roles/{role_name} | Delete a role
+*RoleApi* | [**get_role**](docs/RoleApi.md#get_role) | **GET** /roles/{role_name} | Get a role
+*RoleApi* | [**get_roles**](docs/RoleApi.md#get_roles) | **GET** /roles | List roles
+*RoleApi* | [**patch_role**](docs/RoleApi.md#patch_role) | **PATCH** /roles/{role_name} | Update a role
+*RoleApi* | [**post_role**](docs/RoleApi.md#post_role) | **POST** /roles | Create a role
+*TaskInstanceApi* | [**get_extra_links**](docs/TaskInstanceApi.md#get_extra_links) | **GET** /dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/links | List extra links
+*TaskInstanceApi* | [**get_log**](docs/TaskInstanceApi.md#get_log) | **GET** /dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/logs/{task_try_number} | Get logs
+*TaskInstanceApi* | [**get_mapped_task_instance**](docs/TaskInstanceApi.md#get_mapped_task_instance) | **GET** /dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/{map_index} | Get a mapped task instance
+*TaskInstanceApi* | [**get_mapped_task_instances**](docs/TaskInstanceApi.md#get_mapped_task_instances) | **GET** /dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/listMapped | List mapped task instances
+*TaskInstanceApi* | [**get_task_instance**](docs/TaskInstanceApi.md#get_task_instance) | **GET** /dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id} | Get a task instance
+*TaskInstanceApi* | [**get_task_instances**](docs/TaskInstanceApi.md#get_task_instances) | **GET** /dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances | List task instances
+*TaskInstanceApi* | [**get_task_instances_batch**](docs/TaskInstanceApi.md#get_task_instances_batch) | **POST** /dags/~/dagRuns/~/taskInstances/list | List task instances (batch)
+*TaskInstanceApi* | [**patch_mapped_task_instance**](docs/TaskInstanceApi.md#patch_mapped_task_instance) | **PATCH** /dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/{map_index} | Updates the state of a mapped task instance
+*TaskInstanceApi* | [**patch_task_instance**](docs/TaskInstanceApi.md#patch_task_instance) | **PATCH** /dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id} | Updates the state of a task instance
+*TaskInstanceApi* | [**set_mapped_task_instance_note**](docs/TaskInstanceApi.md#set_mapped_task_instance_note) | **PATCH** /dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/{map_index}/setNote | Update the TaskInstance note.
+*TaskInstanceApi* | [**set_task_instance_note**](docs/TaskInstanceApi.md#set_task_instance_note) | **PATCH** /dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/setNote | Update the TaskInstance note.
+*UserApi* | [**delete_user**](docs/UserApi.md#delete_user) | **DELETE** /users/{username} | Delete a user
+*UserApi* | [**get_user**](docs/UserApi.md#get_user) | **GET** /users/{username} | Get a user
+*UserApi* | [**get_users**](docs/UserApi.md#get_users) | **GET** /users | List users
+*UserApi* | [**patch_user**](docs/UserApi.md#patch_user) | **PATCH** /users/{username} | Update a user
+*UserApi* | [**post_user**](docs/UserApi.md#post_user) | **POST** /users | Create a user
+*VariableApi* | [**delete_variable**](docs/VariableApi.md#delete_variable) | **DELETE** /variables/{variable_key} | Delete a variable
+*VariableApi* | [**get_variable**](docs/VariableApi.md#get_variable) | **GET** /variables/{variable_key} | Get a variable
+*VariableApi* | [**get_variables**](docs/VariableApi.md#get_variables) | **GET** /variables | List variables
+*VariableApi* | [**patch_variable**](docs/VariableApi.md#patch_variable) | **PATCH** /variables/{variable_key} | Update a variable
+*VariableApi* | [**post_variables**](docs/VariableApi.md#post_variables) | **POST** /variables | Create a variable
+*XComApi* | [**get_xcom_entries**](docs/XComApi.md#get_xcom_entries) | **GET** /dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/xcomEntries | List XCom entries
+*XComApi* | [**get_xcom_entry**](docs/XComApi.md#get_xcom_entry) | **GET** /dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/xcomEntries/{xcom_key} | Get an XCom entry
+
+
+## Documentation For Models
+
+ - [Action](docs/Action.md)
+ - [ActionCollection](docs/ActionCollection.md)
+ - [ActionCollectionAllOf](docs/ActionCollectionAllOf.md)
+ - [ActionResource](docs/ActionResource.md)
+ - [BasicDAGRun](docs/BasicDAGRun.md)
+ - [ClassReference](docs/ClassReference.md)
+ - [ClearDagRun](docs/ClearDagRun.md)
+ - [ClearTaskInstances](docs/ClearTaskInstances.md)
+ - [CollectionInfo](docs/CollectionInfo.md)
+ - [Color](docs/Color.md)
+ - [Config](docs/Config.md)
+ - [ConfigOption](docs/ConfigOption.md)
+ - [ConfigSection](docs/ConfigSection.md)
+ - [Connection](docs/Connection.md)
+ - [ConnectionAllOf](docs/ConnectionAllOf.md)
+ - [ConnectionCollection](docs/ConnectionCollection.md)
+ - [ConnectionCollectionAllOf](docs/ConnectionCollectionAllOf.md)
+ - [ConnectionCollectionItem](docs/ConnectionCollectionItem.md)
+ - [ConnectionTest](docs/ConnectionTest.md)
+ - [CronExpression](docs/CronExpression.md)
+ - [DAG](docs/DAG.md)
+ - [DAGCollection](docs/DAGCollection.md)
+ - [DAGCollectionAllOf](docs/DAGCollectionAllOf.md)
+ - [DAGDetail](docs/DAGDetail.md)
+ - [DAGDetailAllOf](docs/DAGDetailAllOf.md)
+ - [DAGRun](docs/DAGRun.md)
+ - [DAGRunCollection](docs/DAGRunCollection.md)
+ - [DAGRunCollectionAllOf](docs/DAGRunCollectionAllOf.md)
+ - [DagScheduleDatasetReference](docs/DagScheduleDatasetReference.md)
+ - [DagState](docs/DagState.md)
+ - [DagWarning](docs/DagWarning.md)
+ - [DagWarningCollection](docs/DagWarningCollection.md)
+ - [DagWarningCollectionAllOf](docs/DagWarningCollectionAllOf.md)
+ - [Dataset](docs/Dataset.md)
+ - [DatasetCollection](docs/DatasetCollection.md)
+ - [DatasetCollectionAllOf](docs/DatasetCollectionAllOf.md)
+ - [DatasetEvent](docs/DatasetEvent.md)
+ - [DatasetEventCollection](docs/DatasetEventCollection.md)
+ - [DatasetEventCollectionAllOf](docs/DatasetEventCollectionAllOf.md)
+ - [Error](docs/Error.md)
+ - [EventLog](docs/EventLog.md)
+ - [EventLogCollection](docs/EventLogCollection.md)
+ - [EventLogCollectionAllOf](docs/EventLogCollectionAllOf.md)
+ - [ExtraLink](docs/ExtraLink.md)
+ - [ExtraLinkCollection](docs/ExtraLinkCollection.md)
+ - [HealthInfo](docs/HealthInfo.md)
+ - [HealthStatus](docs/HealthStatus.md)
+ - [ImportError](docs/ImportError.md)
+ - [ImportErrorCollection](docs/ImportErrorCollection.md)
+ - [ImportErrorCollectionAllOf](docs/ImportErrorCollectionAllOf.md)
+ - [InlineResponse200](docs/InlineResponse200.md)
+ - [InlineResponse2001](docs/InlineResponse2001.md)
+ - [Job](docs/Job.md)
+ - [ListDagRunsForm](docs/ListDagRunsForm.md)
+ - [ListTaskInstanceForm](docs/ListTaskInstanceForm.md)
+ - [MetadatabaseStatus](docs/MetadatabaseStatus.md)
+ - [PluginCollection](docs/PluginCollection.md)
+ - [PluginCollectionAllOf](docs/PluginCollectionAllOf.md)
+ - [PluginCollectionItem](docs/PluginCollectionItem.md)
+ - [Pool](docs/Pool.md)
+ - [PoolCollection](docs/PoolCollection.md)
+ - [PoolCollectionAllOf](docs/PoolCollectionAllOf.md)
+ - [Provider](docs/Provider.md)
+ - [ProviderCollection](docs/ProviderCollection.md)
+ - [RelativeDelta](docs/RelativeDelta.md)
+ - [Resource](docs/Resource.md)
+ - [Role](docs/Role.md)
+ - [RoleCollection](docs/RoleCollection.md)
+ - [RoleCollectionAllOf](docs/RoleCollectionAllOf.md)
+ - [SLAMiss](docs/SLAMiss.md)
+ - [ScheduleInterval](docs/ScheduleInterval.md)
+ - [SchedulerStatus](docs/SchedulerStatus.md)
+ - [SetDagRunNote](docs/SetDagRunNote.md)
+ - [SetTaskInstanceNote](docs/SetTaskInstanceNote.md)
+ - [Tag](docs/Tag.md)
+ - [Task](docs/Task.md)
+ - [TaskCollection](docs/TaskCollection.md)
+ - [TaskExtraLinks](docs/TaskExtraLinks.md)
+ - [TaskInstance](docs/TaskInstance.md)
+ - [TaskInstanceCollection](docs/TaskInstanceCollection.md)
+ - [TaskInstanceCollectionAllOf](docs/TaskInstanceCollectionAllOf.md)
+ - [TaskInstanceReference](docs/TaskInstanceReference.md)
+ - [TaskInstanceReferenceCollection](docs/TaskInstanceReferenceCollection.md)
+ - [TaskOutletDatasetReference](docs/TaskOutletDatasetReference.md)
+ - [TaskState](docs/TaskState.md)
+ - [TimeDelta](docs/TimeDelta.md)
+ - [Trigger](docs/Trigger.md)
+ - [TriggerRule](docs/TriggerRule.md)
+ - [UpdateDagRunState](docs/UpdateDagRunState.md)
+ - [UpdateTaskInstance](docs/UpdateTaskInstance.md)
+ - [UpdateTaskInstancesState](docs/UpdateTaskInstancesState.md)
+ - [User](docs/User.md)
+ - [UserAllOf](docs/UserAllOf.md)
+ - [UserCollection](docs/UserCollection.md)
+ - [UserCollectionAllOf](docs/UserCollectionAllOf.md)
+ - [UserCollectionItem](docs/UserCollectionItem.md)
+ - [UserCollectionItemRoles](docs/UserCollectionItemRoles.md)
+ - [Variable](docs/Variable.md)
+ - [VariableAllOf](docs/VariableAllOf.md)
+ - [VariableCollection](docs/VariableCollection.md)
+ - [VariableCollectionAllOf](docs/VariableCollectionAllOf.md)
+ - [VariableCollectionItem](docs/VariableCollectionItem.md)
+ - [VersionInfo](docs/VersionInfo.md)
+ - [WeightRule](docs/WeightRule.md)
+ - [XCom](docs/XCom.md)
+ - [XComAllOf](docs/XComAllOf.md)
+ - [XComCollection](docs/XComCollection.md)
+ - [XComCollectionAllOf](docs/XComCollectionAllOf.md)
+ - [XComCollectionItem](docs/XComCollectionItem.md)
+
+## Documentation For Authorization
+
+By default the generated client supports the three authentication schemes:
+
+* Basic
+* GoogleOpenID
+* Kerberos
+
+However, you can generate client and documentation with your own schemes by adding your own schemes in
+the security section of the OpenAPI specification. You can do it with Breeze CLI by adding the
+``--security-schemes`` option to the ``breeze release-management prepare-python-client`` command.
+
+## Basic "smoke" tests
+
+You can run basic smoke tests to check if the client is working properly - we have a simple test script
+that uses the API to run the tests. To do that, you need to:
+
+* install the `apache-airflow-client` package as described above
+* install ``rich`` Python package
+* download the [test_python_client.py](test_python_client.py) file
+* make sure you have test airflow installation running. Do not experiment with your production deployment
+* configure your airflow webserver to enable basic authentication
+  In the `[api]` section of your `airflow.cfg` set:
+
+```ini
+[api]
+auth_backend = airflow.api.auth.backend.session,airflow.api.auth.backend.basic_auth
+```
+
+You can also set it by env variable:
+`export AIRFLOW__API__AUTH_BACKENDS=airflow.api.auth.backend.session,airflow.api.auth.backend.basic_auth`
+
+* configure your airflow webserver to load example dags
+  In the `[core]` section of your `airflow.cfg` set:
+
+```ini
+[core]
+load_examples = True
+```
+
+You can also set it by env variable: `export AIRFLOW__CORE__LOAD_EXAMPLES=True`
+
+* optionally expose configuration (NOTE! that this is dangerous setting). The script will happily run with
+  the default setting, but if you want to see the configuration, you need to expose it.
+  In the `[webserver]` section of your `airflow.cfg` set:
+
+```ini
+[webserver]
+expose_config = True
+```
+
+You can also set it by env variable: `export AIRFLOW__WEBSERVER__EXPOSE_CONFIG=True`
+
+* Configure your host/ip/user/password in the `test_python_client.py` file
+
+```python
+import airflow_client
+
+# Configure HTTP basic authorization: Basic
+configuration = airflow_client.client.Configuration(
+    host="http://localhost:8080/api/v1", username="admin", password="admin"
+)
+```
+
+* Run scheduler (or dag file processor you have setup with standalone dag file processor) for few parsing
+  loops (you can pass --num-runs parameter to it or keep it running in the background). The script relies
+  on example DAGs being serialized to the DB and this only
+  happens when scheduler runs with ``core/load_examples`` set to True.
+
+* Run webserver - reachable at the host/port for the test script you want to run. Make sure it had enough
+  time to initialize.
+
+Run `python test_python_client.py` and you should see colored output showing attempts to connect and status.
+
+
+## Notes for Large OpenAPI documents
+
+If the OpenAPI document is large, imports in client.apis and client.models may fail with a
+RecursionError indicating the maximum recursion limit has been exceeded. In that case, there are a couple of solutions:
+
+Solution 1:
+Use specific imports for apis and models like:
+
+- `from airflow_client.client.api.default_api import DefaultApi`
+- `from airflow_client.client.model.pet import Pet`
+
+Solution 2:
+Before importing the package, adjust the maximum recursion limit as shown below:
+
+```python
+import sys
+
+sys.setrecursionlimit(1500)
+import airflow_client.client
+from airflow_client.client.apis import *
+from airflow_client.client.models import *
+```
+
+## Authors
+
+dev@airflow.apache.org
diff --git a/clients/python/pyproject.toml b/clients/python/pyproject.toml
new file mode 100644
index 0000000000000..59022ef9aaa1a
--- /dev/null
+++ b/clients/python/pyproject.toml
@@ -0,0 +1,119 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[project]
+name = "apache-airflow-client"
+dynamic = ["version"]
+description = "Apache Airflow API (Stable)"
+readme = "README.md"
+license-files.globs = ["LICENSE", "NOTICE"]
+requires-python = "~=3.8"
+authors = [
+    { name = "Apache Software Foundation", email = "dev@airflow.apache.org" },
+]
+keywords = [
+    "Apache Airflow API (Stable)",
+    "OpenAPI",
+    "OpenAPI-Generator",
+]
+classifiers = [
+    "Development Status :: 5 - Production/Stable",
+    "Environment :: Console",
+    "Environment :: Web Environment",
+    "Framework :: Apache Airflow",
+    "Intended Audience :: Developers",
+    "Intended Audience :: System Administrators",
+    "License :: OSI Approved :: Apache Software License",
+    "Programming Language :: Python :: 3.8",
+    "Programming Language :: Python :: 3.9",
+    "Programming Language :: Python :: 3.10",
+    "Programming Language :: Python :: 3.11",
+    "Topic :: System :: Monitoring",
+]
+
+dependencies = [
+    "python-dateutil",
+    "urllib3 >= 1.25.3",
+]
+
+[project.urls]
+"Bug Tracker" = "https://github.com/apache/airflow-client-python/issues"
+Changelog = "https://github.com/apache/airflow-client-python/blob/main/CHANGELOG.md"
+Documentation = "https://airflow.apache.org/docs/apache-airflow/stable/stable-rest-api-ref.html"
+Download = "https://archive.apache.org/dist/airflow/clients/python/"
+Homepage = "https://airflow.apache.org/"
+"Source Code" = "https://github.com/apache/airflow/clients/python"
+
+[tool.hatch.envs.test]
+dependencies = [
+    "pytest-cov>=2.8.1",
+    "urllib3 >= 1.25.3",
+]
+
+[tool.hatch.envs.test.scripts]
+run-coverage = "pytest test"
+run = "run-coverage --no-cov"
+
+[[tool.hatch.envs.test.matrix]]
+python = ["3.8", "3.9", "3.10", "3.11"]
+
+[tool.hatch.version]
+path = "./version.txt"
+pattern = "^(?P<version>.+)$"
+
+[tool.hatch.build.targets.sdist]
+artifacts = [
+    "/airflow_client",
+    "/docs",
+    "/test",
+    "v1.yaml",
+]
+include = [
+    "version.txt",
+    "INSTALL",
+    "README.md",
+]
+
+[tool.hatch.build.targets.wheel]
+artifacts = [
+    "/airflow_client",
+    "/docs",
+    "/test",
+    "v1.yaml",
+]
+include = [
+    "/airflow_client",
+]
+
+[tool.pytest.ini_options]
+# make sure that pytest.ini is not read from pyproject.toml in paraent directories
+addopts = "--color=yes --cov-config=pyproject.toml --cov=airflow_client"
+norecursedirs = [
+]
+log_level = "INFO"
+filterwarnings = [
+]
+python_files = [
+    "test_*.py",
+]
+testpaths = [
+    "test",
+]
diff --git a/clients/python/test_python_client.py b/clients/python/test_python_client.py
new file mode 100644
index 0000000000000..d36f6d1bcc03c
--- /dev/null
+++ b/clients/python/test_python_client.py
@@ -0,0 +1,130 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+# PEP 723 compliant inline script metadata (not yet widely supported)
+# /// script
+# requires-python = ">=3.8"
+# dependencies = [
+#   "apache-airflow-client",
+#   "rich",
+# ]
+# ///
+
+from __future__ import annotations
+
+import sys
+import uuid
+
+import airflow_client.client
+
+try:
+    # If you have rich installed, you will have nice colored output of the API responses
+    from rich import print
+except ImportError:
+    print("Output will not be colored. Please install rich to get colored output: `pip install rich`")
+    pass
+from airflow_client.client.api import config_api, dag_api, dag_run_api
+from airflow_client.client.model.dag_run import DAGRun
+
+# The client must use the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+#
+# In case of the basic authentication below, make sure that Airflow is
+# configured also with the basic_auth as backend additionally to regular session backend needed
+# by the UI. In the `[api]` section of your `airflow.cfg` set:
+#
+# auth_backend = airflow.api.auth.backend.session,airflow.api.auth.backend.basic_auth
+#
+# Make sure that your user/name are configured properly - using the user/password that has admin
+# privileges in Airflow
+
+# Configure HTTP basic authorization: Basic
+configuration = airflow_client.client.Configuration(
+    host="http://localhost:8080/api/v1", username="admin", password="admin"
+)
+
+# Make sure in the [core] section, the  `load_examples` config is set to True in your airflow.cfg
+# or AIRFLOW__CORE__LOAD_EXAMPLES environment variable set to True
+DAG_ID = "example_bash_operator"
+
+# Enter a context with an instance of the API client
+with airflow_client.client.ApiClient(configuration) as api_client:
+    errors = False
+
+    print("[blue]Getting DAG list")
+    dag_api_instance = dag_api.DAGApi(api_client)
+    try:
+        api_response = dag_api_instance.get_dags()
+        print(api_response)
+    except airflow_client.client.OpenApiException as e:
+        print(f"[red]Exception when calling DagAPI->get_dags: {e}\n")
+        errors = True
+    else:
+        print("[green]Getting DAG list successful")
+
+    print("[blue]Getting Tasks for a DAG")
+    try:
+        api_response = dag_api_instance.get_tasks(DAG_ID)
+        print(api_response)
+    except airflow_client.client.exceptions.OpenApiException as e:
+        print(f"[red]Exception when calling DagAPI->get_tasks: {e}\n")
+        errors = True
+    else:
+        print("[green]Getting Tasks successful")
+
+    print("[blue]Triggering a DAG run")
+    dag_run_api_instance = dag_run_api.DAGRunApi(api_client)
+    try:
+        # Create a DAGRun object (no dag_id should be specified because it is read-only property of DAGRun)
+        # dag_run id is generated randomly to allow multiple executions of the script
+        dag_run = DAGRun(
+            dag_run_id="some_test_run_" + uuid.uuid4().hex,
+        )
+        api_response = dag_run_api_instance.post_dag_run(DAG_ID, dag_run)
+        print(api_response)
+    except airflow_client.client.exceptions.OpenApiException as e:
+        print(f"[red]Exception when calling DAGRunAPI->post_dag_run: {e}\n")
+        errors = True
+    else:
+        print("[green]Posting DAG Run successful")
+
+    # Get current configuration. Note, this is disabled by default with most installation.
+    # You need to set `expose_config = True` in Airflow configuration in order to retrieve configuration.
+    conf_api_instance = config_api.ConfigApi(api_client)
+    try:
+        api_response = conf_api_instance.get_config()
+        print(api_response)
+    except airflow_client.client.OpenApiException as e:
+        if "FORBIDDEN" in str(e):
+            print(
+                "[yellow]You need to set `expose_config = True` in Airflow configuration"
+                " in order to retrieve configuration."
+            )
+            print("[bright_blue]This is OK. Exposing config is disabled by default.")
+        else:
+            print(f"[red]Exception when calling DAGRunAPI->post_dag_run: {e}\n")
+            errors = True
+    else:
+        print("[green]Config retrieved successfully")
+
+    if errors:
+        print("\n[red]There were errors while running the script - see above for details")
+        sys.exit(1)
+    else:
+        print("\n[green]Everything went well")
diff --git a/clients/python/version.txt b/clients/python/version.txt
new file mode 100644
index 0000000000000..834f262953832
--- /dev/null
+++ b/clients/python/version.txt
@@ -0,0 +1 @@
+2.8.0
diff --git a/dev/README_RELEASE_AIRFLOW.md b/dev/README_RELEASE_AIRFLOW.md
index 6c98f9beb1ea0..c2208de88eff8 100644
--- a/dev/README_RELEASE_AIRFLOW.md
+++ b/dev/README_RELEASE_AIRFLOW.md
@@ -30,12 +30,11 @@
   - [Prepare production Docker Image RC](#prepare-production-docker-image-rc)
   - [Prepare Vote email on the Apache Airflow release candidate](#prepare-vote-email-on-the-apache-airflow-release-candidate)
 - [Verify the release candidate by PMC members](#verify-the-release-candidate-by-pmc-members)
+  - [Reproducible package check](#reproducible-package-check)
   - [SVN check](#svn-check)
   - [Licence check](#licence-check)
   - [Signature check](#signature-check)
   - [SHA512 sum check](#sha512-sum-check)
-  - [Reproducible package check](#reproducible-package-check)
-  - [Source code check](#source-code-check)
 - [Verify the release candidate by Contributors](#verify-the-release-candidate-by-contributors)
   - [Installing release candidate in your local virtual environment](#installing-release-candidate-in-your-local-virtual-environment)
 - [Publish the final Apache Airflow release](#publish-the-final-apache-airflow-release)
@@ -435,11 +434,71 @@ At least 3 (+1) votes should be recorded in accordance to
 
 The legal checks include:
 
+* verifying if packages can be reproducibly built from sources
 * checking if the packages are present in the right dist folder on svn
 * verifying if all the sources have correct licences
 * verifying if release manager signed the releases with the right key
 * verifying if all the checksums are valid for the release
 
+## Reproducible package check
+
+Airflow supports reproducible builds, which means that the packages prepared from the same sources should
+produce binary identical packages in reproducible way. You should check if the packages can be
+binary-reproduced when built from the sources.
+
+Checkout airflow sources and build packages in dist folder (replace X.Y.Zrc1 with the version
+you are checking):
+
+```shell script
+VERSION=X.Y.Zrc1
+git checkout ${VERSION}
+export AIRFLOW_REPO_ROOT=$(pwd)
+rm -rf dist/*
+breeze release-management prepare-airflow-tarball --version ${VERSION}
+breeze release-management prepare-airflow-package --package-format both
+```
+
+The last - build step - by default will use Dockerized build and building of Python client packages
+will be done in a docker container.  However, if you have  `hatch` installed locally you can use
+`--use-local-hatch` flag and it will build and use  docker image that has `hatch` installed.
+
+```bash
+breeze release-management prepare-airflow-package --package-format both --use-local-hatch
+```
+
+This is generally faster and requires less resources/network bandwidth.
+
+The tarball command should produce reproducible `-source.tar.gz` tarball of sources.
+
+The `prepare-airflow-package` command (no matter if docker or local hatch is used) should produce the
+reproducible `.whl`, `.tar.gz` packages in the dist folder.
+
+Change to the directory where you have the packages from svn:
+
+```shell script
+# First clone the repo if you do not have it
+cd ..
+[ -d asf-dist ] || svn checkout --depth=immediates https://dist.apache.org/repos/dist asf-dist
+svn update --set-depth=infinity asf-dist/dev/airflow
+
+# Then compare the packages
+cd asf-dist/dev/airflow/X.Y.Zrc1
+for i in ${AIRFLOW_REPO_ROOT}/dist/*
+do
+  echo "Checking if $(basename $i) is the same as $i"
+  diff "$(basename $i)" "$i" && echo "OK"
+done
+```
+
+The output should be empty (files are identical).
+In case the files are different, you should see:
+
+```
+Binary files apache_airflow-2.9.0.dev0.tar.gz and .../apache_airflow-2.9.0.dev0.tar.gz differ
+```
+
+
+
 ## SVN check
 
 The files should be present in the sub-folder of
@@ -579,129 +638,6 @@ Checking apache_airflow-2.0.2rc4-py2.py3-none-any.whl.sha512
 Checking apache-airflow-2.0.2rc4-source.tar.gz.sha512
 ```
 
-## Reproducible package check
-
-Airflow supports reproducible builds, which means that the packages prepared from the same sources should
-produce binary identical packages in reproducible way. You should check if the packages can be
-binary-reproduced when built from the sources.
-
-Checkout airflow sources and build packages in dist folder (replace X.Y.Zrc1 with the version
-you are checking):
-
-```shell script
-VERSION=X.Y.Zrc1
-git checkout ${VERSION}
-export AIRFLOW_REPO_ROOT=$(pwd)
-rm -rf dist/*
-breeze release-management prepare-airflow-tarball --version ${VERSION}
-breeze release-management prepare-airflow-package --package-format both --use-local-hatch
-```
-
-Note that you need to have `hatch` installed in order to build the packages with the last command.
-If you do not have `hatch`, you can remove the `--use-local-hatch` flag and it will build and use
-docker image that has `hatch` and other necessary tools installed.
-
-That should produce `-source.tar.gz` tarball of sources and  `.whl`, `.tar.gz` packages in dist folder.
-
-Change to the directory where you have the packages from svn:
-
-```shell script
-# First clone the repo if you do not have it
-cd ..
-[ -d asf-dist ] || svn checkout --depth=immediates https://dist.apache.org/repos/dist asf-dist
-svn update --set-depth=infinity asf-dist/dev/airflow
-
-# Then compare the packages
-cd asf-dist/dev/airflow/X.Y.Zrc1
-for i in ${AIRFLOW_REPO_ROOT}/dist/*
-do
-  echo "Checking if $(basename $i) is the same as $i"
-  diff "$(basename $i)" "$i" && echo "OK"
-done
-```
-
-The output should be empty (files are identical).
-In case the files are different, you should see:
-
-```
-Binary files apache_airflow-2.9.0.dev0.tar.gz and .../apache_airflow-2.9.0.dev0.tar.gz differ
-```
-
-## Source code check
-
-You should check if the sources in the packages produced are the same as coming from the tag in git.
-
-In checked out sources of Airflow:
-
-```bash
-git checkout X.Y.Zrc1
-export SOURCE_DIR=$(pwd)
-```
-
-Change to the directory where you have the packages from svn:
-
-Check if sources are the same as in the tag:
-
-```bash
-cd X.Y.Zrc1
-tar -xvzf *-source.tar.gz
-pushd apache-airflow-X.Y.Z
-diff -r airflow "${SOURCE_DIR}"
-popd && rm -rf apache-airflow-X.Y.Z
-```
-
-The output should only miss some files - but they should not show any differences in the files:
-
-```
-Only in /Users/jarek/code/airflow: .DS_Store
-Only in /Users/jarek/code/airflow: .asf.yaml
-Only in /Users/jarek/code/airflow: .bash_aliases
-Only in /Users/jarek/code/airflow: .bash_completion
-Only in /Users/jarek/code/airflow: .bash_history
-...
-```
-
-
-Check if .whl is the same as in tag:
-
-```
-unzip -d a *.whl
-pushd a
-diff -r airflow "${SOURCE_DIR}"
-popd && rm -rf a
-```
-
-The output should only miss some files - but they should not show any differences in the files:
-
-```
-Only in /Users/jarek/code/airflow: .DS_Store
-Only in /Users/jarek/code/airflow: .asf.yaml
-Only in /Users/jarek/code/airflow: .bash_aliases
-Only in /Users/jarek/code/airflow: .bash_completion
-Only in /Users/jarek/code/airflow: .bash_history
-...
-```
-
-Check if sdist are the same as in the tag:
-
-```bash
-cd X.Y.Zrc1
-tar -xvzf apache-airflow-X.Y.Z.tar.gz
-pushd apache-airflow-X.Y.Z
-diff -r airflow "${SOURCE_DIR}"
-popd && rm -rf apache-airflow-X.Y.Z
-```
-
-The output should only miss some files - but they should not show any differences in the files:
-
-```
-Only in /Users/jarek/code/airflow: .DS_Store
-Only in /Users/jarek/code/airflow: .asf.yaml
-Only in /Users/jarek/code/airflow: .bash_aliases
-Only in /Users/jarek/code/airflow: .bash_completion
-Only in /Users/jarek/code/airflow: .bash_history
-...
-```
 
 # Verify the release candidate by Contributors
 
diff --git a/dev/README_RELEASE_PYTHON_CLIENT.md b/dev/README_RELEASE_PYTHON_CLIENT.md
new file mode 100644
index 0000000000000..f7091397377b1
--- /dev/null
+++ b/dev/README_RELEASE_PYTHON_CLIENT.md
@@ -0,0 +1,601 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ -->
+
+<!-- START doctoc generated TOC please keep comment here to allow auto update -->
+<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
+**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*
+
+- [Release Process](#release-process)
+  - [Prepare PyPI convenience "RC" packages](#prepare-pypi-convenience-rc-packages)
+  - [Prepare Vote email on the Airflow Client release candidate](#prepare-vote-email-on-the-airflow-client-release-candidate)
+- [Verify the release candidate by PMC members](#verify-the-release-candidate-by-pmc-members)
+  - [SVN check](#svn-check)
+  - [Reproducible package check](#reproducible-package-check)
+  - [Signature check](#signature-check)
+  - [SHA512 checksum check](#sha512-checksum-check)
+- [Verify the release candidate by Contributors](#verify-the-release-candidate-by-contributors)
+  - [Testing with Breeze's start-airflow](#testing-with-breezes-start-airflow)
+- [Publish the final Apache Airflow client release](#publish-the-final-apache-airflow-client-release)
+  - [Summarize the voting for the Apache Airflow client release](#summarize-the-voting-for-the-apache-airflow-client-release)
+  - [Publish release to SVN](#publish-release-to-svn)
+  - [Prepare PyPI "release" packages](#prepare-pypi-release-packages)
+  - [Create release on GitHub](#create-release-on-github)
+  - [Notify developers of release](#notify-developers-of-release)
+  - [Add release data to Apache Committee Report Helper](#add-release-data-to-apache-committee-report-helper)
+
+<!-- END doctoc generated TOC please keep comment here to allow auto update -->
+
+# Release Process
+
+The client versioning is independent of the Airflow versioning.
+
+The Python client is generated using Airflow's [openapi spec](https://github.com/apache/airflow/blob/master/clients/gen/python.sh).
+To update the client for new APIs do the following steps:
+
+```bash
+- Checkout the v2-*-test branch of Airflow where you generate the client from
+
+```bash
+# If you have not done so yet
+git clone git@github.com/apache/airflow
+cd airflow
+# Checkout the right branch
+git checkout v2-8-test
+export AIRFLOW_REPO_ROOT=$(pwd -P)
+cd ..
+```
+
+- Checkout the right branch (usually main) of the Airflow Python client where you
+  generate the source code to
+
+```bash
+# If you have not done so yet
+git clone git@github.com/apache/airflow-client-python
+cd airflow-client-python
+# Checkout the right branch
+git checkout main
+export CLIENT_REPO_ROOT=$(pwd -P)
+cd ..
+```
+
+- Set your version in `clients/python/version.txt` in the **Airflow** repository.
+  Set the `VERSION` and `VERSION_SUFFIX` environment variables. Note that version.txt should contain
+  the target version - without the suffix.
+
+```bash
+cd ${AIRFLOW_REPO_ROOT}
+VERSION="2.8.0"
+VERSION_SUFFIX="rc1"
+echo "${VERSION}" > clients/python/version.txt
+```
+
+- Get a diff between the last airflow version and the current airflow version
+  which this release is based on:
+
+```shell script
+cd ${AIRFLOW_REPO_ROOT}
+git log 2.8.0..HEAD --pretty=oneline -- airflow/api_connexion/openapi/v1.yaml
+```
+
+- Update CHANGELOG.md with the details.
+
+- Create PR where you add the changelog in `main` branch and cherry-pick it to the `v2-test` branch - same
+  as in case of Airflow changelog.
+
+- Merge it to the `v2-*-stable` branch. You will release API client from the latest `v2-*-stable` branch
+  of Airflow repository - same branch that is used to release Airflow.
+
+- Tag your release with RC candidate tag (note that this is the RC tag even if version of the packages
+  is the same as the final version. This is because when the packages get approved and released they
+  will turn into official release and must be binary identical to the RC packages in SVN). The tags
+  should be set in both Airflow and Airflow Client repositories (with python-client prefix in Airflow repo and
+  without the prefix in the Python Client repo).
+
+```shell script
+cd ${AIRFLOW_REPO_ROOT}
+git tag -s python-client-${VERSION}${VERSION_SUFFIX} -m "Airflow Python Client ${VERSION}${VERSION_SUFFIX}"
+git push apache python-client-${VERSION}${VERSION_SUFFIX}
+cd ${CLIENT__REPO_ROOT}
+git tag -s ${VERSION}${VERSION_SUFFIX} -m "Airflow Python Client ${VERSION}${VERSION_SUFFIX}"
+git push apache ${VERSION}${VERSION_SUFFIX}
+```
+
+- Build the sdist and wheel packages to be added to SVN and copy generated client sources to the
+  Python Client repository.
+
+```shell script
+cd ${AIRFLOW_REPO_ROOT}
+rm dist/*
+breeze release-management prepare-python-client --package-format both --python-client-repo "${CLIENT_REPO_ROOT}"
+```
+
+- This should generate both sdist and .whl package in `dist` folder of the Airflow repository. It should
+  also override the client sources in the Python Client repository.
+
+- Commit generated code to the main branch of the Python Client repository. No need to have code reviews
+  for that code if it is automatically generated. However make sure that `git diff HEAD` shows expected
+  changes only.
+
+```shell script
+cd ${CLIENT_REPO_ROOT}
+git diff HEAD
+git add .
+git commit -m "Update Python Client to ${VERSION}${VERSION_SUFFIX}"
+git push origin main
+```
+
+- Generate signatures and checksum files for the packages (if you have not generated a key yet, generate
+  it by following instructions on http://www.apache.org/dev/openpgp.html#key-gen-generate-key)
+
+```shell script
+cd ${AIRFLOW_REPO_ROOT}
+pushd dist
+../dev/sign.sh *
+popd
+```
+
+- Commit the artifacts to ASF dev dist SVN repository
+
+```shell script
+# First clone the repo somewhere if you have not done it yet
+svn checkout https://dist.apache.org/repos/dist/dev/airflow airflow-dev
+
+# Create new folder for the release
+cd airflow-dev/clients/python
+svn mkdir ${VERSION}${VERSION_SUFFIX}
+
+# Move the artifacts to svn folder & commit
+mv ${AIRLFOW_REPO_ROOT}/dist/apache_airflow_client-* ${VERSION}${VERSION_SUFFIX}/
+cd ${VERSION}${VERSION_SUFFIX}
+svn add *
+svn commit -m "Add artifacts for Apache Airflow Python Client ${VERSION}${VERSION_SUFFIX}"
+```
+
+## Prepare PyPI convenience "RC" packages
+
+At this point we have the artefact that we vote on, but as a convenience to developers we also want to
+publish "snapshots" of the RC builds to pypi for installing via pip. Note that these packages must be
+generated with RC version.
+
+To do this we need to:
+
+- Build the package with the RC version. Note that we are not copying the generated sources, we just
+  build the package from the sources in the Airflow repository and generate packages from those sources.
+
+```shell script
+rm dist/*
+breeze release-management prepare-python-client --package-format both --version-suffix-for-pypi "${VERSION_SUFFIX}"
+```
+
+- Verify the artifacts that would be uploaded:
+
+```shell script
+twine check dist/*
+```
+
+- Upload the package to PyPi's production environment:
+
+```shell script
+twine upload -r pypi dist/*
+```
+
+- Confirm that the package is available here: https://pypi.python.org/pypi/apache-airflow-client
+
+## Prepare Vote email on the Airflow Client release candidate
+
+Subject:
+
+```shell script
+cat <<EOF
+[VOTE] Release Airflow Python Client ${VERSION} from ${VERSION}${VERSION_SUFFIX}
+EOF
+```
+
+Body:
+
+```shell script
+cat <<EOF
+Hey fellow Airflowers,
+
+I have cut the first release candidate for the Airflow Python Client ${VERSION}.
+This email is calling for a vote on the release,
+which will last for 72 hours. Consider this my (binding) +1.
+
+Airflow Client ${VERSION}${VERSION_SUFFIX} is available at:
+https://dist.apache.org/repos/dist/dev/airflow/clients/python/${VERSION}${VERSION_SUFFIX}/
+
+The apache_airflow_client-${VERSION}.tar.gz is sdist release that contains INSTALL instructions, and also
+is the official source release.
+
+The apache_airflow_client-${VERSION}-py3-none-any.whl is a binary wheel release that pip can installl.
+
+Those packages do not contain .rc* version as, when approved, they will be released as the final version.
+
+The rc packages are also available at PyPI (with rc suffix) and you can install it with pip as usual:
+https://pypi.org/project/apache-airflow-client/${VERSION}${VERSION_SUFFIX}/
+
+Public keys are available at:
+https://dist.apache.org/repos/dist/release/airflow/KEYS
+
+The
+
+Only votes from PMC members are binding, but the release manager should
+encourage members of the community to test the release and vote with
+"(non-binding)".
+
+The way how PMC members can check the candidate release is described here:
+https://github.com/apache/airflow/blob/main/dev/README_RELEASE_PYTHON_CLIENT.md#verify-the-release-candidate-by-pmc-members
+
+The way how anyone can test the candidate release is described here:
+https://github.com/apache/airflow/blob/main/dev/README_RELEASE_PYTHON_CLIENT.md#verify-the-release-candidate-by-contributors
+
+*Changelog:*
+
+*Major changes:*
+...
+
+*Major fixes:*
+...
+
+*New API supported:*
+...
+
+Cheers,
+<your name>
+EOF
+```
+
+# Verify the release candidate by PMC members
+
+PMC members should verify the releases in order to make sure the release is following the
+[Apache Legal Release Policy](http://www.apache.org/legal/release-policy.html).
+
+At least 3 (+1) votes should be recorded in accordance to
+[Votes on Package Releases](https://www.apache.org/foundation/voting.html#ReleaseVotes)
+
+The legal checks include:
+
+* verifying if packages can be reproducibly built from sources
+* checking if the packages are present in the right dist folder on svn
+* verifying if release manager signed the releases with the right key
+* verifying if all the checksums are valid for the release
+* verifying if all the sources have correct licences
+
+## SVN check
+
+The files should be present in the sub-folder of
+[Airflow dist](https://dist.apache.org/repos/dist/dev/airflow/clients/python)
+
+The following files should be present (6 files):
+
+* .tar.gz + .asc + .sha512
+* -py3-none-any.whl + .asc + .sha512
+
+As a PMC you should be able to clone the SVN repository
+
+```shell script
+svn co https://dist.apache.org/repos/dist/dev/airflow/clients/python
+```
+
+Or update it if you already checked it out:
+
+```shell script
+svn update .
+```
+
+## Reproducible package check
+
+Airflow Python client supports reproducible builds, which means that the packages prepared from the same
+sources should produce binary identical packages in reproducible way. You should check if the packages can be
+binary-reproduced when built from the sources.
+
+Checkout airflow sources and build packages in dist folder (replace X.Y.Z with the version
+you are checking):
+
+```shell script
+VERSION=X.Y.Z
+git checkout python-client-${VERSION}
+export AIRFLOW_REPO_ROOT=$(pwd)
+rm -rf dist/*
+breeze release-management prepare-python-client --package-format both
+```
+
+The last - build step - by default will use Dockerized build and building of Python client packages
+will be done in a docker container.  However, if you have  `hatch` installed locally you can use
+`--use-local-hatch` flag and it will build and use  docker image that has `hatch` installed.
+
+```bash
+breeze release-management prepare-python-client --package-format both --use-local-hatch
+```
+
+This is generally faster and requires less resources/network bandwidth.
+
+Both commands should produce reproducible `.whl`, `.tar.gz` packages in dist folder.
+
+Change to the directory where you have the packages from svn:
+
+```shell script
+# First clone the repo if you do not have it
+cd ..
+[ -d asf-dist ] || svn checkout --depth=immediates https://dist.apache.org/repos/dist asf-dist
+svn update --set-depth=infinity asf-dist/dev/airflow/clients/python
+
+# Then compare the packages
+cd asf-dist/dev/airflow/clients/python/X.Y.Zrc1
+for i in ${AIRFLOW_REPO_ROOT}/dist/*
+do
+  echo "Checking if $(basename $i) is the same as $i"
+  diff "$(basename $i)" "$i" && echo "OK"
+done
+```
+
+The output should be empty (files are identical).
+In case the files are different, you should see:
+
+```
+Binary files apache_airflow-client-2.9.0.tar.gz and .../apache_airflow-2.9.0.tar.gz differ
+```
+
+## Signature check
+
+Make sure you have imported into your GPG the PGP key of the person signing the release. You can find the valid keys in
+[KEYS](https://dist.apache.org/repos/dist/release/airflow/KEYS).
+
+You can import the whole KEYS file:
+
+```shell script
+gpg --import KEYS
+```
+
+You can also import the keys individually from a keyserver. The below one uses Kaxil's key and
+retrieves it from the default GPG keyserver
+[OpenPGP.org](https://keys.openpgp.org):
+
+```shell script
+gpg --keyserver keys.openpgp.org --receive-keys CDE15C6E4D3A8EC4ECF4BA4B6674E08AD7DE406F
+```
+
+You should choose to import the key when asked.
+
+Note that by being default, the OpenPGP server tends to be overloaded often and might respond with
+errors or timeouts. Many of the release managers also uploaded their keys to the
+[GNUPG.net](https://keys.gnupg.net) keyserver, and you can retrieve it from there.
+
+```shell script
+gpg --keyserver keys.gnupg.net --receive-keys CDE15C6E4D3A8EC4ECF4BA4B6674E08AD7DE406F
+```
+
+Once you have the keys, the signatures can be verified by running this:
+
+```shell script
+for i in *.asc
+do
+   echo -e "Checking $i\n"; gpg --verify $i
+done
+```
+
+This should produce results similar to the below. The "Good signature from ..." is indication
+that the signatures are correct. Do not worry about the "not certified with a trusted signature"
+warning. Most of the certificates used by release managers are self-signed, and that's why you get this
+warning. By importing the key either from the server in the previous step or from the
+[KEYS](https://dist.apache.org/repos/dist/release/airflow/KEYS) page, you know that
+this is a valid key already.  To suppress the warning you may edit the key's trust level
+by running `gpg --edit-key <key id> trust` and entering `5` to assign trust level `ultimate`.
+
+```
+Checking apache-airflow-2.0.2rc4.tar.gz.asc
+gpg: assuming signed data in 'apache-airflow-2.0.2rc4.tar.gz'
+gpg: Signature made sob, 22 sie 2020, 20:28:28 CEST
+gpg:                using RSA key 12717556040EEF2EEAF1B9C275FCCD0A25FA0E4B
+gpg: Good signature from "Kaxil Naik <kaxilnaik@gmail.com>" [unknown]
+gpg: WARNING: This key is not certified with a trusted signature!
+gpg:          There is no indication that the signature belongs to the owner.
+Primary key fingerprint: 1271 7556 040E EF2E EAF1  B9C2 75FC CD0A 25FA 0E4B
+
+Checking apache_airflow-2.0.2rc4-py2.py3-none-any.whl.asc
+gpg: assuming signed data in 'apache_airflow-2.0.2rc4-py2.py3-none-any.whl'
+gpg: Signature made sob, 22 sie 2020, 20:28:31 CEST
+gpg:                using RSA key 12717556040EEF2EEAF1B9C275FCCD0A25FA0E4B
+gpg: Good signature from "Kaxil Naik <kaxilnaik@gmail.com>" [unknown]
+gpg: WARNING: This key is not certified with a trusted signature!
+gpg:          There is no indication that the signature belongs to the owner.
+Primary key fingerprint: 1271 7556 040E EF2E EAF1  B9C2 75FC CD0A 25FA 0E4B
+```
+
+## SHA512 checksum check
+
+Run this:
+
+```shell script
+for i in *.sha512
+do
+    echo "Checking $i"; shasum -a 512 `basename $i .sha512 ` | diff - $i
+done
+```
+
+You should get output similar to:
+
+```
+Checking apache-airflow-client-2.0.2rc4.tar.gz.sha512
+Checking apache_airflow-client-2.0.2rc4-py2.py3-none-any.whl.sha512
+```
+
+
+# Verify the release candidate by Contributors
+
+This can be done (and we encourage to) by any of the Contributors. In fact, it's best if the
+actual users of Airflow Client test it in their own staging/test installations. Each release candidate
+is available on PyPI apart from SVN packages, so everyone should be able to install
+the release candidate version of Airflow Client via simply (<VERSION> is 2.0.0 for example, and <X> is
+release candidate number 1,2,3,....).
+
+Once you install and run Airflow Client, you should perform any verification you see as necessary to check
+that the client works as you expected.
+
+## Testing with Breeze's start-airflow
+
+You can test the client by running the `start-airflow` command from Breeze. This will start Airflow
+and allows you to test the client in a real environment.
+
+1. Enable basic authentication configuration for breeze. This can be done by setting the right environment
+   variable in `files/airflow-breeze-config/init.sh`:
+
+```shell
+export AIRFLOW__API__AUTH_BACKENDS=airflow.api.auth.backend.session,airflow.api.auth.backend.basic_auth
+export AIRFLOW__WEBSERVER__EXPOSE_CONFIG=True
+```
+
+
+When you enter Breeze the webserver will be available at `http://localhost:8080` (from inside the container)
+or `http://localhost:28080` from the host) and you should be able to access the API
+with `admin`/`admin` credentials. The `http://localhost:8080` and `admin`/`admin` credentials are
+default in the `clients/python/test_python_client.py` test.
+
+The ``AIRFLOW__WEBSERVER__EXPOSE_CONFIG`` is optional - the script will also succeed when
+(default setting) exposing configuration is disabled.
+
+2. Start Airflow in Breeze with example dags enabled:
+
+```shell
+breeze start-airflow --load-example-dags
+```
+
+Give the server 20-30 seconds to serialize the example DAGs to DB
+
+3. In the meantime install the python client you want to test - in the terminal window in the container.
+   It can be installed from `PyPI` via `pip install apache-airflow-client==X.Y.Zrc1` or installed
+   from a file (for example if you nust built the client with `breeze release-management prepare-python-client`,
+   there will be `/dist/apache_airflow_client-py*.whl` file in in your `/dist` folder (mapped from `dist`
+   folder in your checked out airflow repository and you can install it with:
+   `pip install /dist/apache_airflow_client-py*.whl`.
+
+4. The client script is available in `/opt/airflow/clients/python/test_python_client.py` and you can run it
+   from inside the container with:
+
+```shell script
+python /opt/airflow/clients/python/test_python_client.py
+```
+
+
+# Publish the final Apache Airflow client release
+
+## Summarize the voting for the Apache Airflow client release
+
+```shell script
+Hello,
+
+Apache Airflow Python Client 2.5.0 (based on RC1) has been accepted.
+
+3 "+1" binding votes received:
+- Ephraim Anierobi
+- Jarek Potiuk
+- Jed Cunningham
+
+
+1 "+1" non-binding votes received:
+
+- Pierre Jeambrun
+
+Vote thread:
+https://lists.apache.org/thread/1qcj0r67dff3zg0w2vyfhr30fx9xtp3y
+
+I'll continue with the release process, and the release announcement will follow shortly.
+
+Cheers,
+<your name>
+```
+
+## Publish release to SVN
+
+```shell script
+# Go to Airflow python client sources first
+cd <YOUR_AIRFLOW_CLIENT_REPO_ROOT>
+export CLIENT_REPO_ROOT="$(pwd)"
+cd ..
+# Clone the AS
+[ -d asf-dist ] || svn checkout --depth=immediates https://dist.apache.org/repos/dist asf-dist
+svn update --set-depth=infinity asf-dist/{release,dev}/airflow
+CLIENT_DEV_SVN="${PWD}/asf-dist/dev/airflow/clients/python"
+CLIENT_RELEASE_SVN="${PWD}/asf-dist/release/airflow/clients/python"
+cd "${CLIENT_RELEASE_SVN}"
+
+export VERSION="2.8.1"
+# Update the approved RC version here
+export VERSION_SUFFIX="rc1"
+# Update the previous version that have been released here
+# There should be only one version in https://downloads.apache.org/airflow/clients/python/
+# Policy here: http://www.apache.org/legal/release-policy.html#when-to-archive
+export PREVIOUS_VERSION=2.8.0
+
+# Create new folder for the release
+svn mkdir ${VERSION}
+cd ${VERSION}
+
+# Move the artifacts to svn folder & commit
+for f in ${CLIENT_DEV_SVN}/${VERSION}${VERSION_SUFFIX}/*; do
+  svn mv $f . ;
+done
+# Remove old release
+cd ..
+svn rm ${PREVIOUS_VERSION}
+svn commit -m "Release Apache Airflow Python Client ${VERSION} from ${RC}"
+```
+
+Verify that the packages appear in [airflow](https://downloads.apache.org/airflow/clients/python/)
+
+## Prepare PyPI "release" packages
+
+We need to upload the packages to PyPI. Note that we are not copying the generated sources, we just
+
+```shell script
+cd ${VERSION}
+twine check *.tar.gz *.whl
+```
+
+- Upload the package to PyPi's production environment:
+
+```shell script
+twine upload -r pypi *.tar.gz *.whl
+```
+
+- Confirm that the package is available here: https://pypi.python.org/pypi/apache-airflow-client
+
+- Push Tag for the final version to the Airflow repository and the Python Client repository:
+
+```shell script
+cd ${AIRFLOW_REPO_ROOT}
+git tag -s python-client-${VERSION}
+git push origin python-client-${VERSION}
+cd ${CLIENT_REPO_ROOT}
+git tag -s ${VERSION}
+git push origin ${VERSION}
+```
+
+## Create release on GitHub
+
+Create a new release on GitHub "airflow-python-client" repo  with the release notes and assets
+from the release svn.
+
+## Notify developers of release
+
+See Airflow process documented [here](https://github.com/apache/airflow/blob/master/dev/README_RELEASE_AIRFLOW.md#notify-developers-of-release) (just replace Airflow with Airflow Client)
+
+## Add release data to Apache Committee Report Helper
+
+Add the release data (version and date) at: https://reporter.apache.org/addrelease.html?airflow
diff --git a/dev/breeze/src/airflow_breeze/commands/release_management_commands.py b/dev/breeze/src/airflow_breeze/commands/release_management_commands.py
index 5d132036e9bbc..f5cf168c75fdb 100644
--- a/dev/breeze/src/airflow_breeze/commands/release_management_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/release_management_commands.py
@@ -191,6 +191,11 @@
     show_default=True,
     envvar="PACKAGE_FORMAT",
 )
+option_use_local_hatch = click.option(
+    "--use-local-hatch",
+    is_flag=True,
+    help="Use local hatch instead of docker to build the package. You need to have hatch installed.",
+)
 
 if TYPE_CHECKING:
     from packaging.version import Version
@@ -281,46 +286,7 @@ class VersionedFile(NamedTuple):
 AIRFLOW_BUILD_DOCKERFILE_IGNORE_PATH = AIRFLOW_SOURCES_ROOT / "airflow-build-dockerfile.dockerignore"
 
 
-@release_management.command(
-    name="prepare-airflow-package",
-    help="Prepare sdist/whl package of Airflow.",
-)
-@click.option(
-    "--use-local-hatch",
-    is_flag=True,
-    help="Use local hatch instead of docker to build the package. You need to have hatch installed.",
-)
-@option_package_format
-@option_version_suffix_for_pypi
-@option_verbose
-@option_dry_run
-def prepare_airflow_packages(
-    package_format: str,
-    version_suffix_for_pypi: str,
-    use_local_hatch: bool,
-):
-    perform_environment_checks()
-    fix_ownership_using_docker()
-    cleanup_python_generated_files()
-    source_date_epoch = get_source_date_epoch()
-    if use_local_hatch:
-        hatch_build_command = ["hatch", "build", "-c", "-t", "custom"]
-        if package_format in ["sdist", "both"]:
-            hatch_build_command.extend(["-t", "sdist"])
-        if package_format in ["wheel", "both"]:
-            hatch_build_command.extend(["-t", "wheel"])
-        env_copy = os.environ.copy()
-        env_copy["SOURCE_DATE_EPOCH"] = str(source_date_epoch)
-        run_command(
-            hatch_build_command,
-            check=True,
-            env=env_copy,
-        )
-        get_console().print("[success]Successfully prepared Airflow packages:")
-        for file in sorted(DIST_DIR.glob("apache_airflow*")):
-            get_console().print(file.name)
-        get_console().print()
-        return
+def _build_local_build_image():
     # This is security feature.
     #
     # Building the image needed to build airflow package including .git directory
@@ -346,6 +312,12 @@ def prepare_airflow_packages(
         cwd=AIRFLOW_SOURCES_ROOT,
         env={"DOCKER_CLI_HINTS": "false"},
     )
+
+
+def _build_airflow_packages_with_docker(
+    package_format: str, source_date_epoch: int, version_suffix_for_pypi: str
+):
+    _build_local_build_image()
     container_id = f"airflow-build-{random.getrandbits(64):08x}"
     result = run_command(
         cmd=[
@@ -357,6 +329,8 @@ def prepare_airflow_packages(
             "-e",
             f"VERSION_SUFFIX_FOR_PYPI={version_suffix_for_pypi}",
             "-e",
+            f"SOURCE_DATE_EPOCH={source_date_epoch}",
+            "-e",
             "HOME=/opt/airflow/files/home",
             "-e",
             "GITHUB_ACTIONS",
@@ -377,7 +351,57 @@ def prepare_airflow_packages(
     DIST_DIR.mkdir(parents=True, exist_ok=True)
     # Copy all files in the dist directory in container to the host dist directory (note '/.' in SRC)
     run_command(["docker", "cp", f"{container_id}:/opt/airflow/dist/.", "./dist"], check=True)
-    run_command(["docker", "rm", "--force", container_id], check=True)
+    run_command(["docker", "rm", "--force", container_id], check=False, stderr=DEVNULL, stdout=DEVNULL)
+
+
+def _build_airflow_packages_with_hatch(
+    package_format: str, source_date_epoch: int, version_suffix_for_pypi: str
+):
+    hatch_build_command = ["hatch", "build", "-c", "-t", "custom"]
+    if package_format in ["sdist", "both"]:
+        hatch_build_command.extend(["-t", "sdist"])
+    if package_format in ["wheel", "both"]:
+        hatch_build_command.extend(["-t", "wheel"])
+    env_copy = os.environ.copy()
+    env_copy["SOURCE_DATE_EPOCH"] = str(source_date_epoch)
+    env_copy["VERSION_SUFFIX_FOR_PYPI"] = version_suffix_for_pypi
+    run_command(
+        hatch_build_command,
+        check=True,
+        env=env_copy,
+    )
+
+
+@release_management.command(
+    name="prepare-airflow-package",
+    help="Prepare sdist/whl package of Airflow.",
+)
+@option_package_format
+@option_version_suffix_for_pypi
+@option_use_local_hatch
+@option_verbose
+@option_dry_run
+def prepare_airflow_packages(
+    package_format: str,
+    version_suffix_for_pypi: str,
+    use_local_hatch: bool,
+):
+    perform_environment_checks()
+    fix_ownership_using_docker()
+    cleanup_python_generated_files()
+    source_date_epoch = get_source_date_epoch()
+    if use_local_hatch:
+        _build_airflow_packages_with_hatch(
+            package_format=package_format,
+            source_date_epoch=source_date_epoch,
+            version_suffix_for_pypi=version_suffix_for_pypi,
+        )
+    else:
+        _build_airflow_packages_with_docker(
+            package_format=package_format,
+            source_date_epoch=source_date_epoch,
+            version_suffix_for_pypi=version_suffix_for_pypi,
+        )
     get_console().print("[success]Successfully prepared Airflow packages:")
     for file in sorted(DIST_DIR.glob("apache_airflow*")):
         get_console().print(file.name)
@@ -2081,3 +2105,292 @@ def split_version_and_suffix(file_name: str, suffix: str) -> VersionedFile:
         comparable_version=Version(version),
         file_name=file_name,
     )
+
+
+PYTHON_CLIENT_DIR_PATH = AIRFLOW_SOURCES_ROOT / "clients" / "python"
+PYTHON_CLIENT_DIST_DIR_PATH = PYTHON_CLIENT_DIR_PATH / "dist"
+PYTHON_CLIENT_TMP_DIR = PYTHON_CLIENT_DIR_PATH / "tmp"
+
+REPRODUCIBLE_BUILD_YAML = AIRFLOW_SOURCES_ROOT / "airflow" / "reproducible_build.yaml"
+
+VERSION_FILE = PYTHON_CLIENT_DIR_PATH / "version.txt"
+SOURCE_API_YAML_PATH = AIRFLOW_SOURCES_ROOT / "airflow" / "api_connexion" / "openapi" / "v1.yaml"
+TARGET_API_YAML_PATH = PYTHON_CLIENT_DIR_PATH / "v1.yaml"
+OPENAPI_GENERATOR_CLI_VER = "5.4.0"
+
+GENERATED_CLIENT_DIRECTORIES_TO_COPY = ["airflow_client", "docs", "test"]
+FILES_TO_COPY_TO_CLIENT_REPO = [
+    ".gitignore",
+    ".openapi-generator-ignore",
+    "CHANGELOG.md",
+    "README.md",
+    "INSTALL",
+    "LICENSE",
+    "NOTICE",
+    "pyproject.toml",
+    "test_python_client.py",
+    "version.txt",
+]
+
+
+def _get_python_client_version(version_suffix_for_pypi):
+    from packaging.version import Version
+
+    python_client_version = VERSION_FILE.read_text().strip()
+    version = Version(python_client_version)
+    if version_suffix_for_pypi:
+        if version.pre:
+            currrent_suffix = version.pre[0] + str(version.pre[1])
+            if currrent_suffix != version_suffix_for_pypi:
+                get_console().print(
+                    f"[error]The version suffix for PyPI ({version_suffix_for_pypi}) does not match the "
+                    f"suffix in the version ({version})[/]"
+                )
+                sys.exit(1)
+    return version.base_version + version_suffix_for_pypi
+
+
+def _generate_python_client_sources(python_client_version: str) -> None:
+    get_console().print(f"\n[info]Generating client code in {PYTHON_CLIENT_TMP_DIR}[/]")
+    result = run_command(
+        [
+            "docker",
+            "run",
+            "--rm",
+            "-u",
+            f"{os.getuid()}:{os.getgid()}",
+            "-v",
+            f"{TARGET_API_YAML_PATH}:/spec.yaml",
+            "-v",
+            f"{PYTHON_CLIENT_TMP_DIR}:/output",
+            f"openapitools/openapi-generator-cli:v{OPENAPI_GENERATOR_CLI_VER}",
+            "generate",
+            "--input-spec",
+            "/spec.yaml",
+            "--generator-name",
+            "python",
+            "--git-user-id",
+            f"{os.environ.get('GIT_USER')}",
+            "--output",
+            "/output",
+            "--package-name",
+            "airflow_client.client",
+            "--git-repo-id",
+            "airflow-client-python",
+            "--additional-properties",
+            f'packageVersion="{python_client_version}"',
+        ],
+        capture_output=True,
+        text=True,
+    )
+    if result.returncode != 0:
+        get_console().print("[error]Failed to generate client code[/]")
+        get_console().print(result.stdout, markup=False)
+        get_console().print(result.stderr, markup=False, style="error")
+        sys.exit(result.returncode)
+    get_console().print(f"[success]Generated client code in {PYTHON_CLIENT_TMP_DIR}:[/]")
+    get_console().print(f"\n[info]Content of {PYTHON_CLIENT_TMP_DIR}:[/]")
+    for file in sorted(PYTHON_CLIENT_TMP_DIR.glob("*")):
+        get_console().print(f"[info]  {file.name}[/]")
+    get_console().print()
+
+
+def _copy_selected_sources_from_tmp_directory_to_clients_python():
+    get_console().print(
+        f"[info]Copying selected sources: {GENERATED_CLIENT_DIRECTORIES_TO_COPY} from "
+        f"{PYTHON_CLIENT_TMP_DIR} to {PYTHON_CLIENT_DIR_PATH}[/]"
+    )
+    for dir in GENERATED_CLIENT_DIRECTORIES_TO_COPY:
+        source_dir = PYTHON_CLIENT_TMP_DIR / dir
+        target_dir = PYTHON_CLIENT_DIR_PATH / dir
+        get_console().print(f"[info]  Copying generated sources from {source_dir} to {target_dir}[/]")
+        shutil.rmtree(target_dir, ignore_errors=True)
+        shutil.copytree(source_dir, target_dir)
+        get_console().print(f"[success]  Copied generated sources from {source_dir} to {target_dir}[/]")
+    get_console().print(
+        f"[info]Copied selected sources {GENERATED_CLIENT_DIRECTORIES_TO_COPY} from "
+        f"{PYTHON_CLIENT_TMP_DIR} to {PYTHON_CLIENT_DIR_PATH}[/]\n"
+    )
+    get_console().print(f"\n[info]Content of {PYTHON_CLIENT_DIR_PATH}:[/]")
+    for file in sorted(PYTHON_CLIENT_DIR_PATH.glob("*")):
+        get_console().print(f"[info]  {file.name}[/]")
+    get_console().print()
+
+
+def _build_client_packages_with_hatch(source_date_epoch: int, package_format: str):
+    command = [
+        "hatch",
+        "build",
+        "-c",
+    ]
+    if package_format == "sdist" or package_format == "both":
+        command += ["-t", "sdist"]
+    if package_format == "wheel" or package_format == "both":
+        command += ["-t", "wheel"]
+    env_copy = os.environ.copy()
+    env_copy["SOURCE_DATE_EPOCH"] = str(source_date_epoch)
+    run_command(
+        cmd=command,
+        cwd=PYTHON_CLIENT_DIR_PATH,
+        env=env_copy,
+        check=True,
+    )
+    shutil.copytree(PYTHON_CLIENT_DIST_DIR_PATH, DIST_DIR, dirs_exist_ok=True)
+
+
+def _build_client_packages_with_docker(source_date_epoch: int, package_format: str):
+    _build_local_build_image()
+    command = "hatch build -c "
+    if package_format == "sdist" or package_format == "both":
+        command += "-t sdist "
+    if package_format == "wheel" or package_format == "both":
+        command += "-t wheel "
+    container_id = f"airflow-build-{random.getrandbits(64):08x}"
+    result = run_command(
+        cmd=[
+            "docker",
+            "run",
+            "--name",
+            container_id,
+            "-t",
+            "-e",
+            f"SOURCE_DATE_EPOCH={source_date_epoch}",
+            "-e",
+            "HOME=/opt/airflow/files/home",
+            "-e",
+            "GITHUB_ACTIONS",
+            "-w",
+            "/opt/airflow/clients/python",
+            AIRFLOW_BUILD_IMAGE_TAG,
+            "bash",
+            "-c",
+            command,
+        ],
+        check=False,
+    )
+    if result.returncode != 0:
+        get_console().print("[error]Error preparing Python client packages[/]")
+        fix_ownership_using_docker()
+        sys.exit(result.returncode)
+    DIST_DIR.mkdir(parents=True, exist_ok=True)
+    get_console().print()
+    # Copy all files in the dist directory in container to the host dist directory (note '/.' in SRC)
+    run_command(["docker", "cp", f"{container_id}:/opt/airflow/clients/python/dist/.", "./dist"], check=True)
+    run_command(["docker", "rm", "--force", container_id], check=False, stdout=DEVNULL, stderr=DEVNULL)
+
+
+@release_management.command(name="prepare-python-client", help="Prepares python client packages.")
+@option_package_format
+@option_version_suffix_for_pypi
+@option_use_local_hatch
+@click.option(
+    "--python-client-repo",
+    envvar="PYTHON_CLIENT_REPO",
+    type=click.Path(file_okay=False, dir_okay=True, path_type=Path, exists=True),
+    help="Directory where the python client repo is checked out",
+)
+@click.option(
+    "--only-publish-build-scripts",
+    envvar="ONLY_PUBLISH_BUILD_SCRIPTS",
+    is_flag=True,
+    help="Only publish updated build scripts to puthon client repo, not generated client code.",
+)
+@click.option(
+    "--security-schemes",
+    default="Basic,GoogleOpenID,Kerberos",
+    envvar="SECURITY_SCHEMES",
+    show_default=True,
+    help="Security schemes to be added to the API documentation (coma separated)",
+)
+@option_dry_run
+@option_verbose
+def prepare_python_client(
+    package_format: str,
+    version_suffix_for_pypi: str,
+    use_local_hatch: bool,
+    python_client_repo: Path | None,
+    only_publish_build_scripts: bool,
+    security_schemes: str,
+):
+    shutil.rmtree(PYTHON_CLIENT_TMP_DIR, ignore_errors=True)
+    PYTHON_CLIENT_TMP_DIR.mkdir(parents=True, exist_ok=True)
+    shutil.copy(src=SOURCE_API_YAML_PATH, dst=TARGET_API_YAML_PATH)
+    import yaml
+
+    openapi_yaml = yaml.safe_load(TARGET_API_YAML_PATH.read_text())
+
+    # Add security schemes to documentation
+    security: list[dict[str, Any]] = []
+    for scheme in security_schemes.split(","):
+        security.append({scheme: []})
+    openapi_yaml["security"] = security
+    python_client_version = _get_python_client_version(version_suffix_for_pypi)
+    TARGET_API_YAML_PATH.write_text(yaml.dump(openapi_yaml))
+
+    _generate_python_client_sources(python_client_version=python_client_version)
+    _copy_selected_sources_from_tmp_directory_to_clients_python()
+
+    reproducible_build_yaml = yaml.safe_load(REPRODUCIBLE_BUILD_YAML.read_text())
+    source_date_epoch = reproducible_build_yaml["source-date-epoch"]
+
+    if python_client_repo:
+        if not only_publish_build_scripts:
+            get_console().print(
+                f"[info]Copying generated client from {PYTHON_CLIENT_DIR_PATH} to {python_client_repo}[/]"
+            )
+            for dir in GENERATED_CLIENT_DIRECTORIES_TO_COPY:
+                source_dir = PYTHON_CLIENT_DIR_PATH / dir
+                target_dir = python_client_repo / dir
+                get_console().print(f"[info]  Copying {source_dir} to {target_dir}[/]")
+                shutil.rmtree(target_dir, ignore_errors=True)
+                shutil.copytree(source_dir, target_dir)
+                get_console().print(f"[success]  Copied {source_dir} to {target_dir}[/]")
+            get_console().print(
+                f"[info]Copied generated client from {PYTHON_CLIENT_DIR_PATH} to {python_client_repo}[/]"
+            )
+        get_console().print(
+            f"[info]Copying build scripts from {PYTHON_CLIENT_DIR_PATH} to {python_client_repo}[/]"
+        )
+        for file in FILES_TO_COPY_TO_CLIENT_REPO:
+            source_file = PYTHON_CLIENT_DIR_PATH / file
+            target_file = python_client_repo / file
+            get_console().print(f"[info]  Copying {source_file} to {target_file}[/]")
+            shutil.copy(source_file, target_file)
+            get_console().print(f"[success]  Copied {source_file} to {target_file}[/]")
+        get_console().print(
+            f"[success]Copied build scripts from {PYTHON_CLIENT_DIR_PATH} to {python_client_repo}[/]"
+        )
+        spec_dir = python_client_repo / "spec"
+        spec_dir.mkdir(parents=True, exist_ok=True)
+        source_spec_file = PYTHON_CLIENT_DIR_PATH / "v1.yaml"
+        target_spec_file = spec_dir / "v1.yaml"
+        get_console().print(f"[info]  Copying {source_spec_file} to {target_spec_file}[/]")
+        shutil.copy(source_spec_file, target_spec_file)
+        get_console().print(f"[success]  Copied {source_spec_file} to {target_spec_file}[/]")
+        get_console().print(
+            f"[success]Copied client code from {PYTHON_CLIENT_DIR_PATH} to {python_client_repo}[/]\n"
+        )
+    else:
+        get_console().print(
+            "\n[warning]No python client repo directory provided - skipping copying the generated client[/]\n"
+        )
+    get_console().print(f"\n[info]Building packages in {PYTHON_CLIENT_DIST_DIR_PATH}[/]\n")
+    shutil.rmtree(PYTHON_CLIENT_DIST_DIR_PATH, ignore_errors=True)
+    PYTHON_CLIENT_DIST_DIR_PATH.mkdir(parents=True, exist_ok=True)
+    version = _get_python_client_version(version_suffix_for_pypi)
+    original_version = VERSION_FILE.read_text().strip()
+    if version_suffix_for_pypi:
+        VERSION_FILE.write_text(version)
+    try:
+        if use_local_hatch:
+            _build_client_packages_with_hatch(
+                source_date_epoch=source_date_epoch, package_format=package_format
+            )
+        else:
+            _build_client_packages_with_docker(
+                source_date_epoch=source_date_epoch, package_format=package_format
+            )
+        get_console().print(f"\n[success]Built packages in {DIST_DIR}[/]\n")
+    finally:
+        if version_suffix_for_pypi:
+            VERSION_FILE.write_text(original_version)
diff --git a/dev/breeze/src/airflow_breeze/commands/release_management_commands_config.py b/dev/breeze/src/airflow_breeze/commands/release_management_commands_config.py
index b0b1bb96e0377..ea587fd4b1f6d 100644
--- a/dev/breeze/src/airflow_breeze/commands/release_management_commands_config.py
+++ b/dev/breeze/src/airflow_breeze/commands/release_management_commands_config.py
@@ -45,6 +45,7 @@
     "name": "Other release commands",
     "commands": [
         "add-back-references",
+        "prepare-python-client",
         "publish-docs",
         "generate-constraints",
         "update-constraints",
@@ -57,8 +58,8 @@
             "name": "Package flags",
             "options": [
                 "--package-format",
-                "--use-local-hatch",
                 "--version-suffix-for-pypi",
+                "--use-local-hatch",
             ],
         }
     ],
@@ -167,6 +168,19 @@
             ],
         }
     ],
+    "breeze release-management prepare-python-client": [
+        {
+            "name": "Python client preparation flags",
+            "options": [
+                "--package-format",
+                "--version-suffix-for-pypi",
+                "--use-local-hatch",
+                "--python-client-repo",
+                "--only-publish-build-scripts",
+                "--security-schemes",
+            ],
+        }
+    ],
     "breeze release-management generate-constraints": [
         {
             "name": "Generate constraints flags",
diff --git a/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py b/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py
index f091c6f9ed985..a5aa389e9efb4 100644
--- a/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py
+++ b/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py
@@ -84,6 +84,7 @@
     ("RELEASE_NOTES.rst", "/opt/airflow/RELEASE_NOTES.rst"),
     ("airflow", "/opt/airflow/airflow"),
     ("constraints", "/opt/airflow/constraints"),
+    ("clients", "/opt/airflow/clients"),
     ("dags", "/opt/airflow/dags"),
     ("dev", "/opt/airflow/dev"),
     ("docs", "/opt/airflow/docs"),
diff --git a/images/breeze/output_release-management.svg b/images/breeze/output_release-management.svg
index 745601db244e2..34ce075ae3d2b 100644
--- a/images/breeze/output_release-management.svg
+++ b/images/breeze/output_release-management.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 806.4" xmlns="http://www.w3.org/2000/svg">
+<svg class="rich-terminal" viewBox="0 0 1482 830.8" xmlns="http://www.w3.org/2000/svg">
     <!-- Generated with Rich https://www.textualize.io -->
     <style>
 
@@ -42,7 +42,7 @@
 
     <defs>
     <clipPath id="breeze-release-management-clip-terminal">
-      <rect x="0" y="0" width="1463.0" height="755.4" />
+      <rect x="0" y="0" width="1463.0" height="779.8" />
     </clipPath>
     <clipPath id="breeze-release-management-line-0">
     <rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -134,9 +134,12 @@
 <clipPath id="breeze-release-management-line-29">
     <rect x="0" y="709.1" width="1464" height="24.65"/>
             </clipPath>
+<clipPath id="breeze-release-management-line-30">
+    <rect x="0" y="733.5" 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="804.4" rx="8"/><text class="breeze-release-management-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command:&#160;release-management</text>
+    <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="828.8" rx="8"/><text class="breeze-release-management-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command:&#160;release-management</text>
             <g transform="translate(26,22)">
             <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
             <circle cx="22" cy="0" r="7" fill="#febc2e"/>
@@ -172,11 +175,12 @@
 </text><text class="breeze-release-management-r5" x="0" y="581.2" textLength="12.2" clip-path="url(#breeze-release-management-line-23)">│</text><text class="breeze-release-management-r4" x="24.4" y="581.2" textLength="439.2" clip-path="url(#breeze-release-management-line-23)">clean-old-provider-artifacts&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-release-management-r1" x="488" y="581.2" textLength="951.6" clip-path="url(#breeze-release-management-line-23)">Cleans&#160;the&#160;old&#160;provider&#160;artifacts&#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-release-management-r5" x="1451.8" y="581.2" textLength="12.2" clip-path="url(#breeze-release-management-line-23)">│</text><text class="breeze-release-management-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#breeze-release-management-line-23)">
 </text><text class="breeze-release-management-r5" x="0" y="605.6" textLength="1464" clip-path="url(#breeze-release-management-line-24)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-release-management-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#breeze-release-management-line-24)">
 </text><text class="breeze-release-management-r5" x="0" y="630" textLength="24.4" clip-path="url(#breeze-release-management-line-25)">╭─</text><text class="breeze-release-management-r5" x="24.4" y="630" textLength="292.8" clip-path="url(#breeze-release-management-line-25)">&#160;Other&#160;release&#160;commands&#160;</text><text class="breeze-release-management-r5" x="317.2" y="630" textLength="1122.4" clip-path="url(#breeze-release-management-line-25)">────────────────────────────────────────────────────────────────────────────────────────────</text><text class="breeze-release-management-r5" x="1439.6" y="630" textLength="24.4" clip-path="url(#breeze-release-management-line-25)">─╮</text><text class="breeze-release-management-r1" x="1464" y="630" textLength="12.2" clip-path="url(#breeze-release-management-line-25)">
-</text><text class="breeze-release-management-r5" x="0" y="654.4" textLength="12.2" clip-path="url(#breeze-release-management-line-26)">│</text><text class="breeze-release-management-r4" x="24.4" y="654.4" textLength="280.6" clip-path="url(#breeze-release-management-line-26)">add-back-references&#160;&#160;&#160;&#160;</text><text class="breeze-release-management-r1" x="329.4" y="654.4" textLength="1110.2" clip-path="url(#breeze-release-management-line-26)">Command&#160;to&#160;add&#160;back&#160;references&#160;for&#160;documentation&#160;to&#160;make&#160;it&#160;backward&#160;compatible.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-release-management-r5" x="1451.8" y="654.4" textLength="12.2" clip-path="url(#breeze-release-management-line-26)">│</text><text class="breeze-release-management-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#breeze-release-management-line-26)">
-</text><text class="breeze-release-management-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#breeze-release-management-line-27)">│</text><text class="breeze-release-management-r4" x="24.4" y="678.8" textLength="280.6" clip-path="url(#breeze-release-management-line-27)">publish-docs&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-release-management-r1" x="329.4" y="678.8" textLength="1110.2" clip-path="url(#breeze-release-management-line-27)">Command&#160;to&#160;publish&#160;generated&#160;documentation&#160;to&#160;airflow-site&#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-release-management-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#breeze-release-management-line-27)">│</text><text class="breeze-release-management-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#breeze-release-management-line-27)">
-</text><text class="breeze-release-management-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#breeze-release-management-line-28)">│</text><text class="breeze-release-management-r4" x="24.4" y="703.2" textLength="280.6" clip-path="url(#breeze-release-management-line-28)">generate-constraints&#160;&#160;&#160;</text><text class="breeze-release-management-r1" x="329.4" y="703.2" textLength="1110.2" clip-path="url(#breeze-release-management-line-28)">Generates&#160;pinned&#160;constraint&#160;files&#160;with&#160;all&#160;extras&#160;from&#160;pyproject.toml&#160;in&#160;parallel.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-release-management-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#breeze-release-management-line-28)">│</text><text class="breeze-release-management-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#breeze-release-management-line-28)">
-</text><text class="breeze-release-management-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#breeze-release-management-line-29)">│</text><text class="breeze-release-management-r4" x="24.4" y="727.6" textLength="280.6" clip-path="url(#breeze-release-management-line-29)">update-constraints&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-release-management-r1" x="329.4" y="727.6" textLength="1110.2" clip-path="url(#breeze-release-management-line-29)">Update&#160;released&#160;constraints&#160;with&#160;manual&#160;changes.&#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-release-management-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#breeze-release-management-line-29)">│</text><text class="breeze-release-management-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#breeze-release-management-line-29)">
-</text><text class="breeze-release-management-r5" x="0" y="752" textLength="1464" clip-path="url(#breeze-release-management-line-30)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-release-management-r1" x="1464" y="752" textLength="12.2" clip-path="url(#breeze-release-management-line-30)">
+</text><text class="breeze-release-management-r5" x="0" y="654.4" textLength="12.2" clip-path="url(#breeze-release-management-line-26)">│</text><text class="breeze-release-management-r4" x="24.4" y="654.4" textLength="292.8" clip-path="url(#breeze-release-management-line-26)">add-back-references&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-release-management-r1" x="341.6" y="654.4" textLength="1098" clip-path="url(#breeze-release-management-line-26)">Command&#160;to&#160;add&#160;back&#160;references&#160;for&#160;documentation&#160;to&#160;make&#160;it&#160;backward&#160;compatible.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-release-management-r5" x="1451.8" y="654.4" textLength="12.2" clip-path="url(#breeze-release-management-line-26)">│</text><text class="breeze-release-management-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#breeze-release-management-line-26)">
+</text><text class="breeze-release-management-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#breeze-release-management-line-27)">│</text><text class="breeze-release-management-r4" x="24.4" y="678.8" textLength="292.8" clip-path="url(#breeze-release-management-line-27)">prepare-python-client&#160;&#160;&#160;</text><text class="breeze-release-management-r1" x="341.6" y="678.8" textLength="1098" clip-path="url(#breeze-release-management-line-27)">Prepares&#160;python&#160;client&#160;packages.&#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;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-release-management-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#breeze-release-management-line-27)">│</text><text class="breeze-release-management-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#breeze-release-management-line-27)">
+</text><text class="breeze-release-management-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#breeze-release-management-line-28)">│</text><text class="breeze-release-management-r4" x="24.4" y="703.2" textLength="292.8" clip-path="url(#breeze-release-management-line-28)">publish-docs&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-release-management-r1" x="341.6" y="703.2" textLength="1098" clip-path="url(#breeze-release-management-line-28)">Command&#160;to&#160;publish&#160;generated&#160;documentation&#160;to&#160;airflow-site&#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-release-management-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#breeze-release-management-line-28)">│</text><text class="breeze-release-management-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#breeze-release-management-line-28)">
+</text><text class="breeze-release-management-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#breeze-release-management-line-29)">│</text><text class="breeze-release-management-r4" x="24.4" y="727.6" textLength="292.8" clip-path="url(#breeze-release-management-line-29)">generate-constraints&#160;&#160;&#160;&#160;</text><text class="breeze-release-management-r1" x="341.6" y="727.6" textLength="1098" clip-path="url(#breeze-release-management-line-29)">Generates&#160;pinned&#160;constraint&#160;files&#160;with&#160;all&#160;extras&#160;from&#160;pyproject.toml&#160;in&#160;parallel.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-release-management-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#breeze-release-management-line-29)">│</text><text class="breeze-release-management-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#breeze-release-management-line-29)">
+</text><text class="breeze-release-management-r5" x="0" y="752" textLength="12.2" clip-path="url(#breeze-release-management-line-30)">│</text><text class="breeze-release-management-r4" x="24.4" y="752" textLength="292.8" clip-path="url(#breeze-release-management-line-30)">update-constraints&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-release-management-r1" x="341.6" y="752" textLength="1098" clip-path="url(#breeze-release-management-line-30)">Update&#160;released&#160;constraints&#160;with&#160;manual&#160;changes.&#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-release-management-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#breeze-release-management-line-30)">│</text><text class="breeze-release-management-r1" x="1464" y="752" textLength="12.2" clip-path="url(#breeze-release-management-line-30)">
+</text><text class="breeze-release-management-r5" x="0" y="776.4" textLength="1464" clip-path="url(#breeze-release-management-line-31)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-release-management-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#breeze-release-management-line-31)">
 </text>
     </g>
     </g>
diff --git a/images/breeze/output_release-management.txt b/images/breeze/output_release-management.txt
index 81a7a34a0e755..4a66a02926467 100644
--- a/images/breeze/output_release-management.txt
+++ b/images/breeze/output_release-management.txt
@@ -1 +1 @@
-531a745e860b739dd3e802e594db6e7e
+8de953c7706d780e6598d34b93a65714
diff --git a/images/breeze/output_release-management_prepare-airflow-package.svg b/images/breeze/output_release-management_prepare-airflow-package.svg
index 8ee42db614711..4065a19bcd9ef 100644
--- a/images/breeze/output_release-management_prepare-airflow-package.svg
+++ b/images/breeze/output_release-management_prepare-airflow-package.svg
@@ -109,9 +109,9 @@
 </text><text class="breeze-release-management-prepare-airflow-package-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-4)">
 </text><text class="breeze-release-management-prepare-airflow-package-r5" x="0" y="142" textLength="24.4" clip-path="url(#breeze-release-management-prepare-airflow-package-line-5)">╭─</text><text class="breeze-release-management-prepare-airflow-package-r5" x="24.4" y="142" textLength="183" clip-path="url(#breeze-release-management-prepare-airflow-package-line-5)">&#160;Package&#160;flags&#160;</text><text class="breeze-release-management-prepare-airflow-package-r5" x="207.4" y="142" textLength="1232.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-5)">─────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="breeze-release-management-prepare-airflow-package-r5" x="1439.6" y="142" textLength="24.4" clip-path="url(#breeze-release-management-prepare-airflow-package-line-5)">─╮</text><text class="breeze-release-management-prepare-airflow-package-r1" x="1464" y="142" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-5)">
 </text><text class="breeze-release-management-prepare-airflow-package-r5" x="0" y="166.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-6)">│</text><text class="breeze-release-management-prepare-airflow-package-r4" x="24.4" y="166.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-6)">-</text><text class="breeze-release-management-prepare-airflow-package-r4" x="36.6" y="166.4" textLength="97.6" clip-path="url(#breeze-release-management-prepare-airflow-package-line-6)">-package</text><text class="breeze-release-management-prepare-airflow-package-r4" x="134.2" y="166.4" textLength="85.4" clip-path="url(#breeze-release-management-prepare-airflow-package-line-6)">-format</text><text class="breeze-release-management-prepare-airflow-package-r1" x="378.2" y="166.4" textLength="231.8" clip-path="url(#breeze-release-management-prepare-airflow-package-line-6)">Format&#160;of&#160;packages.</text><text class="breeze-release-management-prepare-airflow-package-r6" x="622.2" y="166.4" textLength="268.4" clip-path="url(#breeze-release-management-prepare-airflow-package-line-6)">(wheel&#160;|&#160;sdist&#160;|&#160;both)</text><text class="breeze-release-management-prepare-airflow-package-r5" x="902.8" y="166.4" textLength="195.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-6)">[default:&#160;wheel]</text><text class="breeze-release-management-prepare-airflow-package-r5" x="1451.8" y="166.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-6)">│</text><text class="breeze-release-management-prepare-airflow-package-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-6)">
-</text><text class="breeze-release-management-prepare-airflow-package-r5" x="0" y="190.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-7)">│</text><text class="breeze-release-management-prepare-airflow-package-r4" x="24.4" y="190.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-7)">-</text><text class="breeze-release-management-prepare-airflow-package-r4" x="36.6" y="190.8" textLength="48.8" clip-path="url(#breeze-release-management-prepare-airflow-package-line-7)">-use</text><text class="breeze-release-management-prepare-airflow-package-r4" x="85.4" y="190.8" textLength="146.4" clip-path="url(#breeze-release-management-prepare-airflow-package-line-7)">-local-hatch</text><text class="breeze-release-management-prepare-airflow-package-r1" x="378.2" y="190.8" textLength="1061.4" clip-path="url(#breeze-release-management-prepare-airflow-package-line-7)">Use&#160;local&#160;hatch&#160;instead&#160;of&#160;docker&#160;to&#160;build&#160;the&#160;package.&#160;You&#160;need&#160;to&#160;have&#160;hatch&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-release-management-prepare-airflow-package-r5" x="1451.8" y="190.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-7)">│</text><text class="breeze-release-management-prepare-airflow-package-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-7)">
-</text><text class="breeze-release-management-prepare-airflow-package-r5" x="0" y="215.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-8)">│</text><text class="breeze-release-management-prepare-airflow-package-r1" x="378.2" y="215.2" textLength="1061.4" clip-path="url(#breeze-release-management-prepare-airflow-package-line-8)">installed.&#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;&#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-release-management-prepare-airflow-package-r5" x="1451.8" y="215.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-8)">│</text><text class="breeze-release-management-prepare-airflow-package-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-8)">
-</text><text class="breeze-release-management-prepare-airflow-package-r5" x="0" y="239.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-9)">│</text><text class="breeze-release-management-prepare-airflow-package-r4" x="24.4" y="239.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-9)">-</text><text class="breeze-release-management-prepare-airflow-package-r4" x="36.6" y="239.6" textLength="97.6" clip-path="url(#breeze-release-management-prepare-airflow-package-line-9)">-version</text><text class="breeze-release-management-prepare-airflow-package-r4" x="134.2" y="239.6" textLength="195.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-9)">-suffix-for-pypi</text><text class="breeze-release-management-prepare-airflow-package-r1" x="378.2" y="239.6" textLength="768.6" clip-path="url(#breeze-release-management-prepare-airflow-package-line-9)">Version&#160;suffix&#160;used&#160;for&#160;PyPI&#160;packages&#160;(alpha,&#160;beta,&#160;rc1,&#160;etc.).</text><text class="breeze-release-management-prepare-airflow-package-r6" x="1159" y="239.6" textLength="73.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-9)">(TEXT)</text><text class="breeze-release-management-prepare-airflow-package-r5" x="1451.8" y="239.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-9)">│</text><text class="breeze-release-management-prepare-airflow-package-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-9)">
+</text><text class="breeze-release-management-prepare-airflow-package-r5" x="0" y="190.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-7)">│</text><text class="breeze-release-management-prepare-airflow-package-r4" x="24.4" y="190.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-7)">-</text><text class="breeze-release-management-prepare-airflow-package-r4" x="36.6" y="190.8" textLength="97.6" clip-path="url(#breeze-release-management-prepare-airflow-package-line-7)">-version</text><text class="breeze-release-management-prepare-airflow-package-r4" x="134.2" y="190.8" textLength="195.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-7)">-suffix-for-pypi</text><text class="breeze-release-management-prepare-airflow-package-r1" x="378.2" y="190.8" textLength="768.6" clip-path="url(#breeze-release-management-prepare-airflow-package-line-7)">Version&#160;suffix&#160;used&#160;for&#160;PyPI&#160;packages&#160;(alpha,&#160;beta,&#160;rc1,&#160;etc.).</text><text class="breeze-release-management-prepare-airflow-package-r6" x="1159" y="190.8" textLength="73.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-7)">(TEXT)</text><text class="breeze-release-management-prepare-airflow-package-r5" x="1451.8" y="190.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-7)">│</text><text class="breeze-release-management-prepare-airflow-package-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-7)">
+</text><text class="breeze-release-management-prepare-airflow-package-r5" x="0" y="215.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-8)">│</text><text class="breeze-release-management-prepare-airflow-package-r4" x="24.4" y="215.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-8)">-</text><text class="breeze-release-management-prepare-airflow-package-r4" x="36.6" y="215.2" textLength="48.8" clip-path="url(#breeze-release-management-prepare-airflow-package-line-8)">-use</text><text class="breeze-release-management-prepare-airflow-package-r4" x="85.4" y="215.2" textLength="146.4" clip-path="url(#breeze-release-management-prepare-airflow-package-line-8)">-local-hatch</text><text class="breeze-release-management-prepare-airflow-package-r1" x="378.2" y="215.2" textLength="1061.4" clip-path="url(#breeze-release-management-prepare-airflow-package-line-8)">Use&#160;local&#160;hatch&#160;instead&#160;of&#160;docker&#160;to&#160;build&#160;the&#160;package.&#160;You&#160;need&#160;to&#160;have&#160;hatch&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-release-management-prepare-airflow-package-r5" x="1451.8" y="215.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-8)">│</text><text class="breeze-release-management-prepare-airflow-package-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-8)">
+</text><text class="breeze-release-management-prepare-airflow-package-r5" x="0" y="239.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-9)">│</text><text class="breeze-release-management-prepare-airflow-package-r1" x="378.2" y="239.6" textLength="1061.4" clip-path="url(#breeze-release-management-prepare-airflow-package-line-9)">installed.&#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;&#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-release-management-prepare-airflow-package-r5" x="1451.8" y="239.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-9)">│</text><text class="breeze-release-management-prepare-airflow-package-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-9)">
 </text><text class="breeze-release-management-prepare-airflow-package-r5" x="0" y="264" textLength="1464" clip-path="url(#breeze-release-management-prepare-airflow-package-line-10)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-release-management-prepare-airflow-package-r1" x="1464" y="264" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-10)">
 </text><text class="breeze-release-management-prepare-airflow-package-r5" x="0" y="288.4" textLength="24.4" clip-path="url(#breeze-release-management-prepare-airflow-package-line-11)">╭─</text><text class="breeze-release-management-prepare-airflow-package-r5" x="24.4" y="288.4" textLength="195.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-11)">&#160;Common&#160;options&#160;</text><text class="breeze-release-management-prepare-airflow-package-r5" x="219.6" y="288.4" textLength="1220" clip-path="url(#breeze-release-management-prepare-airflow-package-line-11)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="breeze-release-management-prepare-airflow-package-r5" x="1439.6" y="288.4" textLength="24.4" clip-path="url(#breeze-release-management-prepare-airflow-package-line-11)">─╮</text><text class="breeze-release-management-prepare-airflow-package-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-11)">
 </text><text class="breeze-release-management-prepare-airflow-package-r5" x="0" y="312.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-12)">│</text><text class="breeze-release-management-prepare-airflow-package-r4" x="24.4" y="312.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-12)">-</text><text class="breeze-release-management-prepare-airflow-package-r4" x="36.6" y="312.8" textLength="97.6" clip-path="url(#breeze-release-management-prepare-airflow-package-line-12)">-verbose</text><text class="breeze-release-management-prepare-airflow-package-r7" x="158.6" y="312.8" textLength="24.4" clip-path="url(#breeze-release-management-prepare-airflow-package-line-12)">-v</text><text class="breeze-release-management-prepare-airflow-package-r1" x="207.4" y="312.8" textLength="585.6" clip-path="url(#breeze-release-management-prepare-airflow-package-line-12)">Print&#160;verbose&#160;information&#160;about&#160;performed&#160;steps.</text><text class="breeze-release-management-prepare-airflow-package-r5" x="1451.8" y="312.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-12)">│</text><text class="breeze-release-management-prepare-airflow-package-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-airflow-package-line-12)">
diff --git a/images/breeze/output_release-management_prepare-airflow-package.txt b/images/breeze/output_release-management_prepare-airflow-package.txt
index 315a3f647a0b8..5a8e577122b62 100644
--- a/images/breeze/output_release-management_prepare-airflow-package.txt
+++ b/images/breeze/output_release-management_prepare-airflow-package.txt
@@ -1 +1 @@
-92215dd76f7de9837fa03e88324d4be7
+d1eb314d4c9e949306d06f079a1463e5
diff --git a/images/breeze/output_release-management_prepare-python-client.svg b/images/breeze/output_release-management_prepare-python-client.svg
new file mode 100644
index 0000000000000..7849985a72f58
--- /dev/null
+++ b/images/breeze/output_release-management_prepare-python-client.svg
@@ -0,0 +1,140 @@
+<svg class="rich-terminal" viewBox="0 0 1482 538.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-release-management-prepare-python-client-matrix {
+        font-family: Fira Code, monospace;
+        font-size: 20px;
+        line-height: 24.4px;
+        font-variant-east-asian: full-width;
+    }
+
+    .breeze-release-management-prepare-python-client-title {
+        font-size: 18px;
+        font-weight: bold;
+        font-family: arial;
+    }
+
+    .breeze-release-management-prepare-python-client-r1 { fill: #c5c8c6 }
+.breeze-release-management-prepare-python-client-r2 { fill: #d0b344 }
+.breeze-release-management-prepare-python-client-r3 { fill: #c5c8c6;font-weight: bold }
+.breeze-release-management-prepare-python-client-r4 { fill: #68a0b3;font-weight: bold }
+.breeze-release-management-prepare-python-client-r5 { fill: #868887 }
+.breeze-release-management-prepare-python-client-r6 { fill: #8d7b39 }
+.breeze-release-management-prepare-python-client-r7 { fill: #98a84b;font-weight: bold }
+    </style>
+
+    <defs>
+    <clipPath id="breeze-release-management-prepare-python-client-clip-terminal">
+      <rect x="0" y="0" width="1463.0" height="487.0" />
+    </clipPath>
+    <clipPath id="breeze-release-management-prepare-python-client-line-0">
+    <rect x="0" y="1.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-python-client-line-1">
+    <rect x="0" y="25.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-python-client-line-2">
+    <rect x="0" y="50.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-python-client-line-3">
+    <rect x="0" y="74.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-python-client-line-4">
+    <rect x="0" y="99.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-python-client-line-5">
+    <rect x="0" y="123.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-python-client-line-6">
+    <rect x="0" y="147.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-python-client-line-7">
+    <rect x="0" y="172.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-python-client-line-8">
+    <rect x="0" y="196.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-python-client-line-9">
+    <rect x="0" y="221.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-python-client-line-10">
+    <rect x="0" y="245.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-python-client-line-11">
+    <rect x="0" y="269.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-python-client-line-12">
+    <rect x="0" y="294.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-python-client-line-13">
+    <rect x="0" y="318.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-python-client-line-14">
+    <rect x="0" y="343.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-python-client-line-15">
+    <rect x="0" y="367.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-python-client-line-16">
+    <rect x="0" y="391.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-python-client-line-17">
+    <rect x="0" y="416.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-python-client-line-18">
+    <rect x="0" y="440.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="536" rx="8"/><text class="breeze-release-management-prepare-python-client-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command:&#160;release-management&#160;prepare-python-client</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-release-management-prepare-python-client-clip-terminal)">
+    
+    <g class="breeze-release-management-prepare-python-client-matrix">
+    <text class="breeze-release-management-prepare-python-client-r1" x="1464" y="20" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-0)">
+</text><text class="breeze-release-management-prepare-python-client-r2" x="12.2" y="44.4" textLength="73.2" clip-path="url(#breeze-release-management-prepare-python-client-line-1)">Usage:</text><text class="breeze-release-management-prepare-python-client-r3" x="97.6" y="44.4" textLength="573.4" clip-path="url(#breeze-release-management-prepare-python-client-line-1)">breeze&#160;release-management&#160;prepare-python-client</text><text class="breeze-release-management-prepare-python-client-r1" x="683.2" y="44.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-1)">[</text><text class="breeze-release-management-prepare-python-client-r4" x="695.4" y="44.4" textLength="85.4" clip-path="url(#breeze-release-management-prepare-python-client-line-1)">OPTIONS</text><text class="breeze-release-management-prepare-python-client-r1" x="780.8" y="44.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-1)">]</text><text class="breeze-release-management-prepare-python-client-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-1)">
+</text><text class="breeze-release-management-prepare-python-client-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-2)">
+</text><text class="breeze-release-management-prepare-python-client-r1" x="12.2" y="93.2" textLength="390.4" clip-path="url(#breeze-release-management-prepare-python-client-line-3)">Prepares&#160;python&#160;client&#160;packages.</text><text class="breeze-release-management-prepare-python-client-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-3)">
+</text><text class="breeze-release-management-prepare-python-client-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-4)">
+</text><text class="breeze-release-management-prepare-python-client-r5" x="0" y="142" textLength="24.4" clip-path="url(#breeze-release-management-prepare-python-client-line-5)">╭─</text><text class="breeze-release-management-prepare-python-client-r5" x="24.4" y="142" textLength="402.6" clip-path="url(#breeze-release-management-prepare-python-client-line-5)">&#160;Python&#160;client&#160;preparation&#160;flags&#160;</text><text class="breeze-release-management-prepare-python-client-r5" x="427" y="142" textLength="1012.6" clip-path="url(#breeze-release-management-prepare-python-client-line-5)">───────────────────────────────────────────────────────────────────────────────────</text><text class="breeze-release-management-prepare-python-client-r5" x="1439.6" y="142" textLength="24.4" clip-path="url(#breeze-release-management-prepare-python-client-line-5)">─╮</text><text class="breeze-release-management-prepare-python-client-r1" x="1464" y="142" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-5)">
+</text><text class="breeze-release-management-prepare-python-client-r5" x="0" y="166.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-6)">│</text><text class="breeze-release-management-prepare-python-client-r4" x="24.4" y="166.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-6)">-</text><text class="breeze-release-management-prepare-python-client-r4" x="36.6" y="166.4" textLength="97.6" clip-path="url(#breeze-release-management-prepare-python-client-line-6)">-package</text><text class="breeze-release-management-prepare-python-client-r4" x="134.2" y="166.4" textLength="85.4" clip-path="url(#breeze-release-management-prepare-python-client-line-6)">-format</text><text class="breeze-release-management-prepare-python-client-r1" x="414.8" y="166.4" textLength="231.8" clip-path="url(#breeze-release-management-prepare-python-client-line-6)">Format&#160;of&#160;packages.</text><text class="breeze-release-management-prepare-python-client-r6" x="658.8" y="166.4" textLength="268.4" clip-path="url(#breeze-release-management-prepare-python-client-line-6)">(wheel&#160;|&#160;sdist&#160;|&#160;both)</text><text class="breeze-release-management-prepare-python-client-r5" x="939.4" y="166.4" textLength="195.2" clip-path="url(#breeze-release-management-prepare-python-client-line-6)">[default:&#160;wheel]</text><text class="breeze-release-management-prepare-python-client-r5" x="1451.8" y="166.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-6)">│</text><text class="breeze-release-management-prepare-python-client-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-6)">
+</text><text class="breeze-release-management-prepare-python-client-r5" x="0" y="190.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-7)">│</text><text class="breeze-release-management-prepare-python-client-r4" x="24.4" y="190.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-7)">-</text><text class="breeze-release-management-prepare-python-client-r4" x="36.6" y="190.8" textLength="97.6" clip-path="url(#breeze-release-management-prepare-python-client-line-7)">-version</text><text class="breeze-release-management-prepare-python-client-r4" x="134.2" y="190.8" textLength="195.2" clip-path="url(#breeze-release-management-prepare-python-client-line-7)">-suffix-for-pypi</text><text class="breeze-release-management-prepare-python-client-r1" x="414.8" y="190.8" textLength="768.6" clip-path="url(#breeze-release-management-prepare-python-client-line-7)">Version&#160;suffix&#160;used&#160;for&#160;PyPI&#160;packages&#160;(alpha,&#160;beta,&#160;rc1,&#160;etc.).</text><text class="breeze-release-management-prepare-python-client-r6" x="1195.6" y="190.8" textLength="73.2" clip-path="url(#breeze-release-management-prepare-python-client-line-7)">(TEXT)</text><text class="breeze-release-management-prepare-python-client-r5" x="1451.8" y="190.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-7)">│</text><text class="breeze-release-management-prepare-python-client-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-7)">
+</text><text class="breeze-release-management-prepare-python-client-r5" x="0" y="215.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-8)">│</text><text class="breeze-release-management-prepare-python-client-r4" x="24.4" y="215.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-8)">-</text><text class="breeze-release-management-prepare-python-client-r4" x="36.6" y="215.2" textLength="48.8" clip-path="url(#breeze-release-management-prepare-python-client-line-8)">-use</text><text class="breeze-release-management-prepare-python-client-r4" x="85.4" y="215.2" textLength="146.4" clip-path="url(#breeze-release-management-prepare-python-client-line-8)">-local-hatch</text><text class="breeze-release-management-prepare-python-client-r1" x="414.8" y="215.2" textLength="1024.8" clip-path="url(#breeze-release-management-prepare-python-client-line-8)">Use&#160;local&#160;hatch&#160;instead&#160;of&#160;docker&#160;to&#160;build&#160;the&#160;package.&#160;You&#160;need&#160;to&#160;have&#160;hatch&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-release-management-prepare-python-client-r5" x="1451.8" y="215.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-8)">│</text><text class="breeze-release-management-prepare-python-client-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-8)">
+</text><text class="breeze-release-management-prepare-python-client-r5" x="0" y="239.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-9)">│</text><text class="breeze-release-management-prepare-python-client-r1" x="414.8" y="239.6" textLength="1024.8" clip-path="url(#breeze-release-management-prepare-python-client-line-9)">installed.&#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;&#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-release-management-prepare-python-client-r5" x="1451.8" y="239.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-9)">│</text><text class="breeze-release-management-prepare-python-client-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-9)">
+</text><text class="breeze-release-management-prepare-python-client-r5" x="0" y="264" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-10)">│</text><text class="breeze-release-management-prepare-python-client-r4" x="24.4" y="264" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-10)">-</text><text class="breeze-release-management-prepare-python-client-r4" x="36.6" y="264" textLength="85.4" clip-path="url(#breeze-release-management-prepare-python-client-line-10)">-python</text><text class="breeze-release-management-prepare-python-client-r4" x="122" y="264" textLength="146.4" clip-path="url(#breeze-release-management-prepare-python-client-line-10)">-client-repo</text><text class="breeze-release-management-prepare-python-client-r1" x="414.8" y="264" textLength="646.6" clip-path="url(#breeze-release-management-prepare-python-client-line-10)">Directory&#160;where&#160;the&#160;python&#160;client&#160;repo&#160;is&#160;checked&#160;out</text><text class="breeze-release-management-prepare-python-client-r6" x="1073.6" y="264" textLength="134.2" clip-path="url(#breeze-release-management-prepare-python-client-line-10)">(DIRECTORY)</text><text class="breeze-release-management-prepare-python-client-r5" x="1451.8" y="264" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-10)">│</text><text class="breeze-release-management-prepare-python-client-r1" x="1464" y="264" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-10)">
+</text><text class="breeze-release-management-prepare-python-client-r5" x="0" y="288.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-11)">│</text><text class="breeze-release-management-prepare-python-client-r4" x="24.4" y="288.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-11)">-</text><text class="breeze-release-management-prepare-python-client-r4" x="36.6" y="288.4" textLength="61" clip-path="url(#breeze-release-management-prepare-python-client-line-11)">-only</text><text class="breeze-release-management-prepare-python-client-r4" x="97.6" y="288.4" textLength="268.4" clip-path="url(#breeze-release-management-prepare-python-client-line-11)">-publish-build-scripts</text><text class="breeze-release-management-prepare-python-client-r1" x="414.8" y="288.4" textLength="1024.8" clip-path="url(#breeze-release-management-prepare-python-client-line-11)">Only&#160;publish&#160;updated&#160;build&#160;scripts&#160;to&#160;puthon&#160;client&#160;repo,&#160;not&#160;generated&#160;client&#160;code.</text><text class="breeze-release-management-prepare-python-client-r5" x="1451.8" y="288.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-11)">│</text><text class="breeze-release-management-prepare-python-client-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-11)">
+</text><text class="breeze-release-management-prepare-python-client-r5" x="0" y="312.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-12)">│</text><text class="breeze-release-management-prepare-python-client-r4" x="24.4" y="312.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-12)">-</text><text class="breeze-release-management-prepare-python-client-r4" x="36.6" y="312.8" textLength="109.8" clip-path="url(#breeze-release-management-prepare-python-client-line-12)">-security</text><text class="breeze-release-management-prepare-python-client-r4" x="146.4" y="312.8" textLength="97.6" clip-path="url(#breeze-release-management-prepare-python-client-line-12)">-schemes</text><text class="breeze-release-management-prepare-python-client-r1" x="414.8" y="312.8" textLength="854" clip-path="url(#breeze-release-management-prepare-python-client-line-12)">Security&#160;schemes&#160;to&#160;be&#160;added&#160;to&#160;the&#160;API&#160;documentation&#160;(coma&#160;separated)</text><text class="breeze-release-management-prepare-python-client-r6" x="1281" y="312.8" textLength="73.2" clip-path="url(#breeze-release-management-prepare-python-client-line-12)">(TEXT)</text><text class="breeze-release-management-prepare-python-client-r5" x="1451.8" y="312.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-12)">│</text><text class="breeze-release-management-prepare-python-client-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-12)">
+</text><text class="breeze-release-management-prepare-python-client-r5" x="0" y="337.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-13)">│</text><text class="breeze-release-management-prepare-python-client-r5" x="414.8" y="337.2" textLength="854" clip-path="url(#breeze-release-management-prepare-python-client-line-13)">[default:&#160;Basic,GoogleOpenID,Kerberos]&#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-release-management-prepare-python-client-r5" x="1451.8" y="337.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-13)">│</text><text class="breeze-release-management-prepare-python-client-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-13)">
+</text><text class="breeze-release-management-prepare-python-client-r5" x="0" y="361.6" textLength="1464" clip-path="url(#breeze-release-management-prepare-python-client-line-14)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-release-management-prepare-python-client-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-14)">
+</text><text class="breeze-release-management-prepare-python-client-r5" x="0" y="386" textLength="24.4" clip-path="url(#breeze-release-management-prepare-python-client-line-15)">╭─</text><text class="breeze-release-management-prepare-python-client-r5" x="24.4" y="386" textLength="195.2" clip-path="url(#breeze-release-management-prepare-python-client-line-15)">&#160;Common&#160;options&#160;</text><text class="breeze-release-management-prepare-python-client-r5" x="219.6" y="386" textLength="1220" clip-path="url(#breeze-release-management-prepare-python-client-line-15)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="breeze-release-management-prepare-python-client-r5" x="1439.6" y="386" textLength="24.4" clip-path="url(#breeze-release-management-prepare-python-client-line-15)">─╮</text><text class="breeze-release-management-prepare-python-client-r1" x="1464" y="386" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-15)">
+</text><text class="breeze-release-management-prepare-python-client-r5" x="0" y="410.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-16)">│</text><text class="breeze-release-management-prepare-python-client-r4" x="24.4" y="410.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-16)">-</text><text class="breeze-release-management-prepare-python-client-r4" x="36.6" y="410.4" textLength="48.8" clip-path="url(#breeze-release-management-prepare-python-client-line-16)">-dry</text><text class="breeze-release-management-prepare-python-client-r4" x="85.4" y="410.4" textLength="48.8" clip-path="url(#breeze-release-management-prepare-python-client-line-16)">-run</text><text class="breeze-release-management-prepare-python-client-r7" x="158.6" y="410.4" textLength="24.4" clip-path="url(#breeze-release-management-prepare-python-client-line-16)">-D</text><text class="breeze-release-management-prepare-python-client-r1" x="207.4" y="410.4" textLength="719.8" clip-path="url(#breeze-release-management-prepare-python-client-line-16)">If&#160;dry-run&#160;is&#160;set,&#160;commands&#160;are&#160;only&#160;printed,&#160;not&#160;executed.</text><text class="breeze-release-management-prepare-python-client-r5" x="1451.8" y="410.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-16)">│</text><text class="breeze-release-management-prepare-python-client-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-16)">
+</text><text class="breeze-release-management-prepare-python-client-r5" x="0" y="434.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-17)">│</text><text class="breeze-release-management-prepare-python-client-r4" x="24.4" y="434.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-17)">-</text><text class="breeze-release-management-prepare-python-client-r4" x="36.6" y="434.8" textLength="97.6" clip-path="url(#breeze-release-management-prepare-python-client-line-17)">-verbose</text><text class="breeze-release-management-prepare-python-client-r7" x="158.6" y="434.8" textLength="24.4" clip-path="url(#breeze-release-management-prepare-python-client-line-17)">-v</text><text class="breeze-release-management-prepare-python-client-r1" x="207.4" y="434.8" textLength="585.6" clip-path="url(#breeze-release-management-prepare-python-client-line-17)">Print&#160;verbose&#160;information&#160;about&#160;performed&#160;steps.</text><text class="breeze-release-management-prepare-python-client-r5" x="1451.8" y="434.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-17)">│</text><text class="breeze-release-management-prepare-python-client-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-17)">
+</text><text class="breeze-release-management-prepare-python-client-r5" x="0" y="459.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-18)">│</text><text class="breeze-release-management-prepare-python-client-r4" x="24.4" y="459.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-18)">-</text><text class="breeze-release-management-prepare-python-client-r4" x="36.6" y="459.2" textLength="61" clip-path="url(#breeze-release-management-prepare-python-client-line-18)">-help</text><text class="breeze-release-management-prepare-python-client-r7" x="158.6" y="459.2" textLength="24.4" clip-path="url(#breeze-release-management-prepare-python-client-line-18)">-h</text><text class="breeze-release-management-prepare-python-client-r1" x="207.4" y="459.2" textLength="329.4" clip-path="url(#breeze-release-management-prepare-python-client-line-18)">Show&#160;this&#160;message&#160;and&#160;exit.</text><text class="breeze-release-management-prepare-python-client-r5" x="1451.8" y="459.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-18)">│</text><text class="breeze-release-management-prepare-python-client-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-18)">
+</text><text class="breeze-release-management-prepare-python-client-r5" x="0" y="483.6" textLength="1464" clip-path="url(#breeze-release-management-prepare-python-client-line-19)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-release-management-prepare-python-client-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-python-client-line-19)">
+</text>
+    </g>
+    </g>
+</svg>
diff --git a/images/breeze/output_release-management_prepare-python-client.txt b/images/breeze/output_release-management_prepare-python-client.txt
new file mode 100644
index 0000000000000..8c5d80f2c9fff
--- /dev/null
+++ b/images/breeze/output_release-management_prepare-python-client.txt
@@ -0,0 +1 @@
+aa5da16329704d537cf3c6d6f38ab8d9
diff --git a/images/breeze/output_setup_check-all-params-in-groups.svg b/images/breeze/output_setup_check-all-params-in-groups.svg
index 05beab1bb3227..ae38c42e9608f 100644
--- a/images/breeze/output_setup_check-all-params-in-groups.svg
+++ b/images/breeze/output_setup_check-all-params-in-groups.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 855.1999999999999" xmlns="http://www.w3.org/2000/svg">
+<svg class="rich-terminal" viewBox="0 0 1482 879.5999999999999" xmlns="http://www.w3.org/2000/svg">
     <!-- Generated with Rich https://www.textualize.io -->
     <style>
 
@@ -43,7 +43,7 @@
 
     <defs>
     <clipPath id="breeze-setup-check-all-params-in-groups-clip-terminal">
-      <rect x="0" y="0" width="1463.0" height="804.1999999999999" />
+      <rect x="0" y="0" width="1463.0" height="828.5999999999999" />
     </clipPath>
     <clipPath id="breeze-setup-check-all-params-in-groups-line-0">
     <rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -141,9 +141,12 @@
 <clipPath id="breeze-setup-check-all-params-in-groups-line-31">
     <rect x="0" y="757.9" width="1464" height="24.65"/>
             </clipPath>
+<clipPath id="breeze-setup-check-all-params-in-groups-line-32">
+    <rect x="0" y="782.3" 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="853.2" rx="8"/><text class="breeze-setup-check-all-params-in-groups-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command:&#160;setup&#160;check-all-params-in-groups</text>
+    <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="877.6" rx="8"/><text class="breeze-setup-check-all-params-in-groups-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command:&#160;setup&#160;check-all-params-in-groups</text>
             <g transform="translate(26,22)">
             <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
             <circle cx="22" cy="0" r="7" fill="#febc2e"/>
@@ -172,20 +175,21 @@
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="410.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-16)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="410.4" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-16)">release-management:generate-providers-metadata&#160;|&#160;release-management:install-provider-packages&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="410.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-16)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-16)">
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="434.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-17)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="434.8" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-17)">release-management:prepare-airflow-package&#160;|&#160;release-management:prepare-airflow-tarball&#160;|&#160;&#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="1451.8" y="434.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-17)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-17)">
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="459.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-18)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="459.2" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-18)">release-management:prepare-provider-documentation&#160;|&#160;release-management:prepare-provider-packages&#160;|&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="459.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-18)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-18)">
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="483.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-19)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="483.6" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-19)">release-management:publish-docs&#160;|&#160;release-management:release-prod-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;</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="483.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-19)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-19)">
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="508" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-20)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="508" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-20)">release-management:start-rc-process&#160;|&#160;release-management:start-release&#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-setup-check-all-params-in-groups-r5" x="1451.8" y="508" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-20)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="508" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-20)">
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-21)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="532.4" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-21)">release-management:update-constraints&#160;|&#160;release-management:verify-provider-packages&#160;|&#160;sbom&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-21)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-21)">
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="556.8" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">sbom:build-all-airflow-images&#160;|&#160;sbom:generate-providers-requirements&#160;|&#160;sbom:update-sbom-information&#160;|&#160;&#160;</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="581.2" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">setup&#160;|&#160;setup:autocomplete&#160;|&#160;setup:check-all-params-in-groups&#160;|&#160;setup:config&#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-setup-check-all-params-in-groups-r5" x="1451.8" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="605.6" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">setup:regenerate-command-images&#160;|&#160;setup:self-upgrade&#160;|&#160;setup:synchronize-local-mounts&#160;|&#160;setup:version&#160;|</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">
-</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)">shell&#160;|&#160;start-airflow&#160;|&#160;static-checks&#160;|&#160;testing&#160;|&#160;testing:db-tests&#160;|&#160;testing:docker-compose-tests&#160;|&#160;&#160;&#160;&#160;</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" 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-r1" x="1464" 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-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)">testing:helm-tests&#160;|&#160;testing:integration-tests&#160;|&#160;testing:non-db-tests&#160;|&#160;testing:tests)&#160;&#160;&#160;&#160;&#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="1451.8" 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-r1" x="1464" 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-r5" x="0" y="678.8" textLength="1464" clip-path="url(#breeze-setup-check-all-params-in-groups-line-27)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" 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-r5" x="0" y="703.2" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">╭─</text><text class="breeze-setup-check-all-params-in-groups-r5" x="24.4" y="703.2" textLength="195.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">&#160;Common&#160;options&#160;</text><text class="breeze-setup-check-all-params-in-groups-r5" x="219.6" y="703.2" textLength="1220" clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1439.6" y="703.2" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">─╮</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" 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-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-r4" x="24.4" 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-r4" x="36.6" y="727.6" textLength="97.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">-verbose</text><text class="breeze-setup-check-all-params-in-groups-r7" x="158.6" y="727.6" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">-v</text><text class="breeze-setup-check-all-params-in-groups-r1" x="207.4" y="727.6" textLength="585.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">Print&#160;verbose&#160;information&#160;about&#160;performed&#160;steps.</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" 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-r1" x="1464" 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-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-r4" x="24.4" 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-r4" x="36.6" y="752" textLength="48.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">-dry</text><text class="breeze-setup-check-all-params-in-groups-r4" x="85.4" y="752" textLength="48.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">-run</text><text class="breeze-setup-check-all-params-in-groups-r7" x="158.6" y="752" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">-D</text><text class="breeze-setup-check-all-params-in-groups-r1" x="207.4" y="752" textLength="719.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">If&#160;dry-run&#160;is&#160;set,&#160;commands&#160;are&#160;only&#160;printed,&#160;not&#160;executed.</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" 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-r1" x="1464" 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-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-r4" x="24.4" 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-r4" x="36.6" y="776.4" textLength="61" clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">-help</text><text class="breeze-setup-check-all-params-in-groups-r7" x="158.6" y="776.4" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">-h</text><text class="breeze-setup-check-all-params-in-groups-r1" x="207.4" y="776.4" textLength="329.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">Show&#160;this&#160;message&#160;and&#160;exit.</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" 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-r1" x="1464" 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-r5" x="0" y="800.8" textLength="1464" clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="483.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-19)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="483.6" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-19)">release-management:prepare-python-client&#160;|&#160;release-management:publish-docs&#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-setup-check-all-params-in-groups-r5" x="1451.8" y="483.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-19)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-19)">
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="508" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-20)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="508" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-20)">release-management:release-prod-images&#160;|&#160;release-management:start-rc-process&#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-setup-check-all-params-in-groups-r5" x="1451.8" y="508" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-20)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="508" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-20)">
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-21)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="532.4" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-21)">release-management:start-release&#160;|&#160;release-management:update-constraints&#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-setup-check-all-params-in-groups-r5" x="1451.8" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-21)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-21)">
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="556.8" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">release-management:verify-provider-packages&#160;|&#160;sbom&#160;|&#160;sbom:build-all-airflow-images&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#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="1451.8" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="581.2" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">sbom:generate-providers-requirements&#160;|&#160;sbom:update-sbom-information&#160;|&#160;setup&#160;|&#160;setup:autocomplete&#160;|&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="605.6" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">setup:check-all-params-in-groups&#160;|&#160;setup:config&#160;|&#160;setup:regenerate-command-images&#160;|&#160;setup:self-upgrade&#160;</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">
+</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)">|&#160;setup:synchronize-local-mounts&#160;|&#160;setup:version&#160;|&#160;shell&#160;|&#160;start-airflow&#160;|&#160;static-checks&#160;|&#160;testing&#160;|&#160;&#160;&#160;</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" 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-r1" x="1464" 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-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)">testing:db-tests&#160;|&#160;testing:docker-compose-tests&#160;|&#160;testing:helm-tests&#160;|&#160;testing:integration-tests&#160;|&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" 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-r1" x="1464" 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-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)">testing:non-db-tests&#160;|&#160;testing:tests)&#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;&#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-setup-check-all-params-in-groups-r5" x="1451.8" 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-r1" x="1464" 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-r5" x="0" y="703.2" textLength="1464" clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" 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-r5" x="0" y="727.6" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">╭─</text><text class="breeze-setup-check-all-params-in-groups-r5" x="24.4" y="727.6" textLength="195.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">&#160;Common&#160;options&#160;</text><text class="breeze-setup-check-all-params-in-groups-r5" x="219.6" y="727.6" textLength="1220" clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1439.6" y="727.6" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">─╮</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" 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-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-r4" x="24.4" 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-r4" x="36.6" y="752" textLength="97.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">-verbose</text><text class="breeze-setup-check-all-params-in-groups-r7" x="158.6" y="752" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">-v</text><text class="breeze-setup-check-all-params-in-groups-r1" x="207.4" y="752" textLength="585.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">Print&#160;verbose&#160;information&#160;about&#160;performed&#160;steps.</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" 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-r1" x="1464" 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-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-r4" x="24.4" 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-r4" x="36.6" y="776.4" textLength="48.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">-dry</text><text class="breeze-setup-check-all-params-in-groups-r4" x="85.4" y="776.4" textLength="48.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">-run</text><text class="breeze-setup-check-all-params-in-groups-r7" x="158.6" y="776.4" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">-D</text><text class="breeze-setup-check-all-params-in-groups-r1" x="207.4" y="776.4" textLength="719.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">If&#160;dry-run&#160;is&#160;set,&#160;commands&#160;are&#160;only&#160;printed,&#160;not&#160;executed.</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" 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-r1" x="1464" 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-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">│</text><text class="breeze-setup-check-all-params-in-groups-r4" x="24.4" y="800.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">-</text><text class="breeze-setup-check-all-params-in-groups-r4" x="36.6" y="800.8" textLength="61" clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">-help</text><text class="breeze-setup-check-all-params-in-groups-r7" x="158.6" y="800.8" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">-h</text><text class="breeze-setup-check-all-params-in-groups-r1" x="207.4" y="800.8" textLength="329.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">Show&#160;this&#160;message&#160;and&#160;exit.</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="825.2" textLength="1464" clip-path="url(#breeze-setup-check-all-params-in-groups-line-33)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-33)">
 </text>
     </g>
     </g>
diff --git a/images/breeze/output_setup_check-all-params-in-groups.txt b/images/breeze/output_setup_check-all-params-in-groups.txt
index 243d3eca55e50..bc749d3570277 100644
--- a/images/breeze/output_setup_check-all-params-in-groups.txt
+++ b/images/breeze/output_setup_check-all-params-in-groups.txt
@@ -1 +1 @@
-69ae9158510708ca0793c715a62368b2
+0ca4a64e910acc7ff95e90385b3c1540
diff --git a/images/breeze/output_setup_regenerate-command-images.svg b/images/breeze/output_setup_regenerate-command-images.svg
index fc59c7c21164e..11bca82b2d27a 100644
--- a/images/breeze/output_setup_regenerate-command-images.svg
+++ b/images/breeze/output_setup_regenerate-command-images.svg
@@ -185,15 +185,15 @@
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="434.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-17)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="219.6" y="434.8" textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-line-17)">release-management:generate-providers-metadata&#160;|&#160;release-management:install-provider-packages&#160;|&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="434.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-17)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-17)">
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="459.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-18)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="219.6" y="459.2" textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-line-18)">release-management:prepare-airflow-package&#160;|&#160;release-management:prepare-airflow-tarball&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="459.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-18)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-18)">
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="483.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-19)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="219.6" y="483.6" textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-line-19)">release-management:prepare-provider-documentation&#160;|&#160;release-management:prepare-provider-packages&#160;|&#160;&#160;</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="483.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-19)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-19)">
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="508" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-20)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="219.6" y="508" textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-line-20)">release-management:publish-docs&#160;|&#160;release-management:release-prod-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;</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="508" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-20)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="508" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-20)">
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-21)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="219.6" y="532.4" textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-line-21)">release-management:start-rc-process&#160;|&#160;release-management:start-release&#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-setup-regenerate-command-images-r5" x="1451.8" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-21)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-21)">
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-22)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="219.6" y="556.8" textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-line-22)">release-management:update-constraints&#160;|&#160;release-management:verify-provider-packages&#160;|&#160;sbom&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-22)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-22)">
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-23)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="219.6" y="581.2" textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-line-23)">sbom:build-all-airflow-images&#160;|&#160;sbom:generate-providers-requirements&#160;|&#160;sbom:update-sbom-information&#160;</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-23)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-23)">
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-24)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="219.6" y="605.6" textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-line-24)">|&#160;setup&#160;|&#160;setup:autocomplete&#160;|&#160;setup:check-all-params-in-groups&#160;|&#160;setup:config&#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-setup-regenerate-command-images-r5" x="1451.8" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-24)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-24)">
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="630" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-25)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="219.6" y="630" textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-line-25)">setup:regenerate-command-images&#160;|&#160;setup:self-upgrade&#160;|&#160;setup:synchronize-local-mounts&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="630" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-25)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="630" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-25)">
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="654.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-26)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="219.6" y="654.4" textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-line-26)">setup:version&#160;|&#160;shell&#160;|&#160;start-airflow&#160;|&#160;static-checks&#160;|&#160;testing&#160;|&#160;testing:db-tests&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="654.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-26)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-26)">
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-27)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="219.6" y="678.8" textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-line-27)">testing:docker-compose-tests&#160;|&#160;testing:helm-tests&#160;|&#160;testing:integration-tests&#160;|&#160;testing:non-db-tests</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-27)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-27)">
-</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)">|&#160;testing:tests)&#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;&#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-setup-regenerate-command-images-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-28)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-28)">
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="508" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-20)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="219.6" y="508" textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-line-20)">release-management:prepare-python-client&#160;|&#160;release-management:publish-docs&#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-setup-regenerate-command-images-r5" x="1451.8" y="508" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-20)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="508" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-20)">
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-21)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="219.6" y="532.4" textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-line-21)">release-management:release-prod-images&#160;|&#160;release-management:start-rc-process&#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-setup-regenerate-command-images-r5" x="1451.8" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-21)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-21)">
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-22)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="219.6" y="556.8" textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-line-22)">release-management:start-release&#160;|&#160;release-management:update-constraints&#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-setup-regenerate-command-images-r5" x="1451.8" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-22)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-22)">
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-23)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="219.6" y="581.2" textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-line-23)">release-management:verify-provider-packages&#160;|&#160;sbom&#160;|&#160;sbom:build-all-airflow-images&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-23)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-23)">
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-24)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="219.6" y="605.6" textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-line-24)">sbom:generate-providers-requirements&#160;|&#160;sbom:update-sbom-information&#160;|&#160;setup&#160;|&#160;setup:autocomplete&#160;|&#160;&#160;</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-24)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-24)">
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="630" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-25)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="219.6" y="630" textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-line-25)">setup:check-all-params-in-groups&#160;|&#160;setup:config&#160;|&#160;setup:regenerate-command-images&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="630" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-25)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="630" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-25)">
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="654.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-26)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="219.6" y="654.4" textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-line-26)">setup:self-upgrade&#160;|&#160;setup:synchronize-local-mounts&#160;|&#160;setup:version&#160;|&#160;shell&#160;|&#160;start-airflow&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="654.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-26)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-26)">
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-27)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="219.6" y="678.8" textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-line-27)">static-checks&#160;|&#160;testing&#160;|&#160;testing:db-tests&#160;|&#160;testing:docker-compose-tests&#160;|&#160;testing:helm-tests&#160;|&#160;&#160;&#160;&#160;</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-27)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-27)">
+</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)">testing:integration-tests&#160;|&#160;testing:non-db-tests&#160;|&#160;testing:tests)&#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-setup-regenerate-command-images-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-28)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-28)">
 </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-r4" x="24.4" y="727.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-29)">-</text><text class="breeze-setup-regenerate-command-images-r4" x="36.6" y="727.6" textLength="73.2" clip-path="url(#breeze-setup-regenerate-command-images-line-29)">-check</text><text class="breeze-setup-regenerate-command-images-r4" x="109.8" y="727.6" textLength="61" clip-path="url(#breeze-setup-regenerate-command-images-line-29)">-only</text><text class="breeze-setup-regenerate-command-images-r1" x="219.6" y="727.6" textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-line-29)">Only&#160;check&#160;if&#160;some&#160;images&#160;need&#160;to&#160;be&#160;regenerated.&#160;Return&#160;0&#160;if&#160;no&#160;need&#160;or&#160;1&#160;if&#160;needed.&#160;Cannot&#160;be&#160;used</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-29)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-29)">
 </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-r1" x="219.6" y="752" textLength="170.8" clip-path="url(#breeze-setup-regenerate-command-images-line-30)">together&#160;with&#160;</text><text class="breeze-setup-regenerate-command-images-r4" x="390.4" y="752" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-30)">-</text><text class="breeze-setup-regenerate-command-images-r4" x="402.6" y="752" textLength="97.6" clip-path="url(#breeze-setup-regenerate-command-images-line-30)">-command</text><text class="breeze-setup-regenerate-command-images-r1" x="500.2" y="752" textLength="109.8" clip-path="url(#breeze-setup-regenerate-command-images-line-30)">&#160;flag&#160;or&#160;</text><text class="breeze-setup-regenerate-command-images-r4" x="610" y="752" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-30)">-</text><text class="breeze-setup-regenerate-command-images-r4" x="622.2" y="752" textLength="73.2" clip-path="url(#breeze-setup-regenerate-command-images-line-30)">-force</text><text class="breeze-setup-regenerate-command-images-r1" x="695.4" y="752" textLength="744.2" clip-path="url(#breeze-setup-regenerate-command-images-line-30)">.&#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;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-30)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="752" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-30)">
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="776.4" textLength="1464" clip-path="url(#breeze-setup-regenerate-command-images-line-31)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-31)">
diff --git a/images/breeze/output_setup_regenerate-command-images.txt b/images/breeze/output_setup_regenerate-command-images.txt
index 87d87112baaa0..396d3494bb33e 100644
--- a/images/breeze/output_setup_regenerate-command-images.txt
+++ b/images/breeze/output_setup_regenerate-command-images.txt
@@ -1 +1 @@
-4f1d4b74c81fd81e8c6f32ec137ff480
+2cd063e443a03f8dbacff6674a27dfe8
diff --git a/scripts/ci/docker-compose/local.yml b/scripts/ci/docker-compose/local.yml
index 9258b3b504607..bcfe9b757dff9 100644
--- a/scripts/ci/docker-compose/local.yml
+++ b/scripts/ci/docker-compose/local.yml
@@ -67,6 +67,9 @@ services:
       - type: bind
         source: ../../../constraints
         target: /opt/airflow/constraints
+      - type: bind
+        source: ../../../clients
+        target: /opt/airflow/clients
       - type: bind
         source: ../../../dags
         target: /opt/airflow/dags
diff --git a/scripts/ci/openapi/client_codegen_diff.sh b/scripts/ci/openapi/client_codegen_diff.sh
deleted file mode 100755
index 7e2f40184708a..0000000000000
--- a/scripts/ci/openapi/client_codegen_diff.sh
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/usr/bin/env bash
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-set -eu
-
-# HEAD^1 says the "first" parent. For PR merge commits, or main commits, this is the "right" commit.
-#
-# In this example, 9c532b6 is the PR commit (HEAD^2), 4840892 is the head GitHub checks-out for us, and db121f7 is the
-# "merge target" (HEAD^1) -- i.e. mainline
-#
-# *   4840892 (HEAD, pull/11906/merge) Merge 9c532b6a2c56cd5d4c2a80ecbed60f9dfd1f5fe6 into db121f726b3c7a37aca1ea05eb4714f884456005 [Ephraim Anierobi]
-# |\
-# | * 9c532b6 (grafted) make taskinstances pid and duration nullable [EphraimBuddy]
-# * db121f7 (grafted) Add truncate table (before copy) option to S3ToRedshiftOperator (#9246) [JavierLopezT]
-
-previous_mainline_commit="$(git rev-parse --short HEAD^1)"
-
-echo "Diffing openapi spec against ${previous_mainline_commit}..."
-
-SPEC_FILE="airflow/api_connexion/openapi/v1.yaml"
-readonly SPEC_FILE
-
-GO_CLIENT_PATH="clients/go/airflow"
-readonly GO_CLIENT_PATH
-
-GO_TARGET_CLIENT_PATH="clients/go_target_branch/airflow"
-readonly GO_TARGET_CLIENT_PATH
-
-# generate client for current patch
-mkdir -p "${GO_CLIENT_PATH}"
-
-./clients/gen/go.sh "${SPEC_FILE}" "${GO_CLIENT_PATH}"
-# generate client for target patch
-mkdir -p "${GO_TARGET_CLIENT_PATH}"
-
-git checkout "${previous_mainline_commit}" -- "$SPEC_FILE"
-./clients/gen/go.sh "${SPEC_FILE}" "${GO_TARGET_CLIENT_PATH}"
-
-diff -u "${GO_TARGET_CLIENT_PATH}" "${GO_CLIENT_PATH}" || true
