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.
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 buildbuilds your app.sweetpad testruns your tests.sweetpad runbuilds, 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.tomlfile 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-interactivenever 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-annotationsmakes 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.
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.
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.