Apps, Stubs, and entrypoints

An App is the object that represents an application running on Modal. Every other object in Modal is attached to some App, including Functions, Secrets, and Images. When you run or deploy an App, it creates an ephemeral or a deployed App, respectively.

You can view a list of all currently running Apps on the apps page.

Apps were once Stubs

The App class in the client was previously called Stub. Both names are still supported, but Stub is an alias for App and will not be supported at some point in the future.

Ephemeral Apps

An ephemeral App is created when you use the modal run CLI command, or the app.run method. This creates a temporary App that only exists for the duration of your script.

Ephemeral Apps are stopped automatically when the calling program exits, or when the server detects that the client is no longer connected. You can use --detach in order to keep an ephemeral App running even after the client exits.

By using app.run you can run your Modal apps from within your Python scripts:

def main():
    ...
    with app.run():
        some_modal_function.remote()

Deployed Apps

A deployed App is created using the modal deploy CLI command. The App is persisted indefinitely until you delete it via the web UI. Functions in a deployed App that have an attached schedule will be run on a schedule. Otherwise, you can invoke them manually using web endpoints or Python.

Deployed Apps are named via the App constructor. Re-deploying an existing App (based on the name) will update it in place.

Entrypoints for ephemeral Apps

The code that runs first when you modal run an App is called the “entrypoint”.

You can register a local entrypoint using the @app.local_entrypoint() decorator. You can also use a regular Modal function as an entrypoint, in which case only the code in global scope is executed locally.

Argument parsing

If your entrypoint function takes arguments with primitive types, modal run automatically parses them as CLI options. For example, the following function can be called with modal run script.py --foo 1 --bar "hello":

# script.py

@app.local_entrypoint()
def main(foo: int, bar: str):
    some_modal_function.remote(foo, bar)

You can also use your own argument parsing library, such as argparse and use app.run to run your app manually. Note that in this case you need to invoke your script as you would invoke any other python script, e.g. with python script.py --foo 1 --bar "hello".

import modal
import argparse

app = modal.App()


@app.function()
def func(a, b):
    print(f"a={a}, b={b}")


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--foo", type=int)
    parser.add_argument("--bar", type=str)
    args = parser.parse_args()

    with app.run():
        func.remote(args.foo, args.bar)

Manually specifying an entrypoint

If there is only one local_entrypoint registered, modal run script.py will automatically use it. If you have no entrypoint specified, and just one decorated Modal function, that will be used as a remote entrypoint instead. Otherwise, you can direct modal run to use a specific entrypoint.

For example, if you have a function decorated with @app.function() in your file:

# script.py

@app.function()
def f():
    print("Hello world!")


@app.function()
def g():
    print("Goodbye world!")


@app.local_entrypoint()
def main():
    f.remote()

Running modal run script.py will execute the main function locally, which would call the f function remotely. However you can instead run modal run script.py::app.f or modal run script.py::app.g to execute f or g directly.