Flask provides a command-line interface (CLI) built on Click for managing and running your application.
CLI Commands
run
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:
The interface to bind to. Use 0.0.0.0 to make the server publicly available.
--cert
path | 'adhoc' | SSLContext
Specify a certificate file to use HTTPS.
The key file to use when specifying a certificate.
Enable or disable the reloader. By default the reloader is active if debug is enabled.
Enable or disable the debugger. By default the debugger is active if debug is enabled.
--with-threads/--without-threads
Enable or disable multithreading.
Extra files that trigger a reload on change. Multiple paths are separated by the OS path separator.
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
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
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.
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
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:
--app option: flask --app myapp run
FLASK_APP environment variable: export FLASK_APP=myapp
- 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:
.flaskenv - Flask-specific variables, committed to version control
.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:
The import path for the Flask application.
A function that creates the application instance.
Whether to set the debug flag from environment.
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:
- Use Click decorators - Leverage Click’s powerful option/argument handling
- Provide help text - Always add docstrings to commands
- Group related commands - Organize commands into logical groups
- Use environment files - Keep configuration in .env files
- Handle errors gracefully - Provide clear error messages
- 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()