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

potiuk pushed a commit to branch ci-upgrade-main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/ci-upgrade-main by this push:
     new 7f4f484a1b1 Switch Breeze from mprocs to dekit
7f4f484a1b1 is described below

commit 7f4f484a1b1f50044b3038a89332265db266331c
Author: Jarek Potiuk <[email protected]>
AuthorDate: Tue Oct 6 00:37:02 2026 +0200

    Switch Breeze from mprocs to dekit
    
    mprocs is released as dekit since 0.10.0, with no mprocs assets any
    more, so the scheduled CI-environment upgrade broke the CI image build
    by plugging 0.10.0 into the old mprocs download URL.
    
    Breeze now installs dekit and runs the Airflow components as tasks of a
    native dekit.yaml project rather than through dekit's mprocs mode, so it
    uses the current configuration format directly. "mprocs" stays accepted
    as a hidden alias of "dekit" for --terminal-multiplexer, the
    TERMINAL_MULTIPLEXER variable and inside the container, and a
    remembered "mprocs" choice is migrated to "dekit" so users keep their
    preference.
    
    Generated-by: Claude Opus 5
---
 Dockerfile.ci                                      |  29 ++--
 contributing-docs/03_contributors_quick_start.rst  |  25 ++--
 .../03a_contributors_quick_start_beginners.rst     |   4 +-
 .../20_debugging_airflow_components.rst            |  22 +--
 contributing-docs/dekit/DEKIT_QUICK_REFERENCE.md   | 156 +++++++++++++++++++++
 .../{mprocs/mprocs.yaml => dekit/dekit.yaml}       |  58 ++++----
 contributing-docs/mprocs/MPROCS_QUICK_REFERENCE.md | 148 -------------------
 dev/README_RELEASE_PROVIDERS.md                    |   2 +-
 dev/breeze/doc/03_developer_tasks.rst              |   2 +-
 dev/breeze/doc/images/output_setup_config.svg      |   2 +-
 dev/breeze/doc/images/output_setup_config.txt      |   2 +-
 dev/breeze/doc/images/output_start-airflow.svg     |   4 +-
 dev/breeze/doc/images/output_start-airflow.txt     |   2 +-
 dev/breeze/src/airflow_breeze/global_constants.py  |   6 +-
 dev/breeze/src/airflow_breeze/utils/cache.py       |  16 ++-
 .../src/airflow_breeze/utils/custom_param_types.py |   2 +
 dev/breeze/tests/test_cache.py                     |  61 +++++++-
 scripts/ci/prek/upgrade_important_versions.py      |   9 +-
 scripts/docker/entrypoint_ci.sh                    |   7 +-
 ...e_mprocs_config.py => generate_dekit_config.py} |  80 +++++------
 scripts/in_container/bin/run_dekit                 |  39 ++++++
 scripts/in_container/bin/run_mprocs                |  28 ----
 .../in_container/test_generate_dekit_config.py     |  93 ++++++++++++
 23 files changed, 492 insertions(+), 305 deletions(-)

diff --git a/Dockerfile.ci b/Dockerfile.ci
index d40106f147f..52b99f6bf34 100644
--- a/Dockerfile.ci
+++ b/Dockerfile.ci
@@ -1383,9 +1383,10 @@ SSH_CONFIG
         if [[ ${SKIP_ASSETS_COMPILATION:="false"} == "false" ]]; then
             wait_for_asset_compilation
         fi
-        if [[ ${TERMINAL_MULTIPLEXER:="mprocs"} == "mprocs" ]]; then
-            # shellcheck source=scripts/in_container/bin/run_mprocs
-            exec run_mprocs
+        # "mprocs" is the old name of dekit, still accepted from older Breeze 
versions.
+        if [[ ${TERMINAL_MULTIPLEXER:="dekit"} == "dekit" || 
${TERMINAL_MULTIPLEXER} == "mprocs" ]]; then
+            # shellcheck source=scripts/in_container/bin/run_dekit
+            exec run_dekit
         else
             # shellcheck source=scripts/in_container/bin/run_tmux
             exec run_tmux
@@ -1844,17 +1845,17 @@ RUN SYSTEM=$(uname -s | tr '[:upper:]' '[:lower:]') \
     && rm -f /tmp/helm.tar.gz \
     && chmod +x /usr/local/bin/helm
 
-# Install mprocs - a modern process manager for managing multiple Airflow 
components
-ARG MPROCS_VERSION="0.10.0"
-
-RUN SYSTEM=$(uname -s | tr '[:upper:]' '[:lower:]') \
-    && PLATFORM="$(uname -m)" \
-    && 
MPROCS_URL="https://github.com/pvolok/mprocs/releases/download/v${MPROCS_VERSION}/mprocs-${MPROCS_VERSION}-${SYSTEM}-${PLATFORM}-musl.tar.gz";
 \
-    && echo "Downloading mprocs from ${MPROCS_URL}" \
-    && curl --silent --location --fail --retry 3 --retry-delay 5 -o 
/tmp/mprocs.tar.gz "${MPROCS_URL}" \
-    && tar -xzf /tmp/mprocs.tar.gz -C /usr/local/bin/ mprocs \
-    && rm -f /tmp/mprocs.tar.gz \
-    && chmod +x /usr/local/bin/mprocs
+# Install dekit - the process manager formerly released as mprocs - that runs 
the Airflow
+# components of `breeze start-airflow` (see 
scripts/in_container/bin/run_dekit).
+ARG DEKIT_VERSION="0.10.0"
+
+RUN ARCH="$(uname -m)" \
+    && 
DEKIT_URL="https://github.com/pvolok/mprocs/releases/download/v${DEKIT_VERSION}/dekit-${ARCH}-unknown-linux-musl.tar.gz";
 \
+    && echo "Downloading dekit from ${DEKIT_URL}" \
+    && curl --silent --location --fail --retry 3 --retry-delay 5 -o 
/tmp/dekit.tar.gz "${DEKIT_URL}" \
+    && tar -xzf /tmp/dekit.tar.gz -C /usr/local/bin/ dekit \
+    && rm -f /tmp/dekit.tar.gz \
+    && chmod +x /usr/local/bin/dekit
 
 WORKDIR ${AIRFLOW_SOURCES}
 
diff --git a/contributing-docs/03_contributors_quick_start.rst 
b/contributing-docs/03_contributors_quick_start.rst
index ae53fd1e4f9..fb0df5f3896 100644
--- a/contributing-docs/03_contributors_quick_start.rst
+++ b/contributing-docs/03_contributors_quick_start.rst
@@ -644,7 +644,7 @@ Using Breeze
 If Breeze was started with ``breeze start-airflow``, first exit the terminal 
multiplexer so that the
 Breeze container stops and releases its forwarded ports:
 
-* With mprocs (the default), press ``q`` in the mprocs interface.
+* With dekit (the default), press ``q`` in the dekit interface.
 * With tmux, run ``stop_airflow`` from the main shell pane:
 
 .. code-block:: bash
