Jamie van Gulik Roosendaal

Case study 01 · 2026

Vormik

Een native macOS-app in SwiftUI die per project je processen, quick actions en macro's beheert — zodat drie terminaltabs er één worden.

Swift SwiftUI

Rol

Solo developer
(eigen product)

Duur

doorlopend
juli 2026 — heden

Stack

Swift · SwiftUI · SwiftData
macOS 26 · XCTest

Vormik met een workspace van twee processen en zijn quick actions

01 — Het probleem

Drie terminaltabs die niets van elkaar wisten

Elk Laravel-project dat ik open kost drie terminaltabs: een webserver, een queue worker en Vite. Ze weten niets van elkaar, ze onthouden niets, en na een herstart begin je opnieuw met uitzoeken welke tab welke was.

De commando's ertussenin — migreren, tests draaien, een sitemap genereren — typ je elke keer opnieuw, in de juiste map, met de juiste PATH. Geen moeilijk probleem. Wel een dat elke dag twintig keer terugkomt.

02 — De aanpak

Eén venster dat het project al kent

Je wijst een projectmap aan en de ProjectFolderDetector leest wat er staat: een artisan-bestand, de scripts in package.json, een docker-compose. Daaruit komt een voorstel — Laravel, Herd, Vite, Node of Docker Compose — met de commando's die daarbij horen, klaar om te bevestigen.

Wat overblijft is één venster per project: langlopende processen als kaarten met hun status, quick actions in secties die je zelf indeelt, en macro's die een reeks stappen op volgorde afwerken. SwiftData houdt het vast, zodat het er morgen nog net zo bij staat.

03 — Onder de motorkap

De PATH van jouw shell, niet die van mij

De eerste versie had een lijstje met paden: Homebrew, /usr/local, Herd. Dat dekt veel en mist hele categorieën — nvm, asdf, mise, pyenv, rbenv, Volta, en alles wat iemand zelf op zijn PATH heeft gezet. Als het misgaat faalt een commando dat in Terminal gewoon werkt hier met command not found, en dat is het meest verwarrende wat deze app iemand kan aandoen.

Dus vraagt Vormik het gewoon: één keer je login shell starten en teruglezen wat PATH is. Dat vangt ook de version manager die volgend jaar bedacht wordt, juist omdat er nergens een tool bij naam herkend wordt. De prijs is een timeout — een zware .zshrc kan seconden duren, en het ophalen van de omgeving mag nooit zijn wat de app traag laat voelen.

nonisolated static func resolve(timeout: TimeInterval = 5) -> ShellEnvironment? {
    let shellPath = ProcessInfo.processInfo.environment["SHELL"] ?? "/bin/zsh"

    guard let output = ProcessRunner.run(
        executable: shellPath,
        arguments: ["-l", "-c", "echo $PATH"],
        timeout: timeout
    ) else {
        return nil
    }

    let searchPaths = parsePath(output)

    guard !searchPaths.isEmpty else { return nil }

    return ShellEnvironment(shellPath: shellPath, searchPaths: searchPaths)
}
Vormik-instellingen met de gekozen shell en de zoekpaden uit de login shell

04 — De vorm van het ding

Wat het is, en wat het niet is

3

terminaltabs die het per project vervangt

1×

login shell starten, voor de PATH die jij echt hebt

0

sandbox — het start /bin/zsh zelf, dus geen App Store

Wat ik zou veranderen

ContentView is inmiddels opgesplitst in zes extensies en tóch is de persistentielaag nog ruim dertienhonderd regels. Daar zou ik opnieuw beginnen: dat hoort achter een service te zitten die niets van SwiftUI weet, precies zoals de rest van Services/ dat al doet.

Het tweede is geen code. Vijf euro per maand vragen voor een lokale tool zonder backend, aan ontwikkelaars die weten dat er geen backend is, is een lastig verhaal. Eenmalig kopen met twaalf maanden updates past beter bij wat dit werkelijk is — en dat wil je beslissen vóór je de licentiecode schrijft, niet erna.