SpecterQA iOS
AI-driven iOS testing that records once and replays free in CI — no AI cost on repeat runs.
Install
pip install "git+https://github.com/SyncTek-LLC/specterqa-ios.git"
Quick Start with Claude Code (MCP)
pip install 'specterqa-ios[mcp]'
Add to .claude/mcp.json:
{
"mcpServers": {
"specterqa-ios": {
"command": "specterqa-ios-mcp",
"env": { "ANTHROPIC_API_KEY": "sk-ant-..." }
}
}
}
Then in Claude Code: "Run a smoke test on the Palace app, record it as palace-smoke". Claude drives the simulator, records every action. After that, CI runs it free — no AI involved.
Your First Session (30 seconds)
# Claude calls these 6 MCP tools in order:
ios_start_session(bundle_id="com.example.app")
ios_screenshot() # see what's on screen
ios_tap(label="Sign In") # tap by label
ios_screenshot() # verify result
ios_stop_recording(name="signin-smoke") # save replay YAML to .specterqa/replays/
ios_stop_session() # clean up
The replay YAML is now in .specterqa/replays/signin-smoke.yaml. Run it in CI with:
specterqa-ios replay .specterqa/replays/signin-smoke.yaml
No AI needed on replay — it runs the deterministic engine directly.
Dual-Mode Architecture
| Phase | Who drives | Cost |
|---|---|---|
| Record (once) | Claude AI via MCP | AI tokens |
| Replay (every CI run) | Deterministic replay engine | Free |
Record once with Claude, replay forever without it. This is the key advantage over traditional frameworks.
Maestro-Compatible YAML
Users migrating from Maestro can use familiar shorthand — SpecterQA understands it natively:
replay:
bundle_id: com.example.app
steps:
- tapOn: "Sign In" # same as: action: tap, element_label: Sign In
- inputText: "user@example.com"
- assertVisible: "Dashboard" # asserts element is present
- assertNotVisible: "Loading"
- waitFor: "Feed" # waits up to 10s for element
All Maestro shortcuts work alongside native SpecterQA syntax in the same file.
CI Commands
# Run all replays (shared runner on by default — ~10x faster)
specterqa-ios ci .specterqa/replays/
# Parallel execution — run 4 replays simultaneously
specterqa-ios ci --parallel 4
# Per-replay isolation (full reset between each replay)
specterqa-ios ci --no-reuse-runner
# Validate a replay file before running it
specterqa-ios validate-replay .specterqa/replays/smoke.yaml
Full CLI Reference
| Command | Description |
|---|---|
setup |
Check Xcode, simulators, API key |
devices |
List available iOS simulators |
boot |
Boot a simulator |
install <app.app> |
Install app on simulator |
init |
Scaffold .specterqa/ project files |
validate --product <slug> |
Validate product/journey config |
validate-replay <file> |
Validate a replay YAML (schema + references) |
run --product <slug> --journey <id> |
Run a test journey (AI-driven) |
smoke --product <slug> |
Quick smoke test |
replay <file> |
Replay a recorded session |
ci [dir] |
Run all replays in CI mode |
serve |
Start the MCP server |
vs. Maestro / Appium / XCUITest
| SpecterQA | Maestro | Appium | XCUITest | |
|---|---|---|---|---|
| No AI in CI | Yes | Yes | Yes | Yes |
| AI-assisted recording | Yes | No | No | No |
| Maestro YAML syntax | Yes | Native | No | No |
| Parallel CI | Yes (--parallel N) |
No | Yes | Yes |
| Zero config | Yes | Yes | No | No |
| Claude Code native | Yes (MCP) | No | No | No |
Physical device support (experimental)
SpecterQA can drive a connected iOS device (iPhone or iPad) in addition to the simulator. Physical device support uses devicectl-based deployment and communicates with the XCTest runner over the device's IP address, exactly as in the simulator path.
To opt in, set the environment variable SPECTERQA_ALLOW_PHYSICAL_DEVICE=1 and pass device_type="physical" when calling ios_start_session:
export SPECTERQA_ALLOW_PHYSICAL_DEVICE=1
# In your MCP tool call:
ios_start_session(bundle_id="com.example.app", device_id="<device-udid>", device_type="physical")
Call ios_get_capabilities() first to confirm the physical device type is advertised and check whether opt_in_active is true. Known limitations: xcodebuild integration has rough edges on iOS 26 that can cause intermittent failures; the install/deploy step is slower than the simulator path; and there is no guarantee of stability on non-GM OS builds. The simulator (device_type="simulator", the default) remains the fully supported path.
Requirements
- macOS + Xcode 15+
- Python 3.10+
ANTHROPIC_API_KEY(recording only — not needed for replay)
License
Elastic License 2.0 — see LICENSE.
Metadata
Release files for specterqa-ios 15.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| specterqa_ios-15.2.0.tar.gz | 371.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| specterqa_ios-15.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 709.9 kB
Release files / specterqa_ios-15.2.0.tar.gz
| Download URL | specterqa_ios-15.2.0.tar.gz |
|---|---|
| Size | 371.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
65854d3d8465f2a0f4f9e1efb8d040ea0e6152e9fbf0903a412bd861f6fe9f61
|
|
BLAKE2b-256 checksum How to use checksums |
0cec6f19846414da45bef20cc2a094e0390a1208adf0f04d2282c94b075cec93
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / specterqa_ios-15.2.0-py3-none-any.whl
| Download URL | specterqa_ios-15.2.0-py3-none-any.whl |
|---|---|
| Size | 338.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
02d187adfe7d2189144aa07f9013570d0de43463bececf1370bbc5ad4abc581b
|
|
BLAKE2b-256 checksum How to use checksums |
12c048ca434873c52f70daf9ee16ff46b0b718f97ed114f57640cd923cf9a05b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|