Skip to main content

SweetPad CLI

The SweetPad CLI is a command-line tool named sweetpad that builds, runs, and tests your Xcode and Swift Package apps from the terminal. If you've ever wished xcodebuild were friendlier, this is that.

It's a self-contained binary. It doesn't need VS Code, and it doesn't care which editor you use. It works the same from a terminal in Xcode, Vim, Zed, a git hook, or a CI job.

tip

New here? Start with Get started with the CLI: install, then build and run your app in a few minutes. This page is the fuller tour.

Installing and updating

Install with Homebrew:

brew install sweetpad-dev/tap/sweetpad

Update it later the same way you update anything else with Homebrew:

brew upgrade sweetpad

You'll need Xcode installed too, since SweetPad uses Xcode's own tools to do the actual building.

How commands are shaped

Most commands read as a thing followed by an action, for example sweetpad simulator list or sweetpad scheme list. The common actions have a shortcut, so you can usually just say the thing:

  • sweetpad build builds your app.
  • sweetpad test runs your tests.
  • sweetpad run builds, launches, and shows the logs.

Not sure what's available? --help always works:

sweetpad --help # every command
sweetpad run --help # options for one command

Everyday commands

Start a project. sweetpad project new scaffolds a minimal SwiftUI app. Run it with no options for a short wizard, or pass a name to use defaults. Already have a project? Skip this and just cd into it.

sweetpad project new # answer a few questions
sweetpad project new MyApp # or use defaults

The rest of these run from inside your project folder.

Build and run. sweetpad run is the one you'll use most. It builds the app, launches it on your chosen simulator or device, and streams the logs into your terminal.

sweetpad run # build, launch, and follow logs
sweetpad run --on "iPhone 16 Pro" # ...on a specific simulator
sweetpad build # just build
sweetpad test # run the tests

Build and run and Testing cover these two in full.

See where you can run. sweetpad devices lists every simulator, connected device, and macOS, each with a copy-paste-ready name.

sweetpad devices

Look at your project. Handy when you're not sure what's inside a project:

sweetpad scheme list # the schemes SweetPad found
sweetpad project info # targets and configurations
sweetpad settings show # the resolved build settings
sweetpad dependency list # Swift Package dependencies

Project and dependencies covers these, including adding and updating packages.

Tidy up and fix things.

sweetpad format # format your Swift files
sweetpad clean # remove build artifacts
sweetpad doctor # check your Xcode setup for problems
sweetpad open xcode # open the project in Xcode

Formatting covers the formatter and its check mode; Troubleshooting starts from doctor and works outward.

Ship a build. sweetpad archive produces an .ipa you can upload or distribute. See Archive and distribute for export methods and signing.

sweetpad archive

There's more: simulator control, the app lifecycle beyond run, git merge drivers for .pbxproj conflicts, and shell completions among them. Projects generated by Tuist or XcodeGen work the same way, with a couple of guards that keep a stale project from misleading you. Run sweetpad --help to see the whole list, or browse the CLI reference for every command on one page.

Choosing where to run

Commands like build, run, and test need to know which scheme to build and where to run it. The easiest way to say where is --on, which understands plain descriptions:

sweetpad run --on "iPhone 16 Pro" # a simulator by name
sweetpad build --on mac # your Mac
sweetpad test --on booted # whatever simulator is already open

You usually don't have to say any of this, though. The first time you build in a project, SweetPad asks which scheme and destination to use, then remembers your answer so it won't ask again. Check what's currently chosen, and where each choice came from, with:

sweetpad status

To change or clear the remembered choices, use sweetpad context. Destinations and devices has all of this in detail: the full --on grammar, physical devices, aliases, and the raw specifier form for CI.

Passing options straight to xcodebuild

SweetPad has its own flags for the things you reach for daily, but it doesn't wrap all of xcodebuild. Anything you write after -- is handed to xcodebuild untouched, so one unusual option doesn't send you back to the raw tool:

