Disk snapshots
Use a disk snapshot to carry source files, dependencies, and Xcode's DerivedData into your next instance. Snapshots belong to your organization. Without snapshot configuration, a new instance starts without a saved workspace.
Save and reuse a disk snapshot
With the CLI installed and LIM_API_KEY set, run these commands from your project directory. Replace MyApp with your scheme:
XCODE_ID=$(lim xcode create --snapshot-key myapp-main --quiet)
lim xcode build . --id "$XCODE_ID" --scheme MyApp
lim xcode delete "$XCODE_ID" --wait-snapshotThe first run builds from scratch. After a successful build, deleting the instance saves its workspace under myapp-main. Run the same sequence again to restore that snapshot before building. Each successful publication replaces the previous archive under that key.
--wait-snapshot waits for publication and prints its result. Without it, deletion returns while publication continues in the background. Wait for publication before starting a build that needs the new snapshot. In CI, put the delete command in a cleanup step that runs even if the build fails.
Leave --snapshot-paths unset to save the whole workspace. This keeps source files and their sync state alongside DerivedData so Xcode can reuse unchanged build outputs. --basis-cache-dir is a separate, local cache for source uploads; it does not preserve remote build state.
You can keep building on the same running instance without restoring again. The saved snapshot is for future instances and is only published when this instance terminates.
Restore from another branch
Use --snapshot-key for the destination and --snapshot-restore-keys for an ordered list of sources. For example, restore a pull request's previous snapshot, falling back to main, then save under the pull request's key:
XCODE_ID=$(lim xcode create \
--snapshot-key myapp-pr51 \
--snapshot-restore-keys "myapp-pr51,myapp-main" \
--quiet)
lim xcode build . --id "$XCODE_ID" --scheme MyApp
lim xcode delete "$XCODE_ID" --wait-snapshotFor each restore key, Limrun tries an exact match, then the most recently published snapshot whose key starts with that prefix. It moves to the next restore key only if neither matches. Prefixes are literal; no * is needed. With no match, the instance starts cold and can save a new snapshot after building.
When --snapshot-restore-keys is omitted, --snapshot-key is also the restore key. When you supply a restore list, include the destination key yourself if you want to try it first.
To consume a snapshot without replacing it, create an instance with only restore keys:
lim xcode create --snapshot-restore-keys myapp-mainBuild on that instance as usual and delete it when finished. It will not publish a snapshot unless you explicitly bind a destination key later.
Use keys that identify the project and Xcode version, such as myapp-xcode27-main. Keep fallbacks within the same Xcode version. For concurrent CI jobs, use separate destination keys to avoid overwriting each other's results.
Configure disk snapshots before the build
Set snapshot options on lim xcode create for predictable behavior. Restore keys and snapshot paths are fixed when the instance is created. --reuse-if-exists keeps the reused instance's original configuration.
lim xcode build --snapshot-key ... also works when the command creates a new instance. On an existing instance, it only binds a save destination to a workspace already prepared for snapshots. It does not restore a snapshot or enable snapshots on an instance created without snapshots. Once a destination key is set, it cannot be changed for that instance.
Understand a cold build or skipped save
- Keep the synced project folder's name the same between runs. A different folder name puts the source at a different remote path, so Xcode cannot reuse the previous build state.
- Changing Xcode versions clears incompatible cached build state. Use a separate snapshot key for each version.
- A restore must use the same snapshot path set as the saved archive. Use a new key if you change that set.
- A failed compile or cancelled build does not produce a new snapshot. A test build can still save its snapshot if compilation succeeds but tests fail. Syncing changes after a successful build prevents saving until another build succeeds. Running commands with
lim xcode runalone does not qualify a workspace for publication. - A concurrent instance using the same restored workspace on the same host can cause a cold fallback with saving disabled. The CLI reports the restore outcome; check the
--wait-snapshotoutput for the save outcome.
Use the TypeScript SDK
Pass the same settings as spec.snapshot. Wait for the restore before syncing, build, then delete the instance to trigger publication:
import Limrun from '@limrun/api';
const lim = new Limrun({ apiKey: process.env['LIM_API_KEY'] });
const instance = await lim.xcodeInstances.create({
wait: true,
spec: {
snapshot: {
key: 'myapp-pr51',
restoreKeys: ['myapp-pr51', 'myapp-main'],
},
},
});
try {
const { snapshot, gone } = await lim.xcodeInstances.followSnapshot(instance.metadata.id);
if (gone || snapshot.restore.phase === 'failed') {
throw new Error(snapshot.restore.message ?? 'Disk snapshot restore did not complete');
}
const xcode = await lim.xcodeInstances.createClient({ instance });
await xcode.sync('./my-app');
const result = await xcode.xcodebuild({ scheme: 'MyApp' });
if (result.exitCode !== 0) throw new Error(`Build ${result.status}`);
} finally {
await lim.xcodeInstances.delete(instance.metadata.id);
}SDK deletion returns before publication finishes. To track progress, use getSnapshot(id) for the current state or followSnapshot(id, { side: 'save' }) for updates. Start the save watcher and wait for its onOpen callback before deleting, so it can observe publication before the instance disappears. A save phase of published confirms success; skipped means nothing was saved.
Existing --cache-* flags, --wait-cache, spec.cache, and cache-named SDK methods remain supported for compatibility. Use the snapshot names in new integrations.
Was this guide helpful?