Swift and SwiftUI tutorials for Swift Developers

How to open Xcode Simulator from Terminal

In the fast-paced world of mobile app development, every second counts. As an iOS developer, you spend a large part of your day switching between writing code in Xcode, designing interfaces in SwiftUI, and testing your creations in the simulator. However, relying exclusively on the mouse and graphical menus can become a bottleneck for your workflow.

Have you ever wanted to feel like a computer engineer and control your development environment with just the keyboard? Or perhaps you need to automate tests on a Continuous Integration (CI/CD) server where there is no graphical interface? This is where the magic of the macOS terminal comes in.

In this comprehensive Swift programming tutorial, you will learn not only how to open the Xcode simulator from the terminal but how to master it completely. From basic commands to automation scripts in Swift, we will transform the way you develop apps for iOS, macOS, and watchOS.


Why Use the Terminal Instead of Xcode?

Before diving into the commands, it is vital to understand why a Swift and SwiftUI expert should invest time in this:

  • Speed: Executing a command is infinitely faster than searching for the right device in Xcode’s dropdown menu.
  • Automation: You can create scripts to open multiple simulators at once (e.g., an iPhone SE and an iPhone 15 Pro Max) to test the adaptability of your UI.
  • Cleanliness: The terminal allows you to reset simulators to their factory state much faster than the GUI, ideal for clearing corrupt Core Data or UserDefaults data.

Method 1: The Quick and Easy Way

If your only goal is to launch the “Simulator.app” application without specifying a concrete device, macOS offers the open command. This command is equivalent to double-clicking the application icon.

Open your terminal and type the following:

open -a Simulator

This command will open the simulator with the last device you used. It’s useful, but as a professional iOS developer, we need more control. We need simctl.


Method 2: Total Control with xcrun simctl

Here is where true advanced system-level Swift programming begins. Apple provides a command-line tool called simctl (Simulator Control), which lives inside xcrun. This tool is the bridge between your terminal and the Xcode simulation engine.

Step 1: List Available Devices

To open a specific simulator, we first need to know what it is called internally or what its unique identifier (UUID) is. Run the following command to see a list of all devices installed on your system (iOS, watchOS, tvOS):

xcrun simctl list

The output will be extensive. You will see categories like “Device Types”, “Runtimes”, and “Devices”. Look for the == Devices == section. It will look something like this (simplified):

-- iOS 17.0 --
    iPhone SE (3rd generation) (A1B2C3D4-E5F6-...) (Shutdown)
    iPhone 15 (12345678-90AB-...) (Shutdown)
    iPhone 15 Pro Max (98765432-10FE-...) (Booted)

Step 2: Boot a Specific Device

Suppose you are working on a complex SwiftUI view and need to test it on an iPhone 15. To boot it without opening the graphical interface yet, we use the boot command followed by the name or UUID.

xcrun simctl boot "iPhone 15"

Pro Note: If you have multiple devices with the same name (e.g., on different iOS versions), it is better to use the UUID that appears in parentheses in the list above.

Step 3: Show the Simulator

The previous command boots the operating system in the background. To see it, we must open the Simulator app. If you have already booted the device with simctl, when opening the app, it will detect the “booted” device and show it immediately.

open -a Simulator

Advanced Automation with Swift

As Swift programming enthusiasts, why use Bash when we can use Swift? We can create executable scripts in Swift that manage our simulators. This is ideal for integrating complex logic, such as “delete all simulators and create a new one for clean testing”.

Below, I present a Swift script that you can run from your terminal to search for a device by name and open it. Save this code in a file named OpenSim.swift.

#!/usr/bin/env swift

import Foundation

// Helper function to execute shell commands from Swift
func shell(_ command: String) -> String {
    let task = Process()
    let pipe = Pipe()
    
    task.standardOutput = pipe
    task.standardError = pipe
    task.arguments = ["-c", command]
    task.launchPath = "/bin/zsh"
    task.launch()
    
    let data = pipe.fileHandleForReading.readDataToEndOfFile()
    return String(data: data, encoding: .utf8) ?? ""
}

// Input arguments (the name of the device we want to open)
let args = CommandLine.arguments

guard args.count > 1 else {
    print("❌ Error: You must specify the device name.")
    print("Usage: ./OpenSim.swift 'iPhone 15'")
    exit(1)
}

let deviceName = args[1]
print("🔍 Searching for device: \(deviceName)...")

// Get the JSON list of devices from simctl
let jsonOutput = shell("xcrun simctl list devices available -j")