sweetpad app install -- -allowProvisioningUpdates # let Xcode fix up signing
sweetpad build -- SWIFT_ACTIVE_COMPILATION_CONDITIONS="DEBUG STAGING"
sweetpad app install --device -- DEVELOPMENT_TEAM=ABCDE12345
sweetpad run -- -derivedDataPath ./build # build somewhere else

Both shapes work: xcodebuild's own flags, and KEY=VALUE build-setting overrides.

The commands that run a build take it: build, test, archive, run, app install, app debug, and app diagnose. The ones that only act on an app that's already installed (app launch, app stop, app logs, app uninstall) build nothing, so they turn a -- down rather than accept options that would go nowhere.

If your project always needs the same option, write it down instead of typing it every time. An [xcodebuild] args list in sweetpad.toml is added to every command that builds, and it's committed, so your whole team gets it:

# sweetpad.toml
[xcodebuild]
args = ["-skipMacroValidation"]

A -- you type is appended after the file's arguments, so it wins for anything they both set. sweetpad status shows the effective list, which helps when a build behaves differently than you expect and the reason is in a file you didn't write.

Live reload while you edit

sweetpad run --hot keeps your app running and applies each Swift file you save without a full rebuild, so the app updates in place, keeping its current screen and state. It works on the iOS Simulator and on native macOS apps, and there's nothing extra to install.

sweetpad run --hot

SwiftUI needs one small setup step. Hot reload walks through it.

Autocomplete in your editor

Swift's language server can't work out how an Xcode project compiles a file on its own. The CLI contains a build server that answers that question, and one command connects the two:

sweetpad bsp init

That's the whole setup, and it works in any editor with a language server: Neovim, Zed, Helix, Emacs. Editor autocomplete covers the details and what to do when completions go missing.

Saving your settings

If you'd rather not answer the scheme and destination prompt each time, or you want your whole team to share the same defaults, you can write them down.

  • Put your personal defaults in ~/.config/sweetpad/config.toml.
  • Put shared, checked-in defaults in a sweetpad.toml file next to your project, so everyone who clones the repo gets them.

Configuration has every key in both files, plus the rule for which one wins when they disagree. The same material is available offline with:

sweetpad help config

Using the CLI in scripts and CI

Every command can print JSON instead of text, which makes it easy to use from scripts, git hooks, and CI pipelines. Scripts and CI covers this properly: the envelope, the streaming mode, GitHub annotations, and a working workflow file. The short version: add --json for a single JSON result.

sweetpad --json settings show

A few options help in automation:

  • --non-interactive never stops to ask a question, so a missing scheme or destination becomes an error instead of a prompt. (SweetPad also turns this on automatically when it detects a CI environment.)
  • -C <folder> runs as if you'd started in that folder.
  • --gh-annotations makes build and test errors show up inline on your GitHub pull request.

Commands also return meaningful exit codes: 0 when everything's fine, and specific non-zero codes for a failed build, a missing tool, and so on, so a script can react to what happened. Run sweetpad help exit-codes for the list.

tip

When you ask for JSON, a successful response means "the command ran," not "the result was good." A failing test run, for example, still reports its own failure inside the result, so check the status in the payload rather than whether the command completed.

Built-in guides

Alongside --help on each command, the tool ships a few longer explanations you can read offline:

sweetpad help # list the guides
sweetpad help config # settings you can save
sweetpad help environment # every SWEETPAD_* variable
sweetpad help destinations # how to describe where to run
sweetpad help exit-codes # what each exit code means
sweetpad help hot-reload # setting up live reload

Shell completions

Turn on tab-completion for your shell. For example, with zsh:

sweetpad completions zsh > /path/to/completions/_sweetpad

Bash, zsh, fish, elvish, and PowerShell are all supported.

Controlling VS Code from the terminal

Everything above is standalone. One command group is not: sweetpad vscode talks to a running VS Code window so a script or an AI coding agent can trigger builds and read results inside your editor session.

note

This is the only part of the CLI that needs the VS Code extension installed and running. Skip it if you don't use VS Code, because nothing else on this page depends on it.

It's an advanced topic with its own page: Agent CLI & RPC server.