The goal is to Build a local SwiftUI desktop application that turns the current OpenSource workspace into a stable, maintainable, and portable workbench for running tools such as:

  • ChatTTS text-to-speech
  • whisper.cpp transcription
  • demucs audio separation
  • future local scripts and model-driven workflows

The app should not behave like a thin GUI wrapper around shell commands. It should provide a controlled runtime, structured logging, safe file handling, reproducible environments, and a migration path across machines.

Product Principles

  • Stability first. Avoid clever runtime magic that makes the app hard to debug.
  • Source files are read-only by default.
  • Outputs must be isolated from inputs.
  • Dependencies must be pinned, explicit, and upgradeable on purpose.
  • Tool execution must be observable through structured events, not terminal scraping.
  • The system must survive app restarts, task cancellation, and machine migration.
  • GUI and tool runtime must be decoupled.

Non-Goals For V1

  • No attempt to expose every script in the workspace on day one.
  • No automatic dependency upgrades during task execution.
  • No shared global Python environment.
  • No direct editing of arbitrary files from the GUI.
  • No plugin marketplace or remote sync in the first version.

High-Level Architecture

SwiftUI App
  -> App Core
    -> Task Runner
    -> Workspace Registry
    -> Artifact Store
    -> SQLite State Store
    -> Tool Registry
      -> Tool Adapter
        -> Managed Runtime
          -> Python env / binary / model assets

Main Modules

1. SwiftUI Frontend

Responsibilities:

  • workspace picker
  • tool list and tool detail pages
  • task launch forms
  • live progress and logs
  • artifact browser
  • settings and runtime health screens

Rules:

  • no business logic in views
  • no shell command construction in views or view models
  • no direct filesystem mutation outside designated service layers

2. App Core

Responsibilities:

  • task lifecycle state machine
  • validation and preflight checks
  • cancellation and retry
  • recovery after app restart
  • routing structured events from tool processes to UI

Suggested task states:

  • queued
  • preflighting
  • running
  • cancelling
  • completed
  • failed
  • cancelled

3. Tool Registry

Each tool should be described declaratively, not hardcoded throughout the UI.

Each tool definition should include:

  • stable id
  • display name
  • supported input types
  • parameter schema
  • runtime type
  • output contract
  • health check command
  • artifact kinds produced

Example initial tools:

  • chattts.read_blog
  • whisper.transcribe_audio
  • demucs.separate_track

4. Tool Adapters

Each tool should have a wrapper entrypoint owned by this project.

Do not call third-party scripts directly from SwiftUI.

Adapter responsibilities:

  • accept validated structured input
  • emit JSON Lines events
  • normalize errors
  • write outputs to provided artifact paths
  • return stable exit codes

Example event stream:

{"type":"task.started","tool":"chattts.read_blog"}
{"type":"progress","phase":"load_model","current":1,"total":3}
{"type":"progress","phase":"synthesize","current":3,"total":30}
{"type":"artifact","kind":"audio/wav","path":"/.../artifacts/.../walk_listen.wav"}
{"type":"task.completed"}

5. Managed Runtime Layer

This is the most important boundary for long-term stability.

Responsibilities:

  • resolve the correct runtime per tool
  • execute tools with controlled environment variables
  • pin interpreter and dependency set
  • detect missing assets
  • expose health status to the GUI

Preferred model:

  • Swift side: Swift Package Manager
  • Python side: pyproject.toml plus lock file, or exact pinned requirements.txt
  • one managed environment per tool family, or one per tool if conflicts justify it

Do not rely on:

  • system Python
  • shell startup files
  • global pip install
  • implicit PATH assumptions

File Safety Model

This is where file loss prevention is designed in, not patched later.

Rules

  • input files are read-only by default
  • outputs go to an app-managed artifacts/ root
  • temporary files go to a dedicated temp area
  • destructive actions require explicit confirmation
  • source files are never overwritten silently

Write Strategy

  • write to temp file first
  • fsync if needed for critical outputs
  • rename atomically into final artifact path

Deletion Strategy

  • prefer move to Trash for user-managed files
  • for app-generated artifacts, support soft-delete before permanent cleanup

Task Manifest

Every run should save a manifest containing:

  • task id
  • tool id
  • workspace root
  • input file paths
  • output artifact paths
  • parameter values
  • runtime versions
  • model asset versions
  • start time and end time
  • final status

This makes debugging, migration, and reproducibility much easier.

Dependency Strategy

Swift Dependencies

  • use Swift Package Manager
  • pin versions
  • keep third-party packages minimal

Python Dependencies

  • pin exact versions
  • maintain lock files in repo
  • separate runtime from source code
  • no auto-update during normal app usage

Recommended policy:

  • upgrades happen in a maintenance workflow
  • each upgrade is tested per tool
  • runtime metadata records the exact dependency set used

