Repository: mkdocs/mkdocs

Issue:
Please allow overriding use_directory_urls option via a command line flag
Dear mkdocs developers,

Some projects have `use_directory_urls: true` in their `mkdocs.yml` files, which creates some problems when browsing the documentation locally.

I am Debian packager, and we often package documentation to make it easier for developers to browse it locally. So it would be nice to have a `--use-directory-urls=false` flag (or similar) to override that setting, so that I don’t have to patch `mkdocs.yml`.


Discussion:
That seems like a reasonable reason for adding that option. However, it's not going to be high on my priority list, so a PR is more likely to get the change made sooner than later.
use-directory-urls: false does not work in mkdocs.yml while using 1.0.4, also 'mkdocs build --use-directory-urls=false' reports 'no such option', when can we have 'use-directory-urls=false'? my markdown files are generated locally and I would like to browse them without a http server sometimes.
> use-directory-urls: false does not work in mkdocs.yml while using 1.0.4

Please report this as a separate issue.
@laoshaw In `mkdocs.yml` it should be `use_directory_urls`, with underscores and not with hyphens.

Resolving patch:
diff --git a/mkdocs/__main__.py b/mkdocs/__main__.py
--- a/mkdocs/__main__.py
+++ b/mkdocs/__main__.py
@@ -38,6 +38,38 @@ def __init__(self, log_name='mkdocs', level=logging.INFO):
 
 pass_state = click.make_pass_decorator(State, ensure=True)
 
+clean_help = "Remove old files from the site_dir before building (the default)."
+config_help = "Provide a specific MkDocs config"
+dev_addr_help = ("IP address and port to serve documentation locally (default: "
+                 "localhost:8000)")
+strict_help = ("Enable strict mode. This will cause MkDocs to abort the build "
+               "on any warnings.")
+theme_dir_help = "The theme directory to use when building your documentation."
+theme_help = "The theme to use when building your documentation."
+theme_choices = utils.get_theme_names()
+site_dir_help = "The directory to output the result of the documentation build."
+use_directory_urls_help = "Use directory URLs when building pages (the default)."
+reload_help = "Enable the live reloading in the development server (this is the default)"
+no_reload_help = "Disable the live reloading in the development server."
+dirty_reload_help = "Enable the live reloading in the development server, but only re-build files that have changed"
+commit_message_help = ("A commit message to use when committing to the "
+                       "Github Pages remote branch. Commit {sha} and MkDocs {version} are available as expansions")
+remote_branch_help = ("The remote branch to commit to for Github Pages. This "
+                      "overrides the value specified in config")
+remote_name_help = ("The remote name to commit to for Github Pages. This "
+                    "overrides the value specified in config")
+force_help = "Force the push to the repository."
+ignore_version_help = "Ignore check that build is not being deployed with an older version of MkDocs."
+
+
+def add_options(opts):
+    def inner(f):
+        for i in reversed(opts):
+            f = i(f)
+        return f
+
+    return inner
+
 
 def verbose_option(f):
     def callback(ctx, param, value):
@@ -63,33 +95,18 @@ def callback(ctx, param, value):
                         callback=callback)(f)
 
 
