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.3intentionally (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
.pyscript (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:
- Open the project
- Change the Target dropdown in the chat panel
- 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) —
QMainWindowwithQListWidgetfor the playlist,QMediaPlayerfor playback, full menu bar, dockable now-playing panel - Mobile (Flet) —
ft.Pagewith aListViewof tracks, bottomNavigationBar,ft.Audiocontrol wired to a slider, phone-sized layout - Basic (CustomTkinter) —
CTkroot window with aCTkFramefor the playlist,CTkButtoncontrols,pygame.mixerfor audio (Tk doesn't include audio) - General Python —
mpvorvlcCLI wrapper with argparse forplay,pause,queuecommands, 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¶
- Your First Project — if you haven't created one yet, start here
- Mobile Builds — the full Flet / APK workflow if you picked Mobile
- Multi-file Projects — how Whittl handles splits across files (applies to all targets)
- Building an Installer — turning a finished project into a shippable
.exe/.AppImage/.apk