I’m developing a Cocoa app with a graphical user interface, but I also want to create a command line interface that shares the same output, allowing me to use it with monitoring tools like GeekTool.
Do I need to set up a separate command line target within my Xcode project for this? I need help understanding the correct way to configure the project so that both versions can operate smoothly and utilize the shared codebase effectively.
You need to plan your architecture carefully from the start. Separate your business logic into a shared framework or static library that both versions can use. I did this with a file processing app - kept the core functionality in its own module, then built thin presentation layers for GUI and CLI. Your Cocoa app handles the UI stuff while the shared classes do the heavy lifting. The command line version just wraps those same core classes but dumps results to stdout instead of updating the interface. This keeps both versions consistent and makes maintenance way easier since you’re not copying the same logic everywhere.
What about code signing though? Running into any entitlement issues when you switch between GUI and CLI modes in the same binary? I’m wondering if GeekTool has specific requirements for the command line tools it monitors…
Nice approach! How do you handle the different lifecycles between GUI and CLI tho? Does your shared code need to know which enviroment it’s in, or do you keep it totally agnostic? Also curious about dependency injection for progress reporting…
for sure, set up a separate command line target in xcode. that way, you can share source files between both while keeping gui stuff separate. it helps in managing the core logic better and keeps stuff running smoothly across the board.
i’ve had good luck using argument parsing to switch modes in the same target. just check for CLI flags at startup - either initialize the full Cocoa stack or run headless with shared classes. saves you from duplicate targets and keeps things way simpler.
Creating dual interfaces is tricky - you need to think about how your app starts up and runs. The biggest headache is NSApplication initialization since command line tools don’t want the full Cocoa lifecycle. I ran into this building a document converter that needed both GUI and CLI modes. My fix was detecting launch arguments early and skipping NSApplicationMain for CLI mode. Rather than sharing frameworks, I used conditional compilation flags to strip out GUI code from the command line build. Way more reliable than juggling two targets with shared dependencies. The trick is treating the CLI version as a stripped-down variant, not a separate app entirely. Makes deployment easier and cuts down on conflicts between the two modes.