-def common_options(f):
-    f = verbose_option(f)
-    f = quiet_option(f)
-    return f
-
-
-clean_help = "Remove old files from the site_dir before building (the default)."
-config_help = "Provide a specific MkDocs config"
-dev_addr_help = ("IP address and port to serve documentation locally (default: "
-                 "localhost:8000)")
-strict_help = ("Enable strict mode. This will cause MkDocs to abort the build "
-               "on any warnings.")
-theme_dir_help = "The theme directory to use when building your documentation."
-theme_help = "The theme to use when building your documentation."
-theme_choices = utils.get_theme_names()
-site_dir_help = "The directory to output the result of the documentation build."
-reload_help = "Enable the live reloading in the development server (this is the default)"
-no_reload_help = "Disable the live reloading in the development server."
-dirty_reload_help = "Enable the live reloading in the development server, but only re-build files that have changed"
-commit_message_help = ("A commit message to use when committing to the "
-                       "Github Pages remote branch. Commit {sha} and MkDocs {version} are available as expansions")
-remote_branch_help = ("The remote branch to commit to for Github Pages. This "
-                      "overrides the value specified in config")
-remote_name_help = ("The remote name to commit to for Github Pages. This "
-                    "overrides the value specified in config")
-force_help = "Force the push to the repository."
-ignore_version_help = "Ignore check that build is not being deployed with an older version of MkDocs."
+common_options = add_options([quiet_option, verbose_option])
+common_config_options = add_options([
+    click.option('-f', '--config-file', type=click.File('rb'), help=config_help),
+    # Don't override config value if user did not specify --strict flag
+    # Conveniently, load_config drops None values
+    click.option('-s', '--strict', is_flag=True, default=None, help=strict_help),
+    click.option('-t', '--theme', type=click.Choice(theme_choices), help=theme_help),
+    click.option('-e', '--theme-dir', type=click.Path(), help=theme_dir_help),
+    # As with --strict, set the default to None so that this doesn't incorrectly
+    # override the config file
+    click.option('--use-directory-urls/--no-directory-urls', is_flag=True, default=None, help=use_directory_urls_help)
+])
 
 pgk_dir = os.path.dirname(os.path.abspath(__file__))
 
@@ -106,32 +123,22 @@ def cli():
 
 
 @cli.command(name="serve")
-@click.option('-f', '--config-file', type=click.File('rb'), help=config_help)
 @click.option('-a', '--dev-addr', help=dev_addr_help, metavar='<IP:PORT>')
-@click.option('-s', '--strict', is_flag=True, help=strict_help)
-@click.option('-t', '--theme', type=click.Choice(theme_choices), help=theme_help)
-@click.option('-e', '--theme-dir', type=click.Path(), help=theme_dir_help)
 @click.option('--livereload', 'livereload', flag_value='livereload', help=reload_help, default=True)
 @click.option('--no-livereload', 'livereload', flag_value='no-livereload', help=no_reload_help)
 @click.option('--dirtyreload', 'livereload', flag_value='dirty', help=dirty_reload_help)
+@common_config_options
 @common_options
-def serve_command(dev_addr, config_file, strict, theme, theme_dir, livereload):
+def serve_command(dev_addr, livereload, **kwargs):
     """Run the builtin development server"""
 
     logging.getLogger('tornado').setLevel(logging.WARNING)
 
-    # Don't override config value if user did not specify --strict flag
-    # Conveniently, load_config drops None values
-    strict = strict or None
-
     try:
         serve.serve(
-            config_file=config_file,
             dev_addr=dev_addr,
-            strict=strict,
-            theme=theme,
-            theme_dir=theme_dir,
-            livereload=livereload
+            livereload=livereload,
+            **kwargs
         )
     except (exceptions.ConfigurationError, socket.error) as e:  # pragma: no cover
         # Avoid ugly, unhelpful traceback
@@ -140,27 +147,14 @@ def serve_command(dev_addr, config_file, strict, theme, theme_dir, livereload):
 
 @cli.command(name="build")
 @click.option('-c', '--clean/--dirty', is_flag=True, default=True, help=clean_help)
-@click.option('-f', '--config-file', type=click.File('rb'), help=config_help)
-@click.option('-s', '--strict', is_flag=True, help=strict_help)
-@click.option('-t', '--theme', type=click.Choice(theme_choices), help=theme_help)
-@click.option('-e', '--theme-dir', type=click.Path(), help=theme_dir_help)
+@common_config_options
 @click.option('-d', '--site-dir', type=click.Path(), help=site_dir_help)
 @common_options
