ReferenceSwift
Agent skill
Installable LLM skill for the Swift SDK (configure() + Client(user), evaluate, experiment + track, testing).
An installable agent skill for the Swift SDK. Fetch it with shipeasy docs skill --sdk swift (--install writes it to your agent skills dir), or copy it below — the YAML frontmatter installs with it.
---
name: shipeasy-swift
description: Use Shipeasy (feature flags, configs, kill switches, A/B experiments, i18n) from Swift. Covers configure() + Client(user), getFlag/getConfig/getExperiment/getKillswitch, track, testing, see() error reporting. Server-side SwiftPM SDK (iOS 15+/macOS 12+).
---
# Shipeasy Swift SDK
Server-side SDK (SwiftPM, iOS 15+/macOS 12+). Server-key only — never embed in a
shipped app bundle. All evaluation methods are `async` (the engine is a Swift
`actor`).
> The documented surface is exactly **`configure()`** (setup) and the bound
> **`Client(user)`** (use), plus the package-level helpers below. For deeper docs,
> fetch any page/snippet from the manifest at
> <https://shipeasy-ai.github.io/sdk-swift/manifest.json> (raw URLs below).
## Install
```swift
// Package.swift
.package(url: "https://github.com/shipeasy-ai/sdk-swift.git", from: "0.10.0"),
```
```swift
import Shipeasy
```
## Configure once, then a Client per user
```swift
// Once at startup. Builds the global engine + kicks off a one-shot fetch.
// Optionally map YOUR user object → the attribute map (runs in the Client ctor).
configure(apiKey: ProcessInfo.processInfo.environment["SHIPEASY_SERVER_KEY"]!) { user in
let u = user as! AppUser
return ["user_id": u.id, "country": u.region]
}
// Long-running server: configure(apiKey: key, poll: true) keeps flags fresh with
// a background poll — you never call initialize() yourself.
// Per request — methods take NO user arg (the user is bound). Throws
// NotConfiguredError if configure() hasn't run.
let client = try Client(["user_id": "u_123", "plan": "pro"]) // construct once per callsite
```
## Evaluate
```swift
let client = try Client(["user_id": "u_123"]) // construct once per callsite
let enabled = await client.getFlag("new_checkout") // Bool
let on = await client.getFlag("new_checkout", default: true) // default only when unevaluable
let detail = await client.getFlagDetail("new_checkout") // .value + .reason
let cfg = await client.getConfig("billing_copy", default: ["headline": "Hi"]) // Any?
let killed = await client.getKillswitch("panic_button") // true = killed
// Named switch: getKillswitch(name, switchKey:) — an unconfigured key falls back
// to the kill switch's top-level value.
```
Reference: <https://shipeasy-ai.github.io/sdk-swift/pages/configuration.md> ·
<https://shipeasy-ai.github.io/sdk-swift/pages/flags.md>
## Experiments + track (Client-only, end to end)
```swift
let client = try Client(["user_id": "u_123"]) // construct once per callsite
let r = await client.getExperiment("checkout_button", defaultParams: ["color": "blue"])
// r.inExperiment: Bool, r.group: String, r.params: Any?
await client.logExposure("checkout_button") // record where you present it
await client.track("purchase", properties: ["amount": 49]) // conversion for the bound user
```
Reference: <https://shipeasy-ai.github.io/sdk-swift/pages/experiments.md> · track
snippet <https://shipeasy-ai.github.io/sdk-swift/snippets/metrics/track.md>
## Testing (no network, no key)
```swift
// Seed values up front; reads go through the ordinary Client(user). Replaces
// prior config, so each test can reconfigure freely.
await configureForTesting(
flags: ["new_checkout": true],
configs: ["billing_copy": ["headline": "50% off"]],
experiments: ["checkout_button": (group: "treatment", params: ["color": "green"])]
)
let client = try Client(["user_id": "u_1"])
_ = await client.getFlag("new_checkout", default: false) // true
await overrideFlag("new_checkout", false) // flip on the spot
await clearOverrides() // drop every override (incl. the seed)
// Offline: evaluate the REAL rules from a snapshot or JSON file, no network.
try await configureForOffline(path: "shipeasy-snapshot.json")
```
Reference: <https://shipeasy-ai.github.io/sdk-swift/pages/testing.md>
## Error reporting — see()
```swift
do {
try chargeCard(order)
} catch {
see(error).causesThe("checkout").to("use the backup processor")
}
seeViolation("inventory_negative").extras(["sku": sku]).to("clamp to zero")
controlFlowException(error).because("expected — token expiry is normal") // reports nothing
```
Package-level `see(_:)` / `seeViolation(_:)` use the configured engine. Reference:
<https://shipeasy-ai.github.io/sdk-swift/pages/error-reporting.md> · snippet
<https://shipeasy-ai.github.io/sdk-swift/snippets/ops/see.md>
## Notes
- **No OpenFeature provider** in Swift — use `getFlag` / `getFlagDetail`.
Reference: <https://shipeasy-ai.github.io/sdk-swift/pages/openfeature.md>
- **i18n**: the server SDK has no `t()`. It emits SSR tags via package-level
`bootstrapScriptTag(_:...)` / `i18nScriptTag(_:profile:)`; the browser client
SDK renders translations. Reference:
<https://shipeasy-ai.github.io/sdk-swift/pages/i18n.md>
- Advanced: `privateAttributes`, `bucketBy`, sticky bucketing
(`StickyBucketStore`), `AnonId` helpers, package-level `onChange` (requires
`poll: true`), `logExposure`. Reference:
<https://shipeasy-ai.github.io/sdk-swift/pages/advanced.md>Was this page helpful?✎ Edit this page