diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-84718-AddCLIExportCommandToImpExpExtension.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-84718-AddCLIExportCommandToImpExpExtension.rst
new file mode 100644
index 0000000000000000000000000000000000000000..a6e368bda13703b4425a0e14935b478a90a4034d
--- /dev/null
+++ b/typo3/sysext/core/Documentation/Changelog/master/Feature-84718-AddCLIExportCommandToImpExpExtension.rst
@@ -0,0 +1,62 @@
+.. include:: ../../Includes.txt
+
+======================================================
+Feature: #84718 - Add CLI export command to EXT:impexp
+======================================================
+
+See :issue:`84718`
+
+Description
+===========
+
+The new CLI command
+
+-  :shell:`impexp:export`
+
+was added as the missing twin of the existing CLI command :shell:`impexp:import`.
+
+The export command can be executed via
+
+.. code-block:: bash
+
+   typo3/sysext/core/bin/typo3 impexp:export [options] [--] [<filename>]
+
+and exports the entire TYPO3 page tree - or parts of it - to a data file of
+format XML or T3D, which can be used for import into any TYPO3 instance or
+as initial page tree of a :ref:`distribution <t3coreapi:distribution>`.
+
+The export can be fine-tuned through the complete set of options already
+available in the export view of the TYPO3 backend:
+
+.. code-block:: bash
+
+   Arguments:
+      filename                           The filename to export to (without file extension)
+
+   Options:
+      --type[=TYPE]                      The file type (xml, t3d, t3d_compressed). [default: "xml"]
+      --pid[=PID]                        The root page of the exported page tree. [default: -1]
+      --levels[=LEVELS]                  The depth of the exported page tree. "-2": "Records on this page", "-1": "Expanded tree", "0": "This page", "1": "1 level down", .. "999": "Infinite levels". [default: 0]
+      --table[=TABLE]                    Include all records of this table. Examples: "_ALL", "tt_content", "sys_file_reference", etc. (multiple values allowed)
+      --record[=RECORD]                  Include this specific record. Pattern is "{table}:{record}". Examples: "tt_content:12", etc. (multiple values allowed)
+      --list[=LIST]                      Include the records of this table and this page. Pattern is "{table}:{pid}". Examples: "sys_language:0", etc. (multiple values allowed)
+      --includeRelated[=INCLUDERELATED]  Include record relations to this table, including the related record. Examples: "_ALL", "sys_category", etc. (multiple values allowed)
+      --includeStatic[=INCLUDESTATIC]    Include record relations to this table, excluding the related record. Examples: "_ALL", "sys_language", etc. (multiple values allowed)
+      --exclude[=EXCLUDE]                Exclude this specific record. Pattern is "{table}:{record}". Examples: "fe_users:3", etc. (multiple values allowed)
+      --excludeDisabledRecords           Exclude records which are handled as disabled by their TCA configuration, e.g. by fields "disabled", "starttime" or "endtime".
+      --excludeHtmlCss                   Exclude referenced HTML and CSS files.
+      --title[=TITLE]                    The meta title of the export.
+      --description[=DESCRIPTION]        The meta description of the export.
+      --notes[=NOTES]                    The meta notes of the export.
+      --dependency[=DEPENDENCY]          This TYPO3 extension is required for the exported records. Examples: "news", "powermail", etc. (multiple values allowed)
+      --saveFilesOutsideExportFile       Save files into separate folder instead of including them into the common export file. Folder name pattern is "{filename}.files".
+
+Impact
+======
+
+Exporting a TYPO3 page tree without time limit is now possible via CLI.
+
+Repeated exports with the same configuration become easily documentable and
+applicable - for example during distribution development.
+
+.. index:: CLI, ext:impexp
diff --git a/typo3/sysext/impexp/Classes/Command/ExportCommand.php b/typo3/sysext/impexp/Classes/Command/ExportCommand.php
new file mode 100644
index 0000000000000000000000000000000000000000..e1504c64ee6b0d3be0ecbcb904dc5bf9cb928e3f
--- /dev/null
+++ b/typo3/sysext/impexp/Classes/Command/ExportCommand.php
@@ -0,0 +1,212 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Impexp\Command;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+use TYPO3\CMS\Core\Core\Bootstrap;
+use TYPO3\CMS\Core\Utility\PathUtility;
+use TYPO3\CMS\Impexp\Export;
+
+/**
+ * Command for exporting T3D/XML data files
+ */
+class ExportCommand extends Command
+{
+    protected Export $export;
+
+    public function __construct(Export $export)
+    {
+        $this->export = $export;
+        parent::__construct();
+    }
+
+    /**
+     * Configure the command by defining the name, options and arguments
+     */
+    protected function configure(): void
+    {
+        $this
+            ->addArgument(
+                'filename',
+                InputArgument::OPTIONAL,
+                'The filename to export to (without file extension)'
+            )
+            ->addOption(
+                'type',
+                null,
+                InputOption::VALUE_OPTIONAL,
+                'The file type (xml, t3d, t3d_compressed).',
+                $this->export->getExportFileType()
+            )
+            ->addOption(
+                'pid',
+                null,
+                InputOption::VALUE_OPTIONAL,
+                'The root page of the exported page tree.',
+                $this->export->getPid()
+            )
+            ->addOption(
+                'levels',
+                null,
+                InputOption::VALUE_OPTIONAL,
+                sprintf(
+                    'The depth of the exported page tree. ' .
+                    '"%d": "Records on this page", ' .
+                    '"%d": "Expanded tree", ' .
+                    '"0": "This page", ' .
+                    '"1": "1 level down", ' .
+                    '.. ' .
+                    '"%d": "Infinite levels".',
+                    Export::LEVELS_RECORDS_ON_THIS_PAGE,
+                    Export::LEVELS_EXPANDED_TREE,
+                    Export::LEVELS_INFINITE
+                ),
+                $this->export->getLevels()
+            )
+            ->addOption(
+                'table',
+                null,
+                InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
+                'Include all records of this table. Examples: "_ALL", "tt_content", "sys_file_reference", etc.'
+            )
+            ->addOption(
+                'record',
+                null,
+                InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
+                'Include this specific record. Pattern is "{table}:{record}". Examples: "tt_content:12", etc.'
+            )
+            ->addOption(
+                'list',
+                null,
+                InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
+                'Include the records of this table and this page. Pattern is "{table}:{pid}". Examples: "sys_language:0", etc.'
+            )
+            ->addOption(
+                'includeRelated',
+                null,
+                InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
+                'Include record relations to this table, including the related record. Examples: "_ALL", "sys_category", etc.'
+            )
+            ->addOption(
+                'includeStatic',
+                null,
+                InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
+                'Include record relations to this table, excluding the related record. Examples: "_ALL", "sys_language", etc.'
+            )
+            ->addOption(
+                'exclude',
+                null,
+                InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
+                'Exclude this specific record. Pattern is "{table}:{record}". Examples: "fe_users:3", etc.'
+            )
+            ->addOption(
+                'excludeDisabledRecords',
+                null,
+                InputOption::VALUE_NONE,
+                'Exclude records which are handled as disabled by their TCA configuration, e.g. by fields "disabled", "starttime" or "endtime".'
+            )
+            ->addOption(
+                'excludeHtmlCss',
+                null,
+                InputOption::VALUE_NONE,
+                'Exclude referenced HTML and CSS files.'
+            )
+            ->addOption(
+                'title',
+                null,
+                InputOption::VALUE_OPTIONAL,
+                'The meta title of the export.'
+            )
+            ->addOption(
+                'description',
+                null,
+                InputOption::VALUE_OPTIONAL,
+                'The meta description of the export.'
+            )
+            ->addOption(
+                'notes',
+                null,
+                InputOption::VALUE_OPTIONAL,
+                'The meta notes of the export.'
+            )
+            ->addOption(
+                'dependency',
+                null,
+                InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
+                'This TYPO3 extension is required for the exported records. Examples: "news", "powermail", etc.'
+            )
+            ->addOption(
+                'saveFilesOutsideExportFile',
+                null,
+                InputOption::VALUE_NONE,
+                'Save files into separate folder instead of including them into the common export file. Folder name pattern is "{filename}.files".'
+            )
+        ;
+    }
+
+    /**
+     * Executes the command for exporting a t3d/xml file from the TYPO3 system
+     *
+     * @param InputInterface $input
+     * @param OutputInterface $output
+     * @return int
+     */
+    protected function execute(InputInterface $input, OutputInterface $output): int
+    {
+        // Ensure the _cli_ user is authenticated
+        Bootstrap::initializeBackendAuthentication();
+
+        $io = new SymfonyStyle($input, $output);
+
+        try {
+            $this->export->setExportFileName(PathUtility::basename((string)$input->getArgument('filename')));
+            $this->export->setExportFileType((string)$input->getOption('type'));
+            $this->export->setPid((int)$input->getOption('pid'));
+            $this->export->setLevels((int)$input->getOption('levels'));
+            $this->export->setTables($input->getOption('table'));
+            $this->export->setRecord($input->getOption('record'));
+            $this->export->setList($input->getOption('list'));
+            $this->export->setRelOnlyTables($input->getOption('includeRelated'));
+            $this->export->setRelStaticTables($input->getOption('includeStatic'));
+            $this->export->setExcludeMap($input->getOption('exclude'));
+            $this->export->setExcludeDisabledRecords($input->getOption('excludeDisabledRecords'));
+            $this->export->setIncludeExtFileResources(!$input->getOption('excludeHtmlCss'));
+            $this->export->setTitle((string)$input->getOption('title'));
+            $this->export->setDescription((string)$input->getOption('description'));
+            $this->export->setNotes((string)$input->getOption('notes'));
+            $this->export->setExtensionDependencies($input->getOption('dependency'));
+            $this->export->setSaveFilesOutsideExportFile($input->getOption('saveFilesOutsideExportFile'));
+            $this->export->process();
+            $saveFile = $this->export->saveToFile();
+            $io->success('Exporting to ' . $saveFile->getPublicUrl() . ' succeeded.');
+            return 0;
+        } catch (\Exception $e) {
+            $saveFolder = $this->export->getOrCreateDefaultImportExportFolder();
+            $io->error('Exporting to ' . $saveFolder->getPublicUrl() . ' failed.');
+            if ($io->isVerbose()) {
+                $io->writeln($e->getMessage());
+            }
+            return 1;
+        }
+    }
+}
diff --git a/typo3/sysext/impexp/Classes/Command/ImportCommand.php b/typo3/sysext/impexp/Classes/Command/ImportCommand.php
index 451a4f161c71d03ee82a3ae4bbf5ddb01c0e1a05..3f7a072660919850e0b46fb4c4490e8f4cf9ee7a 100644
--- a/typo3/sysext/impexp/Classes/Command/ImportCommand.php
+++ b/typo3/sysext/impexp/Classes/Command/ImportCommand.php
@@ -77,7 +77,7 @@ class ImportCommand extends Command
             )
             ->addOption(
                 'importMode',
-                'm',
+                null,
                 InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
                 sprintf(
                     'Set the import mode of this specific record. ' . PHP_EOL .
diff --git a/typo3/sysext/impexp/Configuration/Services.yaml b/typo3/sysext/impexp/Configuration/Services.yaml
index b1355c96c3f755da1b42525608a8143026761b3e..ac086cfd3912f13e7897100e8d13b997bfee76dd 100644
--- a/typo3/sysext/impexp/Configuration/Services.yaml
+++ b/typo3/sysext/impexp/Configuration/Services.yaml
@@ -21,3 +21,9 @@ services:
       - name: 'console.command'
         command: 'impexp:import'
         description: 'Imports a T3D / XML file with content into a page tree'
+
+  TYPO3\CMS\Impexp\Command\ExportCommand:
+    tags:
+      - name: 'console.command'
+        command: 'impexp:export'
+        description: 'Exports a T3D / XML file with content of a page tree'
diff --git a/typo3/sysext/impexp/Tests/Functional/Command/ExportCommandTest.php b/typo3/sysext/impexp/Tests/Functional/Command/ExportCommandTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..788f51f8af6691e56dca9430a01dafcc4c73f7db
--- /dev/null
+++ b/typo3/sysext/impexp/Tests/Functional/Command/ExportCommandTest.php
@@ -0,0 +1,114 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Impexp\Tests\Functional\Command;
+
+use Symfony\Component\Console\Tester\CommandTester;
+use TYPO3\CMS\Core\Core\Environment;
+use TYPO3\CMS\Impexp\Command\ExportCommand;
+use TYPO3\CMS\Impexp\Export;
+use TYPO3\CMS\Impexp\Tests\Functional\AbstractImportExportTestCase;
+
+/**
+ * Test case
+ */
+class ExportCommandTest extends AbstractImportExportTestCase
+{
+    /**
+     * @test
+     */
+    public function exportCommandRequiresNoArguments(): void
+    {
+        $exportMock = $this->getAccessibleMock(Export::class, ['setMetaData']);
+        $tester = new CommandTester(new ExportCommand($exportMock));
+        $tester->execute([], []);
+
+        self::assertEquals(0, $tester->getStatusCode());
+    }
+
+    /**
+     * @test
+     */
+    public function exportCommandSavesExportWithGivenFileName(): void
+    {
+        $fileName = 'empty_export';
+
+        $exportMock = $this->getAccessibleMock(Export::class, ['setMetaData']);
+        $tester = new CommandTester(new ExportCommand($exportMock));
+        $tester->execute(['filename' => $fileName], []);
+
+        preg_match('/([^\s]*importexport[^\s]*)/', $tester->getDisplay(), $display);
+        $filePath = Environment::getPublicPath() . '/' . $display[1];
+
+        self::assertEquals(0, $tester->getStatusCode());
+        self::assertStringEndsWith('empty_export.xml', $filePath);
+        self::assertXmlFileEqualsXmlFile(__DIR__ . '/../Fixtures/XmlExports/empty.xml', $filePath);
+    }
+
+    /**
+     * @test
+     */
+    public function exportCommandPassesArgumentsToExportObject(): void
+    {
+        $input = [
+            'filename' => 'empty_export',
+            '--type' => Export::FILETYPE_T3D,
+            '--pid' => 123,
+            '--levels' => Export::LEVELS_RECORDS_ON_THIS_PAGE,
+            '--table' => ['tt_content'],
+            '--record' => ['sys_category:6'],
+            '--list' => ['sys_category:123'],
+            '--includeRelated' => ['be_users'],
+            '--includeStatic' => ['sys_language'],
+            '--exclude' => ['be_users:3'],
+            '--excludeDisabledRecords' => true,
+            '--excludeHtmlCss' => true,
+            '--title' => 'Export Command',
+            '--description' => 'The export which considers all arguments passed on the command line.',
+            '--notes' => 'This export is not for production use.',
+            '--dependency' => ['bootstrap_package'],
+            '--saveFilesOutsideExportFile' => true
+        ];
+
+        $exportMock = $this->getAccessibleMock(Export::class, [
+            'setExportFileType', 'setExportFileName', 'setPid', 'setLevels', 'setTables', 'setRecord', 'setList',
+            'setRelOnlyTables', 'setRelStaticTables', 'setExcludeMap', 'setExcludeDisabledRecords',
+            'setIncludeExtFileResources', 'setTitle', 'setDescription', 'setNotes', 'setExtensionDependencies',
+            'setSaveFilesOutsideExportFile'
+        ]);
+        $exportMock->expects(self::once())->method('setExportFileName')->with(self::equalTo($input['filename']));
+        $exportMock->expects(self::once())->method('setExportFileType')->with(self::equalTo($input['--type']));
+        $exportMock->expects(self::once())->method('setPid')->with(self::equalTo($input['--pid']));
+        $exportMock->expects(self::once())->method('setLevels')->with(self::equalTo($input['--levels']));
+        $exportMock->expects(self::once())->method('setTables')->with(self::equalTo($input['--table']));
+        $exportMock->expects(self::once())->method('setRecord')->with(self::equalTo($input['--record']));
+        $exportMock->expects(self::once())->method('setList')->with(self::equalTo($input['--list']));
+        $exportMock->expects(self::once())->method('setRelOnlyTables')->with(self::equalTo($input['--includeRelated']));
+        $exportMock->expects(self::once())->method('setRelStaticTables')->with(self::equalTo($input['--includeStatic']));
+        $exportMock->expects(self::once())->method('setExcludeMap')->with(self::equalTo($input['--exclude']));
+        $exportMock->expects(self::once())->method('setExcludeDisabledRecords')->with(self::equalTo($input['--excludeDisabledRecords']));
+        $exportMock->expects(self::once())->method('setIncludeExtFileResources')->with(self::equalTo(!$input['--excludeHtmlCss']));
+        $exportMock->expects(self::once())->method('setTitle')->with(self::equalTo($input['--title']));
+        $exportMock->expects(self::once())->method('setDescription')->with(self::equalTo($input['--description']));
+        $exportMock->expects(self::once())->method('setNotes')->with(self::equalTo($input['--notes']));
+        $exportMock->expects(self::once())->method('setExtensionDependencies')->with(self::equalTo($input['--dependency']));
+        $exportMock->expects(self::once())->method('setSaveFilesOutsideExportFile')->with(self::equalTo($input['--saveFilesOutsideExportFile']));
+
+        $tester = new CommandTester(new ExportCommand($exportMock));
+        $tester->execute($input);
+    }
+}