-def build_command(clean, config_file, strict, theme, theme_dir, site_dir):
+def build_command(clean, **kwargs):
     """Build the MkDocs documentation"""
 
-    # Don't override config value if user did not specify --strict flag
-    # Conveniently, load_config drops None values
-    strict = strict or None
-
     try:
-        build.build(config.load_config(
-            config_file=config_file,
-            strict=strict,
-            theme=theme,
-            theme_dir=theme_dir,
-            site_dir=site_dir
-        ), dirty=not clean)
+        build.build(config.load_config(**kwargs), dirty=not clean)
     except exceptions.ConfigurationError as e:  # pragma: no cover
         # Avoid ugly, unhelpful traceback
         raise SystemExit('\n' + str(e))
@@ -168,20 +162,21 @@ def build_command(clean, config_file, strict, theme, theme_dir, site_dir):
 
 @cli.command(name="gh-deploy")
 @click.option('-c', '--clean/--dirty', is_flag=True, default=True, help=clean_help)
-@click.option('-f', '--config-file', type=click.File('rb'), help=config_help)
 @click.option('-m', '--message', help=commit_message_help)
 @click.option('-b', '--remote-branch', help=remote_branch_help)
 @click.option('-r', '--remote-name', help=remote_name_help)
 @click.option('--force', is_flag=True, help=force_help)
 @click.option('--ignore-version', is_flag=True, help=ignore_version_help)
+@common_config_options
+@click.option('-d', '--site-dir', type=click.Path(), help=site_dir_help)
 @common_options
-def gh_deploy_command(config_file, clean, message, remote_branch, remote_name, force, ignore_version):
+def gh_deploy_command(clean, message, remote_branch, remote_name, force, ignore_version, **kwargs):
     """Deploy your documentation to GitHub Pages"""
     try:
         cfg = config.load_config(
-            config_file=config_file,
             remote_branch=remote_branch,
-            remote_name=remote_name
+            remote_name=remote_name,
+            **kwargs
         )
         build.build(cfg, dirty=not clean)
         gh_deploy.gh_deploy(cfg, message=message, force=force, ignore_version=ignore_version)
