Skip to main content
Flask provides a command-line interface (CLI) built on Click for managing and running your application.

CLI Commands

run

flask run [OPTIONS]
Run a local development server.
This server is for development purposes only. It does not provide the stability, security, or performance of production WSGI servers.
Options:
--host
str
default:"127.0.0.1"
The interface to bind to. Use 0.0.0.0 to make the server publicly available.
--port
int
default:"5000"
The port to bind to.
--cert
path | 'adhoc' | SSLContext
Specify a certificate file to use HTTPS.
--key
path
The key file to use when specifying a certificate.
--reload/--no-reload
bool
Enable or disable the reloader. By default the reloader is active if debug is enabled.
--debugger/--no-debugger
bool
Enable or disable the debugger. By default the debugger is active if debug is enabled.
--with-threads/--without-threads
bool
default:"True"
Enable or disable multithreading.
--extra-files
str
Extra files that trigger a reload on change. Multiple paths are separated by the OS path separator.
--exclude-patterns
str
Files matching these fnmatch patterns will not trigger a reload on change.
Examples:
# Basic usage
flask run

# Run on all interfaces
flask run --host=0.0.0.0

# Custom port
flask run --port=8000

# Enable debug mode
flask --debug run

# With HTTPS
flask run --cert=cert.pem --key=key.pem

# Ad-hoc SSL certificate (requires cryptography)
flask run --cert=adhoc

# Watch additional files for reload
flask run --extra-files=config.yaml:static/styles.css

# Disable reloader
flask run --no-reload

shell

flask shell
Run an interactive Python shell in the context of the Flask application. The application will populate the default namespace with useful objects. Default Context:
  • app - The Flask application instance
  • g - The global context object
  • Additional objects from app.make_shell_context()
Example:
$ flask shell
Python 3.11.0 on linux
App: myapp
Instance: /path/to/instance
>>> app.config['DEBUG']
True
>>> from myapp.models import User
>>> User.query.all()
[<User 1>, <User 2>]

routes

flask routes [OPTIONS]
Show all registered routes with endpoints and methods. Options:
--sort
'endpoint' | 'methods' | 'domain' | 'rule' | 'match'
default:"endpoint"
Method to sort routes by. ‘match’ is the order that Flask will match routes when dispatching a request.
--all-methods
bool
Show HEAD and OPTIONS methods.
Example:
$ flask routes
Endpoint      Methods    Rule
-----------   -------    ------------------
index         GET        /
user.profile  GET        /user/<username>
api.users     GET,POST   /api/users
static        GET        /static/<path:filename>

# Sort by rule
$ flask routes --sort=rule

# Show all methods including HEAD and OPTIONS  
$ flask routes --all-methods

CLI Options

—app

flask --app IMPORT [COMMAND]
The Flask application or factory function to load, in the form ‘module:name’. Format:
  • module:name - Load the name object from module
  • module:name(args) - Call name with arguments
  • module - Auto-discover app in module (looks for app, application, create_app, make_app)
  • path/to/file.py - Load from file path
Examples:
# Load app from module attribute
flask --app myapp:app run

# Load from factory function
flask --app myapp:create_app run

# Call factory with arguments
flask --app "myapp:create_app('development')" run

# Auto-discover
flask --app myapp run

# Load from file
flask --app path/to/app.py run

—debug

flask --debug [COMMAND]
flask --no-debug [COMMAND]
Set debug mode. When enabled, the reloader and debugger are active by default. Example:
# Enable debug mode
flask --debug run

# Disable debug mode
flask --no-debug run

—env-file

flask --env-file PATH [COMMAND]
Load environment variables from this file. Takes precedence over .env and .flaskenv files. Example:
# Load from custom env file
flask --env-file .env.development run

# Load production config
flask --env-file .env.production run

—version

flask --version
Show the Flask version. Example:
$ flask --version
Python 3.11.0
Flask 3.0.0
Werkzeug 3.0.0

Custom Commands

Creating Commands

Create custom CLI commands using the @app.cli.command() decorator:
import click
from flask import Flask

app = Flask(__name__)

@app.cli.command()
def init_db():
    """Initialize the database."""
    db.create_all()
    click.echo('Database initialized.')

@app.cli.command()
@click.argument('name')
def greet(name):
    """Greet a user."""
    click.echo(f'Hello, {name}!')

@app.cli.command()
@click.option('--count', default=1, help='Number of users to create.')
def create_users(count):
    """Create test users."""
    for i in range(count):
        user = User(username=f'user{i}')
        db.session.add(user)
    db.session.commit()
    click.echo(f'Created {count} users.')
Usage:
flask init-db
flask greet John
flask create-users --count=10

Command Groups

Organize commands into groups:
import click
from flask import Flask

app = Flask(__name__)

@app.cli.group()
def user():
    """User management commands."""
    pass

@user.command()
def create():
    """Create a new user."""
    click.echo('User created.')

@user.command()
@click.argument('username')
def delete(username):
    """Delete a user."""
    click.echo(f'User {username} deleted.')

@app.cli.group()
def db():
    """Database management commands."""
    pass

@db.command()
def init():
    """Initialize the database."""
    db.create_all()
    click.echo('Database initialized.')

@db.command()
def seed():
    """Seed the database with sample data."""
    create_sample_data()
    click.echo('Database seeded.')
