Skip to content

Instantly share code, notes, and snippets.

@GeorgeLyon
Last active March 22, 2025 22:51
Show Gist options
  • Save GeorgeLyon/bbd443dcabef5ca5ae71ae83db6524ef to your computer and use it in GitHub Desktop.
Save GeorgeLyon/bbd443dcabef5ca5ae71ae83db6524ef to your computer and use it in GitHub Desktop.
#!/usr/bin/env xcrun -sdk macosx swift
// Displays UI in an NSWindow which can interact with the commandline
// Usage: `echo "Bar" | ./swift-ui-commandline-tool.swift`
import Foundation
import SwiftUI
extension CommandLine {
static let input: String = { AnyIterator { readLine() }.joined() }()
}
struct App: SwiftUI.App {
var body: some Scene {
WindowGroup {
VStack {
Text("Hello, George!")
Button("Print \"Foo\"") { print("Foo") }
Button("Echo Input") { print(CommandLine.input) }
Button("Done") { exit(0) }
}
.padding(100)
}
.windowStyle(HiddenTitleBarWindowStyle())
}
}
App.main()
@rchrd2
Copy link

rchrd2 commented May 20, 2023

This is amazing. Thank you!

@GeorgeLyon
Copy link
Author

Happy to help, this code is a bit old so thank you for checking it still works :)

@markiv
Copy link

markiv commented Apr 5, 2024

Very cool! For me the window wouldn't open unless:

DispatchQueue.main.async {
    NSApplication.shared.setActivationPolicy(.regular)
    NSApplication.shared.activate(ignoringOtherApps: true)
}
App.main()

@GeorgeLyon
Copy link
Author

Thanks! Yeah I haven't re-ran this in some time so it probably is a bit out of date.

@Samasaur1
Copy link

You shouldn't need to run NSApplication.shared.setActivationPolicy(.regular) inside an async block. I'd also recommend running NSApplication.shared.activate() inside an onAppear modifier attached to a view, rather than in an async block

@johncwelch
Copy link

That actually works really well other than the input not working.

@johncwelch
Copy link

never mind, it works, I had the dumb

@GeorgeLyon
Copy link
Author

Oh, no not the dumb! Glad folks are still finding this useful!

@johncwelch
Copy link

It's very useful. I was wondering if you'd ever played around with setting it up to take multiple parameters that might be of different types, so like:

swift-ui-commandline-tool -myInt -"myString"?

@GeorgeLyon
Copy link
Author

Swift argument parser (https://github.com/apple/swift-argument-parser) is pretty good for this but it doesn’t work well with scripts. Some attempts have been made to add functionality to make this work better but as far as I know nothing has landed in the tool chain.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment