Swift bridge

Run the zot agent natively inside iOS and macOS apps.

The Swift bridge runs zot's Go agent core natively inside iOS and macOS apps. It compiles the core into an Apple xcframework using gomobile and exposes a small, streaming, Swift-friendly API, so you get on-device chat that talks directly to Anthropic, OpenAI, or Gemini with no separate backend.

  • Native: ships as a binary xcframework, no Go toolchain needed by consumers.
  • Streaming: text deltas, tool events, usage, and errors arrive as they happen.
  • Cross-platform: one API for iOS and macOS.
  • Small surface: create a session, send a prompt, abort when needed.

Requirements

  • iOS 15+ or macOS 12+, with Xcode 15+.
  • A provider API key (Anthropic, OpenAI, or Gemini), or subscription OAuth credentials for Claude/ChatGPT.

Install

In Xcode use File > Add Package Dependencies and enter the repo URL, or add it to your Package.swift:

swift
dependencies: [
    .package(url: "https://github.com/patriceckhart/zot-swift-bridge", from: "0.0.1")
]

Quick start

Conform to ZotStreamProtocol to receive streaming output, create a session, then send a prompt. prompt() blocks until the turn ends, so run it off the main thread.

swift
import Zot

final class ChatStream: NSObject, ZotStreamProtocol {
    func onText(_ delta: String?) {
        print(delta ?? "", terminator: "")
    }
    func onEvent(_ kind: String?, payload: String?) {
        // kind: tool_call, tool_progress, tool_result, turn_start, turn_end, usage
    }
    func onError(_ message: String?) { print("error:", message ?? "") }
    func onDone() { print("\n[done]") }
}

var error: NSError?
let session = ZotNewSession(
    "anthropic",                    // anthropic | openai | openai-responses | gemini
    apiKey,
    "claude-sonnet-4-5",            // "" uses the provider default
    "You are a concise assistant.", // system prompt (optional)
    &error
)

Task.detached {
    session?.prompt("Explain async/await in Swift in two sentences.", stream: ChatStream())
}

Call session?.abort() to cancel an in-flight response.

API

CallDescription
ZotNewSessionCreate a session with an API key: ZotNewSession(provider, apiKey, model, systemPrompt, &error). Pass "" for model to use the provider default.
ZotNewSessionWithOAuthCreate a session from subscription OAuth credentials: ZotNewSessionWithOAuth(provider, accessToken, accountID, model, systemPrompt, &error).
ZotExtractOpenAIAccountIDParse the ChatGPT account id from an OpenAI OAuth id_token: ZotExtractOpenAIAccountID(idToken).
session.promptSend one user message and stream the reply (session.prompt(_:stream:)). Blocks until the turn completes.
session.abortCancel the active prompt, if any (session.abort()).

Stream callbacks

CallbackWhen
onTextA chunk of assistant text. Concatenate to build the full reply.
onEventA lifecycle/tool event with a JSON payload string.
onErrorA non-fatal error occurred.
onDoneThe turn finished (success or failure).

Providers

API-key providers: anthropic, openai, openai-responses, gemini. Subscription OAuth providers: anthropic and openai-codex (the ChatGPT Plus/Pro Codex route, which needs both an OAuth access token and the ChatGPT account id from the OAuth id_token).

Subscription OAuth

The bridge does not run the OAuth browser login itself. Collect tokens with your own native flow (for example ASWebAuthenticationSession), then pass the access token to ZotNewSessionWithOAuth. Refresh and secure storage are the app's responsibility.

Security

Do not hardcode provider keys or OAuth tokens in a shipped app; users can extract them. Prefer user-supplied credentials, Keychain storage, or a proxy server. iOS cannot run zot's desktop shell, filesystem, or subprocess tools, and the bridge registers none of them, so it stays inside the App Store sandbox.

Source and full docs: https://github.com/patriceckhart/zot-swift-bridge.