npm.io
0.0.1 • Published 2d agoCLI

@xsim/cli

Licence
Version
0.0.1
Deps
2
Size
96 kB
Vulns
0
Weekly
0

XSim

XSim is a small Node.js CLI for building, seeding, and replaying iOS Simulator profiles from YAML.

It helps you:

  • scaffold a profile from an Xcode project or workspace
  • seed simulator state with files, media, permissions, location, push notifications, clipboard content, and app data
  • launch a fresh simulator from that profile
  • record new AXe launch steps back into the profile
  • clone a booted simulator into a reusable profile
  • tear down generated simulators when you are done

Requirements

  • macOS
  • Node.js 18 or newer
  • Xcode command line tools
  • xcodebuild and xcrun available on PATH
  • AXe available on PATH, or Homebrew so xsim init can install it for you
  • swift on PATH if you want to use xsim record

xsim init checks for AXe and installs it with Homebrew if it is missing.

Quick Start

Choose one of these two setup paths. Most people will use the default profile, so the examples below assume default unless noted otherwise.

Option 1: Install from npm

Install the package globally:

npm install -g @xsim/cli

Then verify the CLI is available:

xsim --help

From there, create a profile and launch it:

xsim init .
xsim launch

If you omit the profile name, default is used.

Option 2: Clone the repo locally

Use this path if you want to make changes and test them from your own checkout.

git clone <repo-url>
cd xsim-cli
npm install
npm run link

That makes the local xsim command available globally from this checkout.

To remove the global symlink later:

npm run unlink

Once linked, you can create and launch a profile the same way:

xsim init .
xsim launch

That will search upward and downward from the path you pass to find the Xcode project or workspace, detect a default scheme, and write a profile under .xsim/default/.

What XSim Creates

An initialized profile lives alongside your project:

your-project/
  .xsim/
    default/
      config.yml
      files/
      media/
      DerivedData/

Some commands may add more folders:

.xsim/
  default/
    appData/
    apps/

These are used when cloning simulators or restoring captured app data.

How It Works

At a high level, xsim launch does this:

  1. Finds the .xsim/<profile> directory.
  2. Reads config.yml.
  3. Resolves the Xcode project and scheme.
  4. Creates a new simulator with a generated display name like XSIM Default #ABCDE.
  5. Boots the simulator.
  6. Applies appearance, locale, location, and status bar overrides.
  7. Applies keychain, media, files, app data, permissions, clipboard, and push notification seed data.
  8. Builds the app from the detected scheme or installs a copied app bundle.
  9. Launches the app.
  10. Runs AXe launch steps, if any are configured.

The command prints the new simulator UUID on success.

Commands

xsim init <path> [name]

Creates a new profile for a project.

What it does:

  • discovers the Xcode project or workspace starting at <path>
  • resolves a default scheme with xcodebuild -list -json
  • creates .xsim/<name>/
  • writes config.yml
  • creates files/, media/, and DerivedData/

Options:

  • -f, --force overwrite an existing profile

Examples:

xsim init .
xsim init ~/Projects/MyApp staging
xsim init ~/Projects/MyApp staging --force
xsim launch [name]

Creates, seeds, and launches a simulator from a profile.

What it does:

  • finds .xsim/<name>
  • reads the profile config
  • creates a simulator using the configured or default device/runtime
  • applies all configured seed blocks
  • builds the app from the project scheme, or installs a cloned app bundle if the profile points to one
  • launches the app
  • runs any AXe batch steps in launchSteps

Options:

  • -q, --quiet suppress progress output and print only the simulator UUID

Examples:

xsim launch
xsim launch staging
xsim launch staging --quiet
xsim clone [name]

Clones a booted simulator into a new profile.

What it does:

  • prompts for a booted simulator if more than one is available
  • picks a running app when possible, otherwise a user app
  • tries to reuse an existing .xsim profile that matches the source simulator name
  • copies the source profile’s files/ and media/ folders when a matching profile exists
  • captures the selected app’s data container and app group containers into appData/
  • copies the app bundle into apps/ when no matching source profile exists
  • writes a new profile config

Options:

  • -q, --quiet suppress progress output

Examples:

xsim clone
xsim clone debug-profile
xsim record [name]

Launches a profile, then records new simulator interactions as AXe steps.

What it does:

  • locates the profile root
  • lets you choose a profile if one is not provided
  • boots a seeded simulator
  • starts a lightweight recorder that listens for mouse and keyboard events while the Simulator is frontmost
  • replays any existing launchSteps first
  • appends newly captured steps to config.yml

Options:

  • -q, --quiet suppress progress output

Notes:

  • you need swift installed
  • the terminal or shell must have Accessibility permissions so event capture can work

Example:

xsim record
xsim teardown [uuid]

Deletes simulator devices created by XSim.

What it does:

  • if you pass a UUID, it shuts down and deletes that simulator and removes its device directory
  • if you omit the UUID, it deletes every simulator whose name matches XSIM <profile> #ABCDE

Examples:

xsim teardown
xsim teardown 12345678-1234-1234-1234-123456789ABC

Profile Layout

The profile is just a directory with YAML and seed assets.

