Repository: BrianPugh/cyclopts

Issue:
Lazy command loader changes a subapp's `--help` output
Without lazy loading:
```py
# a.py
import cyclopts

app = cyclopts.App("App")
subapp = cyclopts.App("greet")

@subapp.default
def greet(name: str):
    """Greet a person by name."""
    print(f"Hello, {name}!")

app.command(subapp)

if __name__ == "__main__":
    app()
```
```console
❯ uv run a.py greet --help
Usage: App greet NAME

Greet a person by name.

╭─ Parameters ────────────────────────────────────────────────────────────╮
│ *  NAME --name  [required]                                              │
╰─────────────────────────────────────────────────────────────────────────╯
```
With lazy loading:
```py
# a.py
import cyclopts

app = cyclopts.App("App")
subapp = cyclopts.App("greet")

@subapp.default
def greet(name: str):
    """Greet a person by name."""
    print(f"Hello, {name}!")

app.command("a:subapp", name="greet")

if __name__ == "__main__":
    app()
```
```console
❯ uv run a.py greet --help
Usage: App greet NAME

Greet a person by name.

╭─ Commands ──────────────────────────────────────────────────────────────╮
│ --help -h  Display this message and exit.                               │
│ --version  Display application version.                                 │
╰─────────────────────────────────────────────────────────────────────────╯
╭─ Parameters ────────────────────────────────────────────────────────────╮
│ *  NAME --name  [required]                                              │
╰─────────────────────────────────────────────────────────────────────────╯
```
Notice how the `--help` output changed, it now includes `--help` and `--version`. These flags were removed from a subapp's `--help` output in [v3.10](https://github.com/BrianPugh/cyclopts/releases/tag/v3.10.0) (https://github.com/BrianPugh/cyclopts/pull/363) so this seems to be a regression that only appears when a subapp is lazy loaded.

Discussion:

Fix (patch):
diff --git a/cyclopts/command_spec.py b/cyclopts/command_spec.py
index f112eb3b..09cf86fa 100644
--- a/cyclopts/command_spec.py
+++ b/cyclopts/command_spec.py
@@ -1,6 +1,7 @@
 """Lazy-loadable command specification for deferred imports."""
 
 import importlib
+from itertools import chain
 from typing import TYPE_CHECKING, Any
 
 from attrs import Factory, define, field
@@ -137,6 +138,11 @@ def resolve(self, parent_app: "App") -> "App":
             self._resolved = App(name=self.name, **app_kwargs)
             self._resolved.default(target)
 
+        # Hide help and version flags from subapp help output
+        # This matches the behavior of direct App/function registration in core.py
+        for flag in chain(self._resolved.help_flags, self._resolved.version_flags):
+            self._resolved[flag].show = False
+
         return self._resolved
 
     @property


Test changes:
diff --git a/tests/test_lazy_commands.py b/tests/test_lazy_commands.py
index b9d6294d..7758dd53 100644
--- a/tests/test_lazy_commands.py
+++ b/tests/test_lazy_commands.py
@@ -590,3 +590,43 @@ def test_lazy_app_name_match_allows_resolution():
         assert resolved is test_module.subapp
     finally:
         del sys.modules["test_lazy_module"]
+
+
+def test_lazy_subapp_help_excludes_help_version_flags(console):
+    """Test that lazy-loaded subapps don't show --help/--version in their help.
+
+    Regression test for issue #697.
+    When a subapp is registered via lazy loading, its help output should NOT
+    include --help and --version flags (matching behavior of direct registration).
+    """
+    test_module = ModuleType("test_lazy_module")
+
+    # Create a subapp with a default command
+    subapp = App(name="greet")
+
+    @subapp.default
+    def greet(name: str):
+        """Greet a person by name."""
+        print(f"Hello, {name}!")
+
+    test_module.subapp = subapp  # type: ignore[attr-defined]
+    sys.modules["test_lazy_module"] = test_module
+
+    try:
+        # Test lazy registration (should not show --help/--version)
+        app_lazy = App(name="App", result_action="return_value")
+        app_lazy.command("test_lazy_module:subapp", name="greet")
+
+        with console.capture() as capture:
+            app_lazy(["greet", "--help"], console=console)
+
+        output_lazy = capture.get()
+
+        # Lazy registration should not include --help/--version in the subapp help
+        assert "--help" not in output_lazy
+        assert "--version" not in output_lazy
+        assert "Commands" not in output_lazy  # Should not have a Commands section at all
+        assert "NAME" in output_lazy
+        assert "Greet a person by name" in output_lazy
+    finally:
+        del sys.modules["test_lazy_module"]