Skip to main content

Command Line Interface

Flask provides a robust command-line interface (CLI) built on top of the Click library. You can extend this interface with custom commands, manage application context automatically, and organize commands within Blueprints.

Registering Commands to the Application

The most direct way to add a custom command is by using the @app.cli.command() decorator on a Flask application instance. Commands registered this way are automatically available when running the flask command.

from flask import Flask, current_app
import click

app = Flask(__name__)

@app.cli.command("hello")
@click.argument("name")
def hello_command(name):
"""Say hello to the user."""
click.echo(f"Hello, {name}! Running in {current_app.name}")

When you run flask hello world, Flask automatically loads the application and executes the command within an application context.

Grouping Commands

To organize related commands, use the AppGroup class. This class ensures that all commands within the group are executed within a Flask application context.

from flask.cli import AppGroup
import click

user_cli = AppGroup("user")

@user_cli.command("create")
@click.argument("username")
def create_user(username):
click.echo(f"Creating user: {username}")

app.cli.add_command(user_cli)

In this example, the command is invoked as flask user create <username>.

Blueprint-Specific Commands

Blueprints can also contribute commands to the CLI. By default, commands are placed in a group named after the blueprint. You can customize this using the cli_group parameter when creating the Blueprint.

from flask import Blueprint
import click

# Commands will be under the 'auth' group by default
auth_bp = Blueprint("auth", __name__)

@auth_bp.cli.command("login")
def login_command():
click.echo("Logging in...")

# Custom group name
custom_bp = Blueprint("custom", __name__, cli_group="customized")

@custom_bp.cli.command("run-task")
def task_command():
click.echo("Running custom task")

# Registering without a group (commands appear at the top level)
merged_bp = Blueprint("merged", __name__, cli_group=None)

@merged_bp.cli.command("top-level")
def top_level_command():
click.echo("Top level command from blueprint")

Application Context Management

Flask CLI commands often need access to current_app or other application-bound resources. Flask manages this using the with_appcontext decorator and the AppGroup class.

Automatic Context

Commands registered via app.cli.command() or within an AppGroup (including Blueprint.cli) are automatically wrapped in @with_appcontext. You do not need to add the decorator manually.

Manual Context for Standalone Commands

If you define a standalone Click command that is not registered to app.cli but still needs the application context, use the with_appcontext decorator.

from flask.cli import with_appcontext
from flask import current_app
import click

@click.command()
@with_appcontext
def standalone_cmd():
click.echo(f"Active app: {current_app.name}")

To run such a command, you must provide a ScriptInfo object to the Click context, which Flask uses to locate and load the application.

Custom CLI Executables

For advanced use cases, you can create a custom executable script using FlaskGroup. This is useful if you want to provide a specialized CLI tool for your application that behaves like the flask command but includes your own logic or defaults.

import click
from flask import Flask
from flask.cli import FlaskGroup

def create_app():
return Flask("my_custom_app")

@click.group(cls=FlaskGroup, create_app=create_app)
def cli():
"""Management script for my_custom_app."""
pass

if __name__ == "__main__":
cli()

FlaskGroup handles:

  • Loading the application via the create_app factory or FLASK_APP environment variable.
  • Supporting --app, --debug, and --env-file options.
  • Automatically loading commands from the app and any installed Flask plugins.

Troubleshooting and Gotchas

Application Discovery

If FLASK_APP is not set, the CLI searches for app.py or wsgi.py in the current directory. It uses locate_app to find an instance named app or application, or a factory named create_app or make_app.

Preventing Blocking Imports

When running from the CLI, Flask sets the environment variable FLASK_RUN_FROM_CLI="true". This is used to prevent app.run() from blocking the CLI if it is called outside of a if __name__ == "__main__": guard.

Dotenv Support

Flask automatically loads .env and .flaskenv files if python-dotenv is installed. You can skip this by setting FLASK_SKIP_DOTENV=1.

Command Execution Order

The FlaskGroup class evaluates --env-file and --app eagerly. This ensures that the application is loaded and its custom commands are available even when --help is requested. If you are implementing custom group logic, ensure you do not break this eager loading sequence.