Usage:
flask user create
flask user delete john
flask db init
flask db seed

with_appcontext Decorator

from flask.cli import with_appcontext

@click.command()
@with_appcontext
def my_command():
    """A command that needs app context."""
    # App context is available here
    current_app.config['SETTING']
The @with_appcontext decorator ensures the command runs with an application context. Commands registered with @app.cli.command() automatically have this.

AppGroup Class

from flask.cli import AppGroup

user_cli = AppGroup('user', help='User management commands.')

@user_cli.command('create')
@click.argument('username')
def create_user(username):
    """Create a new user."""
    user = User(username=username)
    db.session.add(user)
    db.session.commit()
    click.echo(f'Created user: {username}')

@user_cli.command('list')
def list_users():
    """List all users."""
    users = User.query.all()
    for user in users:
        click.echo(user.username)

app.cli.add_command(user_cli)
Usage:
flask user create john
flask user list

Application Discovery

Flask discovers your application using these methods in order:
  1. --app option: flask --app myapp run
  2. FLASK_APP environment variable: export FLASK_APP=myapp
  3. Auto-discovery in current directory:
    • Look for wsgi.py or app.py
    • Find app or application variable
    • Find create_app or make_app factory function

Factory Functions

Factory functions are automatically detected and called:
# myapp.py
def create_app():
    app = Flask(__name__)
    # Configure app
    return app

# No arguments needed
def create_app(config=None):
    app = Flask(__name__)
    if config:
        app.config.from_object(config)
    return app
Usage:
# Auto-discover and call create_app()
flask --app myapp run

# Call with arguments
flask --app "myapp:create_app('development')" run

Environment Configuration

.flaskenv and .env Files

Flask automatically loads environment variables from these files:
  1. .flaskenv - Flask-specific variables, committed to version control
  2. .env - Secret values, not committed to version control
Requires the python-dotenv package to be installed.
Example .flaskenv:
FLASK_APP=myapp
FLASK_DEBUG=1
FLASK_RUN_PORT=8000
FLASK_RUN_HOST=0.0.0.0
Example .env:
SECRET_KEY=your-secret-key
DATABASE_URL=postgresql://localhost/mydb
API_KEY=your-api-key

Environment Variables

Common Flask environment variables:
  • FLASK_APP - Application to load
  • FLASK_DEBUG - Enable debug mode (1, true, yes)
  • FLASK_RUN_HOST - Host to bind to
  • FLASK_RUN_PORT - Port to bind to
  • FLASK_RUN_CERT - Certificate for HTTPS
  • FLASK_RUN_KEY - Key for HTTPS
  • FLASK_SKIP_DOTENV - Skip loading .env files (1, true, yes)

ScriptInfo Class

class ScriptInfo:
    def __init__(
        self,
        app_import_path: str | None = None,
        create_app: Callable[..., Flask] | None = None,
        set_debug_flag: bool = True,
        load_dotenv_defaults: bool = True
    )
Helper object to deal with Flask applications in the CLI. Usually created automatically by FlaskGroup. Attributes:
app_import_path
str | None
The import path for the Flask application.
create_app
Callable | None
A function that creates the application instance.
set_debug_flag
bool
default:"True"
Whether to set the debug flag from environment.
load_dotenv_defaults
bool
default:"True"
Whether to load default .env files.
Methods:
def load_app() -> Flask:
    """Load and return the Flask application."""

FlaskGroup Class

class FlaskGroup(AppGroup):
    def __init__(
        self,
        add_default_commands: bool = True,
        create_app: Callable[..., Flask] | None = None,
        add_version_option: bool = True,
        load_dotenv: bool = True,
        set_debug_flag: bool = True,
        **extra: Any
    )
Special Click group that supports loading commands from the configured Flask app. Example:
import click
from flask import Flask
from flask.cli import FlaskGroup

def create_app():
    return Flask(__name__)

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

if __name__ == '__main__':
    cli()

Best Practices

Recommendations:
  1. Use Click decorators - Leverage Click’s powerful option/argument handling
  2. Provide help text - Always add docstrings to commands
  3. Group related commands - Organize commands into logical groups
  4. Use environment files - Keep configuration in .env files
  5. Handle errors gracefully - Provide clear error messages
  6. Use color and formatting - Make output easy to read with click.echo() and click.style()
Example:
import click
from flask import Flask

app = Flask(__name__)

@app.cli.group()
def db():
    """Database management commands."""
    pass

@db.command()
@click.option('--drop', is_flag=True, help='Drop existing tables.')
@click.confirmation_option(prompt='Are you sure you want to initialize the database?')
def init(drop):
    """Initialize the database."""
    if drop:
        db.drop_all()
        click.secho('Dropped all tables.', fg='yellow')
    
    db.create_all()
    click.secho('Database initialized successfully!', fg='green')

@db.command()
@click.argument('filename', type=click.Path(exists=True))
def load(filename):
    """Load data from a file."""
    try:
        with open(filename) as f:
            data = json.load(f)
        # Process data
        click.secho(f'Loaded {len(data)} records.', fg='green')
    except Exception as e:
        click.secho(f'Error: {e}', fg='red', err=True)
        raise click.Abort()

Build docs developers (and LLMs) love