Skip to content

Your First Project

This page walks you end-to-end from a fresh Whittl install to a running generated app. About five minutes. Assumes you've installed Whittl and configured at least one backend.

Create the project

Click + New in the Projects panel (left side). The New Project dialog appears with four tabs:

  • Blank — start from an empty project.
  • Utilities / Productivity / Games / Media — pre-built templates with starter code. Useful for getting oriented; we'll skip them for this walkthrough.
  • My Templates — your own saved templates from previous projects.

Pick Blank, give the project a name like "todo", leave the default target as Desktop (PySide6), and click Create.

Whittl creates a project folder at ~/.whittl/projects/todo_<random_id>/, opens an empty main.py in the code editor, and drops you into the chat panel with an empty prompt.

Why the random ID

Each project folder is suffixed with a short random hash (todo_27176a00) so two projects with the same name don't collide. The name shown in the sidebar is the human-readable one; the ID is used internally.

Generate the first version

In the chat input, type:

Make me a simple todo list app. The user can type a task in a text box, hit Enter or click Add, and the task appears in a list below. Each item has a checkbox to mark it done and an X button to remove it. Save the list to a JSON file in the project folder so it persists between runs.

Click Generate (or press Ctrl+Enter).

What happens, in sequence:

  1. The planner decides the action. You'll see a brief status: Action: generate_code. The planner classified your prompt as a fresh generation, not a modification of existing code.
  2. Skills are injected into the system prompt. Whittl's skill library contributes PySide6-specific guidance (how to use signals, how to wire QListWidget, avoid common threading mistakes). You'll see a log line like [SKILLS] Injected 8058 chars into system prompt: [...].
  3. The AI streams the code back. The code editor fills in character-by-character. For a single-file project this happens in one tab; for multi-file, tabs appear as the AI writes each file.
  4. Auto-fix runs. Regex-based fixers catch common mistakes (trailing whitespace, missing newlines, Qt enum bugs, missing imports). You'll see [AUTO-FIX] Applied N automatic fixes if anything was corrected.
  5. Safety validation runs. The generated code is parsed as Python and structurally validated before being written to disk.

On a cloud backend (Gemini Flash, Claude Haiku, cheap OpenRouter model), typical time: 10-30 seconds. On Ollama locally: 30-120 seconds depending on model and hardware.

Review the generated code

When generation finishes, the code editor shows the result. For the todo app prompt above, you'll typically see a single-file main.py with:

  • A QMainWindow subclass as the app's main window
  • A QLineEdit + QPushButton row for adding tasks
  • A QListWidget for the task list, with custom widgets per row containing a checkbox, a label, and an X button
  • Load and save helpers that read/write todo.json in the project folder
  • if __name__ == "__main__": boilerplate to launch the app

Skim it. You don't need to understand every line to run it — but noticing how the app is structured makes follow-up prompts more precise.

Don't edit yet

Resist the urge to manually edit the generated code on your first project. Use chat follow-ups to iterate — Whittl's skill system and auto-fix are designed to act on AI-written code. Once you're comfortable, hand-edits are fine and Whittl handles the diff.

Run it

Click Test Run in the bottom-right (or press F5).

Whittl:

  1. Detects imports in the code (PyQt6 / PySide6 etc.) and installs missing packages into the bundled Python runtime.
  2. Writes all project files to the project folder.
  3. Launches the app using _whittl_launcher.py (a wrapper that handles logging and error capture).

The generated todo app window should appear. Type a task, hit Enter, watch it appear in the list. Check the box, X a task, close the window. Reopen by clicking Test Run again — your list should persist.

What the Test Run button actually does

Test Run launches the app in a fresh subprocess with a special QT_QPA_PLATFORM=offscreen flag briefly at startup so it doesn't flash a visible window during the initial smoke test. If the smoke test passes, the app is relaunched in normal visible mode. If the smoke test fails with an error, Whittl's auto-fix kicks in to try to patch the code before showing you the error.

Iterate

Say the task items are hard to read. Back in chat:

Make the task text bigger and add a bit of padding between items.

Click Generate again. This time the planner recognizes the prompt as a modification of existing code. Whittl uses surgical editing through tool calls instead of regenerating the whole file — the AI reads the current code, identifies the few lines that need changing, and emits a targeted edit.

You'll see log entries like:

[EDIT] edit_code: main.py at line 47 (stylesheet)
[EDIT] edit_code: main.py at line 52 (spacing)

The editor updates in place. Hit Test Run again, the app restarts with the fix.

Typical cost for a small modification on Claude Haiku or OpenRouter Qwen: $0.001 - $0.01. Way cheaper than a full regeneration.

Build an executable

When you're happy with the app, turn it into a standalone .exe (Windows) or AppImage (Linux):

  1. Click Download (F3) in the bottom-right.
  2. The Build Executable dialog opens. Leave the defaults (or pick a custom icon), click Build.
  3. Whittl uses PyInstaller to bundle your code + the Python runtime + all dependencies into a single file. Takes 1-3 minutes.
  4. When done, the Build Output path opens in your file manager. You have a shippable app.

The resulting executable is fully standalone — you can send it to someone with no Python and no Whittl installed and it'll run.

Where to go from here

  • Want to try Screenshot to App — rebuild an existing UI from a screenshot
  • Want to learn about Skills — teach Whittl patterns it should remember
  • Want to understand Agent Mode — let a capable model iterate fully autonomously
  • Want a deeper backend comparison — see Choosing a Backend