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:
ChatTTStext-to-speechwhisper.cpptranscriptiondemucsaudio 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:
queuedpreflightingrunningcancellingcompletedfailedcancelled
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_blogwhisper.transcribe_audiodemucs.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.tomlplus lock file, or exact pinnedrequirements.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:
workspacestoolstool_runtimestaskstask_eventsartifactssettings
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:
- choose
blog.md - choose voice and output name
- run
ChatTTS - view structured logs and progress
- 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:
ChatTTSworkflow 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 -> wavwithout 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
Recommended First Technical Spike
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:
- stabilize one CLI adapter
- define its event contract
- add SwiftUI launcher and live progress UI
- add persistence
- repeat for the next tool
This keeps the system shippable at every stage instead of drifting into a large unfinished rewrite.