diff --git a/.readthedocs.yml b/.readthedocs.yml
deleted file mode 100644
index 89aed7f..0000000
--- a/.readthedocs.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-# Read the Docs configuration file
-# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
-
-version: 2
-
-build:
- os: ubuntu-24.04
- tools:
- python: "3.13"
-
-sphinx:
- configuration: docs/conf.py
-
- # Optionally, but recommended,
- # declare the Python requirements required to build your documentation
- # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
- # python:
- # install:
- # - requirements: docs/requirements.txt
diff --git a/docs/.readthedocs.yaml b/docs/.readthedocs.yaml
new file mode 100644
index 0000000..cc127a2
--- /dev/null
+++ b/docs/.readthedocs.yaml
@@ -0,0 +1,19 @@
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+version: 2
+
+build:
+ os: ubuntu-24.04
+ tools:
+ python: "3.13"
+ jobs:
+ pre_install:
+ - pip install mkdocs-material
+
+mkdocs:
+ configuration: docs/mkdocs.yml
+
+python:
+ install:
+ - requirements: docs/requirements.txt
diff --git a/docs/assets/css/theme.css b/docs/assets/css/theme.css
new file mode 100644
index 0000000..c6e012f
--- /dev/null
+++ b/docs/assets/css/theme.css
@@ -0,0 +1,44 @@
+body {
+ cursor: default;
+}
+
+h1 {
+ margin-bottom: 0.5em !important;
+ color: #4051B5 !important;
+ font-weight: 500 !important;
+}
+
+h2 {
+ margin-top: 0.5em !important;
+ margin-bottom: 0.5em !important;
+ color: #4051B5 !important;
+ font-size: 1.3em;
+}
+
+div.md-main__inner {
+ margin-top: 0;
+}
+
+:root {
+ --md-typeset-a-color: #30a2a9;
+}
+
+.icon-green {
+ color: #069006;
+}
+
+.md-typeset .admonition > .admonition-title {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.tryit-link {
+ margin-left: auto;
+}
+
+li.md-nav__item--active > label.md-nav__link > span.md-ellipsis,
+li.md-nav__item--active > label.md-nav__link > span.md-nav__icon
+{
+ color: var(--md-typeset-a-color);
+}
diff --git a/docs/assets/images/demo.gif b/docs/assets/images/demo.gif
new file mode 100644
index 0000000..ec6ee6d
Binary files /dev/null and b/docs/assets/images/demo.gif differ
diff --git a/docs/assets/js/readthedocs-search.js b/docs/assets/js/readthedocs-search.js
new file mode 100644
index 0000000..432bd90
--- /dev/null
+++ b/docs/assets/js/readthedocs-search.js
@@ -0,0 +1,6 @@
+document.addEventListener("DOMContentLoaded", function(event) {
+ document.querySelector(".md-search__input").addEventListener("focus", (e) => {
+ const event = new CustomEvent("readthedocs-search-show");
+ document.dispatchEvent(event);
+ });
+});
diff --git a/docs/assets/js/try-it.js b/docs/assets/js/try-it.js
new file mode 100644
index 0000000..93d8ee5
--- /dev/null
+++ b/docs/assets/js/try-it.js
@@ -0,0 +1,11 @@
+document.addEventListener("DOMContentLoaded", () => {
+ document.querySelectorAll(".admonition .admonition-title").forEach(title => {
+ if (title.textContent.trim() === "Try it!") {
+ const link = document.createElement("a");
+ link.href = "/en/latest/examples/available-examples";
+ link.className = "tryit-link";
+ link.textContent = "How to execute examples";
+ title.appendChild(link);
+ }
+ });
+});
diff --git a/docs/contributing/tips-for-devs.md b/docs/contributing/tips-for-devs.md
new file mode 100644
index 0000000..6229195
--- /dev/null
+++ b/docs/contributing/tips-for-devs.md
@@ -0,0 +1,33 @@
+---
+hide:
+ - toc
+---
+
+# Work on the code
+
+You can clone the project:
+```bash
+git clone git@github.com:steevanb/php-parallel-processes.git
+```
+
+Then, when you to execute your local code, you need to add a volume on `/composer/vendor/steevanb/php-parallel-processes`:
+```bash hl_lines="6"
+docker \
+ run \
+ --rm \
+ -it \
+ -v "$(pwd)":/app \
+ -v "$(pwd)":/composer/vendor/steevanb/php-parallel-processes \
+ steevanb/php-parallel-processes:{{ package_version }}-alpine \
+ php /app/parallel-processes.php
+```
+
+# Work on the documentation
+
+We use [readthedocs](https://about.readthedocs.com/),
+[mkdocs](https://docs.readthedocs.com/platform/stable/intro/mkdocs.html)
+and [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/reference).
+
+Documentation is written in Markdown in [docs/](https://github.com/steevanb/php-parallel-processes/tree/readthedocs/docs).
+
+See [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/reference/code-blocks/) for Markdown syntaxes and examples.
diff --git a/docs/examples/available-examples.md b/docs/examples/available-examples.md
new file mode 100644
index 0000000..25635a6
--- /dev/null
+++ b/docs/examples/available-examples.md
@@ -0,0 +1,28 @@
+---
+hide:
+ - toc
+---
+
+# Available examples
+
+All examples are in [examples/](https://github.com/steevanb/php-parallel-processes/tree/master/examples).
+
+# How to execute an example
+
+You need to download the latest version of [parallel-processes-example.sh](https://raw.githubusercontent.com/steevanb/php-parallel-processes/refs/heads/master/examples/parallel-processes-example.sh).
+
+`parallel-processes-example.sh` has one mandatory argument: the path to the example, after `examples/` directory:
+```bash
+parallel-processes-example.sh path/to/example.php
+```
+
+# Configure an example
+
+Some of them can be configured with env vars.
+
+All configuration are prefixed by `PP_`.
+
+```bash hl_lines="1"
+PP_CANCELED_AS_ERROR=true \
+ parallel-processes-example.sh usage/process-configuration/canceled-as-error.php
+```
diff --git a/docs/getting-started/license.md b/docs/getting-started/license.md
new file mode 100644
index 0000000..daaabc9
--- /dev/null
+++ b/docs/getting-started/license.md
@@ -0,0 +1,11 @@
+---
+hide:
+ - toc
+---
+
+# License
+
+`parallel-processes` is licensed under the [Apache 2.0 License](https://github.com/steevanb/php-parallel-processes/blob/master/LICENSE).
+
+The Apache 2.0 license allows you to freely use, modify, and distribute software, including for commercial purposes,
+as long as you keep the copyright and license notices and indicate any changes made.
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000..87786bd
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,76 @@
+---
+hide:
+ - toc
+---
+
+# Presentation
+
+`parallel-processes` is an open-source PHP library for running multiple processes in parallel.
+
+
+
+# Key features
+
+
+
+- :material-docker:{ .lg .middle } __Install it or use Docker images__
+
+ ---
+
+ Install it as a Composer dependency or use the provided Docker images to avoid a local installation.
+
+ [:octicons-arrow-right-24: Installation](installation/composer-dependency.md)
+
+- :material-file-tree:{ .lg .middle } __Process start rules__
+
+ ---
+
+ Configure when a process should start: immediately, after another process, during bootstrap, or during teardown.
+
+ [:octicons-arrow-right-24: Bootstrap or tear down](usage/bootstrap-tear-down.md)
+
+- :material-cog-outline:{ .lg .middle } __Process configuration__
+
+ ---
+
+ Configure each process: name, command, maximum execution time, output verbosity, etc.
+
+ [:octicons-arrow-right-24: Configure process](usage/process-configuration/miscellaneous.md)
+
+- :material-cog-outline:{ .lg .middle } __Execution configuration__
+
+ ---
+
+ Configure execution settings for your processes using PHP: process order, refresh interval, timeout, etc.
+
+ [:octicons-arrow-right-24: Minimal configuration](usage/minimal-configuration.md)
+
+- :material-message-bulleted:{ .lg .middle } __Verbosity__
+
+ ---
+
+ Control output verbosity: show process output, execution time, only errors, or all outputs.
+
+ [:octicons-arrow-right-24: Output verbosity](usage/output-verbosity.md)
+
+- :material-compare:{ .lg .middle } __Theme__
+
+ ---
+
+ Choose between the Default and Summary themes, or create a custom theme.
+
+ [:octicons-arrow-right-24: Theme configuration](theme/configuration.md)
+
+
+
+# License
+
+`parallel-processes` is licensed under the [Apache 2.0 License](getting-started/license.md).
+
+# Links
+
+GitHub: [steevanb/php-parallel-processes](https://github.com/steevanb/php-parallel-processes)
+
+Docker Hub: [steevanb/php-parallel-processes](https://hub.docker.com/r/steevanb/php-parallel-processes)
+
+Creator: [Steevan BARBOYON](http://prestation.info-droid.fr/)
diff --git a/docs/installation/composer-dependency.md b/docs/installation/composer-dependency.md
new file mode 100644
index 0000000..c41659f
--- /dev/null
+++ b/docs/installation/composer-dependency.md
@@ -0,0 +1,33 @@
+---
+hide:
+ - toc
+---
+
+# Composer dependency
+
+If you want to install `parallel-processses` in your project, with Composer:
+
+```bash
+composer require steevanb/php-parallel-processes:^{{ package_version }}
+```
+
+# Dependencies
+
+
+
+- :material-penguin: __OS__: Linux and macOS, no tested on Windows
+- :material-language-php: __PHP__: ^8.2
+- :material-symfony: __[symfony/console](https://symfony.com/doc/current/components/console.html)__: ^7.0
+- :material-symfony: __[symfony/process](https://symfony.com/doc/current/components/process.html)__: ^7.0
+
+
+
+# Configure your processes
+
+See [minimal configuration](../usage/minimal-configuration.md).
+
+# Available versions
+
+See [releases](https://github.com/steevanb/php-parallel-processes/releases).
+
+See [changelog](https://github.com/steevanb/php-parallel-processes/blob/master/changelog.md).
diff --git a/docs/installation/docker-image.md b/docs/installation/docker-image.md
new file mode 100644
index 0000000..83c5e0c
--- /dev/null
+++ b/docs/installation/docker-image.md
@@ -0,0 +1,106 @@
+---
+hide:
+ - toc
+---
+
+# Use Docker image
+
+`parallel-processses` provide Docker images with everything installed: PHP, the library and Docker.
+
+You can choose between this 3 versions:
+
+* `alpine`: smallest version, but could be "too much simple" sometimes
+* `buster`: middle version, contains almost everything needed
+* `bookworm`: larger version, should contain what you need
+
+# Dependencies
+
+
+
+- :material-penguin: __OS__: Linux, Windows and macOS
+- :material-docker: __Docker__: you should already have a compatible version
+
+
+
+# Basic usage
+
+See [minimal configuration](../usage/minimal-configuration.md) to create your parallel processes configuration.
+
+Then you can use official images to execute it:
+```bash
+docker \
+ run \
+ --rm \
+ -it \
+ -v "$(pwd)":/app \
+ steevanb/php-parallel-processes:{{ package_version }}-alpine \
+ php /app/parallel-processes.php
+```
+
+# Docker outside of Docker (DooD)
+
+If your processes need to execute Docker commands on your host, you can do it with DooD.
+
+You have to add a volume to your Docker socket, that's all:
+
+```bash hl_lines="6"
+docker \
+ run \
+ --rm \
+ -it \
+ -v "$(pwd)":/app \
+ -v /var/run/docker.sock:/var/run/docker.sock \
+ steevanb/php-parallel-processes:{{ package_version }}-alpine \
+ php /app/parallel-processes.php
+```
+
+!!! info "docker.sock host path"
+ Use `docker context inspect` to get your socket path if it's not `/var/run/docker.sock`.
+
+ In this case, keep `/var/run/docker.sock` for the volume target.
+
+Examples of processes that use the Docker host's socket:
+```php
+addProcess(new Process(['docker', 'build']))
+
+ // You can use Docker compose plugin
+ ->addProcess(new Process(['docker', 'compose', 'build']))
+
+ // You can use Docker buildx plugin, but only with buster and bookworm images
+ // alpine do not contain buildx
+ ->addProcess(new Process(['docker', 'buildx', 'build']))
+
+ ->run(new ArgvInput($argv));
+```
+
+Official images are bundled with Docker and some plugins:
+
+| Image | docker | compose plugin | buildx plugin |
+|-------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------:|:-----------------------------------------:|:-----------------------------------------:|
+| [{{ package_version }}-alpine](https://hub.docker.com/r/steevanb/php-parallel-processes/tags?name={{ package_version }}-alpine) | :material-checkbox-marked:{ .icon-green } | :material-checkbox-marked:{ .icon-green } | |
+| [{{ package_version }}-buster](https://hub.docker.com/r/steevanb/php-parallel-processes/tags?name={{ package_version }}-buster) | :material-checkbox-marked:{ .icon-green } | :material-checkbox-marked:{ .icon-green } | :material-checkbox-marked:{ .icon-green } |
+| [{{ package_version }}-bookworm](https://hub.docker.com/r/steevanb/php-parallel-processes/tags?name={{ package_version }}-bookworm) | :material-checkbox-marked:{ .icon-green } | :material-checkbox-marked:{ .icon-green } | :material-checkbox-marked:{ .icon-green } |
+
+!!! info "Docker is installed since 1.1.0"
+ Docker, compose and buildx plugins are installed in Docker images since `1.1.0`.
+
+# Available versions
+
+See [Docker tags](https://hub.docker.com/r/steevanb/php-parallel-processes/tags).
+
+See [changelog](https://github.com/steevanb/php-parallel-processes/blob/master/changelog.md).
diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml
new file mode 100644
index 0000000..2e1ce9d
--- /dev/null
+++ b/docs/mkdocs.yml
@@ -0,0 +1,57 @@
+site_name: Parallel processes
+theme:
+ name: material
+ features:
+ - content.code.copy
+site_url: !ENV READTHEDOCS_CANONICAL_URL
+extra_javascript:
+ - assets/js/readthedocs-search.js
+ - assets/js/try-it.js
+extra_css:
+ - assets/css/theme.css
+ - assets/css/try-it.css
+docs_dir: .
+nav:
+ - Getting started:
+ - Presentation: index.md
+ - License: getting-started/license.md
+ - Installation:
+ - Composer dependency: installation/composer-dependency.md
+ - Docker image: installation/docker-image.md
+ - Usage:
+ - Minimal configuration: usage/minimal-configuration.md
+ - Application configuration: usage/application-configuration.md
+ - Process configuration:
+ - Miscellaneous: usage/process-configuration/miscellaneous.md
+ - Output prefix: usage/process-configuration/output-prefix.md
+ - Verbosity: usage/process-configuration/verbosity.md
+ - Bootstrap / tear down: usage/bootstrap-tear-down.md
+ - Output verbosity: usage/output-verbosity.md
+ - Theme:
+ - Configuration: theme/configuration.md
+ - Create a theme: theme/create-a-theme.md
+ - Examples:
+ - Available examples: examples/available-examples.md
+ - Contributing:
+ - Tips for devs: contributing/tips-for-devs.md
+markdown_extensions:
+ - pymdownx.highlight:
+ anchor_linenums: true
+ line_spans: __span
+ pygments_lang_class: true
+ - pymdownx.inlinehilite
+ - pymdownx.snippets
+ - pymdownx.superfences
+ - admonition
+ - pymdownx.details
+ - pymdownx.superfences
+ - attr_list
+ - md_in_html
+ - pymdownx.emoji:
+ emoji_index: !!python/name:material.extensions.emoji.twemoji
+ emoji_generator: !!python/name:material.extensions.emoji.to_svg
+extra:
+ package_version: "1.1.0"
+plugins:
+ - search
+ - macros
diff --git a/docs/requirements.txt b/docs/requirements.txt
new file mode 100644
index 0000000..c5f6e24
--- /dev/null
+++ b/docs/requirements.txt
@@ -0,0 +1,3 @@
+mkdocs
+mkdocs-material
+mkdocs-macros-plugin
diff --git a/docs/theme/configuration.md b/docs/theme/configuration.md
new file mode 100644
index 0000000..285cce4
--- /dev/null
+++ b/docs/theme/configuration.md
@@ -0,0 +1,68 @@
+---
+hide:
+ - toc
+---
+
+# Themes
+
+`parallel-processes` contains 2 themes: `Default` and `Summary`.
+
+## Default theme
+
+This theme output processes status at regular interval, configured by [application refresh interval](../usage/application-configuration.md).
+
+The ouput is rewritten at each refresh interval.
+
+This theme is the default one, and should be used most of the time.
+
+## Summary theme
+
+This theme output only one line at the start: `Starting X processes...`.
+
+Processes status are not showned / refreshed.
+
+At the end, all processes status and output are written, only one time.
+
+This theme should be used in environments who can't rewrite output, like CI : GitHub Actions logs for example.
+
+# Configure a theme
+
+## In PHP configuration
+
+You can configure the theme in your PHP configuration:
+
+```php
+setTheme(new Defaultheme())
+ # Configure the theme to Summary
+ ->setTheme(new SummaryTheme())
+```
+
+## In CLI
+
+You can configure the theme in CLI.
+
+`Default` theme (default value):
+
+```bash
+php parallel-process.php --theme=default
+```
+
+`Summary` theme:
+
+```bash
+php parallel-process.php --theme=summary
+```
+
+!!! info "CLI override PHP"
+
+ The theme configured in the CLI overrides the one configured in PHP.
diff --git a/docs/theme/create-a-theme.md b/docs/theme/create-a-theme.md
new file mode 100644
index 0000000..8e1fd8e
--- /dev/null
+++ b/docs/theme/create-a-theme.md
@@ -0,0 +1,59 @@
+---
+hide:
+ - toc
+---
+
+# Create a theme
+
+To create a theme, you have to create a class who implements
+[ThemeInterface](https://github.com/steevanb/php-parallel-processes/blob/master/src/Console/Application/Theme/ThemeInterface.php).
+
+## ThemeInterface::outputStart()
+
+This method will be called before starting the processes.
+
+You can output headers here for example.
+
+## ThemeInterface::outputProcessesState()
+
+This method will be called at each [application refresh interval](../usage/application-configuration.md), to output processes state.
+
+## ThemeInterface::outputSummary()
+
+This method will be called after all processes are terminated.
+
+For example, you can take verbosity into account here to write processes outputs, add a footer etc.
+
+## Example
+
+See [DefaultTheme](https://github.com/steevanb/php-parallel-processes/blob/master/src/Console/Application/Theme/DefaultTheme.php).
+
+# How to use it
+
+## Configure it in PHP
+
+Like Default and Summary themes, call `ParallelProcessesApplication::setTheme()` with your theme instance:
+
+```php
+setTheme(new FooTheme());
+```
+
+## Configure it in CLI
+
+Like Default and Summary theme, add `--theme` in your CLI command, the value should be the FQCN of your theme:
+
+```bash
+php parallel-process.php --theme=App\\FooTheme
+```
+
+!!! info "Creation or the theme object"
+
+ Your theme class should not have parameters in `__construct()` to be used in CLI.
+
+ See [ParallelProcessesApplication::defineThemeFromInput()](https://github.com/steevanb/php-parallel-processes/blob/master/src/Console/Application/ParallelProcessesApplication.php).
+
+ If you need a different behavior, do not hesitate to contribute!
diff --git a/docs/usage/application-configuration.md b/docs/usage/application-configuration.md
new file mode 100644
index 0000000..76b5065
--- /dev/null
+++ b/docs/usage/application-configuration.md
@@ -0,0 +1,57 @@
+---
+hide:
+ - toc
+---
+
+# Global timeout
+
+Default value: `null` (no timeout).
+
+Configured timeout is in seconds.
+
+```php
+setTimeout(10)
+```
+
+# Refresh interval
+
+You can configure the refresh interval, to scan all processes status and start the next ones,
+with `ParallelProcessesApplication::setRefreshInterval()`.
+
+Default value: `10000` (10ms).
+
+Configured refresh interval is in microseconds.
+
+```php
+setRefreshInterval(50000)
+```
+
+# Maximum processes in parallel
+
+Default value: `null` (no maximum).
+
+```php
+setMaximumParallelProcesses(3)
+```
+
+# Theme
+
+See [Configure a theme](../theme/configuration.md).
diff --git a/docs/usage/bootstrap-tear-down.md b/docs/usage/bootstrap-tear-down.md
new file mode 100644
index 0000000..7e2aea4
--- /dev/null
+++ b/docs/usage/bootstrap-tear-down.md
@@ -0,0 +1,76 @@
+---
+hide:
+ - toc
+---
+
+# Boostrap process
+
+You can execute a process before any other process with a bootstrap process.
+
+Bootstrap process can be added with `ParallelProcessesApplication::addProcess()`,
+and should be an instance of [BootstrapProcessInterface](https://github.com/steevanb/php-parallel-processes/blob/master/src/Process/BootstrapProcessInterface.php).
+
+You can use [BootstrapProcess](https://github.com/steevanb/php-parallel-processes/blob/master/src/Process/BoostrapProcess.php),
+who implements `BootstrapProcessInterface`,
+instead of [Process](https://github.com/steevanb/php-parallel-processes/blob/master/src/Process/Process.php).
+
+You can add this process when you want, before calling `ParallelProcessesApplication::run()`: before normal process, or after, it does not matter.
+
+!!! info "Bootstrap process failure"
+ If a bootstrap process fail, normal processes will not be executed.
+
+ In this case, tear down processes will be executed.
+
+```php hl_lines="10 12"
+addProcess(new BootstrapProcess(['bootstrap', 'process', '#1']))
+ ->addProcess(new Process(['normal', 'process']))
+ ->addProcess(new BootstrapProcess(['bootstrap', 'process', '#2']))
+ ->run(new ArgvInput($argv));
+```
+
+!!! bug "Typo in BootstrapProcess class name before 1.1.0"
+ Before 1.1.0, `BootstrapProcess` class name contains a typo: it was `BoostrapProcess`.
+
+ It has been fixed in [1.1.0](https://github.com/steevanb/php-parallel-processes/blob/readthedocs/changelog.md):
+ a new `BootstrapProcess` class has been created, and `BoostrapProcess` has been depreciated.
+
+# Tear down process
+
+You can execute a process after all other processes with a tear down process.
+
+Tear down process can be added with `ParallelProcessesApplication::addProcess()`,
+and should be an instance of [TearDownProcessInterface](https://github.com/steevanb/php-parallel-processes/blob/master/src/Process/TearDownProcessInterface.php).
+
+You can use [TearDownProcess](https://github.com/steevanb/php-parallel-processes/blob/master/src/Process/TearDownProcess.php),
+who implements `TearDownProcessInterface`,
+instead of [Process](https://github.com/steevanb/php-parallel-processes/blob/master/src/Process/Process.php).
+
+You can add this process when you want, before calling `ParallelProcessesApplication::run()`: before normal process, or after, it does not matter.
+
+!!! info "Tear down process execution rule"
+ The tear down processes will always be executed, whether the previous processes succeeded or failed.
+
+```php hl_lines="10 12"
+addProcess(new TearDownProcess(['tear', 'down', 'process', '#1']))
+ ->addProcess(new Process(['normal', 'process']))
+ ->addProcess(new TearDownProcess(['tear', 'down', 'process', '#2']))
+ ->run(new ArgvInput($argv));
+```
diff --git a/docs/usage/minimal-configuration.md b/docs/usage/minimal-configuration.md
new file mode 100644
index 0000000..645156b
--- /dev/null
+++ b/docs/usage/minimal-configuration.md
@@ -0,0 +1,36 @@
+---
+hide:
+ - toc
+---
+
+# Minimal configuration
+
+Here is an example of the minimal configuration, to have 2 processes running in parallel:
+
+```php
+addProcess(new Process(['first', 'process']))
+ ->addProcess(new Process(['second', 'process']))
+ ->run(new ArgvInput($argv));
+```
+
+# Advanced usage
+
+See [application configuration](application-configuration.md).
+
+See [process configuration](process-configuration/miscellaneous.md).
diff --git a/docs/usage/output-verbosity.md b/docs/usage/output-verbosity.md
new file mode 100644
index 0000000..df12974
--- /dev/null
+++ b/docs/usage/output-verbosity.md
@@ -0,0 +1,42 @@
+---
+hide:
+ - toc
+---
+
+# Output verbosity
+
+By default, default theme will output only the state, the process name and the process error output.
+
+You can add information, depending on the verbosity level.
+
+| Output | Normal | Verbose | Very verbose | Debug |
+|-------------------------|:-----------------------------------------:|:-----------------------------------------:|:-----------------------------------------:|:-----------------------------------------:|
+| Process state | :material-checkbox-marked:{ .icon-green } | :material-checkbox-marked:{ .icon-green } | :material-checkbox-marked:{ .icon-green } | :material-checkbox-marked:{ .icon-green } |
+| Process name | :material-checkbox-marked:{ .icon-green } | :material-checkbox-marked:{ .icon-green } | :material-checkbox-marked:{ .icon-green } | :material-checkbox-marked:{ .icon-green } |
+| Execution time | | :material-checkbox-marked:{ .icon-green } | :material-checkbox-marked:{ .icon-green } | :material-checkbox-marked:{ .icon-green } |
+| Process standard output | | | :material-checkbox-marked:{ .icon-green } | :material-checkbox-marked:{ .icon-green } |
+| Process error output | :material-checkbox-marked:{ .icon-green } | :material-checkbox-marked:{ .icon-green } | :material-checkbox-marked:{ .icon-green } | :material-checkbox-marked:{ .icon-green } |
+
+# Configure verbosity level
+
+Verbosity level is configured on the CLI command with `-v`, `-vv` or `-vvv`.
+
+**Normal**: default level, do not add anything.
+```bash
+php parallel-process.php
+```
+
+**Verbose**: add `-v`.
+```bash
+php parallel-process.php -v
+```
+
+**Very verbose**: add `-vv`.
+```bash
+php parallel-process.php -vv
+```
+
+**Debug**: add `-vvv`.
+```bash
+php parallel-process.php -vvv
+```
diff --git a/docs/usage/process-configuration/miscellaneous.md b/docs/usage/process-configuration/miscellaneous.md
new file mode 100644
index 0000000..c62720d
--- /dev/null
+++ b/docs/usage/process-configuration/miscellaneous.md
@@ -0,0 +1,46 @@
+---
+hide:
+ - toc
+---
+
+# Name
+
+Default: Last word of the command.
+
+Example with `new Process(['/foo', 'bar', 'baz'])`: name will be `baz`.
+
+```php
+setName('foo');
+```
+
+# Canceled as error
+
+You can configure if the cancelation of a process is considered as an error (`1`) or not (`0`) for the exit code.
+
+Default: `true`.
+
+```php
+setCanceledAsError(true);
+```
+
+See [example](https://github.com/steevanb/php-parallel-processes/tree/master/examples/usage/process-configuration/canceled-as-error.php).
+
+!!! example "Try it!"
+
+ With `setCanceledAsError(true)` (default value):
+ ```bash
+ PP_CANCELED_AS_ERROR=true parallel-processes-example.sh usage/process-configuration/canceled-as-error.php ; echo "Exit code: $?"
+ ```
+ With `setCanceledAsError(false)`:
+ ```bash
+ PP_CANCELED_AS_ERROR=false parallel-processes-example.sh usage/process-configuration/canceled-as-error.php ; echo "Exit code: $?"
+ ```
diff --git a/docs/usage/process-configuration/output-prefix.md b/docs/usage/process-configuration/output-prefix.md
new file mode 100644
index 0000000..038fe84
--- /dev/null
+++ b/docs/usage/process-configuration/output-prefix.md
@@ -0,0 +1,76 @@
+---
+hide:
+ - toc
+---
+
+# State line prefix
+
+You can add a prefix before the state line only.
+
+Default: `null`.
+
+```php
+setOutputStatePrefix('foo');
+```
+
+See [example](https://github.com/steevanb/php-parallel-processes/tree/master/examples/usage/process-configuration/output-state-prefix.php).
+
+!!! example "Try it!"
+
+ ```bash
+ parallel-processes-example.sh usage/process-configuration/output-state-prefix.php
+ ```
+
+# Summary lines prefix
+
+You can add a prefix before process output lines.
+
+Default: `null`.
+
+```php
+setOutputSummaryPrefix('foo');
+```
+
+See [example](https://github.com/steevanb/php-parallel-processes/tree/master/examples/usage/process-configuration/output-summary_prefix.php).
+
+!!! info "Indentation"
+
+ Indentation will be added after the configured summary prefix, to show output lines are for this process.
+
+!!! example "Try it!"
+
+ ```bash
+ parallel-processes-example.sh usage/process-configuration/output-summaryprefix.php
+ ```
+
+# All lines
+
+You can add an output prefix before any line.
+
+It's a shortcut for calling `Process::setOutputStatePrefix()` then `Process::setOutputSummaryPrefix()` with the same prefix.
+
+Default: `null`.
+
+```php
+setOutputPrefix('foo');
+```
+
+See [example](https://github.com/steevanb/php-parallel-processes/tree/master/examples/usage/process-configuration/output-prefix.php).
+
+!!! example "Try it!"
+
+ ```bash
+ parallel-processes-example.sh usage/process-configuration/output-prefix.php
+ ```
diff --git a/docs/usage/process-configuration/verbosity.md b/docs/usage/process-configuration/verbosity.md
new file mode 100644
index 0000000..0497a19
--- /dev/null
+++ b/docs/usage/process-configuration/verbosity.md
@@ -0,0 +1,77 @@
+---
+hide:
+ - toc
+---
+
+# Output verbosity
+
+All processes outputs will be written at the end of all processes execution.
+
+Nothing will be written during execution.
+
+See [verbosity](../output-verbosity.md).
+
+# Standard output verbosity
+
+Default: `OutputInterface::VERBOSITY_VERY_VERBOSE` (`-vv`).
+
+```php
+setStandardOutputVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
+```
+
+# Error output verbosity
+
+Default: `OutputInterface::VERBOSITY_VERY_VERBOSE` (`-vv`).
+
+```php
+setErrorOutputVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
+```
+
+# Canceled output verbosity
+
+Default: `OutputInterface::VERBOSITY_VERY_VERBOSE` (`-vv`).
+
+```php
+setCanceledOutputVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
+```
+
+# Standard output verbosity when the process fails
+
+Default: `OutputInterface::VERBOSITY_NORMAL`.
+
+```php
+setFailureStandardOutputVerbosity(OutputInterface::VERBOSITY_NORMAL);
+```
+
+# Error output verbosity when the process fails
+
+Default: `OutputInterface::VERBOSITY_NORMAL`.
+
+```php
+setFailureErrorOutputVerbosity(OutputInterface::VERBOSITY_NORMAL);
+```
diff --git a/examples/demo.php b/examples/demo.php
new file mode 100644
index 0000000..0aa566e
--- /dev/null
+++ b/examples/demo.php
@@ -0,0 +1,42 @@
+setName('Check installation');
+
+$process1 = (new Process(['sleep', '2']))
+ ->setName('Start docker stack');
+
+$process2 = (new Process(['sleep', '1']))
+ ->setName('Install dependencies');
+$process2->getStartCondition()->getProcessesSuccessful()->add($process1);
+
+$process3 = (new Process(['sleep', '2']))
+ ->setName('Create database');
+$process3->getStartCondition()->getProcessesSuccessful()->add($process1);
+
+$process4 = (new Process(['sleep', '1']))
+ ->setName('Clear cache');
+
+$tearDownProcess = (new TearDownProcess(['sleep', '1']))
+ ->setName('Wait everything is started');
+
+(new ParallelProcessesApplication())
+ ->addProcess($bootstrapProcess)
+ ->addProcess($process1)
+ ->addProcess($process2)
+ ->addProcess($process3)
+ ->addProcess($process4)
+ ->addProcess($tearDownProcess)
+ ->run(new ArgvInput($argv));
diff --git a/examples/parallel-processes-example.sh b/examples/parallel-processes-example.sh
new file mode 100755
index 0000000..6aa8f00
--- /dev/null
+++ b/examples/parallel-processes-example.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+
+ENV_ARGS=()
+while IFS='=' read -r name value; do
+ ENV_ARGS+=("-e" "$name=$value")
+done < <(env | grep '^PP_')
+
+readonly SOURCE_CODE_PATH=/composer/vendor/steevanb/php-parallel-processes
+
+LOCAL_SOURCE=true
+VOLUME_ARGS=()
+if [[ "${LOCAL_SOURCE,,}" == "true" ]]; then
+ VOLUME_ARGS+=("-v" "$(pwd):${SOURCE_CODE_PATH}")
+fi
+
+readonly EXAMPLE="${1}"
+shift
+
+docker \
+ run \
+ --rm \
+ -it \
+ "${ENV_ARGS[@]}" \
+ "${VOLUME_ARGS[@]}" \
+ steevanb/php-parallel-processes:1.1.0-alpine \
+ php "${SOURCE_CODE_PATH}"/examples/"${EXAMPLE}" "$@"
diff --git a/examples/usage/process-configuration/canceled-as-error.php b/examples/usage/process-configuration/canceled-as-error.php
new file mode 100644
index 0000000..ef0900f
--- /dev/null
+++ b/examples/usage/process-configuration/canceled-as-error.php
@@ -0,0 +1,35 @@
+setName('This process will fail')
+ ->setFailureErrorOutputVerbosity(OutputInterface::VERBOSITY_VERBOSE)
+ ->setSpreadErrorToApplicationExitCode(false);
+
+$canceledProcess = (new Process(['cancel-me']))
+ ->setName('This proces will be canceled')
+ ->setCanceledAsError(
+ ($_ENV['PP_CANCELED_AS_ERROR'] ?? 'true') === 'true'
+ );
+
+$canceledProcess
+ ->getStartCondition()
+ ->getProcessesSuccessful()
+ ->add($errorProcess);
+
+(new ParallelProcessesApplication())
+ ->addProcess($errorProcess)
+ ->addProcess($canceledProcess)
+ ->run(new ArgvInput($argv));
diff --git a/examples/usage/process-configuration/output-prefix.php b/examples/usage/process-configuration/output-prefix.php
new file mode 100644
index 0000000..63be4db
--- /dev/null
+++ b/examples/usage/process-configuration/output-prefix.php
@@ -0,0 +1,27 @@
+addProcess(
+ (new Process(['pwd']))
+ ->setOutputPrefix('--Output prefix--')
+ ->setStandardOutputVerbosity(OutputInterface::VERBOSITY_NORMAL)
+ )
+ ->addProcess(
+ (new Process(['pwd']))
+ ->setOutputPrefix('--Another output prefix--')
+ ->setStandardOutputVerbosity(OutputInterface::VERBOSITY_NORMAL)
+ )
+ ->run(new ArgvInput($argv));
diff --git a/examples/usage/process-configuration/output-state-prefix.php b/examples/usage/process-configuration/output-state-prefix.php
new file mode 100644
index 0000000..e2ac78c
--- /dev/null
+++ b/examples/usage/process-configuration/output-state-prefix.php
@@ -0,0 +1,27 @@
+addProcess(
+ (new Process(['pwd']))
+ ->setOutputStatePrefix('--Output state prefix--')
+ ->setStandardOutputVerbosity(OutputInterface::VERBOSITY_NORMAL)
+ )
+ ->addProcess(
+ (new Process(['pwd']))
+ ->setOutputStatePrefix('--Another output state prefix--')
+ ->setStandardOutputVerbosity(OutputInterface::VERBOSITY_NORMAL)
+ )
+ ->run(new ArgvInput($argv));
diff --git a/examples/usage/process-configuration/output-summary-prefix.php b/examples/usage/process-configuration/output-summary-prefix.php
new file mode 100644
index 0000000..12a6406
--- /dev/null
+++ b/examples/usage/process-configuration/output-summary-prefix.php
@@ -0,0 +1,27 @@
+addProcess(
+ (new Process(['pwd']))
+ ->setOutputSummaryPrefix('--Output summary prefix--')
+ ->setStandardOutputVerbosity(OutputInterface::VERBOSITY_NORMAL)
+ )
+ ->addProcess(
+ (new Process(['pwd']))
+ ->setOutputSummaryPrefix('--Another output summary prefix--')
+ ->setStandardOutputVerbosity(OutputInterface::VERBOSITY_NORMAL)
+ )
+ ->run(new ArgvInput($argv));