diff --git a/mkdocs/commands/serve.py b/mkdocs/commands/serve.py
--- a/mkdocs/commands/serve.py
+++ b/mkdocs/commands/serve.py
@@ -105,7 +105,7 @@ def _static_server(host, port, site_dir):
 
 
 def serve(config_file=None, dev_addr=None, strict=None, theme=None,
-          theme_dir=None, livereload='livereload'):
+          theme_dir=None, livereload='livereload', **kwargs):
     """
     Start the MkDocs development server
 
@@ -127,7 +127,8 @@ def builder():
             strict=strict,
             theme=theme,
             theme_dir=theme_dir,
-            site_dir=site_dir
+            site_dir=site_dir,
+            **kwargs
         )
         # Override a few config settings after validation
         config['site_url'] = 'http://{0}/'.format(config['dev_addr'])


Test patch:
diff --git a/mkdocs/tests/cli_tests.py b/mkdocs/tests/cli_tests.py
--- a/mkdocs/tests/cli_tests.py
+++ b/mkdocs/tests/cli_tests.py
@@ -28,12 +28,13 @@ def test_serve_default(self, mock_serve):
 
         self.assertEqual(result.exit_code, 0)
         mock_serve.assert_called_once_with(
-            config_file=None,
             dev_addr=None,
+            livereload='livereload',
+            config_file=None,
             strict=None,
             theme=None,
             theme_dir=None,
-            livereload='livereload'
+            use_directory_urls=None
         )
 
     @mock.patch('mkdocs.commands.serve.serve', autospec=True)
@@ -60,12 +61,13 @@ def test_serve_dev_addr(self, mock_serve):
 
         self.assertEqual(result.exit_code, 0)
         mock_serve.assert_called_once_with(
-            config_file=None,
             dev_addr='0.0.0.0:80',
+            livereload='livereload',
+            config_file=None,
             strict=None,
             theme=None,
             theme_dir=None,
-            livereload='livereload'
+            use_directory_urls=None
         )
 
     @mock.patch('mkdocs.commands.serve.serve', autospec=True)
@@ -76,12 +78,13 @@ def test_serve_strict(self, mock_serve):
 
         self.assertEqual(result.exit_code, 0)
         mock_serve.assert_called_once_with(
-            config_file=None,
             dev_addr=None,
+            livereload='livereload',
+            config_file=None,
             strict=True,
             theme=None,
             theme_dir=None,
-            livereload='livereload'
+            use_directory_urls=None
         )
 
     @mock.patch('mkdocs.commands.serve.serve', autospec=True)
@@ -92,12 +95,13 @@ def test_serve_theme(self, mock_serve):
 
         self.assertEqual(result.exit_code, 0)
         mock_serve.assert_called_once_with(
-            config_file=None,
             dev_addr=None,
+            livereload='livereload',
+            config_file=None,
             strict=None,
             theme='readthedocs',
             theme_dir=None,
-            livereload='livereload'
+            use_directory_urls=None
         )
 
     @mock.patch('mkdocs.commands.serve.serve', autospec=True)
@@ -108,12 +112,47 @@ def test_serve_theme_dir(self, mock_serve):
 
         self.assertEqual(result.exit_code, 0)
         mock_serve.assert_called_once_with(
-            config_file=None,
             dev_addr=None,
+            livereload='livereload',
+            config_file=None,
             strict=None,
             theme=None,
             theme_dir='custom',
-            livereload='livereload'
+            use_directory_urls=None
+        )
+
+    @mock.patch('mkdocs.commands.serve.serve', autospec=True)
+    def test_serve_use_directory_urls(self, mock_serve):
+
+        result = self.runner.invoke(
+            cli.cli, ["serve", '--use-directory-urls'], catch_exceptions=False)
+
+        self.assertEqual(result.exit_code, 0)
+        mock_serve.assert_called_once_with(
+            dev_addr=None,
+            livereload='livereload',
+            config_file=None,
+            strict=None,
+            theme=None,
+            theme_dir=None,
+            use_directory_urls=True
+        )
+
+    @mock.patch('mkdocs.commands.serve.serve', autospec=True)
+    def test_serve_no_directory_urls(self, mock_serve):
+
+        result = self.runner.invoke(
+            cli.cli, ["serve", '--no-directory-urls'], catch_exceptions=False)
+
+        self.assertEqual(result.exit_code, 0)
+        mock_serve.assert_called_once_with(
+            dev_addr=None,
+            livereload='livereload',
+            config_file=None,
+            strict=None,
+            theme=None,
+            theme_dir=None,
+            use_directory_urls=False
         )
 
     @mock.patch('mkdocs.commands.serve.serve', autospec=True)
@@ -124,12 +163,13 @@ def test_serve_livereload(self, mock_serve):
 
         self.assertEqual(result.exit_code, 0)
         mock_serve.assert_called_once_with(
-            config_file=None,
             dev_addr=None,
+            livereload='livereload',
+            config_file=None,
             strict=None,
             theme=None,
             theme_dir=None,
-            livereload='livereload'
+            use_directory_urls=None
         )
 
     @mock.patch('mkdocs.commands.serve.serve', autospec=True)
@@ -140,12 +180,13 @@ def test_serve_no_livereload(self, mock_serve):
 
         self.assertEqual(result.exit_code, 0)
         mock_serve.assert_called_once_with(
-            config_file=None,
             dev_addr=None,
+            livereload='no-livereload',
+            config_file=None,
             strict=None,
             theme=None,
             theme_dir=None,
-            livereload='no-livereload'
+            use_directory_urls=None
         )
 
     @mock.patch('mkdocs.commands.serve.serve', autospec=True)
@@ -156,12 +197,13 @@ def test_serve_dirtyreload(self, mock_serve):
 
         self.assertEqual(result.exit_code, 0)
         mock_serve.assert_called_once_with(
-            config_file=None,
             dev_addr=None,
+            livereload='dirty',
+            config_file=None,
             strict=None,
             theme=None,
             theme_dir=None,
-            livereload='dirty'
+            use_directory_urls=None
         )
 
     @mock.patch('mkdocs.config.load_config', autospec=True)
@@ -181,6 +223,7 @@ def test_build_defaults(self, mock_build, mock_load_config):
             strict=None,
             theme=None,
             theme_dir=None,
+            use_directory_urls=None,
             site_dir=None
         )
         logger = logging.getLogger('mkdocs')
@@ -244,6 +287,7 @@ def test_build_strict(self, mock_build, mock_load_config):
             strict=True,
             theme=None,
             theme_dir=None,
+            use_directory_urls=None,
             site_dir=None
         )
 
@@ -261,6 +305,7 @@ def test_build_theme(self, mock_build, mock_load_config):
             strict=None,
             theme='readthedocs',
             theme_dir=None,
+            use_directory_urls=None,
             site_dir=None
         )
 
@@ -278,6 +323,43 @@ def test_build_theme_dir(self, mock_build, mock_load_config):
             strict=None,
             theme=None,
             theme_dir='custom',
+            use_directory_urls=None,
+            site_dir=None
+        )
+
+    @mock.patch('mkdocs.config.load_config', autospec=True)
+    @mock.patch('mkdocs.commands.build.build', autospec=True)
+    def test_build_use_directory_urls(self, mock_build, mock_load_config):
+
+        result = self.runner.invoke(
+            cli.cli, ['build', '--use-directory-urls'], catch_exceptions=False)
+
+        self.assertEqual(result.exit_code, 0)
+        self.assertEqual(mock_build.call_count, 1)
+        mock_load_config.assert_called_once_with(
+            config_file=None,
+            strict=None,
+            theme=None,
+            theme_dir=None,
+            use_directory_urls=True,
+            site_dir=None
+        )
+
+    @mock.patch('mkdocs.config.load_config', autospec=True)
+    @mock.patch('mkdocs.commands.build.build', autospec=True)
+    def test_build_no_directory_urls(self, mock_build, mock_load_config):
+
+        result = self.runner.invoke(
+            cli.cli, ['build', '--no-directory-urls'], catch_exceptions=False)
+
+        self.assertEqual(result.exit_code, 0)
+        self.assertEqual(mock_build.call_count, 1)
+        mock_load_config.assert_called_once_with(
+            config_file=None,
+            strict=None,
+            theme=None,
+            theme_dir=None,
+            use_directory_urls=False,
             site_dir=None
         )
 
@@ -295,7 +377,8 @@ def test_build_site_dir(self, mock_build, mock_load_config):
             strict=None,
             theme=None,
             theme_dir=None,
-            site_dir='custom'
+            use_directory_urls=None,
+            site_dir='custom',
         )
 
     @mock.patch('mkdocs.config.load_config', autospec=True)
@@ -353,9 +436,14 @@ def test_gh_deploy_defaults(self, mock_gh_deploy, mock_build, mock_load_config):
         self.assertTrue('dirty' in b_kwargs)
         self.assertFalse(b_kwargs['dirty'])
         mock_load_config.assert_called_once_with(
-            config_file=None,
             remote_branch=None,
-            remote_name=None
+            remote_name=None,
+            config_file=None,
+            strict=None,
+            theme=None,
+            theme_dir=None,
+            use_directory_urls=None,
+            site_dir=None
         )
 
     @mock.patch('mkdocs.config.load_config', autospec=True)
@@ -436,9 +524,14 @@ def test_gh_deploy_remote_branch(self, mock_gh_deploy, mock_build, mock_load_con
         self.assertEqual(mock_gh_deploy.call_count, 1)
         self.assertEqual(mock_build.call_count, 1)
         mock_load_config.assert_called_once_with(
-            config_file=None,
             remote_branch='foo',
-            remote_name=None
+            remote_name=None,
+            config_file=None,
+            strict=None,
+            theme=None,
+            theme_dir=None,
+            use_directory_urls=None,
+            site_dir=None
         )
 
     @mock.patch('mkdocs.config.load_config', autospec=True)
@@ -453,9 +546,14 @@ def test_gh_deploy_remote_name(self, mock_gh_deploy, mock_build, mock_load_confi
         self.assertEqual(mock_gh_deploy.call_count, 1)
         self.assertEqual(mock_build.call_count, 1)
         mock_load_config.assert_called_once_with(
-            config_file=None,
             remote_branch=None,
-            remote_name='foo'
+            remote_name='foo',
+            config_file=None,
+            strict=None,
+            theme=None,
+            theme_dir=None,
+            use_directory_urls=None,
+            site_dir=None
         )
 
     @mock.patch('mkdocs.config.load_config', autospec=True)
@@ -477,7 +575,7 @@ def test_gh_deploy_force(self, mock_gh_deploy, mock_build, mock_load_config):
     @mock.patch('mkdocs.config.load_config', autospec=True)
     @mock.patch('mkdocs.commands.build.build', autospec=True)
     @mock.patch('mkdocs.commands.gh_deploy.gh_deploy', autospec=True)
-    def test_gh_deploy_ognore_version(self, mock_gh_deploy, mock_build, mock_load_config):
+    def test_gh_deploy_ignore_version(self, mock_gh_deploy, mock_build, mock_load_config):
 
         result = self.runner.invoke(
             cli.cli, ['gh-deploy', '--ignore-version'], catch_exceptions=False)
@@ -489,3 +587,135 @@ def test_gh_deploy_ognore_version(self, mock_gh_deploy, mock_build, mock_load_co
         self.assertEqual(g_kwargs['ignore_version'], True)
         self.assertEqual(mock_build.call_count, 1)
         self.assertEqual(mock_load_config.call_count, 1)
+
+    @mock.patch('mkdocs.config.load_config', autospec=True)
+    @mock.patch('mkdocs.commands.build.build', autospec=True)
+    @mock.patch('mkdocs.commands.gh_deploy.gh_deploy', autospec=True)
+    def test_gh_deploy_strict(self, mock_gh_deploy, mock_build, mock_load_config):
+
+        result = self.runner.invoke(
+            cli.cli, ['gh-deploy', '--strict'], catch_exceptions=False)
+
+        self.assertEqual(result.exit_code, 0)
+        self.assertEqual(mock_gh_deploy.call_count, 1)
+        self.assertEqual(mock_build.call_count, 1)
+        mock_load_config.assert_called_once_with(
+            remote_branch=None,
+            remote_name=None,
+            config_file=None,
+            strict=True,
+            theme=None,
+            theme_dir=None,
+            use_directory_urls=None,
+            site_dir=None
+        )
+
+    @mock.patch('mkdocs.config.load_config', autospec=True)
+    @mock.patch('mkdocs.commands.build.build', autospec=True)
+    @mock.patch('mkdocs.commands.gh_deploy.gh_deploy', autospec=True)
+    def test_gh_deploy_theme(self, mock_gh_deploy, mock_build, mock_load_config):
+
+        result = self.runner.invoke(
+            cli.cli, ['gh-deploy', '--theme', 'readthedocs'], catch_exceptions=False)
+
+        self.assertEqual(result.exit_code, 0)
+        self.assertEqual(mock_gh_deploy.call_count, 1)
+        self.assertEqual(mock_build.call_count, 1)
+        mock_load_config.assert_called_once_with(
+            remote_branch=None,
+            remote_name=None,
+            config_file=None,
+            strict=None,
+            theme='readthedocs',
+            theme_dir=None,
+            use_directory_urls=None,
+            site_dir=None
+        )
+
+    @mock.patch('mkdocs.config.load_config', autospec=True)
+    @mock.patch('mkdocs.commands.build.build', autospec=True)
+    @mock.patch('mkdocs.commands.gh_deploy.gh_deploy', autospec=True)
+    def test_gh_deploy_theme_dir(self, mock_gh_deploy, mock_build, mock_load_config):
+
+        result = self.runner.invoke(
+            cli.cli, ['gh-deploy', '--theme-dir', 'custom'], catch_exceptions=False)
+
+        self.assertEqual(result.exit_code, 0)
+        self.assertEqual(mock_gh_deploy.call_count, 1)
+        self.assertEqual(mock_build.call_count, 1)
+        mock_load_config.assert_called_once_with(
+            remote_branch=None,
+            remote_name=None,
+            config_file=None,
+            strict=None,
+            theme=None,
+            theme_dir='custom',
+            use_directory_urls=None,
+            site_dir=None
+        )
+
+    @mock.patch('mkdocs.config.load_config', autospec=True)
+    @mock.patch('mkdocs.commands.build.build', autospec=True)
+    @mock.patch('mkdocs.commands.gh_deploy.gh_deploy', autospec=True)
+    def test_gh_deploy_use_directory_urls(self, mock_gh_deploy, mock_build, mock_load_config):
+
+        result = self.runner.invoke(
+            cli.cli, ['gh-deploy', '--use-directory-urls'], catch_exceptions=False)
+
+        self.assertEqual(result.exit_code, 0)
+        self.assertEqual(mock_gh_deploy.call_count, 1)
+        self.assertEqual(mock_build.call_count, 1)
+        mock_load_config.assert_called_once_with(
+            remote_branch=None,
+            remote_name=None,
+            config_file=None,
+            strict=None,
+            theme=None,
+            theme_dir=None,
+            use_directory_urls=True,
+            site_dir=None
+        )
+
+    @mock.patch('mkdocs.config.load_config', autospec=True)
+    @mock.patch('mkdocs.commands.build.build', autospec=True)
+    @mock.patch('mkdocs.commands.gh_deploy.gh_deploy', autospec=True)
+    def test_gh_deploy_no_directory_urls(self, mock_gh_deploy, mock_build, mock_load_config):
+
+        result = self.runner.invoke(
+            cli.cli, ['gh-deploy', '--no-directory-urls'], catch_exceptions=False)
+
+        self.assertEqual(result.exit_code, 0)
+        self.assertEqual(mock_gh_deploy.call_count, 1)
+        self.assertEqual(mock_build.call_count, 1)
+        mock_load_config.assert_called_once_with(
+            remote_branch=None,
+            remote_name=None,
+            config_file=None,
+            strict=None,
+            theme=None,
+            theme_dir=None,
+            use_directory_urls=False,
+            site_dir=None
+        )
+
+    @mock.patch('mkdocs.config.load_config', autospec=True)
+    @mock.patch('mkdocs.commands.build.build', autospec=True)
+    @mock.patch('mkdocs.commands.gh_deploy.gh_deploy', autospec=True)
+    def test_gh_deploy_site_dir(self, mock_gh_deploy, mock_build, mock_load_config):
+
+        result = self.runner.invoke(
+            cli.cli, ['gh-deploy', '--site-dir', 'custom'], catch_exceptions=False)
+
+        self.assertEqual(result.exit_code, 0)
+        self.assertEqual(mock_gh_deploy.call_count, 1)
+        self.assertEqual(mock_build.call_count, 1)
+        mock_load_config.assert_called_once_with(
+            remote_branch=None,
+            remote_name=None,
+            config_file=None,
+            strict=None,
+            theme=None,
+            theme_dir=None,
+            use_directory_urls=None,
+            site_dir='custom'
+        )