Skip to content

Commit 91fe73e

Browse files
committed
✨ Trim default startup output and add --verbose to dev and run
Shortcake-Parent: 2026-07-09-redesign-startup-output-style
1 parent eada899 commit 91fe73e

3 files changed

Lines changed: 160 additions & 120 deletions

File tree

src/fastapi_cli/cli.py

Lines changed: 63 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -142,17 +142,19 @@ def _run(
142142
proxy_headers: bool = False,
143143
forwarded_allow_ips: str | None = None,
144144
public_url: str | None = None,
145+
verbose: bool = False,
145146
) -> None:
146147
with get_rich_toolkit() as toolkit:
147148
server_type = "development" if command == "dev" else "production"
148149

149150
toolkit.print(f"Starting FastAPI in {server_type} mode", emoji="⚡️")
150151

151-
toolkit.print_line()
152-
toolkit.print(
153-
"Searching for package file structure from directories with [blue]__init__.py[/blue] files",
154-
emoji="🔎",
155-
)
152+
if verbose:
153+
toolkit.print_line()
154+
toolkit.print(
155+
"Searching for package file structure from directories with [blue]__init__.py[/blue] files",
156+
emoji="🔎",
157+
)
156158

157159
if entrypoint and (path or app):
158160
toolkit.print_line()
@@ -194,40 +196,54 @@ def _run(
194196

195197
module_data = import_data.module_data
196198
import_string = import_data.import_string
199+
is_auto_discovery = import_data.module_config_source == "auto-discovery"
197200

198-
toolkit.print_line()
199-
toolkit.print(f"Importing from {module_data.extra_sys_path}", emoji="📂")
200-
toolkit.print_line()
201+
if verbose:
202+
toolkit.print_line()
203+
toolkit.print(f"Importing from {module_data.extra_sys_path}", emoji="📂")
204+
toolkit.print_line()
201205

202-
if module_data.module_paths:
203-
root_tree = _get_module_tree(module_data.module_paths)
206+
if module_data.module_paths:
207+
root_tree = _get_module_tree(module_data.module_paths)
204208

205-
toolkit.print(root_tree)
209+
toolkit.print(root_tree)
206210

207-
toolkit.print_line()
211+
toolkit.print_line()
212+
213+
toolkit.print(
214+
"Importing the FastAPI app object from the module with the following code:",
215+
)
216+
toolkit.print_line()
217+
toolkit.print(
218+
f"[blue]from [bold]{module_data.module_import_str}[/bold] import [bold]{import_data.app_name}[/bold]",
219+
)
220+
221+
# Outside --verbose, fold the resolution source into the import string
222+
# line and point newcomers at --verbose for the full explanation
223+
if is_auto_discovery and not verbose:
224+
app_note = " [dim](auto-discovered, use --verbose to learn more)[/]"
225+
else:
226+
app_note = ""
208227

209-
toolkit.print(
210-
"Importing the FastAPI app object from the module with the following code:",
211-
)
212228
toolkit.print_line()
213229
toolkit.print(
214-
f"[blue]from [bold]{module_data.module_import_str}[/bold] import [bold]{import_data.app_name}[/bold]",
230+
f"Using import string: [blue]{import_string}[/]{app_note}", emoji="🐍"
215231
)
216232

217-
toolkit.print_line()
218-
toolkit.print(f"Using import string: [blue]{import_string}[/]", emoji="🐍")
219-
220-
toolkit.print_line()
221-
mod_source_desc = SOURCE_DESCRIPTIONS[import_data.module_config_source]
222-
app_source_desc = SOURCE_DESCRIPTIONS[import_data.app_name_config_source]
223-
toolkit.print("Configuration sources:", emoji="📋")
224-
if mod_source_desc == app_source_desc:
225-
toolkit.print(f"• Import string: {mod_source_desc}")
226-
else:
227-
toolkit.print(f"• Module: {mod_source_desc}")
228-
toolkit.print(f"• App name: {app_source_desc}")
233+
if verbose:
234+
toolkit.print_line()
235+
mod_source_desc = SOURCE_DESCRIPTIONS[import_data.module_config_source]
236+
app_source_desc = SOURCE_DESCRIPTIONS[import_data.app_name_config_source]
237+
toolkit.print("Configuration sources:", emoji="📋")
238+
if mod_source_desc == app_source_desc:
239+
toolkit.print(f"• Import string: {mod_source_desc}")
240+
else:
241+
toolkit.print(f"• Module: {mod_source_desc}")
242+
toolkit.print(f"• App name: {app_source_desc}")
229243

230-
if import_data.module_config_source == "auto-discovery":
244+
# Nudge to pin the entrypoint whenever it was auto-discovered, so it's
245+
# explicit next time — shown in the default output, not just --verbose
246+
if is_auto_discovery:
231247
toolkit.print_line()
232248
toolkit.print(
233249
"You can configure an entrypoint in [blue]pyproject.toml[/] for this app with:",
@@ -252,13 +268,6 @@ def _run(
252268
toolkit.print(f"Server started at [link={url}]{url}[/]", emoji="🌐")
253269
toolkit.print(f"Documentation at [link={url_docs}]{url_docs}[/]")
254270

255-
if command == "dev":
256-
toolkit.print_line()
257-
toolkit.print(
258-
"Running in development mode, for production use: [bold]fastapi run[/]",
259-
emoji="💡",
260-
)
261-
262271
if not uvicorn:
263272
raise FastAPICLIException(
264273
"Could not import Uvicorn, try running 'pip install uvicorn'"
@@ -356,6 +365,14 @@ def dev(
356365
help="Comma separated list of IP Addresses to trust with proxy headers. The literal '*' means trust everything."
357366
),
358367
] = None,
368+
verbose: Annotated[
369+
bool,
370+
typer.Option(
371+
"--verbose",
372+
"-v",
373+
help="Show detailed startup output and debug logs: how the [bold]FastAPI[/bold] app was discovered, imported, and configured.",
374+
),
375+
] = False,
359376
) -> Any:
360377
"""
361378
Run a [bold]FastAPI[/bold] app in [yellow]development[/yellow] mode. 🧪
@@ -395,6 +412,7 @@ def dev(
395412
proxy_headers=proxy_headers,
396413
forwarded_allow_ips=forwarded_allow_ips,
397414
public_url=os.getenv("FASTAPI_PUBLIC_URL"),
415+
verbose=verbose,
398416
)
399417

400418

@@ -464,6 +482,14 @@ def run(
464482
help="Comma separated list of IP Addresses to trust with proxy headers. The literal '*' means trust everything."
465483
),
466484
] = None,
485+
verbose: Annotated[
486+
bool,
487+
typer.Option(
488+
"--verbose",
489+
"-v",
490+
help="Show detailed startup output and debug logs: how the [bold]FastAPI[/bold] app was discovered, imported, and configured.",
491+
),
492+
] = False,
467493
) -> Any:
468494
"""
469495
Run a [bold]FastAPI[/bold] app in [green]production[/green] mode. 🚀
@@ -503,6 +529,7 @@ def run(
503529
proxy_headers=proxy_headers,
504530
forwarded_allow_ips=forwarded_allow_ips,
505531
public_url=os.getenv("FASTAPI_PUBLIC_URL"),
532+
verbose=verbose,
506533
)
507534

508535

0 commit comments

Comments
 (0)