Python Briefcase Native Apps — Core Concepts

What Briefcase solves

Most Python packaging tools (PyInstaller, cx_Freeze) produce standalone executables but not true platform-native packages. Briefcase goes further — it creates MSI installers, macOS app bundles, Flatpaks, APKs, and Xcode projects that follow each platform’s distribution conventions.

The BeeWare ecosystem

Briefcase is one piece of a larger toolkit:

  • Toga — a native widget toolkit (uses Cocoa on macOS, GTK on Linux, Winforms on Windows, Android views on Android)
  • Briefcase — project scaffolding, building, and packaging
  • Rubicon — bridges to Objective-C (macOS/iOS) and Java (Android) runtimes

You can use Briefcase with any GUI framework (Tkinter, PyQt, Kivy), but it works best with Toga for truly native-looking apps.

Creating a new project

pip install briefcase
briefcase new

The interactive wizard asks for app name, description, author, license, and GUI toolkit. It generates a project structure:

myapp/
├── pyproject.toml      # project configuration
├── src/
│   └── myapp/
│       ├── __init__.py
│       ├── __main__.py
│       ├── app.py       # main application code
│       └── resources/
│           └── icon.png

The development workflow

Briefcase provides a consistent set of commands:

CommandPurpose
briefcase devRun in development mode (no packaging)
briefcase createScaffold platform-specific project files
briefcase buildCompile and prepare the platform build
briefcase runBuild and launch the app
briefcase packageCreate distributable installer
briefcase updateSync code changes into existing build

The typical flow: develop with briefcase dev, then briefcase run to test the native build, and briefcase package for distribution.

Configuration in pyproject.toml

[tool.briefcase]
project_name = "My App"
bundle = "com.example"
version = "1.0.0"
requires = ["toga>=0.4.0", "httpx"]

[tool.briefcase.app.myapp]
formal_name = "My App"
description = "A sample Toga application"
sources = ["src/myapp"]

[tool.briefcase.app.myapp.macOS]
requires = ["toga-cocoa>=0.4.0"]

[tool.briefcase.app.myapp.windows]
requires = ["toga-winforms>=0.4.0"]

[tool.briefcase.app.myapp.linux]
requires = ["toga-gtk>=0.4.0"]
system_requires = ["libgirepository1.0-dev"]

[tool.briefcase.app.myapp.android]
requires = ["toga-android>=0.4.0"]

[tool.briefcase.app.myapp.iOS]
requires = ["toga-iOS>=0.4.0"]

Platform-specific sections let you add OS-specific dependencies, permissions, and build settings.

Platform outputs

PlatformOutput formatDistribution method
macOS.app bundle, .dmgDirect download, notarization for Gatekeeper
WindowsMSI installerDirect download, Windows Store (possible)
LinuxFlatpak, AppImage, SnapFlathub, direct download
AndroidAPK / AABGoogle Play Store, sideloading
iOSXcode projectApp Store via Xcode
WebStatic filesBrowser deployment (experimental)

A minimal Toga application

import toga
from toga.style import Pack
from toga.style.pack import COLUMN, ROW

class MyApp(toga.App):
    def startup(self):
        main_box = toga.Box(style=Pack(direction=COLUMN, padding=10))

        name_input = toga.TextInput(placeholder="Your name",
                                     style=Pack(flex=1))
        button = toga.Button("Say Hello",
                             on_press=lambda w: self.greet(name_input.value),
                             style=Pack(padding_top=10))
        self.label = toga.Label("", style=Pack(padding_top=10))

        main_box.add(name_input, button, self.label)
        self.main_window = toga.MainWindow(title=self.formal_name)
        self.main_window.content = main_box
        self.main_window.show()

    def greet(self, name):
        self.label.text = f"Hello, {name}!"

def main():
    return MyApp()

This renders with native Cocoa widgets on macOS, WinForms on Windows, and GTK on Linux — the same code, truly native appearance.

Common misconception

“Briefcase is just another PyInstaller alternative.”

PyInstaller creates standalone executables. Briefcase creates complete platform-native packages — MSI installers, app bundles with proper Info.plist, Flatpaks with desktop integration, and APKs with Android manifests. It handles icons, splash screens, permissions, and signing — the full distribution story, not just the executable.

One thing to remember: Briefcase is a complete app lifecycle tool — from project scaffolding through native packaging — that makes Python apps first-class citizens on every major platform.

pythonbriefcasebeewarenativepackaging

See Also

  • Python Appimage Distribution An AppImage is like a portable app on a USB stick — download one file, double-click it, and your Python program runs on any Linux computer without installing anything.
  • Python Flatpak Packaging Flatpak wraps your Python app in a safe bubble that works on every Linux system — like a snow globe that keeps your program perfect inside.
  • Python Mypyc Compilation Your type hints are not just for documentation — mypyc turns them into speed boosts by compiling typed Python into fast C extensions.
  • Python Nuitka Compilation What if your Python code could run as fast as a race car instead of a bicycle? Nuitka translates Python into C to make that happen.
  • Python Pex Executables Imagine zipping your entire Python project into a single magic file that runs anywhere Python lives — that's what PEX does.