Skip to content

Choosing a Target

Whittl generates code for four different targets. The target decides which framework the AI writes against, which build outputs are available, and what your Test Run looks like. Picking the right one up front saves iteration later — switching targets mid-project usually means regenerating most of the code.

This page is the decision reference. If you already know you want a desktop app, pick Desktop (PySide6) and move on. If you're not sure, read the decision tree below.

Quick decision

Answer one question:

What are you building?

  • A desktop app for Windows or Linux. Use Desktop (PySide6). This is the default for a reason — it's the most polished, best-tested, and has the richest native widget set.
  • An Android app. Use Mobile (Flet). Experimental but working. Builds a signed APK with one click.
  • A very simple GUI that needs a small binary and fast startup. Use Basic (CustomTkinter). Lighter than PySide6, ships smaller installers.
  • A CLI tool, script, plugin, or anything without a window. Use General Python. No framework, no GUI, just clean Python with argparse / logging / pathlib.

Comparison table

Target Framework Platforms Build output Typical binary size Maturity
Desktop (PySide6) PySide6 / Qt 6 Windows, Linux .exe + Inno installer, AppImage 80 – 120 MB Production-ready
Mobile (Flet) Flet 0.28.3 Android (APK) Signed .apk 30 – 60 MB Experimental
Basic (CustomTkinter) CustomTkinter / Tk Windows, Linux .exe + Inno installer, AppImage 15 – 25 MB Production-ready
General Python None (pure Python) Windows, Linux, anywhere Python runs .exe console build, .py scripts 10 – 30 MB Production-ready

When to use each target

Desktop (PySide6)

Pick PySide6 when you're building a real desktop app. This is what Whittl itself is written in. It's the default target and the one the AI has the most skill at generating.

Strengths:

  • Richest native widget set — tables, trees, splitters, dockable panels, menus, toolbars, system tray, file dialogs, drag-and-drop, all first-class
  • Full styling via QSS (Qt's CSS dialect), including themes and custom controls
  • Built-in support for multimedia, networking, SVG, charts, OpenGL, printing
  • Mature ecosystem with decades of Qt tooling behind it
  • Whittl's auto-fix rules and skills library are deepest for PySide6 — the AI makes the fewest mistakes on this target

Weaknesses:

  • Larger binary size (PyInstaller bundles pull in all of Qt)
  • Slightly slower cold-start than Tk-based apps
  • LGPL license — fine for commercial use, but worth knowing about

Pick Desktop (PySide6) when: you're building anything that needs a window, especially anything with non-trivial UI complexity (multiple panels, tables, custom widgets, drag-and-drop, etc.).

Typical projects: IDEs, note-taking apps, media players, image editors, database viewers, dashboards, Whittl-class tools.

Mobile (Flet)

Pick Flet when you want a mobile app built from Python without leaving the Python ecosystem. Flet wraps Flutter under the hood, so your Python code becomes a Flutter app that renders native controls on the target device.

Strengths:

  • No Android Studio, no JDK, no Gradle — Whittl downloads all the build tools automatically on first APK build
  • One-click APK builds signed and ready to install
  • ADB integration for pushing to a connected device with Install to Device
  • Same codebase can (in theory) target iOS, desktop, and web — though Whittl's current support is Android-first

Weaknesses:

  • Experimental. Works but expect device-specific quirks on some Android versions or OEM skins
  • Flet's control set is smaller than Qt's — fewer native widgets, styling is more opinionated
  • Pinned to Flet 0.28.3 intentionally (newer versions regressed Whittl's template chain; this will be re-evaluated in a future release)
  • First build downloads ~200 MB of toolchain (one-time, cached)

Pick Mobile (Flet) when: you specifically want an Android APK. Don't pick it for desktop or for "maybe mobile later" — use PySide6 and port later if mobile becomes a real requirement.

Typical projects: phone-first utilities, mobile companion apps for services you already run, dashboards you want on your phone, small games.

See Mobile Builds for the full APK build workflow, device installation steps, and known limitations.

Basic (CustomTkinter)

Pick CustomTkinter when you want a GUI but don't need Qt's full surface area. CustomTkinter is a modern, themed wrapper on top of Python's built-in Tk — so binaries are small and startup is fast.

Strengths:

  • Smallest GUI binary footprint of the three desktop targets (15 – 25 MB vs PySide6's 80 – 120 MB)
  • Fast cold-start — Tk is lightweight compared to Qt
  • Modern theming (dark mode, rounded corners, CTk widgets look current rather than 1998)
  • Simpler API for straightforward forms, dashboards, utilities
  • No Qt licensing to think about — Tk ships with CPython

Weaknesses:

  • Widget set is narrower than Qt — no native table view, no dock widgets, less sophisticated styling
  • Less mature than PySide6 in the Whittl ecosystem (fewer auto-fix rules, shallower skills)
  • Tk's threading model is stricter than Qt's — long operations need careful backgrounding
  • Custom widgets are harder to build than in Qt

Pick Basic (CustomTkinter) when: you want a simple, small, fast-starting GUI and you don't need tables, docks, or heavy styling. Good for utilities, converters, calculators, configuration editors, small tools.

Typical projects: file renamers, unit converters, color pickers, launchers, settings editors, single-purpose utilities.

General Python

Pick General Python when there's no GUI at all, OR when you're writing a plugin / add-on that runs inside another application's Python runtime (Blender, Maya, Krita, FreeCAD, Houdini, Nuke). This is the target for CLI tools, automation scripts, background processes, plugins for other apps, data processing pipelines, API clients — anything that runs in a terminal or is loaded as a library by another host.

Blender plugins specifically are a sweet spot: Blender embeds its own Python, expects a single .py file (or folder) with specific module structure, and your code calls into bpy / bmesh / mathutils. General Python target keeps Whittl out of the way — no framework scaffolding, no Test Run window, just clean Python that Blender can load directly from the Add-ons panel.

Strengths:

  • No framework overhead — the AI writes clean Python with argparse, pathlib, logging, click, typer, etc. where appropriate
  • Smallest binaries when built with PyInstaller console mode
  • Easiest to ship as a .py script (no compilation needed) — users with Python installed just run it
  • Easiest to test — no Qt event loop, no Tk mainloop, just functions
  • Cleanest output in the terminal tab (stdout / stderr pipe straight through, no hidden console window)
  • Works as a plugin host language — Blender, Krita, Maya, Houdini, GIMP, Inkscape all embed Python; General Python output drops straight in

Weaknesses:

  • No GUI — if you change your mind and want one, you're regenerating the whole project

Pick General Python when: you're building a CLI, an automation script, a data pipeline, a plugin for Blender / Maya / Krita / Houdini / FreeCAD, an API client, a scheduled task, or anything library-shaped.

Typical projects: Blender add-ons (mesh generators, custom shaders, export scripts), CLI tools, backup scripts, scrapers, API wrappers, image batch-processors, automation bots, cron-style jobs, Krita Python plugins, Maya utility scripts.

Switching targets mid-project

Changing the target after generation is usually a full regeneration. The existing code is framework-specific — a PySide6 app's main.py doesn't port to Flet or CustomTkinter by changing one line.

If you know a project might eventually need to be mobile, it's better to start on Mobile (Flet) from day one than to write it in PySide6 first and plan to port. Flet constrains you up front in ways that keep the port viable.

That said, target-switching is a supported operation:

  1. Open the project
  2. Change the Target dropdown in the chat panel
  3. Ask the AI to "regenerate this as a \<new target> app"

The AI will generate fresh code for the new target. Existing files you want to keep (assets, data, non-framework utility modules) can be preserved manually.

What the AI generates differently per target

A prompt like "make a music player" produces different code depending on the target:

  • Desktop (PySide6)QMainWindow with QListWidget for the playlist, QMediaPlayer for playback, full menu bar, dockable now-playing panel
  • Mobile (Flet)ft.Page with a ListView of tracks, bottom NavigationBar, ft.Audio control wired to a slider, phone-sized layout
  • Basic (CustomTkinter)CTk root window with a CTkFrame for the playlist, CTkButton controls, pygame.mixer for audio (Tk doesn't include audio)
  • General Pythonmpv or vlc CLI wrapper with argparse for play, pause, queue commands, no window at all

The AI picks target-appropriate libraries and patterns automatically. You don't need to specify "use QMediaPlayer" — it reads the target and picks.

What's next