A complete iPhone chat app that streams Claude, built on Swift Chat's assistant style
See the codeA complete iPhone chat app that streams answers from Claude, built on Swift Chat’s assistant style. Your question rises to the top of the screen and the answer streams in under it as Markdown, the way Siri and ChatGPT answer.
SwiftChatAIStarter.xcodeproj in Xcode 26 and run it on an iPhone or the simulator.| File | What it does |
|---|---|
AssistantView.swift | The whole UI: one Chat with .chatStyle(.assistant) and a few modifiers |
Conversation.swift | Holds the thread, appends one reply per answer and rewrites its text as tokens arrive |
ClaudeRequest.swift | Builds the Messages API request from the thread, including photos |
ClaudeClient.swift | Streams the reply over server-sent events with URLSession |
KeychainStore.swift | Keeps the API key in the Keychain |
The UI is these few lines:
Chat(conversation.entries, typingUsers: conversation.isWaiting ? [Conversation.assistant] : []) { entry in
Message(entry.text, role: entry.role, timestamp: entry.sentAt)
.messageMedia(entry.media)
}
.chatStyle(.assistant)
.chatTypingStatus(conversation.status)
.chatInputCapabilities([.camera, .photoLibrary])
.onChatSend { text, media in
await conversation.send(text, media: media)
}
The app sends your key straight to api.anthropic.com, which is fine on your own phone and wrong in an app other people install. Put a small server in front of the API, call it from ClaudeClient, and keep the key there.
Requests use claude-opus-5-5 at low effort, which suits chat. They opt into server-side fallbacks (fallbacks: "default"), so a request a safety classifier declines is retried on another model instead of failing. Change any of this in ClaudeRequest.swift.
MIT. Swift Chat itself is free to use in any app; see its license.
A complete iPhone chat app that streams Claude, built on Swift Chat's assistant style
See the codeA complete iPhone chat app that streams answers from Claude, built on Swift Chat’s assistant style. Your question rises to the top of the screen and the answer streams in under it as Markdown, the way Siri and ChatGPT answer.
SwiftChatAIStarter.xcodeproj in Xcode 26 and run it on an iPhone or the simulator.| File | What it does |
|---|---|
AssistantView.swift | The whole UI: one Chat with .chatStyle(.assistant) and a few modifiers |
Conversation.swift | Holds the thread, appends one reply per answer and rewrites its text as tokens arrive |
ClaudeRequest.swift | Builds the Messages API request from the thread, including photos |
ClaudeClient.swift | Streams the reply over server-sent events with URLSession |
KeychainStore.swift | Keeps the API key in the Keychain |
The UI is these few lines:
Chat(conversation.entries, typingUsers: conversation.isWaiting ? [Conversation.assistant] : []) { entry in
Message(entry.text, role: entry.role, timestamp: entry.sentAt)
.messageMedia(entry.media)
}
.chatStyle(.assistant)
.chatTypingStatus(conversation.status)
.chatInputCapabilities([.camera, .photoLibrary])
.onChatSend { text, media in
await conversation.send(text, media: media)
}
The app sends your key straight to api.anthropic.com, which is fine on your own phone and wrong in an app other people install. Put a small server in front of the API, call it from ClaudeClient, and keep the key there.
Requests use claude-opus-5-5 at low effort, which suits chat. They opt into server-side fallbacks (fallbacks: "default"), so a request a safety classifier declines is retried on another model instead of failing. Change any of this in ClaudeRequest.swift.
MIT. Swift Chat itself is free to use in any app; see its license.