ThreadAI

A production-quality iOS AI chat app with branching sub-thread conversations.
Powered by OpenAI · Your keys · Beautiful SwiftUI.

iOS 17+ Swift 5.9+ SwiftUI OpenAI API No Dependencies
App Overview · 2025
What is ThreadAI

AI chat that thinks in branches

Most AI chat apps are linear — one conversation, one direction. ThreadAI introduces sub-threads: fork any message into a new branch, where the parent conversation is automatically carried as context. Explore multiple directions, compare approaches, or dive deep on one idea — all without losing the original thread.
Core Features

Everything you need, nothing you don't

🧵

Thread-Based Conversations

The defining feature. Fork any message into a sub-thread — the parent conversation context is carried forward automatically. Sub-threads appear as inline cards inside the parent chat. Nesting is unlimited and context builds recursively.

  • Fork via long-press context menu on any message
  • Parent messages up to the fork point are included as AI context
  • Sub-threads listed inline and in the thread list sheet
  • Arbitrary nesting — sub-threads of sub-threads work perfectly
  • Optional custom system prompt per sub-thread

Real-Time Streaming

Responses stream token-by-token with a live blinking cursor. Stop generation at any time — the partial response is preserved.

  • JSON-line streaming over URLSession
  • Typing indicator before first token
  • Buffered rendering to avoid UI thrash
  • Stop button with immediate cancellation
📝

Full Markdown Rendering

AI responses render with complete markdown support, including syntax-highlighted code blocks.

  • Headers, bold, italic, inline code
  • Bullet lists and ordered lists
  • Block quotes with accent left bar
  • Code blocks with language label + copy button
  • Text selection on all content
🔖

Bookmarks

Save any AI message with a long-press. Each bookmark gets a short auto-generated title for easy identification.

  • Dedicated Bookmarks tab across all conversations
  • Tap to navigate directly to the source message
  • Swipe to remove bookmarks
  • Sorted by recency
🗂️

Conversation Management

Keep your conversations organised with search, pinning, and inline sub-thread previews.

  • Pin conversations to top of list
  • Search by conversation title
  • Swipe to delete conversations
  • Sub-thread previews inline (up to 3 + "+N more")
  • Custom system prompt per conversation
🔐

Secure API Key Management

Your API keys are stored in the iOS Keychain and never leave your device except to reach the AI provider directly.

  • Keychain storage only — never UserDefaults or logs
  • Live validation via 1-token test request
  • Status: Not Set / Validating / Valid / Invalid
  • Keychain-scoped per provider
AI Support

OpenAI — two models

OpenAI
openai api · json-line streaming
GPT-4o GPT-4o mini
Context window: 128,000 tokens

Switch model mid-conversation from the chat toolbar. Adding a new provider requires only a single file that conforms to the AIProvider protocol — nothing else changes.

Architecture

MVVM + Clean Architecture

Presentation
SwiftUI Views
@Observable ViewModels
Domain
Entities
Use Cases
Repo Protocols
Data
CoreData
Repo Impls
Keychain
AI Harness
AIProvider Protocol
OpenAIProvider
OpenAIProvider

Strict one-way dependency flow · Domain has zero framework imports · Providers are plug-and-play

Use Cases

Business logic is explicit and isolated

Use Case What it does
SendMessageUseCase Sends a user message and handles the streaming AI response. Saves both messages to CoreData via the repository.
BuildContextChainUseCase Recursively walks the thread ancestry to assemble the full message context for the AI request. Handles arbitrary nesting depth and excludes messages after the fork point in parent threads.
CreateSubThreadUseCase Forks a sub-thread from a specific message, linking it to the parent conversation with the fork message ID. Creates the new CDConversation record.
BookmarkMessageUseCase Toggles a bookmark on a message. Auto-generates a short title from the message content. Persists via MessageRepository.
Tech Stack

Modern Swift, zero third-party dependencies

Language
Swift 5.9+
UI Framework
SwiftUI only
iOS Target
iOS 17+
State Management
@Observable macro
Persistence
CoreData
Concurrency
Async/Await + AsyncThrowingStream
Security
Keychain Services
Networking
URLSession + SSE
Dependencies
None
Code Quality

Production-grade standards

🚫
No force unwraps Zero ! operators in production code. All optionals are handled explicitly.
🪵
OSLog only No print() in production. Structured logging via Apple's Logger API.
🔑
Keychain-only key storage API keys never touch UserDefaults, logs, or plain files. Keychain with device lock protection.
⚠️
No silent errors All async functions surface errors. No silent try? swallowing.
📏
400-line view cap No SwiftUI view file exceeds 400 lines. Components are extracted into their own files.
🌐
Localisation-ready No hardcoded UI strings. All text uses LocalizedStringKey.
Getting Started

Up and running in under 5 minutes

1

Clone the repository

git clone git@github.com:dsngeu/ThreadAI.git
open ThreadAI.xcodeproj

2

Build and run

Select a simulator or device in Xcode and press Run. No package manager, no pod install, no swift package resolve — zero third-party dependencies.

3

Add your API keys

Open the Settings tab in the app. Tap OpenAI API Key, paste your key, and tap Validate & Save. The app makes a live 1-token test before storing the key in Keychain.

4

Start your first conversation

Tap the compose button, choose a model, and start chatting. Long-press any AI message to fork a sub-thread or bookmark it.

Requirements

What you need

Xcode
15.0 or later
Target device
iOS 17+ (device or sim)
API Key
OpenAI
Project Structure

Where to find things

Path What lives here
App/ Entry point (ThreadAIApp.swift) and dependency wiring (AppDependencies.swift)
Core/AIHarness/ AIProvider protocol, OpenAIProvider, AIHarnessService, all AI models
Core/Domain/ Pure Swift entities (Conversation, Message, Bookmark), UseCases, Repository protocols
Core/Data/ CoreData stack, repository implementations, CoreData ↔ Domain mappings, Keychain service
Features/Chat/ Chat UI: ChatView, MessageBubbleView, StreamingBubbleView, ChatInputBar, CodeBlockView, threading sheets
Features/ConversationList/ Conversation list with search, pin, sub-thread preview cards, create sheet
Features/Bookmarks/ Bookmarks tab: list of saved messages with navigation back to source
Features/Settings/ API key entry and validation, app version info
Shared/UI/Theme/ AppColors, AppTypography, AppSpacing — the design token system
Shared/UI/Components/ MarkdownContentView (full markdown parser), CodeBlockView