.xsim/<profile>/
  config.yml
  files/
  media/
  DerivedData/
  appData/
  apps/
  • config.yml controls simulator settings and seed behavior.
  • files/ is copied into the simulator’s iCloud Drive XSim/<profile>/ folder.
  • media/ is imported with simctl addmedia.
  • DerivedData/ is used as the build output directory.
  • appData/ stores captured app data snapshots for restore.
  • apps/ stores copied app bundles when cloning a simulator without an existing source profile.

Configuration Reference

config.yml is written in YAML and merged with a default schema.

Here is a simplified example:

version: 1
name: default
project:
  path: /absolute/path/to/MyApp.xcodeproj
  kind: xcodeproj
  root: /absolute/path/to
  scheme: MyApp
simulator:
  displayName: XSIM Default
  device: latest
  runtime: latest
  appearance: light
  locale: en_US
  language: en
permissions:
  photos: true
statusBar:
  time: "09:41"
  dataNetwork: wifi
  wifiMode: active
  batteryState: charged
  batteryLevel: 100
location:
  latitude: 37.3349
  longitude: -122.00902
keychain:
  reset: true
  rootCerts:
    - certs/root-ca.cer
pushNotifications:
  - bundleId: com.example.myapp
    payload:
      aps:
        alert:
          title: Hello
          body: Seeded push notification
clipboard:
  text: Hello from XSim
appData:
  - bundleId: com.example.myapp
    source: appData/com.example.myapp
launchSteps:
  steps:
    - tap --label "Continue"
    - sleep 1
    - type "Hello from XSim"
  options:
    waitTimeout: 2
    continueOnError: false
project
  • path points to the discovered .xcodeproj or .xcworkspace
  • kind is xcodeproj, xcworkspace, or app
  • root is the directory that contains the project bundle
  • scheme is the selected Xcode scheme
simulator

Supported fields include:

  • displayName
  • device
  • runtime
  • appearance
  • locale
  • language

The display name is turned into a real simulator name like XSIM Default #ABCDE.

permissions

Permissions are mapped to simctl privacy.

You can use:

  • true to grant
  • false to revoke
  • null to skip

Example:

permissions:
  camera: true
  photos: false
statusBar

statusBar is passed to simctl status_bar.

You can use direct overrides:

statusBar:
  time: "09:41"
  dataNetwork: wifi
  wifiMode: active
  batteryLevel: 100

You can also use:

statusBar:
  clear: true
  override:
    time: "12:00"
location

location is passed to simctl location.

Supported forms include:

location:
  latitude: 37.3349
  longitude: -122.00902
location:
  coordinate: "37.3349,-122.00902"
location:
  scenario: "gpx-route-name"
keychain

Controls simulator keychain seeding.

Supported fields:

  • reset
  • rootCerts
  • certs

Example:

keychain:
  reset: true
  rootCerts:
    - certs/root-ca.cer
  certs:
    - certs/client.cer
pushNotifications

Each entry can provide a bundle ID and either inline payload data or a file path.

Examples:

pushNotifications:
  - bundleId: com.example.myapp
    payload:
      aps:
        alert:
          title: Hello
          body: World
pushNotifications:
  - file: push/welcome.apns
clipboard

Sets the initial pasteboard contents.

Example:

clipboard:
  text: Hello from XSim

You can also use a plain string:

clipboard: Hello from XSim
appData

Two modes are supported:

  • point to a snapshot directory created by xsim clone
  • point to a .xcappdata package

Examples:

appData:
  - bundleId: com.example.myapp
    source: appData/com.example.myapp
appData:
  - path: snapshots/MyApp.xcappdata
launchSteps

Launch steps are run through AXe after the app launches.

You can provide:

  • steps: an array of inline AXe batch steps
  • file: a batch file path
  • options: additional AXe batch flags

Example:

launchSteps:
  steps:
    - tap --label "Continue"
    - sleep 1
    - type "hello"
  options:
    waitTimeout: 2
    continueOnError: false

Recorded steps are appended to the existing launchSteps.steps array.

Examples

Create a new profile
xsim init .
Launch it
xsim launch
Seed a different simulator size or runtime
simulator:
  device: iPhone 16 Pro
  runtime: latest
Add a root certificate and clipboard text
keychain:
  rootCerts:
    - certs/root-ca.cer
clipboard:
  text: "Logged in as demo@example.com"
Seed a location and a push notification
location:
  latitude: 37.3349
  longitude: -122.00902
pushNotifications:
  - bundleId: com.example.myapp
    payload:
      aps:
        alert:
          title: Welcome
          body: Your profile is ready
Record a fresh flow
xsim record

Then interact with the app, press Enter in the terminal when finished, and the new AXe steps are appended to config.yml.

Notes and Limits

  • xsim launch expects a valid Xcode project, workspace, or app bundle path in the profile config.
  • xsim record only captures interactions while the Simulator is frontmost.
  • xsim clone and xsim teardown work against simulators managed by CoreSimulator.
  • If a configured path is relative, XSim resolves it relative to the profile directory.

Contributing

See CONTRIBUTING.md for development guidelines.

License

This project is licensed under the MIT License. See LICENSE.