@@ -665,15 +665,18 @@ If ``breeze`` was started with ``breeze --python 3.10 
--backend postgres`` (or s
   breeze down
 
 .. note::
-    ``stop_airflow`` is available only when ``breeze start-airflow`` uses 
tmux. Use ``q`` to quit
-    the default mprocs interface.
+    ``stop_airflow`` is available only when ``breeze start-airflow`` uses 
tmux. Use ``q`` to leave
+    the default dekit interface.
 
-Using tmux Instead of mprocs
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Using tmux Instead of dekit
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-By default, ``breeze start-airflow`` uses mprocs to manage Airflow components. 
You can use ``tmux`` as an
+By default, ``breeze start-airflow`` uses `dekit 
<https://github.com/pvolok/mprocs>`__ (the next version of
+mprocs, which Breeze used before) to manage Airflow components. You can use 
``tmux`` as an
 alternative with the ``--terminal-multiplexer tmux`` argument. The last choice 
of yours will be remembered
-for the next run, you can switch back to ``mprocs`` anytime by using 
``--terminal-multiplexer mprocs``.
+for the next run, you can switch back to ``dekit`` anytime by using 
``--terminal-multiplexer dekit``.
+``mprocs`` is still accepted as another name for ``dekit``, and a remembered 
``mprocs`` choice is switched
+to ``dekit`` automatically.
 
 .. code-block:: bash
 
@@ -683,14 +686,14 @@ and
 
 .. code-block:: bash
 
-  breeze start-airflow --terminal-multiplexer mprocs
+  breeze start-airflow --terminal-multiplexer dekit
 
 You can also switch terminal multiplexer via breeze config:
 
 .. code-block:: bash
 
   breeze setup config --terminal-multiplexer tmux
-  breeze setup config --terminal-multiplexer mprocs
+  breeze setup config --terminal-multiplexer dekit
 
 **Benefits of using tmux:**
 
@@ -700,7 +703,7 @@ You can also switch terminal multiplexer via breeze config:
 * Wide range of plugins and extensions
 * ability to see more than one log at a time
 
-**Benefits of using mprocs:**
+**Benefits of using dekit:**
 
 * Modern terminal UI with better visual feedback
 * Easier navigation with mouse and keyboard
@@ -708,7 +711,7 @@ You can also switch terminal multiplexer via breeze config:
 * Process status indicators
 * Better cross-platform support
 
-For more information on mprocs, look at `mprocs documentation 
<mprocs/MPROCS_QUICK_REFERENCE.md>`__.
+For more information on dekit, look at `dekit documentation 
<dekit/DEKIT_QUICK_REFERENCE.md>`__.
 
 1. Knowing more about Breeze
 
diff --git a/contributing-docs/03a_contributors_quick_start_beginners.rst 
b/contributing-docs/03a_contributors_quick_start_beginners.rst
index e7540faa64a..f5709b8e19b 100644
--- a/contributing-docs/03a_contributors_quick_start_beginners.rst
+++ b/contributing-docs/03a_contributors_quick_start_beginners.rst
@@ -97,14 +97,14 @@ Option A – Breeze on Your Laptop
 
     breeze start-airflow
 
-The command starts a shell and launches multiple terminals using ``mprocs`` by 
default
+The command starts a shell and launches multiple terminals using ``dekit`` by 
default
 and launches all Airflow necessary components in those terminals.
 You can also choose to use ``tmux`` via the ``--terminal-multiplexer tmux`` 
option.
 If you are using tmux, check out this cheat sheet to learn more about its 
commands: https://tmuxcheatsheet.com/.
 
 Now you can also access the Airflow UI on your local machine at 
`http://localhost:28080 <http://localhost:28080>`_ with user name ``admin`` and 
password ``admin``.
 
-To exit breeze, press ``q`` in the ``mprocs`` interface (or in any of the tmux 
panes) and clean up the resources by running the following command:
+To exit breeze, press ``q`` in the ``dekit`` interface (or in any of the tmux 
panes) and clean up the resources by running the following command:
 
 .. code-block:: bash
 
diff --git a/contributing-docs/20_debugging_airflow_components.rst 
b/contributing-docs/20_debugging_airflow_components.rst
index d7798baab1e..12a346926ca 100644
--- a/contributing-docs/20_debugging_airflow_components.rst
+++ b/contributing-docs/20_debugging_airflow_components.rst
@@ -69,21 +69,25 @@ Breeze supports two debugger options:
     # Use PyCharm debugger
     breeze start-airflow --debug scheduler --debugger pydevd-pycharm
 
-Using mprocs Instead of tmux
------------------------------
+Choosing dekit or tmux
+----------------------
 
-By default, ``breeze start-airflow`` uses tmux to manage multiple Airflow 
components. You can use
-mprocs as an alternative process manager with the ``--use-mprocs`` flag:
+By default, ``breeze start-airflow`` uses dekit (the next version of mprocs) 
to manage multiple Airflow
+components. You can choose the terminal multiplexer with the 
``--terminal-multiplexer`` option, and
+Breeze remembers the choice for the next run:
 
 .. code-block:: bash
 
-    # Use mprocs instead of tmux
-    breeze start-airflow --use-mprocs
+    # Use dekit (the default)
+    breeze start-airflow --terminal-multiplexer dekit
 
-    # Use mprocs with debugging
-    breeze start-airflow --use-mprocs --debug scheduler --debug triggerer
+    # Use dekit with debugging
+    breeze start-airflow --terminal-multiplexer dekit --debug scheduler 
--debug triggerer
 
-**Benefits of mprocs:**
+    # Use tmux instead
+    breeze start-airflow --terminal-multiplexer tmux
+
+**Benefits of dekit:**
 
 * Modern TUI with intuitive navigation
 * Better keyboard shortcuts and mouse support
diff --git a/contributing-docs/dekit/DEKIT_QUICK_REFERENCE.md 
b/contributing-docs/dekit/DEKIT_QUICK_REFERENCE.md
new file mode 100644
index 00000000000..e8fc400940f
--- /dev/null
+++ b/contributing-docs/dekit/DEKIT_QUICK_REFERENCE.md
@@ -0,0 +1,156 @@
+<!--
+ 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.
+ -->
+
+# Quick Reference: dekit Support in Breeze
+
+[dekit](https://github.com/pvolok/mprocs) is the next version of mprocs under 
a new name; Breeze
+used mprocs before. The `mprocs` name is still accepted as an alias of `dekit` 
wherever Breeze
+takes a terminal multiplexer, and a remembered `mprocs` choice is switched to 
`dekit` automatically.
+
+## Basic Command
+
+Start airflow uses dekit by default:
+
+```bash
+breeze start-airflow
+```
+
+You can switch to using `tmux` instead by specifying the option:
+
+```bash
+breeze start-airflow --terminal-multiplexer tmux
+```
+
+Once you select the terminal multiplexer, Breeze will remember your choice for 
future runs.
+
+You can also switch terminal multiplexers by running `breeze setup config`:
+
+```bash
+breeze setup config --terminal-multiplexer dekit
+breeze setup config --terminal-multiplexer tmux
+```
+
+Breeze starts the Airflow components as dekit tasks, so they all run in a 
single terminal window.
+It generates the `dekit.yaml` configuration from the selected executor and 
options; inside the
+container it is in `/tmp/breeze-dekit/dekit.yaml`.
+
+## Common Usage Patterns
+
+| Command                                                        | Description 
                                       |
+|----------------------------------------------------------------|----------------------------------------------------|
+| `breeze start-airflow --terminal-multiplexer dekit`            | Start 
Airflow with dekit (and remember the choice) |
+| `breeze start-airflow --terminal-multiplexer tmux`             | Start 
Airflow with tmux (and remember the choice)  |
+| `breeze start-airflow --debug scheduler`                       | Debug 
scheduler with last selected multiplexer     |
+| `breeze start-airflow --dev-mode --terminal-multiplexer dekit` | Use dekit 
in dev mode (and remember the choice)    |
+
+
+## dekit Keyboard Shortcuts
+
+| Key          | Action                                          |
+|--------------|-------------------------------------------------|
+| `↑↓` / `jk`  | Navigate between tasks                          |
+| `r`          | Restart selected task                           |
+| `x`          | Stop selected task                              |
+| `s`          | Start selected task                             |
+| `z`          | Zoom into the selected task                     |
+| `Ctrl+a`     | Switch focus between the task list and terminal |
+| `q`          | Leave dekit (ends the Breeze session)           |
+| `Q`          | Stop all tasks and leave dekit                  |
+| `?`          | Show all key bindings                           |
+
+When stopping the Breeze environment, press `q` or `Q` rather than stopping 
only the
+selected task. Leaving dekit lets the `breeze start-airflow` container exit
+and release its forwarded ports. After returning to the host shell, run:
+
+```bash
+breeze down
+```
+
+## Components Managed
+
+- **scheduler** - Airflow scheduler
+- **api_server** (3.x+) / **webserver** (2.x) - Web interface
+- **triggerer** - Handles deferred tasks
+- **dag_processor** - Standalone Dag processor (when enabled)
+- **celery_worker** - Celery worker (with CeleryExecutor)
+- **flower** - Celery monitoring (when enabled)
+- **edge_worker** - Edge worker (with EdgeExecutor)
+- **shell** - A bash shell in the container
+
+## Environment Variables
+
+| Variable                   | Purpose                                         
 |
+|----------------------------|--------------------------------------------------|
+| `TERMINAL_MULTIPLEXER`     | `dekit` (default, `mprocs` also works) or 
`tmux` |
+| `INTEGRATION_CELERY`       | Enable Celery components                        
 |
+| `CELERY_FLOWER`            | Enable Flower UI                                
 |
+| `STANDALONE_DAG_PROCESSOR` | Enable standalone Dag processor                 
 |
+| `BREEZE_DEBUG_*`           | Enable component debugging                      
 |
+| `DEV_MODE`                 | Enable development mode                         
 |
+
+## Debug Ports (when debugging enabled)
+
+| Component     | Port   |
+|---------------|--------|
+| Scheduler     | 50231  |
+| Dag Processor | 50232  |
+| Triggerer     | 50233  |
+| API Server    | 50234  |
+| Celery Worker | 50235  |
+| Edge Worker   | 50236  |
+| Web Server    | 50237  |
+
+## Installation
+
+dekit is **pre-installed** in the Breeze CI image. No additional setup is 
required.
+
+For custom setups, you can install it manually:
+
+```bash
+# Download and install dekit (Linux)
+DEKIT_VERSION="0.10.0"
+curl -L 
"https://github.com/pvolok/mprocs/releases/download/v${DEKIT_VERSION}/dekit-$(uname
 -m)-unknown-linux-musl.tar.gz" \
+  | tar -xz -C /usr/local/bin/ dekit
+chmod +x /usr/local/bin/dekit
+```
+
+## Mac OS X and iTerm2
+
+Mouse clicks are not captured correctly by default in iTerm2 (which is often 
used by developers on MacOS).
+You need to configure "Enable Mouse reporting" to take advantage of the 
copying feature and mouse handling:
+
+![Enable mouse reporting](../images/iterm2-enable-mouse-reporting.png)
+
+## Standalone execution
+
+You can run dekit outside of Breeze for custom setups. Put a `dekit.yaml` 
defining your tasks in a
+directory, then start the tasks and attach to them from that directory:
+
+```bash
+dekit up
+dekit
+```
+
+`dekit up` starts every task marked `autostart: true`, and `dekit` attaches to 
them. The tasks keep
+running when you leave with `q`; `dekit down` stops them.
+
+An example [dekit.yaml](dekit.yaml) file for Airflow components can be found 
in this directory - it has
+default configurations for all major Airflow components, but you can customize 
it as needed by copying it
+elsewhere and modifying the task definitions, uncommenting the commented or 
adding new tasks. See
+[Coming from mprocs](https://dekit.run/docs/start/from-mprocs) for how dekit 
differs from mprocs.
diff --git a/contributing-docs/mprocs/mprocs.yaml 
b/contributing-docs/dekit/dekit.yaml
similarity index 52%
rename from contributing-docs/mprocs/mprocs.yaml
rename to contributing-docs/dekit/dekit.yaml
index 9565fff493c..9aca7265975 100644
--- a/contributing-docs/mprocs/mprocs.yaml
+++ b/contributing-docs/dekit/dekit.yaml
@@ -15,44 +15,42 @@
 # specific language governing permissions and limitations
 # under the License.
 
-# Basic mprocs configuration for Airflow
+# Basic dekit configuration for Airflow
 # This is a static example configuration. For dynamic configuration based on
-# your environment, use the generate_mprocs_config.py script from 
../in_container/bin.
+# your environment, use the generate_dekit_config.py script from 
../../scripts/in_container/bin.
+# Run `dekit up` in the directory with this file to start the tasks, then 
`dekit` to attach to them.
 ---
-procs:
+defaults:
+  autorestart: always
+  scrollback_len: 100000
+
+tasks:
   scheduler:
-    shell: airflow scheduler
-    restart: always
-    scrollback: 100000
+    cmd: airflow scheduler
+    autostart: true
 
   api_server:
-    shell: airflow api-server
-    restart: always
-    scrollback: 100000
+    cmd: airflow api-server
+    autostart: true
 
   triggerer:
-    shell: airflow triggerer
-    restart: always
-    scrollback: 100000
+    cmd: airflow triggerer
+    autostart: true
 
   dag_processor:
-    shell: airflow dag-processor
-    restart: always
-    scrollback: 100000
+    cmd: airflow dag-processor
+    autostart: true
+
+  # # Optional: Uncomment to enable Celery worker (requires CeleryExecutor)
+  # celery_worker:
+  #   cmd: airflow celery worker
+  #   autostart: true
+
+  # # Optional: Uncomment to enable Flower (requires Celery)
+  # flower:
+  #   cmd: airflow celery flower
+  #   autostart: true
 
   shell:
-    shell: bash
-    restart: always
-    scrollback: 100000
-
-    # # Optional: Uncomment to enable Celery worker (requires CeleryExecutor)
-    # celery_worker:
-    #   shell: airflow celery worker
-    #   restart: always
-    #   scrollback: 100000
-
-    # # Optional: Uncomment to enable Flower (requires Celery)
-    # flower:
-    #   shell: airflow celery flower
-    #   restart: always
-    #   scrollback: 100000
+    cmd: bash
+    autostart: true
diff --git a/contributing-docs/mprocs/MPROCS_QUICK_REFERENCE.md 
b/contributing-docs/mprocs/MPROCS_QUICK_REFERENCE.md
deleted file mode 100644
index 416fed3b482..00000000000
--- a/contributing-docs/mprocs/MPROCS_QUICK_REFERENCE.md
+++ /dev/null
@@ -1,148 +0,0 @@
-<!--
- 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.
- -->
-
-# Quick Reference: mprocs Support in Breeze
-
-## Basic Command
-
-Start airflow uses mprocs by default:
-
-```bash
-breeze start-airflow
-```
-
-You can switch to using `tmux` instead by specifying the option:
-
-```bash
-breeze start-airflow --terminal-multiplexer tmux
-```
-
-Once you select the terminal multiplexer, Breeze will remember your choice for 
future runs.
-
-You can also switch terminal multiplexers by running `breeze setup config`:
-
-```bash
-breeze setup config --terminal-multiplexer mprocs
-breeze setup config --terminal-multiplexer tmux
-```
-
-
-When Breeze will start Airflow components using mprocs to manage multiple 
processes in a single terminal window.
-It will generate dynamically the required configuration based on the selected 
executor and options and use it,
-the generated configuration file is stored in a `files` folder inside the 
container, so that you can also
-use it outside of Breeze if needed.
-
-## Common Usage Patterns
-
-| Command                                                         | 
Description                                         |
-|-----------------------------------------------------------------|-----------------------------------------------------|
-| `breeze start-airflow --terminal-multiplexer mprocs`            | Start 
Airflow with mprocs (and remember the choice) |
-| `breeze start-airflow --terminal-multiplexer tmux`              | Start 
Airflow with tmux (and remember the choice)   |
-| `breeze start-airflow --debug scheduler`                        | Debug 
scheduler with last selected multiplexer      |
-| `breeze start-airflow --dev-mode --terminal-multiplexer mprocs` | Use mprocs 
in dev mode (and remember the choice)    |
-
-
-## mprocs Keyboard Shortcuts
-
-| Key  | Action                     |
-|------|----------------------------|
-| `↑↓` | Navigate between processes |
-| `r`  | Restart selected process   |
-| `x`  | Stop selected process      |
-| `s`  | Start selected process     |
-| `a`  | Add new process            |
-| `q`  | Quit mprocs                |
-| `?`  | Show help                  |
-
-When stopping the Breeze environment, press `q` rather than stopping only the
-selected process. Quitting mprocs lets the `breeze start-airflow` container 
exit
-and release its forwarded ports. After returning to the host shell, run:
-
-```bash
-breeze down
-```
-
-## Components Managed
-
-- **scheduler** - Airflow scheduler
-- **api_server** (3.x+) / **webserver** (2.x) - Web interface
-- **triggerer** - Handles deferred tasks
-- **dag_processor** - Standalone Dag processor (when enabled)
-- **celery_worker** - Celery worker (with CeleryExecutor)
-- **flower** - Celery monitoring (when enabled)
-- **edge_worker** - Edge worker (with EdgeExecutor)
-
-## Environment Variables
-
-| Variable                   | Purpose                         |
-|----------------------------|---------------------------------|
-| `TERMNAL_MULTIPLEXER`      | Use mprocs when set to "mprocs" |
-| `INTEGRATION_CELERY`       | Enable Celery components        |
-| `CELERY_FLOWER`            | Enable Flower UI                |
-| `STANDALONE_DAG_PROCESSOR` | Enable standalone Dag processor |
-| `BREEZE_DEBUG_*`           | Enable component debugging      |
-| `DEV_MODE`                 | Enable development mode         |
-
-## Debug Ports (when debugging enabled)
-
-| Component     | Port   |
-|---------------|--------|
-| Scheduler     | 50231  |
-| Dag Processor | 50232  |
-| Triggerer     | 50233  |
-| API Server    | 50234  |
-| Celery Worker | 50235  |
-| Edge Worker   | 50236  |
-| Web Server    | 50237  |
-
-## Installation
-
-mprocs is **pre-installed** in the Breeze CI image as of Airflow 3.x 
development. No additional setup is required.
-
-For older images or custom setups, you can install mprocs manually:
-
-```bash
-# Download and install mprocs
-MPROCS_VERSION="0.7.3"
-SYSTEM=$(uname -s | tr '[:upper:]' '[:lower:]')
-PLATFORM=$([ "$(uname -m)" = "aarch64" ] && echo "arm64" || echo "amd64")
-curl -L 
"https://github.com/pvolok/mprocs/releases/download/v${MPROCS_VERSION}/mprocs-${MPROCS_VERSION}-${SYSTEM}-${PLATFORM}.tar.gz";
 \
-  | tar -xz -C /usr/local/bin/ mprocs
-chmod +x /usr/local/bin/mprocs
-```
-
-## Mac OS X and iTerm2
-
-Mouse clicks are not captured correctly by default in iTerm2 (which is often 
used by developers on MacOS).
-You need to configure "Enable Mouse reporting" to take advantage of the 
copying feature and mouse handling:
-
-![Enable mouse reporting](../images/iterm2-enable-mouse-reporting.png)
-
-## Standalone execution
-
-You can run mprocs outside of Breeze for custom setups. Create a `mprocs.yaml` 
configuration
-file defining your processes, then start mprocs:
-
-```bash
-mprocs -f mprocs.yaml
-```
-
-An example [mprocs.yaml](mprocs.yaml) file for Airflow components can be found 
in this directory - it has
-default configurations for all major Airflow components, but you can customize 
it as needed by copying it
-elsewhere and modifying the process definitions, uncommenting the commented or 
adding new processes.
diff --git a/dev/README_RELEASE_PROVIDERS.md b/dev/README_RELEASE_PROVIDERS.md
index eb8097f93e0..abb62392c2b 100644
--- a/dev/README_RELEASE_PROVIDERS.md
+++ b/dev/README_RELEASE_PROVIDERS.md
@@ -1660,7 +1660,7 @@ pip install 
apache-airflow-providers-<provider>==<VERSION>rc<X>
 ```
 
 NOTE! After installing the provider package, restart the Airflow components so 
the new provider is loaded.
-If you started Breeze with `breeze start-airflow`, in the terminal multiplexer 
(mprocs or tmux)
+If you started Breeze with `breeze start-airflow`, in the terminal multiplexer 
(dekit or tmux)
 use the keyboard shortcuts to **stop** and then **start** each managed 
component:
 **scheduler**, **api_server**, **triggerer**, and **dag_processor**.
 
diff --git a/dev/breeze/doc/03_developer_tasks.rst 
b/dev/breeze/doc/03_developer_tasks.rst
index b94b4b01727..2ba9135d614 100644
--- a/dev/breeze/doc/03_developer_tasks.rst
+++ b/dev/breeze/doc/03_developer_tasks.rst
@@ -764,7 +764,7 @@ you are running on your host.
 If you used ``breeze start-airflow``, first exit its terminal multiplexer so 
that the foreground
 container releases its forwarded ports:
 
-* With mprocs (the default), press ``q`` in the mprocs interface.
+* With dekit (the default), press ``q`` in the dekit interface.
 * With tmux, run ``stop_airflow`` from its main shell pane.
 
 After returning to the host shell, stop the remaining Docker Compose services:
diff --git a/dev/breeze/doc/images/output_setup_config.svg 
b/dev/breeze/doc/images/output_setup_config.svg
index 9f06770cc98..d19cdcc229f 100644
--- a/dev/breeze/doc/images/output_setup_config.svg
+++ b/dev/breeze/doc/images/output_setup_config.svg
@@ -174,7 +174,7 @@
 </text><text class="breeze-setup-config-r5" x="0" y="386" textLength="12.2" 
clip-path="url(#breeze-setup-config-line-15)">│</text><text 
class="breeze-setup-config-r7" x="475.8" y="386" textLength="549" 
clip-path="url(#breeze-setup-config-line-15)">(&gt;sqlite&lt;&#160;|&#160;mysql&#160;|&#160;postgres&#160;|&#160;none&#160;|&#160;custom)</text><text
 class="breeze-setup-config-r5" x="1451.8" y="386" textLength="12.2" 
clip-path="url(#breeze-setup-config-line-15)">│</text><text class="breez [...]
 </text><text class="breeze-setup-config-r5" x="0" y="410.4" textLength="12.2" 
clip-path="url(#breeze-setup-config-line-16)">│</text><text 
class="breeze-setup-config-r4" x="24.4" y="410.4" textLength="341.6" 
clip-path="url(#breeze-setup-config-line-16)">--postgres-version&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-setup-config-r6" x="390.4" y="410.4" textLength="61" 
clip-path="url(#breeze-setup-config-line-16)">-P&#160;&#160;&#160;</text><text 
cl [...]
 </text><text class="breeze-setup-config-r5" x="0" y="434.8" textLength="12.2" 
clip-path="url(#breeze-setup-config-line-17)">│</text><text 
class="breeze-setup-config-r4" x="24.4" y="434.8" textLength="341.6" 
clip-path="url(#breeze-setup-config-line-17)">--mysql-version&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-setup-config-r6" x="390.4" y="434.8" textLength="61" 
clip-path="url(#breeze-setup-config-line-17)">-M&#160;&#160;&#160; [...]
-</text><text class="breeze-setup-config-r5" x="0" y="459.2" textLength="12.2" 
clip-path="url(#breeze-setup-config-line-18)">│</text><text 
class="breeze-setup-config-r4" x="24.4" y="459.2" textLength="341.6" 
clip-path="url(#breeze-setup-config-line-18)">--terminal-multiplexer&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-setup-config-r6" x="390.4" y="459.2" textLength="61" 
clip-path="url(#breeze-setup-config-line-18)">-t&#160;&#160;&#160;</text><text 
class="breeze-setup-co [...]
+</text><text class="breeze-setup-config-r5" x="0" y="459.2" textLength="12.2" 
clip-path="url(#breeze-setup-config-line-18)">│</text><text 
class="breeze-setup-config-r4" x="24.4" y="459.2" textLength="341.6" 
clip-path="url(#breeze-setup-config-line-18)">--terminal-multiplexer&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-setup-config-r6" x="390.4" y="459.2" textLength="61" 
clip-path="url(#breeze-setup-config-line-18)">-t&#160;&#160;&#160;</text><text 
class="breeze-setup-co [...]
 </text><text class="breeze-setup-config-r5" x="0" y="483.6" textLength="12.2" 
clip-path="url(#breeze-setup-config-line-19)">│</text><text 
class="breeze-setup-config-r4" x="24.4" y="483.6" textLength="341.6" 
clip-path="url(#breeze-setup-config-line-19)">--auth-manager&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-setup-config-r1" x="475.8" y="483.6" textLength="390.4" 
clip-path="url(#breeze-setup-config-line-19)">Specify&#160 [...]
 </text><text class="breeze-setup-config-r5" x="0" y="508" textLength="12.2" 
clip-path="url(#breeze-setup-config-line-20)">│</text><text 
class="breeze-setup-config-r7" x="475.8" y="508" textLength="463.6" 
clip-path="url(#breeze-setup-config-line-20)">(&gt;SimpleAuthManager&lt;&#160;|&#160;FabAuthManager)</text><text
 class="breeze-setup-config-r5" x="1451.8" y="508" textLength="12.2" 
clip-path="url(#breeze-setup-config-line-20)">│</text><text 
class="breeze-setup-config-r1" x="1464" y="508" [...]
 </text><text class="breeze-setup-config-r5" x="0" y="532.4" textLength="12.2" 
clip-path="url(#breeze-setup-config-line-21)">│</text><text 
class="breeze-setup-config-r4" x="24.4" y="532.4" textLength="341.6" 
clip-path="url(#breeze-setup-config-line-21)">--llm-model&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-setup-config-r1" x="475.8" y="532.4" textLength="963.8" 
clip-path="url(#breeze-setup-config-line-21 [...]
diff --git a/dev/breeze/doc/images/output_setup_config.txt 
b/dev/breeze/doc/images/output_setup_config.txt
index 4bed9f321be..c78a138882b 100644
--- a/dev/breeze/doc/images/output_setup_config.txt
+++ b/dev/breeze/doc/images/output_setup_config.txt
@@ -1 +1 @@
-4fc5026be69f9e924d243365bdaa993d
+7de551475d94895c673732562a5ae6ab
diff --git a/dev/breeze/doc/images/output_start-airflow.svg 
b/dev/breeze/doc/images/output_start-airflow.svg
index 92ae687182f..5e2db6e15a6 100644
--- a/dev/breeze/doc/images/output_start-airflow.svg
+++ b/dev/breeze/doc/images/output_start-airflow.svg
@@ -505,8 +505,8 @@
 </text><text class="breeze-start-airflow-r5" x="0" y="459.2" textLength="12.2" 
clip-path="url(#breeze-start-airflow-line-18)">│</text><text 
class="breeze-start-airflow-r4" x="24.4" y="459.2" textLength="317.2" 
clip-path="url(#breeze-start-airflow-line-18)">--standalone-dag-processor</text><text
 class="breeze-start-airflow-r1" x="341.6" y="459.2" textLength="12.2" 
clip-path="url(#breeze-start-airflow-line-18)">/</text><text 
class="breeze-start-airflow-r4" x="353.8" y="459.2" textLength="3 [...]
 </text><text class="breeze-start-airflow-r5" x="0" y="483.6" textLength="12.2" 
clip-path="url(#breeze-start-airflow-line-19)">│</text><text 
class="breeze-start-airflow-r4" x="24.4" y="483.6" textLength="12.2" 
clip-path="url(#breeze-start-airflow-line-19)">r</text><text 
class="breeze-start-airflow-r1" x="768.6" y="483.6" textLength="317.2" 
clip-path="url(#breeze-start-airflow-line-19)">(required&#160;for&#160;Airflow&#160;3).&#160;</text><text
 class="breeze-start-airflow-r5" x="1085.8" y= [...]
 </text><text class="breeze-start-airflow-r5" x="0" y="508" textLength="12.2" 
clip-path="url(#breeze-start-airflow-line-20)">│</text><text 
class="breeze-start-airflow-r5" x="768.6" y="508" textLength="305" 
clip-path="url(#breeze-start-airflow-line-20)">standalone-dag-processor]</text><text
 class="breeze-start-airflow-r5" x="1451.8" y="508" textLength="12.2" 
clip-path="url(#breeze-start-airflow-line-20)">│</text><text 
class="breeze-start-airflow-r1" x="1464" y="508" textLength="12.2" clip- [...]
-</text><text class="breeze-start-airflow-r5" x="0" y="532.4" textLength="12.2" 
clip-path="url(#breeze-start-airflow-line-21)">│</text><text 
class="breeze-start-airflow-r4" x="24.4" y="532.4" textLength="671" 
clip-path="url(#breeze-start-airflow-line-21)">--terminal-multiplexer&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#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
 clas [...]
-</text><text class="breeze-start-airflow-r5" x="0" y="556.8" textLength="12.2" 
clip-path="url(#breeze-start-airflow-line-22)">│</text><text 
class="breeze-start-airflow-r7" x="768.6" y="556.8" textLength="207.4" 
clip-path="url(#breeze-start-airflow-line-22)">(&gt;mprocs&lt;&#160;|&#160;tmux)</text><text
 class="breeze-start-airflow-r5" x="1451.8" y="556.8" textLength="12.2" 
clip-path="url(#breeze-start-airflow-line-22)">│</text><text 
class="breeze-start-airflow-r1" x="1464" y="556.8" textL [...]
+</text><text class="breeze-start-airflow-r5" x="0" y="532.4" textLength="12.2" 
clip-path="url(#breeze-start-airflow-line-21)">│</text><text 
class="breeze-start-airflow-r4" x="24.4" y="532.4" textLength="671" 
clip-path="url(#breeze-start-airflow-line-21)">--terminal-multiplexer&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#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
 clas [...]
+</text><text class="breeze-start-airflow-r5" x="0" y="556.8" textLength="12.2" 
clip-path="url(#breeze-start-airflow-line-22)">│</text><text 
class="breeze-start-airflow-r7" x="768.6" y="556.8" textLength="195.2" 
clip-path="url(#breeze-start-airflow-line-22)">(&gt;dekit&lt;&#160;|&#160;tmux)</text><text
 class="breeze-start-airflow-r5" x="1451.8" y="556.8" textLength="12.2" 
clip-path="url(#breeze-start-airflow-line-22)">│</text><text 
class="breeze-start-airflow-r1" x="1464" y="556.8" textLe [...]
 </text><text class="breeze-start-airflow-r5" x="0" y="581.2" textLength="12.2" 
clip-path="url(#breeze-start-airflow-line-23)">│</text><text 
class="breeze-start-airflow-r4" x="24.4" y="581.2" textLength="671" 
clip-path="url(#breeze-start-airflow-line-23)">--auth-manager&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#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-start-airflow-r5" x="0" y="605.6" textLength="12.2" 
clip-path="url(#breeze-start-airflow-line-24)">│</text><text 
class="breeze-start-airflow-r5" x="768.6" y="605.6" textLength="219.6" 
clip-path="url(#breeze-start-airflow-line-24)">SimpleAuthManager]</text><text 
class="breeze-start-airflow-r7" x="1000.4" y="605.6" textLength="280.6" 
clip-path="url(#breeze-start-airflow-line-24)">(&gt;SimpleAuthManager&lt;&#160;|&#160;</text><text
 class="breeze-start-airflow-r5"  [...]
 </text><text class="breeze-start-airflow-r5" x="0" y="630" textLength="12.2" 
clip-path="url(#breeze-start-airflow-line-25)">│</text><text 
class="breeze-start-airflow-r7" x="768.6" y="630" textLength="183" 
clip-path="url(#breeze-start-airflow-line-25)">FabAuthManager)</text><text 
class="breeze-start-airflow-r5" x="1451.8" y="630" textLength="12.2" 
clip-path="url(#breeze-start-airflow-line-25)">│</text><text 
class="breeze-start-airflow-r1" x="1464" y="630" textLength="12.2" 
clip-path="url( [...]
diff --git a/dev/breeze/doc/images/output_start-airflow.txt 
b/dev/breeze/doc/images/output_start-airflow.txt
index b6d888c9fcb..69f9857b548 100644
--- a/dev/breeze/doc/images/output_start-airflow.txt
+++ b/dev/breeze/doc/images/output_start-airflow.txt
@@ -1 +1 @@
-14195584ab4f2240677b66688c848ba8
+09f22d94d14c4bc012afd6f3d78cae5c
diff --git a/dev/breeze/src/airflow_breeze/global_constants.py 
b/dev/breeze/src/airflow_breeze/global_constants.py
index ea254d1fb0c..224c23279fe 100644
--- a/dev/breeze/src/airflow_breeze/global_constants.py
+++ b/dev/breeze/src/airflow_breeze/global_constants.py
@@ -176,7 +176,11 @@ AUTOCOMPLETE_ALL_INTEGRATIONS = sorted(
     ]
 )
 ALLOWED_TTY = ["auto", "enabled", "disabled"]
-ALLOWED_TERMINAL_MULTIPLEXERS = ["mprocs", "tmux"]
+ALLOWED_TERMINAL_MULTIPLEXERS = ["dekit", "tmux"]
+# Old names of a choice, still accepted as hidden aliases of the new value: on 
the command line and in
+# environment variables they mean the new value, and a cached old value is 
migrated to the new one.
+# mprocs is released as dekit since 0.10.0; Breeze runs dekit in its mprocs 
mode.
+TERMINAL_MULTIPLEXER_ALIASES = {"mprocs": "dekit"}
 ALLOWED_DOCKER_COMPOSE_PROJECTS = [
     "breeze",
     "breeze-prek",
diff --git a/dev/breeze/src/airflow_breeze/utils/cache.py 
b/dev/breeze/src/airflow_breeze/utils/cache.py
index 533d4f92eae..00b94fdf4ea 100644
--- a/dev/breeze/src/airflow_breeze/utils/cache.py
+++ b/dev/breeze/src/airflow_breeze/utils/cache.py
@@ -37,10 +37,24 @@ def check_if_cache_exists(param_name: str) -> bool:
     return (Path(BUILD_CACHE_PATH) / f".{param_name}").exists()
 
 
+def resolve_value_alias(param_name: str, param_value: str) -> str:
+    """Return the current value for a hidden alias (an old name) of a choice, 
else the value itself."""
+    aliases: dict[str, str] = getattr(global_constants, 
f"{param_name.upper()}_ALIASES", {})
+    return aliases.get(param_value, param_value)
+
+
 def read_from_cache_file(param_name: str) -> str | None:
     cache_exists = check_if_cache_exists(param_name)
     if cache_exists:
-        return (Path(BUILD_CACHE_PATH) / f".{param_name}").read_text().strip()
+        cached_value = (Path(BUILD_CACHE_PATH) / 
f".{param_name}").read_text().strip()
+        resolved_value = resolve_value_alias(param_name, cached_value)
+        if resolved_value != cached_value:
+            # The choice was renamed: keep the user's preference under its new 
name.
+            console_print(
+                f"[info]Migrating the cached {param_name} value {cached_value} 
to {resolved_value}.[/]"
+            )
+            write_to_cache_file(param_name, resolved_value, 
check_allowed_values=False)
+        return resolved_value
     return None
 
 
diff --git a/dev/breeze/src/airflow_breeze/utils/custom_param_types.py 
b/dev/breeze/src/airflow_breeze/utils/custom_param_types.py
index 93f7ccd660c..82204399265 100644
--- a/dev/breeze/src/airflow_breeze/utils/custom_param_types.py
+++ b/dev/breeze/src/airflow_breeze/utils/custom_param_types.py
@@ -30,6 +30,7 @@ from airflow_breeze.utils.cache import (
     check_if_values_allowed,
     read_and_validate_value_from_cache,
     read_from_cache_file,
+    resolve_value_alias,
     write_to_cache_file,
 )
 from airflow_breeze.utils.coertions import coerce_bool_value
@@ -170,6 +171,7 @@ class CacheableChoice(click.Choice):
             if not is_cached:
                 console_print(f"\n[info]Default value of {param.name} 
parameter {new_value} used.[/]\n")
         else:
+            value = resolve_value_alias(param_name, value)
             allowed, allowed_values = check_if_values_allowed(param_name, 
value)
             if allowed:
                 new_value = value
diff --git a/dev/breeze/tests/test_cache.py b/dev/breeze/tests/test_cache.py
index e8b9a3f4f91..dcafe2293f0 100644
--- a/dev/breeze/tests/test_cache.py
+++ b/dev/breeze/tests/test_cache.py
@@ -19,14 +19,22 @@ from __future__ import annotations
 from pathlib import Path
 from unittest import mock
 
+import click
 import pytest
+from click.testing import CliRunner
 
-from airflow_breeze.global_constants import ALLOWED_PYTHON_MAJOR_MINOR_VERSIONS
+from airflow_breeze.commands.common_options import option_terminal_multiplexer
+from airflow_breeze.global_constants import (
+    ALLOWED_PYTHON_MAJOR_MINOR_VERSIONS,
+    ALLOWED_TERMINAL_MULTIPLEXERS,
+    TERMINAL_MULTIPLEXER_ALIASES,
+)
 from airflow_breeze.utils.cache import (
     check_if_cache_exists,
     check_if_values_allowed,
     delete_cache,
     read_from_cache_file,
+    resolve_value_alias,
 )
 
 AIRFLOW_SOURCES = Path(__file__).parents[3].resolve()
@@ -90,3 +98,54 @@ def test_delete_cache_not_exists(mock_check_if_cache_exists, 
mock_path):
     mock_check_if_cache_exists.return_value = False
     cache_deleted = delete_cache(param)
     assert not cache_deleted
+
+
[email protected](
+    ("param_name", "value", "expected"),
+    [
+        ("TERMINAL_MULTIPLEXER", "mprocs", "dekit"),
+        ("TERMINAL_MULTIPLEXER", "dekit", "dekit"),
+        ("TERMINAL_MULTIPLEXER", "tmux", "tmux"),
+        ("BACKEND", "mprocs", "mprocs"),
+    ],
+)
+def test_resolve_value_alias(param_name, value, expected):
+    assert resolve_value_alias(param_name, value) == expected
+
+
+def test_mprocs_is_not_offered_as_a_choice():
+    assert "mprocs" not in ALLOWED_TERMINAL_MULTIPLEXERS
+    assert TERMINAL_MULTIPLEXER_ALIASES["mprocs"] in 
ALLOWED_TERMINAL_MULTIPLEXERS
+
+
+def test_cached_old_name_is_migrated(monkeypatch, tmp_path):
+    monkeypatch.setattr("airflow_breeze.utils.cache.BUILD_CACHE_PATH", 
tmp_path)
+    (tmp_path / ".TERMINAL_MULTIPLEXER").write_text("mprocs")
+
+    assert read_from_cache_file("TERMINAL_MULTIPLEXER") == "dekit"
+    assert (tmp_path / ".TERMINAL_MULTIPLEXER").read_text() == "dekit"
+
+
+def test_cached_current_value_is_left_alone(monkeypatch, tmp_path):
+    monkeypatch.setattr("airflow_breeze.utils.cache.BUILD_CACHE_PATH", 
tmp_path)
+    (tmp_path / ".TERMINAL_MULTIPLEXER").write_text("tmux")
+
+    assert read_from_cache_file("TERMINAL_MULTIPLEXER") == "tmux"
+    assert (tmp_path / ".TERMINAL_MULTIPLEXER").read_text() == "tmux"
+
+
[email protected]("given", ["mprocs", "dekit"])
+def test_option_accepts_the_old_name_and_remembers_the_new_one(monkeypatch, 
tmp_path, given):
+    monkeypatch.setattr("airflow_breeze.utils.cache.BUILD_CACHE_PATH", 
tmp_path)
+    monkeypatch.delenv("SKIP_SAVING_CHOICES", raising=False)
+
+    @click.command()
+    @option_terminal_multiplexer
+    def command(terminal_multiplexer):
+        click.echo(terminal_multiplexer)
+
+    result = CliRunner().invoke(command, ["--terminal-multiplexer", given])
+
+    assert result.exit_code == 0, result.output
+    assert result.output.strip().splitlines()[-1] == "dekit"
+    assert (tmp_path / ".TERMINAL_MULTIPLEXER").read_text() == "dekit"
diff --git a/scripts/ci/prek/upgrade_important_versions.py 
b/scripts/ci/prek/upgrade_important_versions.py
index 1124935d80c..44e77ba8129 100755
--- a/scripts/ci/prek/upgrade_important_versions.py
+++ b/scripts/ci/prek/upgrade_important_versions.py
@@ -766,7 +766,7 @@ UPGRADE_GITPYTHON: bool = get_env_bool("UPGRADE_GITPYTHON")
 UPGRADE_GOLANG: bool = get_env_bool("UPGRADE_GOLANG")
 UPGRADE_HATCH: bool = get_env_bool("UPGRADE_HATCH")
 UPGRADE_HATCHLING: bool = get_env_bool("UPGRADE_HATCHLING")
-UPGRADE_MPROCS: bool = get_env_bool("UPGRADE_MPROCS")
+UPGRADE_DEKIT: bool = get_env_bool("UPGRADE_DEKIT")
 UPGRADE_NODE_LTS: bool = get_env_bool("UPGRADE_NODE_LTS")
 UPGRADE_PIP: bool = get_env_bool("UPGRADE_PIP")
 UPGRADE_PREK: bool = get_env_bool("UPGRADE_PREK")
@@ -885,8 +885,8 @@ SIMPLE_VERSION_PATTERNS: dict[str, list[tuple[str, str]]] = 
{
     "protoc": [
         (r"(rvolosatovs/protoc:)(v[0-9.]+)", "rvolosatovs/protoc:{version}"),
     ],
-    "mprocs": [
-        (r"(ARG MPROCS_VERSION=)(\"[0-9.]+\")", 'ARG 
MPROCS_VERSION="{version}"'),
+    "dekit": [
+        (r"(ARG DEKIT_VERSION=)(\"[0-9.]+\")", 'ARG 
DEKIT_VERSION="{version}"'),
     ],
     "openapi_generator": [
         (r"(OPENAPI_GENERATOR_CLI_VER = )(\"[0-9.]+\")", 
'OPENAPI_GENERATOR_CLI_VER = "{version}"'),
@@ -942,7 +942,8 @@ def fetch_all_package_versions() -> dict[str, str]:
         "protoc": get_latest_image_version("rvolosatovs/protoc") if 
UPGRADE_PROTOC else "",
         "alpine": get_latest_image_version("alpine") if UPGRADE_ALPINE else "",
         "busybox": get_latest_image_version("busybox") if UPGRADE_BUSYBOX else 
"",
-        "mprocs": get_latest_github_release_version("pvolok/mprocs") if 
UPGRADE_MPROCS else "",
+        # dekit is still released from the mprocs repository.
+        "dekit": get_latest_github_release_version("pvolok/mprocs") if 
UPGRADE_DEKIT else "",
         "openapi_generator": get_latest_openapi_generator_version() if 
UPGRADE_OPENAPI_GENERATOR else "",
         "sphinx_airflow_theme": get_latest_sphinx_airflow_theme_version()
         if UPGRADE_SPHINX_AIRFLOW_THEME
diff --git a/scripts/docker/entrypoint_ci.sh b/scripts/docker/entrypoint_ci.sh
index b27b986df65..ca076ee7024 100755
--- a/scripts/docker/entrypoint_ci.sh
+++ b/scripts/docker/entrypoint_ci.sh
@@ -246,9 +246,10 @@ SSH_CONFIG
         if [[ ${SKIP_ASSETS_COMPILATION:="false"} == "false" ]]; then
             wait_for_asset_compilation
         fi
-        if [[ ${TERMINAL_MULTIPLEXER:="mprocs"} == "mprocs" ]]; then
-            # shellcheck source=scripts/in_container/bin/run_mprocs
-            exec run_mprocs
+        # "mprocs" is the old name of dekit, still accepted from older Breeze 
versions.
+        if [[ ${TERMINAL_MULTIPLEXER:="dekit"} == "dekit" || 
${TERMINAL_MULTIPLEXER} == "mprocs" ]]; then
+            # shellcheck source=scripts/in_container/bin/run_dekit
+            exec run_dekit
         else
             # shellcheck source=scripts/in_container/bin/run_tmux
             exec run_tmux
diff --git a/scripts/in_container/bin/generate_mprocs_config.py 
b/scripts/in_container/bin/generate_dekit_config.py
similarity index 81%
rename from scripts/in_container/bin/generate_mprocs_config.py
rename to scripts/in_container/bin/generate_dekit_config.py
index 823865da19a..7e8c1d7094d 100755
--- a/scripts/in_container/bin/generate_mprocs_config.py
+++ b/scripts/in_container/bin/generate_dekit_config.py
@@ -22,7 +22,7 @@
 #   "PyYAML>=6.0",
 # ]
 # ///
-"""Generate mprocs configuration dynamically based on environment variables."""
+"""Generate the dekit configuration (``dekit.yaml``) for ``breeze 
start-airflow`` from environment variables."""
 
 from __future__ import annotations
 
@@ -46,9 +46,9 @@ def get_env(var_name: str, default: str = "") -> str:
     return os.environ.get(var_name, default)
 
 
-def generate_mprocs_config() -> str:
-    """Generate mprocs YAML configuration based on environment variables."""
-    procs = {}
+def get_component_commands() -> dict[str, str]:
+    """Return the shell command of each Airflow component to run, by task 
name."""
+    procs: dict[str, str] = {}
 
     # Scheduler
     scheduler_cmd = "airflow scheduler"
@@ -56,11 +56,7 @@ def generate_mprocs_config() -> str:
         port = get_env("BREEZE_DEBUG_SCHEDULER_PORT", "5678")
         scheduler_cmd = f"debugpy --listen 0.0.0.0:{port} --wait-for-client -m 
airflow scheduler"
 
-    procs["scheduler"] = {
-        "shell": scheduler_cmd,
-        "restart": "always",
-        "scrollback": 100000,
-    }
+    procs["scheduler"] = scheduler_cmd
 
     # API Server or Webserver (depending on Airflow version)
     use_airflow_version = get_env("USE_AIRFLOW_VERSION", "")
@@ -84,7 +80,7 @@ def generate_mprocs_config() -> str:
             api_cmd = (
                 f"airflow api-server {api_host_arg} -d" if dev_mode else 
f"airflow api-server {api_host_arg}"
             )
-        procs["api_server"] = {"shell": api_cmd, "restart": "always", 
"scrollback": 100000}
+        procs["api_server"] = api_cmd
     else:
         # Webserver (Airflow 2.x)
         if get_env_bool("BREEZE_DEBUG_WEBSERVER"):
@@ -94,11 +90,7 @@ def generate_mprocs_config() -> str:
             dev_mode = get_env_bool("DEV_MODE")
             web_cmd = "airflow webserver -d" if dev_mode else "airflow 
webserver"
 
-        procs["webserver"] = {
-            "shell": web_cmd,
-            "restart": "always",
-            "scrollback": 100000,
-        }
+        procs["webserver"] = web_cmd
 
     # Triggerer
     triggerer_cmd = "airflow triggerer"
@@ -106,11 +98,7 @@ def generate_mprocs_config() -> str:
         port = get_env("BREEZE_DEBUG_TRIGGERER_PORT", "5681")
         triggerer_cmd = f"debugpy --listen 0.0.0.0:{port} --wait-for-client -m 
airflow triggerer"
 
-    procs["triggerer"] = {
-        "shell": triggerer_cmd,
-        "restart": "always",
-        "scrollback": 100000,
-    }
+    procs["triggerer"] = triggerer_cmd
 
     # Celery Worker (conditional)
     if get_env_bool("INTEGRATION_CELERY"):
@@ -120,11 +108,7 @@ def generate_mprocs_config() -> str:
         else:
             celery_cmd = "airflow celery worker"
 
-        procs["celery_worker"] = {
-            "shell": celery_cmd,
-            "restart": "always",
-            "scrollback": 100000,
-        }
+        procs["celery_worker"] = celery_cmd
 
     # Flower (conditional)
     if get_env_bool("INTEGRATION_CELERY") and get_env_bool("CELERY_FLOWER"):
@@ -134,11 +118,7 @@ def generate_mprocs_config() -> str:
         else:
             flower_cmd = "airflow celery flower"
 
-        procs["flower"] = {
-            "shell": flower_cmd,
-            "restart": "always",
-            "scrollback": 100000,
-        }
+        procs["flower"] = flower_cmd
 
     # Edge Worker (conditional)
     executor = get_env("AIRFLOW__CORE__EXECUTOR", "")
@@ -159,7 +139,7 @@ def generate_mprocs_config() -> str:
             ]
             edge_cmd = " && ".join(edge_cmd_parts)
 
-        procs["edge_worker"] = {"shell": edge_cmd, "restart": "always", 
"scrollback": 100000}
+        procs["edge_worker"] = edge_cmd
 
     # Dag Processor (conditional)
     if get_env_bool("STANDALONE_DAG_PROCESSOR"):
@@ -169,20 +149,28 @@ def generate_mprocs_config() -> str:
         else:
             dag_proc_cmd = "airflow dag-processor"
 
-        procs["dag_processor"] = {
-            "shell": dag_proc_cmd,
-            "restart": "always",
-            "scrollback": 100000,
-        }
+        procs["dag_processor"] = dag_proc_cmd
 
-    procs["shell"] = {
-        "shell": "bash",
-        "restart": "always",
-        "scrollback": 100000,
-    }
+    procs["shell"] = "bash"
+    return procs
 
-    # Generate YAML output
-    config_dict = {"procs": procs}
+
+def generate_dekit_config(cwd: str) -> str:
+    """Generate the ``dekit.yaml`` that runs every component as an 
autostarted, always restarted task."""
+    tasks = {
+        # dekit runs a command without a shell, so each runs through bash as 
it did under mprocs.
+        name: {"cmd": ["bash", "-c", command], "autostart": True}
+        for name, command in get_component_commands().items()
+    }
+    config_dict = {
+        "defaults": {
+            # The tasks run where Breeze starts them, not in the dekit project 
directory.
+            "cwd": cwd,
+            "autorestart": "always",
+            "scrollback_len": 100000,
+        },
+        "tasks": tasks,
+    }
     return yaml.dump(config_dict, default_flow_style=False, sort_keys=False)
 
 
@@ -193,14 +181,14 @@ def main():
         os.environ["AIRFLOW__CORE__EXECUTOR"] = "LocalExecutor"
 
     # Generate and print configuration
-    config = generate_mprocs_config()
+    config = generate_dekit_config(cwd=os.getcwd())
 
     # Determine output path
     if len(sys.argv) > 1:
         output_path = sys.argv[1]
     else:
         temp_dir = tempfile.gettempdir()
-        output_path = os.path.join(temp_dir, "mprocs.yaml")
+        output_path = os.path.join(temp_dir, "dekit.yaml")
 
     with open(output_path, "w") as f:
         f.write(config)
@@ -210,7 +198,7 @@ def main():
         console = Console()
 
         console.print(
-            f"\n[bold green]✓[/bold green] Generated mprocs configuration at: 
[cyan]{output_path}[/cyan]"
+            f"\n[bold green]✓[/bold green] Generated dekit configuration at: 
[cyan]{output_path}[/cyan]"
         )
 
         # Display configuration with syntax highlighting
diff --git a/scripts/in_container/bin/run_dekit 
b/scripts/in_container/bin/run_dekit
new file mode 100755
index 00000000000..1b4bcab3870
--- /dev/null
+++ b/scripts/in_container/bin/run_dekit
@@ -0,0 +1,39 @@
+#!/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.
+
+# Run the Airflow components as tasks of a dekit project. The project lives in 
the container, not in
+# the mounted /files, so no runner state from an earlier Breeze session is 
picked up.
+DEKIT_PROJECT_DIR="/tmp/breeze-dekit"
+mkdir -p "${DEKIT_PROJECT_DIR}"
+
+if ! uv run "/opt/airflow/scripts/in_container/bin/generate_dekit_config.py" 
"${DEKIT_PROJECT_DIR}/dekit.yaml"; then
+    echo "Failed to generate dekit configuration"
+    exit 1
+fi
+
+# The task list title is a user setting in dekit; set it unless the user has 
their own config.
+DEKIT_USER_CONFIG="${XDG_CONFIG_HOME:-${HOME}/.config}/dekit/config.yaml"
+if [[ ! -f ${DEKIT_USER_CONFIG} ]]; then
+    mkdir -p "$(dirname "${DEKIT_USER_CONFIG}")"
+    printf 'tui:\n  sidebar:\n    title: Apache Airflow\n' > 
"${DEKIT_USER_CONFIG}"
+fi
+
+# Start the runner with every task, then attach to its console. In the 
console, q detaches, which
+# ends the Breeze session, and Q stops the runner first.
+dekit up -C "${DEKIT_PROJECT_DIR}"
+exec dekit -C "${DEKIT_PROJECT_DIR}"
diff --git a/scripts/in_container/bin/run_mprocs 
b/scripts/in_container/bin/run_mprocs
deleted file mode 100755
index 778b393eb7a..00000000000
--- a/scripts/in_container/bin/run_mprocs
+++ /dev/null
@@ -1,28 +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.
-# Generate mprocs configuration dynamically
-
-MPROCS_CONFIG_PATH="/files/mprocs.yaml"
-
-if ! uv run "/opt/airflow/scripts/in_container/bin/generate_mprocs_config.py" 
"${MPROCS_CONFIG_PATH}"; then
-    echo "Failed to generate mprocs configuration"
-    exit 1
-fi
-
-# Start mprocs with the generated configuration
-exec mprocs --config "${MPROCS_CONFIG_PATH}" --proc-list-title "Apache Airflow"
diff --git a/scripts/tests/in_container/test_generate_dekit_config.py 
b/scripts/tests/in_container/test_generate_dekit_config.py
new file mode 100644
index 00000000000..1ba09882a66
--- /dev/null
+++ b/scripts/tests/in_container/test_generate_dekit_config.py
@@ -0,0 +1,93 @@
+# 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.
+from __future__ import annotations
+
+import importlib.util
+from pathlib import Path
+
+import pytest
+import yaml
+
+_GENERATOR = Path(__file__).parents[2] / "in_container" / "bin" / 
"generate_dekit_config.py"
+_spec = importlib.util.spec_from_file_location("generate_dekit_config", 
_GENERATOR)
+assert _spec is not None
+assert _spec.loader is not None
+generator = importlib.util.module_from_spec(_spec)
+_spec.loader.exec_module(generator)
+
+_COMPONENT_ENV_VARS = (
+    "USE_AIRFLOW_VERSION",
+    "INTEGRATION_CELERY",
+    "CELERY_FLOWER",
+    "STANDALONE_DAG_PROCESSOR",
+    "AIRFLOW__CORE__EXECUTOR",
+    "DEV_MODE",
+)
+
+
[email protected](autouse=True)
+def _clean_env(monkeypatch):
+    for name in _COMPONENT_ENV_VARS:
+        monkeypatch.delenv(name, raising=False)
+
+
+def _config(cwd: str = "/opt/airflow") -> dict:
+    return yaml.safe_load(generator.generate_dekit_config(cwd=cwd))
+
+
+def test_every_component_is_an_autostarted_task_run_through_bash():
+    config = _config()
+
+    assert config["defaults"] == {"cwd": "/opt/airflow", "autorestart": 
"always", "scrollback_len": 100000}
+    assert list(config["tasks"]) == ["scheduler", "api_server", "triggerer", 
"shell"]
+    for task in config["tasks"].values():
+        assert task["autostart"] is True
+        assert task["cmd"][:2] == ["bash", "-c"]
+    assert config["tasks"]["scheduler"]["cmd"][2] == "airflow scheduler"
+    assert config["tasks"]["shell"]["cmd"][2] == "bash"
+
+
+def test_optional_components_follow_the_environment(monkeypatch):
+    monkeypatch.setenv("INTEGRATION_CELERY", "true")
+    monkeypatch.setenv("CELERY_FLOWER", "true")
+    monkeypatch.setenv("STANDALONE_DAG_PROCESSOR", "true")
+    monkeypatch.setenv(
+        "AIRFLOW__CORE__EXECUTOR", 
"airflow.providers.edge3.executors.edge_executor.EdgeExecutor"
+    )
+
+    tasks = _config()["tasks"]
+
+    assert {"celery_worker", "flower", "edge_worker", "dag_processor"} <= 
set(tasks)
+    # The edge worker unsets variables first, which needs the shell.
+    assert "unset AIRFLOW__DATABASE__SQL_ALCHEMY_CONN || true &&" in 
tasks["edge_worker"]["cmd"][2]
+
+
+def test_airflow_2_runs_the_webserver(monkeypatch):
+    monkeypatch.setenv("USE_AIRFLOW_VERSION", "2.11.0")
+
+    tasks = _config()["tasks"]
+
+    assert "webserver" in tasks
+    assert "api_server" not in tasks
+
+
+def test_no_mprocs_keys_are_left():
+    config = _config()
+
+    assert "procs" not in config
+    for task in config["tasks"].values():
+        assert not {"shell", "restart", "scrollback"} & set(task)

Reply via email to