Model Assets

Treat model assets as versioned runtime dependencies.

Store metadata for each asset:

  • source
  • version or commit
  • checksum if available
  • local install path
  • size
  • last verified timestamp

The app should detect:

  • missing assets
  • corrupted assets
  • mismatched runtime and asset expectations

Portability And Migration

Avoid

  • hardcoded absolute paths in source code
  • hidden assumptions about local shell config
  • machine-specific environment setup steps that are not documented

Prefer

  • workspace root plus relative paths
  • app-managed settings in a known location
  • runtime manifests
  • exportable configuration

Migration target:

  • copy the project
  • reinstall app
  • restore managed runtimes and assets
  • reopen workspace
  • resume normal use without rewriting configs by hand

State Persistence

Use SQLite for app state.

Suggested tables:

  • workspaces
  • tools
  • tool_runtimes
  • tasks
  • task_events
  • artifacts
  • settings

Why SQLite:

  • reliable local persistence
  • easy inspection
  • transactional updates
  • straightforward backup and migration

Logging And Error Handling

Logging

Collect logs in three layers:

  • app log
  • task event log
  • raw subprocess stderr log

Error Model

Classify errors so the UI can respond properly:

  • validation error
  • missing dependency
  • missing asset
  • runtime incompatibility
  • tool execution failure
  • user cancellation
  • filesystem write failure

Recovery

On app restart:

  • detect interrupted tasks
  • mark them as interrupted
  • preserve logs
  • keep completed artifacts
  • allow safe rerun

SwiftUI App UX For V1

Primary Screens

  • workspace home
  • tool catalog
  • task launch sheet
  • running task view
  • task history
  • artifacts browser
  • settings and diagnostics

V1 UX Goal

One polished path is better than five partial ones.

Recommended first path:

  1. choose blog.md
  2. choose voice and output name
  3. run ChatTTS
  4. view structured logs and progress
  5. preview and open generated audio

Suggested Repository Layout

OpenSource/
  App/
    OpenSourceWorkbench.xcodeproj
    Sources/
    Tests/
  Tools/
    adapters/
      chattts_read_blog/
      whisper_transcribe/
      demucs_separate/
    runtimes/
      chattts/
        pyproject.toml
        lockfile
      whisper/
      demucs/
  Infrastructure/
    schemas/
    manifests/
    migrations/
  artifacts/
  docs/
    architecture/
    operations/

Implementation Phases

Phase 0: Normalize Existing CLI Workflows

  • wrap each useful script behind a stable adapter entrypoint
  • define structured input and output contracts
  • remove hidden assumptions from ad hoc scripts
  • prove that CLI tasks run reproducibly without manual shell intervention

Exit criteria:

  • ChatTTS workflow works end-to-end through one adapter
  • output path, logs, and errors are controlled

Phase 1: Build Minimal SwiftUI Shell

  • workspace selector
  • tool list
  • launch form for ChatTTS
  • live task console backed by JSON Lines events
  • output artifact link

Exit criteria:

  • a non-technical user can run blog.md -> wav without opening Terminal

Phase 2: Add Runtime Management

  • runtime health checks
  • dependency and asset verification
  • diagnostics screen
  • explicit repair actions

Exit criteria:

  • app can explain why a tool cannot run and what needs repair

Phase 3: Persistence And History

  • SQLite-backed tasks and artifacts
  • rerun with same parameters
  • resume app after restart

Exit criteria:

  • completed tasks remain inspectable and reproducible

Phase 4: Expand Tool Surface

  • add whisper.cpp
  • add demucs
  • unify artifact presentation

Exit criteria:

  • multiple tools share the same execution model without UI duplication

Decisions To Lock Early

  • app sandboxing approach
  • whether Python runtimes live inside the workspace or app support directory
  • how model assets are discovered and versioned
  • JSON event schema versioning
  • artifact storage retention policy
  • naming convention for tools and tasks

Known Risks

  • Python toolchains can conflict across tools if isolation is weak
  • model assets are large and need lifecycle management
  • MPS and ML runtimes on macOS can be fragile and version-sensitive
  • direct integration with arbitrary existing scripts will create long-term maintenance debt
  • overloading V1 with too many tools will delay a stable release

Build only this vertical slice:

  • SwiftUI screen for ChatTTS
  • one adapter wrapping current read_blog.py
  • JSON Lines event output
  • artifact directory creation
  • CPU fallback and structured error handling

If this slice is clean, the rest of the system can follow the same pattern.

Working Agreement For Future Sessions

When building this with Codex, proceed in this order:

  1. stabilize one CLI adapter
  2. define its event contract
  3. add SwiftUI launcher and live progress UI
  4. add persistence
  5. repeat for the next tool

This keeps the system shippable at every stage instead of drifting into a large unfinished rewrite.