Skip to main content

Defining Commands with Application Context

To create custom CLI commands that automatically have access to the Flask application context (allowing you to use current_app, g, or database connections), use the AppGroup class.

Registering Commands on the Application

The most direct way to define commands with application context is to use the cli attribute of your Flask instance. This attribute is an instance of AppGroup, which automatically wraps every command in with_appcontext.

from flask import Flask, current_app

app = Flask(__name__)

@app.cli.command("check-config")
def check_config():
# current_app is automatically available here
click.echo(f"Checking config for: {current_app.name}")
click.echo(f"Debug mode: {current_app.config['DEBUG']}")

Registering Commands on Blueprints

When organizing commands within a Blueprint, use the blueprint's cli attribute. These commands will be nested under the blueprint's name (or the cli_group name if provided) and will also automatically run within the application context.

from flask import Blueprint

# The cli_group parameter determines the command prefix
bp = Blueprint("db", __name__, cli_group="database")

@bp.cli.command("init")
def init_db():
# This command is accessible as 'flask database init'
# and has full access to the app context.
click.echo("Initializing database...")

Creating a Standalone AppGroup

If you need to create a custom group of commands outside of a specific Flask or Blueprint instance, you can use AppGroup directly with click.

import click
from flask.cli import AppGroup
from flask import current_app

@click.group(cls=AppGroup)
def tools():
"""Custom management tools."""
pass

@tools.command("info")
def get_info():
# Automatically wrapped in with_appcontext
click.echo(f"Running tool for {current_app.name}")

Opting Out of Application Context

If you have a command within an AppGroup that does not require the application context (e.g., a command that only prints version info or performs local file operations), you can disable the automatic wrapping by passing with_appcontext=False to the decorator.

@app.cli.command("version", with_appcontext=False)
def print_version():
# This command runs without loading the Flask application
click.echo("CLI Version 1.0")

Troubleshooting: App Loading Failures

When using AppGroup (especially standalone ones), Flask relies on ScriptInfo to find and load your application. If your command fails with an error indicating the application could not be found:

  1. Check Environment Variables: Ensure FLASK_APP is set to the correct entry point.
  2. Verify ScriptInfo: If you are invoking the CLI manually (e.g., in a test or custom runner), ensure you pass a ScriptInfo object in the click context.
# Example of manual invocation in tests/test_cli.py
from flask.cli import ScriptInfo

obj = ScriptInfo(create_app=lambda: Flask("testapp"))
runner.invoke(tools, ["info"], obj=obj)

If with_appcontext is active but the app cannot be loaded, the command will fail before execution. Use with_appcontext=False for commands that must run even when the application is misconfigured.