// Structures to decode the simctl JSON
struct SimctlOutput: Codable {
    let devices: [String: [Device]]
}

struct Device: Codable {
    let name: String
    let udid: String
    let state: String
}

if let data = jsonOutput.data(using: .utf8) {
    do {
        let result = try JSONDecoder().decode(SimctlOutput.self, from: data)
        var foundUDID: String?
        
        // Iterate over all runtimes (iOS 16, iOS 17, etc.)
        for (_, deviceList) in result.devices {
            if let match = deviceList.first(where: { $0.name == deviceName }) {
                foundUDID = match.udid
                break
            }
        }
        
        if let udid = foundUDID {
            print("✅ Device found: \(udid)")
            print("🚀 Booting simulator...")
            
            // Commands to boot and open
            _ = shell("xcrun simctl boot \(udid)")
            _ = shell("open -a Simulator")
            
            print("📲 Simulator opened successfully.")
        } else {
            print("⚠️ No device found named '\(deviceName)'")
        }
        
    } catch {
        print("Error processing JSON: \(error)")
    }
}

To use this script, give it execution permissions in your terminal: chmod +x OpenSim.swift and then run it: ./OpenSim.swift "iPhone 15 Pro".

This level of control demonstrates the power of knowing Swift programming beyond SwiftUI views. You are creating your own development tools.


Expert Tips for the iOS Developer

1. Install Apps without recompiling

Sometimes a colleague sends you an .app file and you don’t have the source code, or you simply don’t want to wait for Xcode to recompile everything. You can install applications directly onto an open simulator:

xcrun simctl install booted Path/To/YourApp.app

2. Record the Simulator screen from Terminal

To demo your SwiftUI views or report visual bugs, recording a video is essential. simctl does this better than QuickTime because it doesn’t record the simulator frame, only the useful screen.

xcrun simctl io booted recordVideo demo_app.mp4

Press Control + C in the terminal to stop recording.

3. Dark Mode and Accessibility

Do you want to test how your SwiftUI interface responds to appearance changes without navigating through the simulated device settings? You can inject UI changes:

# Enable Dark Mode
xcrun simctl ui booted appearance dark

# Enable Light Mode
xcrun simctl ui booted appearance light

# Increase font size (Dynamic Type)
xcrun simctl ui booted content_size extra-large

Integration with SwiftUI and Previews

You are probably wondering: “Why do I need this if I have SwiftUI Previews in Xcode?”.

Previews are fantastic, but they have limitations. They don’t perfectly simulate the application lifecycle, push notifications, or background database behavior. As a senior iOS developer, you know that the final test must always be in the full simulator (and eventually on a real device).

Using the terminal allows you to launch a clean environment (“Cold Start”) for your SwiftUI tests, ensuring there are no residual states in the Preview memory that could falsify your results.

Creating Aliases for Maximum Efficiency

Nobody wants to type xcrun simctl... twenty times a day. Let’s optimize your flow by creating “Aliases” in your shell configuration file (.zshrc or .bash_profile). This will save you hours in the long run.

Open your configuration file and add the following functions. (Although this is Shell code, it is an integral part of the development ecosystem):

# Open default simulator
alias sims="open -a Simulator"

# List devices cleanly
alias ls-sims="xcrun simctl list devices available"

# Function to reset all simulators (Careful!)
function nuke-sims() {
    xcrun simctl shutdown all
    xcrun simctl erase all
    echo "💥 All simulators have been reset."
}

# Quick function to boot a specific iPhone
function boot-iphone() {
    if [ -z "$1" ]; then
        echo "Usage: boot-iphone 'iPhone 15'"
    else
        xcrun simctl boot "$1"
        open -a Simulator
    fi
}

After saving the file and restarting your terminal, you can simply type boot-iphone "iPhone 15" and see your work environment come to life automatically.


Conclusion

Mastering the command line is a superpower for any iOS developer. It frees you from dependence on the mouse, speeds up repetitive tasks, and grants you a deeper understanding of how the tools under the Xcode hood work.

Whether you are debugging a complex SwiftUI view, configuring a CI/CD pipeline, or simply trying to impress your colleagues, knowing how to open the Xcode simulator and control it via text puts you one step ahead.

If you have any questions about this article, please contact me and I will be happy to help you 🙂. You can contact me on my X profile or on my Instagram profile.

Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Article

Popover without Arrow in SwiftUI

Next Article

Best Navigation for SwiftUI

Related Posts