TURRRBO
A desktop application for generating images from StyleGAN2 latent space. Point it at a seed. Adjust truncation. Explore what the model learned. No cloud. No subscription. No internet required.
What is TURRRBO?
TURRRBO is a desktop tool for artists, designers, and image experimenters. It wraps StyleGAN2 — a generative neural network architecture developed by NVIDIA — in a native macOS application that is focused on exploration and iteration rather than photorealism.
The value of the app comes from its model catalog, its parameter controls, and its style route system — a set of named artistic presets that bend the model's output toward specific aesthetic behaviors without requiring you to understand the underlying math.
What makes it different?
What TURRRBO is
- A latent space navigator
- A model behavior explorer
- An art tool for unexpected outputs
- A local, offline application
- A catalog of trained visual behaviors
What TURRRBO is not
- A text-to-image system like Stable Diffusion
- A photorealistic image generator
- A cloud service
- A commercial tool
- A fine-tuning or training platform
Installation
TURRRBO ships as a self-contained macOS app. Everything — Python backend, model weights, and the UI — is bundled inside the .app.
System Requirements
| Component | Requirement |
|---|---|
| OS | macOS 12 Monterey or later |
| Chip | Apple Silicon (M1/M2/M3) recommended · Intel supported |
| RAM | 8 GB minimum · 16 GB recommended for 1024px models |
| Disk | ~3 GB for the full app with all models |
| GPU | MPS (Apple GPU) used automatically · CPU fallback available |
Install the App
Download the .app from the releases page. Drag it to your Applications folder. On first launch, macOS may show a security warning — right-click the app and choose Open to bypass Gatekeeper.
Developer Setup (from source)
If you are building from source rather than using the bundled app, you need to set up the development environment:
# 1. Clone StyleGAN2-ADA-PyTorch into vendor/ git clone https://github.com/NVlabs/stylegan2-ada-pytorch.git backend/vendor/stylegan2 # 2. Create Python virtual environment python3 -m venv backend/.venv # 3. Install dependencies backend/.venv/bin/pip install torch torchvision fastapi uvicorn pydantic pillow numpy requests backend/.venv/bin/pip install "numpy<2.0" # required — StyleGAN2 uses numpy 1.x API backend/.venv/bin/pip install git+https://github.com/openai/CLIP.git # optional: for text prompts # 4. Download model checkpoints backend/.venv/bin/python3 scripts/download_models.py # 5. Install Node dependencies npm install
npm run tauri:dev
Available Models
The following pretrained checkpoints are downloaded by default:
| ID | Name | Resolution | Size |
|---|---|---|---|
| ffhq_1024 | Synthetic Portraits | 1024px | 329 MB |
| metfaces_1024 | Museum Wreckage | 1024px | 329 MB |
| lsun_churches_256 | Haunted Schematics | 256px | 403 MB |
| afhq_cats_512 | Animal Forms | 512px | 329 MB |
| lsun_cars_512 | Automotive Drift | 512px | 403 MB |
Quick Start
Generate your first image in under a minute.
⌘ Enter. The image appears in the center panel. Generation takes 2–20 seconds depending on model resolution and your machine.How It Works
You are not describing an image. You are navigating a mathematical space that a neural network learned from a dataset of real images.
Latent Space
A StyleGAN2 model is trained to compress a dataset of images into a high-dimensional mathematical space called latent space. Every point in this space corresponds to an image. The model learns a mapping from any point in this space back to a full-resolution image.
Seeds
A seed is an integer (0 to 2,147,483,647) that TURRRBO converts into a starting vector in latent space using a deterministic random number generator. The same seed always produces the same image with the same model and parameters. Different seeds are different locations in latent space — different images.
Truncation ψ (psi)
Truncation controls how far your seed's point is allowed to stray from the model's mean (the "average" of everything it learned). Think of it as a dial between safe and typical versus extreme and unusual.
| ψ range | Behavior |
|---|---|
| 0.0 – 0.3 | Collapsed toward the mean. Everything looks very "typical" for the model. |
| 0.4 – 0.7 | Balanced. Most commonly used range for coherent outputs. |
| 0.8 – 1.0 | High diversity. Outputs become unusual and more interesting. |
| 1.0 – 1.4 | Beyond the standard range. Structural breakdown, artifacts, alien geometry. |
Generation Pipeline
Models
Each model is a trained checkpoint that defines a visual territory. Selecting a different model is like switching instruments.
Bundled Models
Adding Custom Models
Any StyleGAN2 or StyleGAN2-ADA checkpoint can be added to TURRRBO. Create a folder inside backend/models/ with a model_card.json and the .pkl file:
{
"id": "your_model_name", // must match folder name
"name": "Display Name",
"description": "What this model produces.",
"resolution": 512, // 256, 512, or 1024
"category": "face", // groups models in left rail
"provenance": "Source and license.",
"checkpoint_file": "your_checkpoint.pkl",
"recommended_psi": 0.7,
"tags": ["portrait", "abstract"]
}
Category values
The category field groups models in the left rail. Built-in values: face, art, architecture, animal, object. You can use any string — it becomes a new group heading.
Parameters
Every parameter in the right rail controls a specific aspect of how the model generates an image. None of them require you to understand the math.
Core Parameters
| Parameter | Type | Range | What it controls |
|---|---|---|---|
| Seed | integer | 0 – 2,147,483,647 | Selects a point in latent Z space. Each seed is a distinct identity. |
| Truncation ψ | float | 0.0 – 1.5 | How far from the model mean to go. Low = safe/typical. High = extreme/unusual. |
| Noise Mode | enum | const / random / none | How stochastic surface detail is generated. const is deterministic. random varies per-run. |
| Noise Strength | float | 0.0 – 3.0 | Scales the stochastic noise layer. High values flood the surface with detail. |
Split Truncation
StyleGAN2 generates images in layers — coarse layers (0–3) control large-scale structure like pose and shape, while fine layers (8+) control surface detail and color. Split truncation lets you use a different ψ for each group.
| Parameter | Layers | Controls |
|---|---|---|
| Coarse ψ | 0–3 | Pose, scale, overall structure |
| Fine ψ | 8+ | Surface texture, color, fine detail |
Style Mixing
Style mixing lets two seeds contribute to a single image. The primary seed provides the default identity. The mix seed donates its W-space values at the selected layers.
| Parameter | What it does |
|---|---|
| Mix Seed | A second seed whose W values are borrowed at the selected layers |
| Mix Layers | Which layers to borrow. Use the preset buttons: coarse / mid / fine / all |
Style Routes
Style routes are named parameter adjustments that shift your dials at generation time — without permanently changing what you've set. Think of them as artistic modes.
Available Routes
How Routes Are Applied
# Routes adjust params at generation time, not permanently def apply_route(route_id, params): route = ROUTES_BY_ID[route_id] result = dict(params) # Shift truncation, clamp to valid range result["truncation_psi"] = clamp( params["truncation_psi"] + route["psi_offset"], 0.0, 1.5 ) # Override noise mode if route specifies one if route["noise_mode_override"]: result["noise_mode"] = route["noise_mode_override"] return result
CLIP / Text Prompts
When you type in the Text Prompt field, TURRRBO switches to CLIP-guided generation. The latent vector is optimized over multiple steps to maximize similarity between the generated image and your text.
backend/.venv/bin/pip install git+https://github.com/openai/CLIP.git. Without it, the text field is still present but CLIP mode is unavailable.How CLIP Guidance Works
CLIP Parameters
| Parameter | Default | Effect |
|---|---|---|
| Steps | 80 | More steps = more influence from the prompt. Also slower. 50–100 is a good range. |
| LR (Learning Rate) | 0.05 | How aggressively the latent moves per step. High values move fast but overshoot. |
UI Overview
TURRRBO is a three-panel desktop instrument. Everything has a fixed place.
Left Rail — Model Catalog
Lists all available model checkpoints grouped by category. Click any model to load it. The selected model is highlighted and its recommended truncation value is applied to the ψ slider automatically.
Center Panel — Preview
Displays the generated image. The meta bar below the image shows the effective parameters used (accounting for any style route adjustments). Clicking a thumbnail in the history strip at the bottom restores those parameters.
Right Rail — Controls
All generation parameters live here. From top to bottom: Text Prompt, Style Route, Templates, Seed, Truncation, Split Truncation, Noise Mode, Noise Strength, Mix Seed, Randomize All, Generate button.
Status Bar
The footer shows backend health, the active compute device (MPS / CUDA / CPU), and the currently loaded model. A pulsing dot means the backend is still starting.
Keyboard Shortcuts
All shortcuts use Cmd on macOS so they never conflict with text input in the prompt field.
History & Export
Every generated image is saved automatically and kept in the history strip. Nothing is lost unless you manually delete it.
History Strip
The row of thumbnails at the bottom of the center panel shows the last 50 generations in the current session. Clicking any thumbnail restores its exact parameters — seed, ψ, noise mode, mix seed, and style route — back to the right rail so you can generate from that state again.
Output Files
All generated images are written to:
~/turrrbo_outputs/
Each generation creates two files:
| File | What it is |
|---|---|
| [run_id].png | Full resolution output |
| [run_id]_preview.png | 512px preview used in the UI |
| [run_id].json | Session metadata (if a note was added) |
Exporting
Click Export PNG in the center panel footer to open a save dialog and copy the full-resolution output to a location of your choice. The file in ~/turrrbo_outputs/ is always preserved — Export creates a copy.
Click Open Folder to reveal the output directory in Finder.
Custom Models
Any StyleGAN2 or StyleGAN2-ADA .pkl checkpoint can be added to TURRRBO. The model catalog is entirely driven by JSON files on disk.
model_card.json — Full Reference
{
"id": "my_model",
// Must match the folder name exactly.
// Used as the internal identifier everywhere.
"name": "Display Name",
// Shown in the left rail catalog.
"description": "What this produces and how it behaves.",
// Shown in the catalog when the model is selected.
"resolution": 512,
// Output resolution in pixels. Must match the checkpoint.
// Valid values: 256, 512, 1024.
"category": "face",
// Groups models in the catalog.
// Built-in: face, art, architecture, animal, object.
// Any string works — creates a new group.
"provenance": "Source URL and license information.",
// Required for any third-party checkpoint.
// Shown in the license panel.
"checkpoint_file": "my_checkpoint.pkl",
// Filename of the .pkl file relative to this folder.
"recommended_psi": 0.7,
// The truncation value loaded when this model is selected.
// 0.5–0.8 is typical. Adjust based on the model's behavior.
"tags": ["portrait", "texture"]
// Shown as small badges. Describe aesthetic character.
}
Bundling Into a Build
For development, dropping the folder in and restarting is all it takes. But a packaged build is different: the .pkl files in backend/models/ are not pulled into the app automatically — Tauri only bundles what lives in src-tauri/resources/models/. Stage them first:
npm run stage:models # then: npm run tauri:build
npm run tauri:dev but is missing from the built .app/.msi, you forgot stage:models. This is the #1 "where did my model go" cause.Finding Compatible Checkpoints
A large catalog of community-trained StyleGAN2 checkpoints is available at:
https://github.com/justinpinkney/awesome-pretrained-stylegan2
Any checkpoint listed there can be added to TURRRBO. Download the .pkl, create a folder in backend/models/, write the model_card.json, and restart the app.
provenance field.Style Mixing
Style mixing is a core StyleGAN2 technique. Two seeds contribute to one image — one seed provides structure, another provides surface.
Concept
StyleGAN2 generates images in sequential layers. The early layers (coarse, 0–3) control global properties like pose, scale, and basic structure. Later layers (fine, 8–14) control surface texture, color, and fine detail.
Style mixing replaces some layers of Seed A's W vector with the corresponding layers from Seed B. The result is an image with Seed A's coarse structure and Seed B's fine texture — or vice versa.
Layer Groups
| Group | Layers | Controls |
|---|---|---|
| Coarse | 0–3 | Pose, global shape, camera angle |
| Mid | 4–7 | Anatomy, proportion, mid-scale structure |
| Fine | 8–13 | Surface texture, color, fine detail, skin |
Using It
Set a primary seed (the Seed field). Enable mixing by entering a mix seed. Use the layer preset buttons (coarse / mid / fine / all) to choose which layers are borrowed from the mix seed. Generate.
Templates
Templates are built-in starting points that demonstrate specific techniques. They load a complete parameter configuration with one click.
Built-in Templates
| Name | What it demonstrates |
|---|---|
| Raw Output | Default settings, no adjustments. Baseline for comparison. |
| Average Collapse | Very low ψ (0.2). Shows what the model considers "most typical." |
| Full Chaos | Maximum ψ (1.4) + random noise + TV Wreckage route. Maximum instability. |
| Structure Swap | Style mixing with coarse layers. Two seeds, one image. |
| Texture Donor | Style mixing with fine layers. Surface from one seed, structure from another. |
| Split Truncation | Low coarse ψ, high fine ψ. Stable structure, chaotic surface. |
| Noise Flood | High noise strength. Stochastic layer overwhelms deterministic structure. |
| Ghost | High ψ + Ghost Contour route. Forms dissolve toward outlines. |
Backend API
TURRRBO's Python backend exposes a local HTTP API on port 47474. The Tauri shell proxies all UI interactions through Rust commands to this API. You can also call it directly for scripting.
127.0.0.1:47474. It is not exposed to the network. Interactive docs are available at http://127.0.0.1:47474/docs when the backend is running.{
"healthy": true,
"gpu_available": true,
"device": "mps",
"loaded_model": "ffhq_1024",
"version": "0.2.0",
"clip_available": true
}
{
"model_id": "ffhq_1024",
"params": {
"seed": 42,
"truncation_psi": 0.7,
"noise_mode": "const",
"mix_seed": null,
"mix_layers": null,
"noise_strength": 1.0,
"coarse_psi": null,
"fine_psi": null
},
"style_route": "none",
"text_prompt": null,
"clip_steps": 80,
"clip_lr": 0.05
}
{
"ok": true,
"output_image": "/Users/.../turrrbo_outputs/2026-04-08T12-00-00Z_abc123.png",
"preview_image": "/Users/.../turrrbo_outputs/2026-04-08T12-00-00Z_abc123_preview.png",
"model_id": "ffhq_1024",
"run_id": "2026-04-08T12-00-00Z_abc123",
"timing_ms": 4821,
"warnings": [],
"effective_params": { /* actual params used after route adjustment */ },
"clip_guided": false
}
Architecture
TURRRBO is a native desktop app with three layers: a Tauri shell (Rust), a React frontend, and a Python inference service.
Communication Flow
The React UI never talks to the Python backend directly. All communication goes through Tauri commands — Rust functions that the frontend calls via invoke(). The Rust layer then makes HTTP requests to the Python sidecar on localhost.
// Frontend calls a Tauri command const result = await invoke("generate_image", { request }) // Rust proxies to Python backend // src-tauri/src/commands.rs client().post("http://127.0.0.1:47474/generate") .json(&request) .send().await // Python handles inference # backend/api/server.py engine.generate(seed, truncation_psi, ...)
Project Structure
Building & Distribution
Building TURRRBO for distribution produces a self-contained app — a macOS .app/.dmg or a Windows .msi/.exe. No Python installation required on the end user's machine.
Prerequisites
You need all developer dependencies installed: Rust, Node.js, Python 3.10–3.13 (not 3.14), and PyInstaller.
backend/.venv/bin/pip install pyinstaller
Build Steps
A distribution build is three steps: stage the model weights, freeze the Python backend into a sidecar binary, then let Tauri bundle everything.
.pkl weights live in backend/models/, but Tauri only packages what's in src-tauri/resources/models/. Staging copies them across. Run this before every build that added or changed a model.npm run stage:models # runs scripts/stage_models.js (cross-platform)
backend/.venv/bin/python3 -m PyInstaller \
--clean --noconfirm \
--distpath "src-tauri/binaries/_dist" \
--workpath "build/pyinstaller" \
backend/turrrbo_backend.spec
cp src-tauri/binaries/_dist/turrrbo-backend \
src-tauri/binaries/turrrbo-backend-aarch64-apple-darwin
chmod +x src-tauri/binaries/turrrbo-backend-aarch64-apple-darwin
backend\.venv\Scripts\python -m PyInstaller ^
--clean --noconfirm ^
--distpath "src-tauri\binaries\_dist" ^
--workpath "build\pyinstaller" ^
backend\turrrbo_backend.spec
copy src-tauri\binaries\_dist\turrrbo-backend.exe ^
src-tauri\binaries\turrrbo-backend-x86_64-pc-windows-msvc.exe
-aarch64-apple-darwin, -x86_64-pc-windows-msvc). Tauri resolves the sidecar by appending the platform triple to the base name in externalBin; a mismatch is a hard build failure.npm run tauri:build
Output Locations
| Platform | Artifact |
|---|---|
| macOS | src-tauri/target/release/bundle/macos/TURRRBO.app (and .dmg) |
| Windows · MSI | src-tauri/target/release/bundle/msi/TURRRBO_0.1.0_x64_en-US.msi |
| Windows · NSIS | src-tauri/target/release/bundle/nsis/TURRRBO_0.1.0_x64-setup.exe |
Build Order
download_models.py → stage:models → PyInstaller (sidecar) → tauri:build
(one-time) (after a model (when backend code (produces
changes) or deps change) installer)
For a routine release with no backend or model changes, the sidecar from a previous build can be reused — only re-run PyInstaller when the Python code or its dependencies changed.
Development Mode
In development, the Python backend is launched by concurrently alongside Tauri. No sidecar binary is needed.
npm run tauri:dev
To iterate on the backend alone (faster restart loop), run it standalone and point Tauri at :47474:
# macOS / Linux backend/.venv/bin/python3 backend/api/server.py --port 47474 # Windows backend\.venv\Scripts\python backend\api\server.py --port 47474
backend script in package.json hard-codes a venv path: backend/.venv/bin/python3 on macOS, backend\.venv\Scripts\python on Windows. When moving the checkout between platforms, update that one script.Troubleshooting
Build and launch failures we've actually hit, with the fix. Ordered roughly by how often they come up — search by the symptom.
ModuleNotFoundError: No module named 'torch'
File ".../backend/api/server.py", line 19, in <module>
import torch
ModuleNotFoundError: No module named 'torch'
Cause. PyTorch is intentionally left out of requirements.txt (the correct wheel is platform-specific), so a fresh venv has no torch — or you launched with a different Python than the venv that has it.
Fix. Install the right variant into backend/.venv and launch with that interpreter:
# Apple Silicon backend/.venv/bin/pip install torch torchvision # CUDA 12.1 backend/.venv/bin/pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121 # CPU backend/.venv/bin/pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu
Sidecar binary not found / Tauri refuses to compile
Symptom. npm run tauri:build (or dev) fails immediately, before any code compiles, complaining about a missing binary referenced in externalBin.
Cause. Tauri validates that every externalBin entry physically exists at build time. If PyInstaller hasn't run yet, or the binary isn't renamed with the correct target triple, the expected file isn't there.
Fix (distribution build). Build the sidecar first and rename it to include the target triple:
src-tauri/binaries/turrrbo-backend-aarch64-apple-darwin # macOS Apple Silicon src-tauri/binaries/turrrbo-backend-x86_64-pc-windows-msvc.exe # Windows x64
Fix (dev only). You don't need a sidecar in dev. Remove the externalBin key from src-tauri/tauri.conf.json and run the Python backend via npm run tauri:dev (or manually). Re-add externalBin only when packaging.
New model missing from the built app
Symptom. A model shows up in npm run tauri:dev but is absent from the packaged .app / .msi / .exe.
Cause. The .pkl was never staged into src-tauri/resources/models/. Tauri only bundles what's under resources/, not what's in backend/models/.
npm run stage:models npm run tauri:build
PyInstaller fails / sidecar crashes on launch
Symptom. PyInstaller errors during the freeze, or the bundled binary exits immediately at runtime.
Model fails to resolve / not appearing in the catalog
Check these, in order:
idinmodel_card.jsondoesn't match the folder name → make them identical.checkpoint_fileis a path instead of a bare filename → it must be just the filename, relative to the model's own folder.resolutiondoesn't match the actual checkpoint → inference errors on first generate; correct the card to the checkpoint's native resolution.- Backend wasn't restarted → the registry only scans on startup.
Cross-platform breakage (macOS ↔ Windows)
- The
backendscript inpackage.jsonuses a per-OS venv path —backend/.venv/bin/python3(macOS) vsbackend\.venv\Scripts\python(Windows). Update it for the current platform. - The sidecar binary needs a
.exeextension on Windows; the rename step andsidecar.rshandle this per platform. - Use
npm run stage:models(Node-basedstage_models.js) rather than any bash loop — the Node script is the cross-platform staging path.
Quick triage checklist
backend/.venv have torch? (backend/.venv/bin/python -c "import torch")2. Is the venv Python 3.10–3.13?
3. Did you
npm run stage:models before tauri:build?4. For a distribution build, does the sidecar binary exist with the correct target-triple suffix?
5. For each model:
id == folder name, checkpoint_file is a bare filename, resolution matches the checkpoint.
License & Attribution
TURRRBO depends on components with specific licensing requirements. Understanding these is important before distributing or using the application.
NVIDIA StyleGAN2 Weights
The pretrained checkpoints (FFHQ, MetFaces, LSUN, AFHQ) are property of NVIDIA Corporation, licensed for non-commercial research use only.
Copyright (c) 2021, NVIDIA Corporation. All rights reserved. Non-commercial research use only. https://nvlabs.github.io/stylegan2/license.html
StyleGAN2-ADA-PyTorch
The inference code from the NVlabs repository is used under the same NVIDIA non-commercial license.
PyTorch
PyTorch is used under the BSD-style license. Full text: https://github.com/pytorch/pytorch/blob/main/LICENSE
Tauri
The Tauri framework is used under the MIT / Apache-2.0 dual license.
CLIP
OpenAI CLIP is used under the MIT license when installed. It is an optional dependency.
Attribution Requirements
Any redistribution of TURRRBO must include:
This file is bundled inside the app at Contents/Resources/resources/licenses/.