Cumbersome: AI LLM API Client
API to ChatGPT, OpenAI, Ollama
Free
IMPORTANT: Requires your own API keys from OpenAI, Anthropic, OpenRouter, Google AI Studio, Z.ai, or Vercel AI Gateway, or your own OpenAI-compatible endpoint.
I built Cumbersome because consumer AI apps kept dumbing things down. Cumbersome is the manual transmission of AI apps: more complex, but with far greater control.
WHY I BUILT THIS
Consumer AI providers like ChatGPT and Claude route requests to cheaper models to keep their costs down. They charge monthly subscriptions whether you use them once or a thousand times. They hide the technical controls that let you tune how models respond. And they lock you into one provider.
I wanted an AI client that connects directly to AI provider APIs. I wanted to pick exactly which model I use and know I'm getting it. I wanted to compare different models on the same prompt. I wanted to pay per use instead of subscriptions. So I built it.
SUPPORTED PROVIDERS
Bring your API keys, or add your own OpenAI-compatible endpoint, for any of the following:
— ChatGPT / OpenAI
— Claude / Anthropic
— Gemini / Google AI Studio
— OpenRouter multi-provider
— Vercel AI Gateway multi-provider
— Z.ai
— OpenAI-compatible custom endpoints (beta), including Ollama, Azure, LM Studio, Groq, Together, and self-hosted backends
WHAT YOU GET
— A simple API client.
— Switch providers or AI models mid-conversation.
— NEW! Local browser tool use. AI can use your local browser to search and browse pages.
— iCloud sync across devices. (Nothing saved to our servers.)
— Face/Off Mode. Three responses generated at once. An AI judge picks the best.
— Extended thinking. Turn on model reasoning for OpenAI and OpenRouter.
— Full parameter control. Temperature, tokens, system prompts. API playground controls on your phone.
— Concurrent chats. Multiple conversations streaming in parallel.
— Edit any message. Remove tangents, fix mistakes, reshape your conversation history.
— Rich content. Markdown, LaTeX math, code blocks with copy, attachments.
— Export everything. Copy conversations, export JSON, or share deep links to specific chats.
— Collapse long messages. Fold them to keep your place in deep conversations.
— Siri and Shortcuts. Ask questions hands-free or build automations in the Shortcuts app.
— Accessible. VoiceOver, Dynamic Type, Voice Control, full keyboard navigation, reduced motion.
— Native on iPhone, iPad, and Mac.
THE DEAL
The app is free. You pay providers directly for API access.
I'm Peter, an indie developer in Portland, Oregon. No VC money. No growth hacking. Just a tool I wanted to exist.
more I have looked around for different LLM API Clients for a while now and this one is definitely the best one I’ve tried by far. It has sync with iCloud so I can use it with my Mac, headless search (didn’t even know that was possible), and easy access to all the models you want (I use DeepInfra). Honestly can’t believe you give it away for free but I’m glad you do :)
Developer Response Thank you so much for your kind words! 😀
I have looked around for different LLM API Clients for a while now and this one is definitely the best one I’ve tried by far. It has sync with iCloud so I can use it with my Mac, headless search (didn’t even know that was possible), and easy access to all the models you want (I use DeepInfra). Honestly can’t believe you give it away for free but I’m glad you do :)
Thank you so much for your kind words! 😀
I’ve been using local LLMs through openwebui for a while, but the lack of a proper iPad client makes the usability hard. Cumbersome is an excellent alternative to being able to access models you host on your own network. If you use VPN or tailscale, you’ll always have access to these models.
I’ve been using local LLMs through openwebui for a while, but the lack of a proper iPad client makes the usability hard. Cumbersome is an excellent alternative to being able to access models you host on your own network. If you use VPN or tailscale, you’ll always have access to these models.
The app itself is pretty cool! And very nice and easy to use for Local LLMs, but I do have an issue.. some APIs actually provide free-to-use, with no api key required… and the app needs an API key, so im asking if we can get update to make it not needed or whatever. Overall, Thanks!
Developer Response Keyless is now available in >= 1.49.0
The app itself is pretty cool! And very nice and easy to use for Local LLMs, but I do have an issue.. some APIs actually provide free-to-use, with no api key required… and the app needs an API key, so im asking if we can get update to make it not needed or whatever. Overall, Thanks!
Keyless is now available in >= 1.49.0
Solid way to use api keys from OpenAI and Claude instead of paying per subscription. Interesting features that I haven’t see before too.
Solid way to use api keys from OpenAI and Claude instead of paying per subscription. Interesting features that I haven’t see before too.
feat(settings): default local tools on and link to Tools tab
feat(settings): OpenRouter PDF processing engine picker in Settings
feat(settings): OpenRouter search picker in Settings
feat(core): offload oversized message text to iCloud Drive
fix(settings): show OpenRouter picker row labels on iOS
fix(openrouter): migrate web search from deprecated plugin to server tool
fix(ios-chat): stop post-send scramble when penultimate reply truncates
fix(settings): make API key optional for OpenAI-compatible providers
fix(ios-chat): descramble transcript on send via layout revalidation
fix(macos): stop file-missing banner from blowing up window height
build(deps): bump textual for empty table cell fix
1.49.0 2d ago
feat(onboarding): tighten API-key welcome copy and vendor list
feat(about): personalize About tab and trim onboarding chrome
feat(settings): organize Settings into Models/Tools/App/About tabs
fix(ios-chat): stop transcript squash on send/delete/loading toggle
fix(ios-chat): clear stale streaming indicator on previous assistant rows
fix(ios-chat): stop transcript drift after breaking streaming auto-follow
fix(core): omit reasoning_effort by default on customOpenAI chat
fix(settings): match iOS About legal row typography to intro copy
perf(chat): add extraHeavy streaming throttle tier and retune gates
1.48.0 May 19
feat(local-tools): cross-reference search and browse tools when both are on
feat(core): enable KVS model-list compression writer (phase 2)
feat(macos): configurable Quick Prompt shortcut and App Visibility settings
feat(ui): apply brand backdrop across chat, Settings, and onboarding
feat(chat): International Orange backdrop and clearer message bubbles
feat(folders): unify move-folder menus with icons and tinted glyphs
fix(macos-chat): pin transcript to bottom on send in long convos
fix(settings): stop model picker and "Updated " from emptying
fix(local-tools): make OpenAI Responses follow-up work on OpenRouter
fix(chat): unwrap OpenRouter error.metadata in chat banners
fix(chat): surface gateway API errors in banners
fix(chat): also silence SwiftLint redundant_discardable_let
fix(chat): keep pending-queue subscribe line SwiftFormat-safe
fix(chat): restore ViewBuilder builds for pending queue subscription
fix(chat): subscribe pending-message bar to queue change counter
fix(core): stop stale sheet onDismiss cancelling chained local tools
fix(ios): pause streaming auto-scroll during user touch/deceleration
fix(ios): tighten toolbar spacing between org chip and new chat
fix(macos): align chat toolbar chrome with primary styling
fix(ui): align iOS chat toolbar organize chip and menus
refactor(chat): split StandardMessageContentView into support file
refactor(core): split Responses DTOs and test helpers across files
refactor(macos-chat): relocate folder chip beside New Chat toolbar cluster
1.47.0 May 15
feat(core): conversation folders, grouping, and organize flows
fix(chat): unbreak OpenAI image-edit follow-ups in /responses
fix(core): raise local tool hop limit from 5 to 25
fix(chat): resolve huge-code-block crash via Textual TextBuilder fix
fix(chat): restore VoiceOver body for expanded message rows
fix(chat): macOS empty-state inset + Ready to Chat body typography
fix(macos): replace hero Image Button with tap gesture layout
1.46.0 May 10
feat(sidebar): collapsible conversation sections with synced persistence
fix(macos): re-anchor LazyVStack transcript after mount race
fix(chat): persist built-in provider before model picker resolves
fix(chat): seed message cache and stabilize macOS transcript layout
fix(settings): tolerate transient iCloud Keychain misses
fix(macos): make error observation archive-safe
fix(macos): bound long chat errors in bottom controls
fix(settings): keep model refresh freshness device-local
fix(ios): improve chat toolbar picker sizing
fix(streaming): compile render-cost logging in release
fix(chat): stop streaming dots from bouncing
fix(chat): keep streaming indicator visible during thinking
fix(ios): allow chat errors to wrap
fix(chat): stream indicator in layout, not over Textual
fix(chat): macOS streaming dots overlay streak
fix(settings): eliminate the "marketing screen with keys present" regression
fix(ios): stop transcript bounce during streaming
fix(ios): restore Liquid Glass toolbar capsules and picker colors
chore: bump deps.
perf(streaming): defer LaTeX rendering while streaming
perf(streaming): adapt UI cadence to render cost
perf(streaming): restore ~30fps UI throttle; align Quick Prompt
1.45.0 May 3
feat(chat): native transcript lists on iOS and macOS
feat(images): add streaming partial previews for OpenAI image generation
feat(images): stream OpenAI image previews
feat(images): OpenAI image gen on OpenRouter; drop Vercel path
feat(images): OpenAI image generation via Responses API image_generation tool
feat(images): Gemini image output via OpenRouter + Vercel gateways
feat(images): Gemini image output, origin tag, full-width render
fix(chat): VStack multi-block markdown; iOS transcript cell sizing
fix(ios): compose UICollectionView insets from measured safeAreaBar heights
fix(settings): ship compressed model-list reader before writer
fix(settings): chat readiness gates on key presence, not stale test
fix(errors): surface hallucinated tool name and special-case hop limit
fix(local-tools): headless mode uses WebPage API, not URLSession
fix(endemic-llm): stop referencing disabled local tools to the model
perf(chat): consolidate streaming auto-follow on revision signal
perf(chat): trim message accessibility payloads
perf(chat): cache parsed message content for visible rows
perf(settings): LZFSE-compress provider model lists in iCloud KVS
refactor(chat): remove automatic conversation collapse
refactor(core): remove dead code and align build metadata
refactor(chat): remove "long press any message to edit" helper tip
1.44.0 Apr 28
feat(core): Chat Completions local tool loop for Z.AI and gateways
feat(core): stream Gemini tool calls end-to-end via local tool loop
feat(core): stream Anthropic tool calls end-to-end via local tool loop
feat(settings): split Local Browser Use into Search + Browse toggles
feat(core): in-modal recovery for local search
feat(core): stream OpenAI post-tool continuations end-to-end + parallel tool calls
style(settings): make macOS section headers dominant
1.42.0 Apr 20
fix(core): non-thinking responses fail on Anthropic Opus 4.7+ due to explicit temperature
fix(core): heal streaming-thinking tables broken by mid-row blank lines
fix(core): restore macOS chat hit-testing after sidebar collapse
1.41.0 Apr 18
feat(chat): searchable model picker for large lists
fix(chat): match searchable model picker to Menu styling
fix(chat): Textual markdown chunking and truncation mask only when fading
fix(chat): cap last-message auto-expand to avoid markdown stack blowups
fix(ios): prevent content scrolling during sidebar edge swipe
fix(ui): remove Beta chip from AI Reasoning in advanced modal
fix(core): review prompt uses host app product name
fix(core): harden chat sync, URLs, and title generation for crash mitigation
fix: add remote-notification background mode for CloudKit sync
fix(core): per-message expand stuck after Collapse All
fix(core): stream thinking UI before think close tag
chore: track Xcode workspace Package.resolved in git
perf(a11y): scale preview icons with @ScaledMetric
perf(core): replace release prints with os.Logger via AppLog
refactor(core): extract large files into focused modules
refactor(core): replace ScrollViewReader with ScrollPosition in sidebar
refactor(core): migrate settings and helpers to @observable
refactor(core): remove LegacyChatMessage alias and getWebSearchTools
refactor(core): remove dead DrawerView struct and clean up tests
1.40.0 Apr 3
feat(message): always show full content for last message, no Show more
feat(message): add header actions menu button for message actions
fix(chat): replace position-based auto-scroll break with gesture detection
fix(markdown): close unclosed code fences from truncated responses
fix(message): rename Copy to Copy Message in context menu
perf(chat): auto-collapse older messages on new message submission
perf(streaming): reduce observation cascades during streaming
1.39.0 Mar 19
fix: bug fixes and improvements
1.38.1 Mar 18
fix(build): pin Textual to patched revision for iOS archive
refactor(ui): consolidate beta chips, simplify Ollama settings copy
refactor(markdown): migrate MarkdownUI to Textual, keep LaTeXSwiftUI for math, remove code block copy
1.38.0 Mar 17
feat(reasoning): always display thinking when returned, regardless of toggle
feat(reasoning): support reasoning option for all providers including custom OpenAI
feat(vercel): add reasoning/thinking support for Vercel AI Gateway
fix(providers): send reasoning_effort none for custom OpenAI-compatible title generation
fix(settings): preserve model selection per custom OpenAI provider
fix(zai): send explicit thinking.type disabled when toggle off
fix(custom-provider): parse native Ollama token counts and remove token estimation fallback
1.37.0 Mar 16
feat(settings): double system message character limit to 10k
fix(ios): preserve show-more position while keeping initial bottom placement
fix(scroll): restore scroll-to-bottom, auto-follow, and geometry-based break detection (iOS and macOS)
1.36.0 Mar 14
feat(quickprompt): render markdown continuously during streaming
feat(shortcuts): save conversations to history
feat(ios): swipe from left edge to open drawer
fix(ios): prevent scroll jump when expanding last message at bottom
fix(links): support ticket and markdown links open correctly on macOS and iOS
1.35.0 Mar 12
feat(widget): add iOS lock screen widget
feat(settings): option to auto-delete conversations after X days
feat(ui): remove bubble view, standardize on document layout
fix(sidebar): fix conversation group ordering and add comprehensive tests
1.34.0 Mar 11
refactor(ToS): centralize receipt store, global ToS agreement
1.33.1 Mar 6
feat(macos): add View menu zoom in/out for macOS
feat(local-browser-tools): Phase 1 local browser tool use for OpenAI direct
feat(local-browser): hardcode extraction limit, inline links, parser extraction, settings copy
feat(local-browser): improve tool transcript visibility, extraction, and OS gating
feat(settings): refine local browser tools + server-side web search UX
feat(gemini): add thinking/reasoning support for Google AI Studio
feat(ui): hide reasoning section for unsupported providers
feat(zai): add thinking support
feat(anthropic): use adaptive thinking for all 4.6+ variants
feat(anthropic): add extended thinking support
feat(widget): implement AI Digest widget extension
feat(widget): AI Digest Widget WIP implementation
revert(widget): back out AI Digest Widget implementation... too frustrating to get working
feat(sidebar): add Duplicate to conversation context menu
fix(openai): support dual-tool selection and valid web_search encoding
fix(settings): persist provider selection when switching to previously-used provider
fix(ios): display zoom on iPhone SE 2022 truncates text and UI elements
perf(test): remove mock streaming delay and reduce ensemble concurrency delay
perf(test): speed up test suite from ~15s to ~7s
refactor(settings): normalize typography, alignment, and spacing across macOS and iOS
style(settings): use SettingsSectionHeader for Model Filters in iOS
1.33.0 Mar 4
feat(custom-provider): add OpenAI-compatible custom provider support
feat(custom-params): prepend messages for Chat Completions system prompts
feat(settings): add Beta chip to OpenAI-Compatible Providers section
feat(settings): OpenAI-Compatible section intro, Add Provider UX, a11y
feat(custom-provider): immediately fetch models when adding custom provider
feat(custom-provider): enable attachments for OpenAI-compatible providers
feat(custom-provider): add title model picker below API key row
feat: disable AI Reasoning for unsupported providers; improve custom provider modal UI
feat(custom-provider): harden API key requirements and fix ensemble metadata
fix(openrouter): use provider-appropriate reasoning-off for Anthropic models
fix(settings): improve macOS settings sizing and simplify status messages
fix(latex): add horizontal scroll for wide block equations
fix(settings): align macOS add-button styling across API key sections
fix(custom-provider): OpenRouter compatibility, title picker UX, prune debug logs
fix(custom-provider): apply model inclusion/exclusion filters to custom provider models
fix(openrouter): explicitly disable reasoning when off
perf(ensemble): parallelize Face/Off candidate calls with async let
refactor(models): replace smart model selection with hardcoded defaults
refactor: DRY pass across settings, URLs, and attachment views
refactor: deduplicate SettingsManager init and title generation dispatch
refactor(core): remove verified dead code paths
1.32.0 Mar 1
feat(search): add "Only Search When Requested" smart search toggle
feat(attachments): add interactive preview and PDF thumbnails
feat(chat): image paste support for iOS and macOS
feat(chat): hide provider picker when only one provider is configured
feat(model-filters): add positive model inclusion filters alongside existing exclusion filters
fix(openrouter): add PDF file attachment support to chat completions
1.31.0 Feb 26
feat(openai): add reasoning/thinking support with collapsible UI
feat(openrouter): add OpenAI-style reasoning support for streaming chat
feat(settings): improve provider recommendations and web search warnings
feat(settings): split API keys into Direct/Multi-providers, improve ZDR copy and UX
fix(ui): restore link colors in markdown and unify with Link views
fix(quick-prompt): persist thinking and raw API response
fix(reasoning): gate capture by request config and prevent double-send race
fix(streaming): preserve thinking content after streaming completes
fix(streaming): repair chunk normalizer corruption and Face/Off judgment reliability
fix(openrouter): add web search plugin support
fix(openai): remove unnecessary reasoning param from title generation
fix(markdown): stop chunking from splitting fenced code blocks
chore: remove dead code (unused CoreData imports, empty deinit)
docs(quick-prompt): document Face/Off intentionally not used
docs(settings): clarify OpenRouter recommendation copy and link ZDR once
style(settings): reduce API key toggle size on macOS
1.30.0 Feb 24
feat(shortcuts): add Siri and Shortcuts integration
feat(vercel): add app attribution headers for Vercel AI Gateway
feat(vercel): add Zero Data Retention toggle for Vercel AI Gateway
fix(shortcuts): add Siri entitlement, fix phrase collision, add ping test
refactor(settings): improve API key addition flow
style(settings): remove redundant Provider row from Add API Key views
style(onboarding): further copy refinements
style(onboarding): tighten welcome screen copy and layout
1.29.0 Feb 22
feat(settings): add model exclusion filters for large provider lists
feat: add Vercel AI Gateway as new API provider
fix: improve title generation prompt for shorter titles
fix(macos): fix Cmd-F Find in conversation
refactor(settings): rename Test to Update in API keys UI
1.28.0 Feb 21
feat(a11y): add Voice Control, Differentiate Without Color, Larger Text, and Sufficient Contrast support
fix(macos): restore arrow key navigation in sidebar
fix(markdown): restore inter-block spacing in chunked content
fix(streaming): show error banner for in-stream API failures
fix(scroll): reduce excessive bottom spacer during auto-scroll
refactor: DRY up duplicated view code in three files
refactor: remove unused code identified by Periphery and manual review
1.27.0 Feb 7
perf(messages): string-truncate long messages to reduce CPU usage
perf(scroll): VStack + scroll-to-bottom + 5fps throttle for reliable positioning
perf(streaming): fix high CPU during streaming with @observable and scroll throttling
perf(views): fix iOS watchdog crash by removing message view observation overhead
refactor(messages): revert to VStack
refactor(scroll): migrate to modern ScrollPosition API with auto-follow
1.26.1 Feb 1
feat(settings): default local tools on and link to Tools tab
feat(settings): OpenRouter PDF processing engine picker in Settings
feat(settings): OpenRouter search picker in Settings
feat(core): offload oversized message text to iCloud Drive
fix(settings): show OpenRouter picker row labels on iOS
fix(openrouter): migrate web search from deprecated plugin to server tool
fix(ios-chat): stop post-send scramble when penultimate reply truncates
fix(settings): make API key optional for OpenAI-compatible providers
fix(ios-chat): descramble transcript on send via layout revalidation
fix(macos): stop file-missing banner from blowing up window height
build(deps): bump textual for empty table cell fix
more Version 1.49.0 2d ago
Data Not Linked to You The following data may be collected but it is not linked to your identity: