callstackincubator

Stars and mentions

Last 30 days, Oct 5 – Nov 3

GitHub stars0
mentions35
036912Oct 5Oct 19Nov 3
UTC days · repositories callstackincubator owns0 repositories

Package downloads

No package download history available yet.

Top repositories

callstackincubator’s repositories ranked by new stars, as on trending.

Loading

Contributes to

Repositories outside callstackincubator’s account where callstackincubator opened or reviewed pull requests in the past 365 days.

Who noticed callstackincubator

Everyone who starred or forked callstackincubator’s repositories since the archive began in 2011.

Notable accounts

Ordered by the stars their own repositories have received.

Biggest fans

Accounts that starred the most of these repositories.

Breakout weeks

Each repository’s best week of new stars, with the release published around it.

Mentions

36posts
Nov 42 posts
  1. Four days since we launched Simlock: 500+ stars, 1,000 npm downloads, 90+ issues, 70+ merged PRs. 0.5.0 is out: agents can rotate leased iOS simulators, and tunnel ports to emulators on other machines. Hit a bug or missing a feature? Open an issue: callstackincubator/simlock t.co

    25 likes · 1,797 views
  2. Simlock leases, serves and manages iOS and Android devices for AI coding agents. You can turn your macOS and linux boxes into self-hosted cloud of simulators, emulators, and physical devices, that guarantees agents not fighting over the same device, control max number of simulators running at the same time to not clog CPU/RAM, run slim simulators with fewer services turned on, and many more. We considered making it a paid but it makes more sense to just open it for everybody. If you have one or more spare Mac or Linux machines laying around, setup simlock and make it your private sim cloud for yourself or your team. It's free, MIT licensed on GitHub: callstackincubator/simlock Enjoy :)

  3. simlock is at 200 stars after half a day, let's make it to 1,000 ⭐ hop on the self-hosted device cloud bandwagon callstackincubator/simlock t.co

    24 likes · 1,326 views
  4. Introducing Simlock: a free, open-source tool that turns your machine into a simulator cloud that manages itself, so every coding agent gets its own iOS or Android device, simulator or real phone. callstackincubator/simlock t.co

    297 likes · 21 reposts · 9,498 views
  5. Reddit · · r/androiddev · u/Hubastard · callstackincubator/agent-device

    Speedrun, an open-source mobile E2E test runner that runs your Maestro flows up to 8x faster I've always been bothered by how slow mobile UI tests are. Most of a test run is spent waiting: fixed sleeps, polling, comparing screenshots to guess whether the app is done animating. Coming from a game dev background, where you fight for every millisecond of a frame, that felt like a solvable problem. So I spent the last while building my own runner from the ground up, and it turns out UI tests can be a lot faster. Speedrun is a black-box E2E test runner for Android and iOS. It's open source (Apache 2.0) and it runs Maestro's YAML flow format so if you already have Maestro tests, trying it is one word: maestro test flows/ # before speedrun test flows/ # after Numbers One user journey (sign in with a code, search a shop, fill a cart, set a PIN under a loading overlay, scroll a long list), written for each tool the way its tests are usually written. Median of 3 runs after a warm-up, start-up included: |Tool|Android emulator|iOS simulator| |:-|:-|:-| |Speedrun|20.4 s|27.2 s| |maestro-runner|65.9 s|49.6 s| |Appium|59.4 s|94.1 s| |XCUITest|-|81.2 s| |Maestro 2.11|126.5 s|113.1 s| On the native Settings app benchmark it's 8x faster than Maestro on Android and 2.8x on iOS. On a 19-flow React-Native test suite it passes all 19 on both platforms, and is 6.1x faster on Android and 2.6x on iOS. Android is where it shines most, which is nice for CI: Android runs on cheap Linux runners. Full disclosure: the main benchmark app is mine, built in React Native to be hard to test (endless animations, late popups, loading overlays, lists that load as you scroll). The flows, per-flow results and scripts to rerun everything are in the repo, and I'd love to see numbers on other apps. Why it's fast - It waits for the app, not the clock. A small on-device agent knows when the app has actually settled (accessibility events on Android, XCTest's idle state checked against the screen on iOS), so each step starts the moment the app is ready. No sleeps, no screenshot diffing. - Reading the screen is cheap. The agent reads the UI tree in about 10 ms on Android and talks to the host over a compact binary protocol. - Screens that never stop moving don't block it. Spinners, tickers and carousels are left out of the "is it done?" check. - Nothing to warm up. One native binary, no JVM. The iOS agent stays running between runs, so later runs start in about 0.2 s. It's also less flaky: it won't tap a popup that's still sliding in or a button under a loading overlay, and it scrolls an element out from under a sticky footer or the keyboard before tapping it. It works with AI agents too speedrun mcp exposes it as an MCP server (Claude Code, Cursor, etc.). Your agent can explore the app on its own: tap around, read each screen in a few lines (cheap on tokens, not a whole accessibility tree), figure out how things work, then save the steps that worked as a YAML flow you can drop into CI. claude mcp add speedrun -- ~/.speedrun/speedrun mcp ||Android emulator|iOS simulator| |:-|:-|:-| |Speedrun (speedrun session)|4.2 s, ~1,560 tokens|9.4 s, ~1,230 tokens| |agent-device 0.21|9.1 s, ~2,240 tokens|14.0 s, ~1,620 tokens| |Argent 0.31|11.7 s, ~3,630 tokens|12.2 s, ~2,650 tokens| Limitations (so you don't have to find them) - Android emulators and devices, iOS **simulators** only (no real iOS devices yet) - macOS (Apple silicon); the Linux x86_64 build is Android-only - Maestro's AI commands (`assertWithAI` and co.) aren't supported; the few other differences are documented - It's young (v0.1.10) and moving fast Try it Repo, docs and benchmark details: hubastard/speedrun If you have a Maestro suite, I'd really like to hear how it does on yours, especially where it breaks or is slower. Happy to answer questions about how it works. edit1: added maestro-runner to the benchmark. edit2: added ai agent benchmark.

    50 points · 9 comments
  6. Reddit · · r/reactnative · u/Hubastard · callstackincubator/agent-device

    Speedrun, an open-source mobile E2E test runner (Android/iOS) that runs your Maestro flows up to 8x faster I've always been bothered by how slow mobile UI tests are. Most of a test run is spent waiting: fixed sleeps, polling, comparing screenshots to guess whether the app is done animating. Coming from a game dev background, where you fight for every millisecond of a frame, that felt like a solvable problem. So I spent the last while building my own runner from the ground up, and it turns out UI tests can be a lot faster. Speedrun is a black-box E2E test runner for Android and iOS. It's open source (Apache 2.0) and it runs Maestro's YAML flow format so if you already have Maestro tests, trying it is one word: maestro test flows/ # before speedrun test flows/ # after Numbers One user journey (sign in with a code, search a shop, fill a cart, set a PIN under a loading overlay, scroll a long list), written for each tool the way its tests are usually written. Median of 3 runs after a warm-up, start-up included: |Tool|Android emulator|iOS simulator| |:-|:-|:-| |Speedrun|20.4 s|27.2 s| |maestro-runner|65.9 s|49.6 s| |Appium|59.4 s|94.1 s| |XCUITest|-|81.2 s| |Maestro 2.11|126.5 s|113.1 s| On the native Settings app benchmark it's 8x faster than Maestro on Android and 2.8x on iOS. On a 19-flow React-Native test suite it passes all 19 on both platforms, and is 6.1x faster on Android and 2.6x on iOS. Android is where it shines most, which is nice for CI: Android runs on cheap Linux runners. Full disclosure: the main benchmark app is mine, built in React Native to be hard to test (endless animations, late popups, loading overlays, lists that load as you scroll). The flows, per-flow results and scripts to rerun everything are in the repo, and I'd love to see numbers on other apps. Why it's fast - It waits for the app, not the clock. A small on-device agent knows when the app has actually settled (accessibility events on Android, XCTest's idle state checked against the screen on iOS), so each step starts the moment the app is ready. No sleeps, no screenshot diffing. - Reading the screen is cheap. The agent reads the UI tree in about 10 ms on Android and talks to the host over a compact binary protocol. - Screens that never stop moving don't block it. Spinners, tickers and carousels are left out of the "is it done?" check. - Nothing to warm up. One native binary, no JVM. The iOS agent stays running between runs, so later runs start in about 0.2 s. It's also less flaky: it won't tap a popup that's still sliding in or a button under a loading overlay, and it scrolls an element out from under a sticky footer or the keyboard before tapping it. It works with AI agents too speedrun mcp exposes it as an MCP server (Claude Code, Cursor, etc.). Your agent can explore the app on its own: tap around, read each screen in a few lines (cheap on tokens, not a whole accessibility tree), figure out how things work, then save the steps that worked as a YAML flow you can drop into CI. claude mcp add speedrun -- ~/.speedrun/speedrun mcp ||Android emulator|iOS simulator| |:-|:-|:-| |Speedrun (speedrun session)|4.2 s, ~1,560 tokens|9.4 s, ~1,230 tokens| |agent-device 0.21|9.1 s, ~2,240 tokens|14.0 s, ~1,620 tokens| |Argent 0.31|11.7 s, ~3,630 tokens|12.2 s, ~2,650 tokens| Limitations (so you don't have to find them) - Android emulators and devices, iOS **simulators** only (no real iOS devices yet) - macOS (Apple silicon); the Linux x86_64 build is Android-only - Maestro's AI commands (`assertWithAI` and co.) aren't supported; the few other differences are documented - It's young (v0.1.10) and moving fast Try it Repo, docs and benchmark details: hubastard/speedrun If you have a Maestro suite, I'd really like to hear how it does on yours, especially where it breaks or is slower. Happy to answer questions about how it works. edit1: added maestro-runner to the benchmark edit2: added ai agent benchmark

    61 points · 21 comments
  7. Fast-Forwarding Past the 9 A.M. Reminder, Bob Ross Paints Straight to the GPU, and a README That Confesses Its Own Bugs --- title: "Fast-Forwarding Past the 9 A.M. Reminder, Bob Ross Paints Straight to the GPU, and a README That Confesses Its Own Bugs" published: true cover_image: dev-to-uploads.s3.us-east-2.amazonaws.com description: "Explore Appduct from Callstack, which turns your running app into an MCP server for AI agents, and react-native-skia-webgpu-video for GPU video editing on Skia 3." tags: reactnative, javascript, mobile, expo canonical_url: thereactnativerewind.com --- You’re reading The React Native Rewind #63. --- Great Scott, Your App Has a Time Machine Doc Brown needed a DeLorean and 1.21 gigawatts to jump forward in time. Our QA agents just need to test a reminder that fires at 9 a.m., and right now they sit and wait for it like the rest of us. Szymon Chmal and Callstack launched Appduct on October 20 to fix exactly that. What does it actually do? Appduct turns your running app into an MCP server (the protocol agents use to call outside tools). You register functions like advance_time, seed_cart or set_feature_flag, and the agent calls them instead of tapping through six screens. The handlers run your app's own code, so a test starts on the screen it cares about rather than the login page. Call advance_time with 60 seconds, and the 9 a.m. reminder fires without anyone staring at a clock. import { useAppductTool } from "@appduct/react-native"; import { z } from "zod"; export function AppductTools() { useAppductTool({ name: "seed_cart", description: "Fill the cart with test items.", inputSchema: z.object({ items: z.number() }), handler: async ({ items }) => ({ added: items }), }); return null; } Mount that near the root, and any agent that speaks MCP can call it. The same tool works in Swift, Kotlin, Flutter and on the web. Release builds leave it out unless you opt in. How does the agent know the app is ready? Instead of sleep(3000) and a prayer, the app posts an event like checkout_completed, and the agent waits for it. The connection runs through a small daemon on your machine and an encrypted WebSocket, paired with a single-use link (or a QR code on a real device). For the taps that still need tapping, it pairs with Callstack's agent-device. Does it work in normal tests? A day later came @appduct/e2e, which wraps the e2e tests you already have. One call fills the cart, and the test runner's AI agent gets the same tools. The same test runs on web, iOS and Android. !Appduct e2e seed cart demo Where our tests are going, they don't need login screens. 👉 Appduct --- !Ancient Aliens ProGuard meme Happy Little Frames Bob Ross could turn a blank canvas into a mountain range in half an hour. React Native video editing usually takes longer, plus a native SDK and a lot of bridge code. Sebastien Hecart published the first beta of react-native-skia-webgpu-video on October 19. What is it? It plays, composes and exports video on top of React Native Skia 3 and William Candillon's React Native WebGPU (the GPU API that Skia 3 now draws through). Every video frame lands on a Skia canvas, so we can paint text, shapes and filters straight on top. Frames travel from the phone's decoder to the encoder on the GPU, without a detour through JavaScript. The trick is that one worklet (a small function that runs off the JS thread) draws both the live preview and the exported file. const drawFrame: FrameDrawer = (props) => { 'worklet'; const { canvas, frames, width, height } = props; const frame = frames.clip; if (frame) { drawVideoFrame(canvas, frame, { x: 0, y: 0, width, height }, { fit: 'contain' }); } // Draw your Skia text, shapes, or overlays here. }; await exportVideoComposition({ videoComposition: composition, drawFrame, outPath, width: 1280, height: 720, frameRate: 30, bitRate: 5_000_000, }); It picks up where the older Skia Video left off, rewritten from scratch for Skia 3. Is anyone using it yet? Giulio Amato has already moved his video editor off Media3 (Android's native media library) and onto it. Because the same code draws the preview and the export, what we see on the timeline is exactly what lands in the file. !Skia video editor demo What's the catch? It's a beta, tested on an iPhone 15 Pro and a Pixel 8a. HDR isn't qualified yet. It pins exact Skia and WebGPU versions and needs the New Architecture and a native rebuild. So Expo Go is out. The README lists its known bugs with refreshing honesty, which is more than most of our side projects manage. Beta 3 on October 22 already cut a 4K frame on iOS from 33 MB to 12 MB. There are no mistakes, just happy little dropped frames. 👉 react-native-skia-webgpu-video --- !Afraid to ask pod install meme 📦 Nitro V1 alpha Marc Rousavy (@mrousavy) has opened the doors on the first Nitro V1 alpha, so library authors can grab the alpha-nightly tag and start poking at the future. The same week, his fbjni PR made every call into Java and Kotlin 14% faster, which is a lot of speed for one merged pull request. 📦 Radon IDE 1.20 The iPhone Duo simulator now folds right inside your editor, and Radon warns you before you launch an app that iOS 27 is about to crash for skipping the UIScene lifecycle. 📝 Supporting iPhone Duo with Expo Apple's first foldable landed on Friday, and Expo's guide explains why insets.top is suddenly zero and your tab bar has moved into a rail on the side. 📦 React Native Windows 0.85 The legacy architecture has finally been shown the door, so it's New Architecture only from here, and you'll need Visual Studio 2026 to get in. 📦 React Native Firebase 27 CocoaPods is out and Swift Package Manager is in on iOS, and the ML package has been laid to rest now that Google has discontinued it. 📦 Unistyles 3.6 A new experimental Metro integration lets you ditch the Babel plugin, and plain views now re-render in half the time. 📦 Hot Updater 1.1 Over-the-air updates now reach brownfield apps too, and bumping your version number no longer locks you out of shipping a quick fix. 📦 React Native Bottom Tabs 1.5 Swift Package Manager support has arrived, along with a new prominent tab role for the one tab on iOS 27 that deserves to stand out from the crowd. 📦 create-react-native-library 0.64 Satyajit Sahoo (@satya164) has taken the C++ template out of experimental, so your next native module can be written in C++ without feeling like a science project. 📦 React Native Better PDF 1.1 Hand it three PDFs and it stitches them into one document with a single page count and search, which is exactly the trick react-native-pdf can't pull off. !Goodbye GIF --- Authored by Luke Farrell and edited by Fran Ríos. If you’re enjoying this newsletter, why not help us grow? Share it with your friends, family, and even that one coworker who always “forgets” to update dependencies. Use this link: thereactnativerewind.com.

  8. 89 PRs in 3 days 🔥 There's an extreme overhaul coming to on-device AI 👀 Keep an eye callstackincubator/ai

    12 likes · 1 repost · 547 views
  9. AI in Mobile Apps: What It Actually Changes for Businesses in 2026 AI in mobile apps helps a business most when it removes a specific, repeated piece of work: answering the same customer messages, taking orders, predicting busy hours, flagging bad data. It helps least when it's added because "every app has AI now." After ten years of building mobile apps for food delivery, healthcare, workforce tracking, education and community products, my rule is simple: understand the business use case first, then decide whether AI belongs in it at all. That's the short answer. The rest of this article is the long one, written for two kinds of readers: business owners deciding where to spend money, and developers who will have to build what gets decided. How big is AI in mobile apps right now? Big, and growing fast. A few numbers worth knowing: - Sensor Tower projects that time spent in generative AI apps will roughly double, from 17.2 billion hours in the first half of 2025 to 36 billion hours in the first half of 2026 (Sensor Tower, State of AI 2026). - More than 200,000 apps now mention AI in their store descriptions, and together they're on track for around 10 billion downloads in that same half year (same report). - Amazon reports that shoppers who use its Rufus assistant convert at close to twice the rate of shoppers who don't (same report). But here's the number I find more useful. When Lazyweb looked at 809 real apps in July 2026, only about one in nine (10.9%) actually had a visible AI assistant or chat screen (Lazyweb Research). So everyone is talking about AI, a lot of apps put "AI" in their listing, and far fewer ship an AI feature that does real work. That gap is both the opportunity and the trap. AI helps an app sell. It doesn't make people stay. The most honest data on this comes from RevenueCat, which processes subscription payments for a huge share of mobile apps. Their 2026 report found that AI-powered apps are better at turning trial users into paying customers: 8.5% conversion versus 5.6% for apps without AI (Dataconomy summary of RevenueCat's report). Then the same users leave faster. After a year, 21.1% of AI app subscribers were still paying, compared with 30.7% for non-AI apps (TechCrunch). The interesting part came in RevenueCat's follow-up study. The best AI apps retained users just as well as non-AI apps, and the difference seemed to come down to whether the app's use case naturally turned into a habit (RevenueCat). That matches what I see with clients. AI is the shiny thing that gets someone to try your app. Whether they keep using it depends on whether the app solves a problem they have every week. AI can't fake that part. Start with the business problem, not the model A lot of clients come to me asking for "AI in the app." When I ask what they want it to do, the answer is usually some version of "we're not sure, but competitors have it." That's not a reason to build anything. Before I suggest AI for any project, I go through four questions: 1. What repeated task is eating your team's time? Replying to the same questions, entering orders by hand, checking timesheets. 2. Where are customers waiting or dropping off? A slow reply on WhatsApp can lose an order. 3. What data do you already have? AI without your own data is mostly a generic chatbot. 4. What happens when the AI is wrong? If the answer is "someone gets the wrong medicine" or "a payment fails," you need a human checking it. And if a plain rule, a filter, a better form or a normal algorithm solves the problem, use that. Every call to a large language model costs money per message, forever. A rule costs nothing to run. There's no reason to burn tokens on something a few lines of logic can handle. This is the same thinking I use when scoping any project, which I wrote about in how much does an app cost in 2026. What AI changes, industry by industry These are the industries I've personally shipped apps in. For each one, I'll say where I think AI earns its cost and where it doesn't. Food delivery and restaurants I spent two years on DineHome, a multi-vendor food delivery platform in Norway, building the customer app, the rider app and a kiosk-mode POS app, along with native modules for kiosk hardening, ESC/POS thermal printing and background GPS. Most of the hard work there was plain engineering. A receipt has to print every time. A kiosk has to stay locked. No AI model makes those more reliable. Where AI does earn its place in food delivery is the guessing work. Today, machine learning sits behind demand forecasting, delivery time estimates, rider dispatch, fraud checks, search ranking, promotions and menu recommendations on the big platforms (Research and Markets). For a smaller restaurant business, the two that matter most are knowing when the rush is coming so the kitchen can prep, and giving customers a delivery time that's actually true. And there's a third one that's often skipped: taking the order in the first place. More on that below. Healthcare At ChopDawg I maintained Nightingale, a tablet app that staff used to log in, see their patients and connect with a backend algorithm that assigned nurses. That assignment logic was an algorithm, not AI, and honestly, that was the right choice. In healthcare you need decisions you can explain and repeat. Where AI is clearly winning in healthcare is the paperwork around care. A 2026 survey of 120 US health systems found AI note-taking at 68% adoption, and AI-drafted replies to patient messages grew 80% in a year. Of the systems that could measure their return, more than half reported at least 2x (Fierce Healthcare). That's the pattern I'd follow in any health app: let AI draft, let a human approve. Workforce and field-service apps For ClickTime, an Australian workforce and timesheet system, I was the only mobile developer on the employee and admin apps. The core work was real-time background GPS through a custom native bridge, plus blocking fake GPS apps. Fake-GPS blocking is a rule problem, and rules handle it well. Where I'd add AI if I were building it today is the second layer: spotting patterns that no single rule catches, like a timesheet that doesn't match the route someone actually drove, and flagging it for a manager to review. The AI doesn't decide anything. It just points a human at the records worth checking. Education apps I've worked on support and maintenance for Kalaam, a Quran vocabulary and recitation app with 100K+ installs. Education is one of the places AI fits naturally: feedback on pronunciation through speech recognition, review sessions built around the words a learner keeps forgetting, and faster drafts for support replies. But for content where accuracy really matters, and religious content is the clearest example, AI should help people practice, not generate the material they're learning. The content stays verified by humans. AI works around it. Community and chat apps On Paragon, a team and community app, I helped deliver the first version from scratch in six months, with encrypted chat, Agora voice and video calling and OneSignal notifications. Community apps have obvious AI use cases: catching spam and abuse, summarizing long threads for people who missed them, and smarter notifications. There's a catch, though. If you promise users that their chat is encrypted, sending their messages to a cloud AI model to summarize them breaks that promise. In a case like that, an on-device model is the only honest option. Banking and retail I haven't built banking apps, but the big players show where this is heading. Bank of America says 60% of its Erica assistant's interactions are now proactive, meaning the assistant reaches out first instead of waiting to be asked (AI2 Work). The lesson for smaller businesses is that AI which nudges at the right moment (a reminder, a reorder, a payment due) is usually worth more than a chat box that sits there waiting. What we're building: order management through WhatsApp and chat This is where my own thinking is right now. At Averolt, we're building a prototype that lets business owners automate how they manage orders, through WhatsApp or a chatbot on their website, with customers writing in normal, human language. A customer types something like "two chicken biryani, one without raita, deliver at 8" the way they'd text a person. The AI turns that into a structured order, the system checks it, and the owner sees it ready to confirm, instead of copying it by hand from a chat thread. It passes my own test from earlier: - It's a repeated task that takes real staff time every day. - It uses a channel customers already use, so nobody needs to install anything new. - Success is easy to measure: orders handled, mistakes, time saved. - There's a human in the loop before anything is final. That's the kind of AI feature I believe in. Not AI for the listing, AI for the boring work. On-device or cloud AI? For most businesses, both There's a lot of excitement about on-device AI, and the tools are genuinely good now. For React Native, React Native ExecuTorch from Software Mansion runs models on the phone, Callstack's React Native AI works with Apple's on-device models and Gemini Nano, and at WWDC 2026 Apple's Foundation Models gained image input on top of text (Callstack). But in my experience, an app that runs fully on-device and offline is a rare requirement for businesses. When a feature truly needs it, because of no connectivity, sensitive data, or server costs that would grow with every user, then stick with on-device and save the server bill. On-device models are also smaller and can only handle short inputs, so they suit focused tasks rather than open-ended chat (Infosys). Most of the time, the right setup is both: an offline layer on the client so the app feels instant and smooth, and cloud sync for backup and the heavier work. It's the same principle I use for data in general, which I covered in Firestore data modeling for offline-first React Native apps. AI is no different. Do the quick, private work on the phone, and send the rest to the cloud only when it adds something. A quick checklist before you add AI to your app - Name the exact task the AI will do, in one sentence. - Check if a rule or simple algorithm already solves it. - Make sure you have the data the feature needs. - Decide what a human must approve before it takes effect. - Estimate the per-use cost, not just the build cost. - Choose on-device, cloud or both based on privacy, connectivity and cost. - Measure whether it improves something real: orders, time saved, retention. FAQ Does every mobile app need AI in 2026? No. Only about one in nine apps had a visible AI assistant as of July 2026, and many successful apps have none. Add AI when it removes repeated work or improves a decision, not to match a competitor's listing. Which industries benefit most from AI in mobile apps? Industries with lots of repeated communication and prediction: food delivery and restaurants (orders, demand, delivery times), healthcare (documentation and patient messages), field service (anomaly checks), education (personalized practice) and retail and banking (proactive reminders). Will AI features help my app keep users? Not on their own. RevenueCat's 2026 data shows AI apps convert trials better but lose subscribers faster, unless the app solves a problem people have regularly. Retention comes from the use case, not from the AI. Is on-device AI better than cloud AI? Neither is better everywhere. On-device AI is private, fast and has no per-use server cost, but the models are smaller. Cloud AI is more capable but costs money per request. Most business apps work best with both. How much does it cost to add AI to an app? It depends on whether the feature runs on-device or calls a cloud model, how often it runs and how much testing it needs. The ongoing cost per use matters as much as the build cost. I break down what drives app costs in this article. Can AI handle customer orders through WhatsApp? Yes. AI can read an order written in normal language and turn it into a structured order for the business to confirm. Keeping a human confirmation step avoids costly mistakes while still saving most of the manual work. Want to figure out where AI fits in your business? If you're a founder or business owner who wants AI to do real work, not just appear in your app listing, there are two ways to work with me: - For a full product, web and mobile: my agency Averolt builds and rescues apps and systems end to end. - For React Native work: I take on senior React Native projects directly, from discovery to post-launch. Book a call. Either way, the first conversation starts with your business, not with AI. --- Sources - Sensor Tower: State of AI 2026 - Lazyweb Research: share of apps with an AI assistant - TechCrunch: AI apps struggle with long-term retention - RevenueCat: AI app retention study - Fierce Healthcare: health system AI adoption 2026 - Research and Markets: food delivery app market - Callstack: on-device AI after WWDC 2026 - Infosys: on-device AI for React Native Originally published on jahanzaibramzan.com.

  10. On-device AI in React Native, late 2026: one AI SDK call, two engines, measured At a glance - Problem: Run an LLM inside a React Native app, with no server and no API key - Fix: Two on-device engines behind one AI SDK call, plus a model picker that checks each engine actually works - Result: 20 vs 2 (valid structured outputs out of 20: Apple's guided generation vs a 1B ExecuTorch model) Short answer: On-device AI in React Native is practical now, but the two engines suit different jobs. Use Apple's Foundation Models when the device has it: no download, and guided generation returned valid structured output 20 times out of 20. Use ExecuTorch for everything else, but not for structured output from a 1B model: only 2 of 20 responses matched my schema. Keep a cloud fallback, and check that each engine really works rather than trusting its availability flag. React Native got a lot of AI news this year. WWDC26 expanded Apple's Foundation Models framework (image input, Private Cloud Compute, third-party models behind the same API). Software Mansion rewrote ExecuTorch for 0.10 with Core ML, MLX and Vulkan backends. Callstack's react-native-ai put Apple's model, llama.rn, MLC and Gemini Nano behind the Vercel AI SDK. An expo-ai package is in review in the Expo repo. Release posts tell you what's possible. I wanted to know what it takes, so I built one small React Native 0.87 app that calls both engines through the same streamText / generateObject code, and measured them on the same tasks. Everything is in a public repo: code, raw results and the failures. > The setup, and what I couldn't measure. React Native 0.87.1, AI SDK 6, @react-native-ai/apple 0.12.0, react-native-executorch 0.10.4 running Llama 3.2 1B. An Apple M1 with 8 GB of memory, the iPhone 17 simulator on iOS 26.3, no physical devices. ExecuTorch ran in the app on the simulator. Apple's model wouldn't run in the simulator (more below), so I ran the same tasks against it from Swift on the Mac. These are Mac numbers, not iPhone numbers: use them to compare the two engines, not to predict latency on a phone. Gemini Nano on Android needs a supported phone, so it's covered from the docs only. The two tasks Five store-audit notes, written the way an auditor types them on a phone: > Freezer 2 door seal torn, temp reading -12 instead of -18. Aisle 4 lights flickering. Fire exit at the back blocked by two pallets of water. 1. Summary: streamed, two sentences, most urgent issue first. I measured time to first text and total time. 2. Checklist: structured output, validated against a Zod schema with generateObject. One item per issue, each with an area, an issue and a severity of low, medium or high. 10 runs per engine, per run of the benchmark. One call site for both engines Apple's model already has an AI SDK provider. ExecuTorch doesn't, so I wrote a small adapter. Version 0.10 makes this easier: below the useLLMChatSession hook it exposes the runner and the model's chat template as separate pieces. I didn't use the chat session itself. It keeps a growing conversation in the model's cache, which suits a chat screen but not a one-off generateText call. The adapter resets the runner and renders the AI SDK prompt from scratch on every call: src/lab/executorchModel.ts (excerpt) async function run(options: LanguageModelV3CallOptions, onToken: (t: string) => void) { const schema = options.responseFormat?.type === 'json' ? options.responseFormat.schema : undefined; const messages = toMessages(options.prompt, schema); // AI SDK prompt -> chat messages runner.reset(); // stateless: no history from earlier calls const prompt = preprocessor.process(messages, messages.length, { addGenPrompt: true }); preprocessor.clear(); const genConfig = { maxNewTokens: options.maxOutputTokens ?? 512, temperature: options.temperature ?? 0.7 }; return generateAsync(runner, prompt, genConfig, stopTokens, onToken); // runs on a worklet thread } doGenerate and doStream wrap that, and after that the calling code is the same for both engines: const result = streamText({ model, system, prompt, maxOutputTokens: 160 }); const { object } = await generateObject({ model, schema: checklistSchema, system, prompt }); There's one difference the code can't hide. Apple's model fills the schema through guided generation: the framework restricts what the model can output to fit the type. ExecuTorch has no equivalent here, so the adapter puts the schema in the prompt and hopes. That difference decided the structured-output results. Getting it to build took seven fixes None of these are hard, but each one stops the app from building or running, and I didn't find any of them in the docs: | Problem | Fix | | --- | --- | | iOS build fails: unknown type name 'RCTCxxBridge' in RnExecutorch.mm | React Native 0.87 removed it. Patch the module to install its JSI bindings through RCTTurboModuleWithJSIBindings (patch) | | CocoaPods: "required a higher minimum deployment target" | platform :ios, '17.0' in the Podfile | | Metro: "Export namespace should be first transformed" | Add @babel/plugin-transform-export-namespace-from, the v7 release (v8 needs Babel 8) | | ExecuTorch native calls fail | react-native-worklets/plugin, last in the Babel plugins | | Property 'TextDecoder' doesn't exist | Polyfills for the AI SDK on Hermes (below) | | ai@latest installs 7.x | Pin ai@6: the React Native AI providers implement the v6 spec | | npm 11 skips ExecuTorch's postinstall | Approve it after reading it: it downloads the native libraries from the project's GitHub releases | The polyfills: src/polyfills.ts import 'web-streams-polyfill/polyfill'; // ReadableStream, TransformStream import 'fast-text-encoding'; // TextDecoder import { TextDecoderStream, TextEncoderStream } from '@stardazed/streams-text-encoding'; import structuredClone from '@ungap/structured-clone'; const g = globalThis as any; g.TextEncoderStream ??= TextEncoderStream; g.TextDecoderStream ??= TextDecoderStream; g.structuredClone ??= (value: unknown) => structuredClone(value); > Gotcha: Use the global ReadableStream in your adapter. My first streaming run died with "First parameter has member 'readable' that is not a ReadableStream". I had imported ReadableStream from web-streams-polyfill, which is a different class from the global one the polyfill installs, and the AI SDK checks against the global. Build streams with globalThis.ReadableStream. > Gotcha: ExecuTorch sends download analytics by default. Version 0.10 reports anonymous download events to Software Mansion unless you call setTelemetryEnabled(false). That's easy to miss, and it matters if you picked on-device AI for privacy. Two things that failed on the simulator Apple's model said it was available, then failed every call. apple.isAvailable() returned true in the iOS 26.3 simulator, and all 30 calls across two runs failed with GenerationError error -1. The simulator log had the real reason: the model catalog had no assets (UnifiedAssetFramework Code=5000). The same model worked from Swift on the Mac, which runs macOS 26.6, so my guess is a mismatch between the simulator runtime and the Mac's model assets. Either way, the availability flag isn't proof. The MLX build of the model downloaded, then wouldn't load. I picked LLAMA3_2_1B.MLX_INT4 to compare against the CPU backend. It downloaded all 1.18 GB, then failed with Error::NotFound. The podspec explains it: the MLX backend is only linked into device builds, because the simulator SDK lacks the Metal APIs it needs. .DEFAULT would have avoided this, because it only picks backends that are actually linked into the build. Both lead to the same rule, and it's built into the model picker below: check that an engine works with a real call, and use the library's defaults rather than hard-coding a variant. Speed: similar once warm | | ExecuTorch, Llama 3.2 1B (simulator) | Apple Foundation Models (Mac) | | --- | --- | --- | | Download before first use | 1.14 GB, 6 min 12 s | none, part of the OS | | Load from disk | 4.4–5.3 s | none | | First call, time to first text | 0.6–0.8 s | 9.7–19.2 s | | Later calls, time to first text (median) | 579 ms | 580 ms | | Later calls, full summary (median) | 2.5 s | 2.9 s | | Generation speed (median) | 43 tokens/s | not reported | | App memory while generating (median) | 907 MB | not in the app's process | Once both were warm, they were close. The differences are at the edges: - ExecuTorch's cost is up front. A 1.14 GB download on first use, then about 5 s to load the model on each launch. While generating, the app used about 900 MB of memory, which matters on phones that kill background apps. - Apple's cost is the first call. That first call took 10–19 s on this Mac, and later calls took about half a second. The model runs in a system process, so it adds nothing to your app's memory, and there's nothing to download. > How I measured. Two full runs per engine: 5 summaries and 10 checklists each, plus a third set of 10 checklists for the prompt fix below. The first call of each run is reported separately. Memory is the app process's resident size, sampled on the Mac at each result. The Mac was swapping during the runs (5.6 of 6 GB of swap in use), which hurts the Apple numbers most. The raw results and the summary script are in the repo's metrics and scripts folders. @react-native-ai/apple reports zero tokens to the AI SDK, so its token counts and tokens per second are missing. Compare time to first text and total time instead. Structured output: 2 out of 20 vs 20 out of 20 This is the biggest difference between the two engines: | Checklist output that passed the Zod schema | Valid | | --- | --- | | ExecuTorch, schema in the prompt | 2 / 20 | | ExecuTorch, example in the prompt, plus a repair step | 6 / 10 | | Apple, guided generation | 20 / 20 | The 1B model failed in three ways: 1. It returned the schema. In 5 of the 9 failures in one run, it replied with the JSON Schema itself ({"$schema": "http://json-schema.org/draft-07/schema#", ...}) instead of filling it in. 2. Wrong case: "severity": "High" where the schema says "high". 3. Not JSON at all: a bulleted list wrapped in braces. Two cheap changes raised the pass rate from 1 in 10 to 6 in 10 in the same run. Show an example instead of the schema, and lower-case the enum values before validation: const { object } = await generateObject({ model, schema: checklistSchema, prompt, // The adapter puts this example in the prompt instead of the JSON Schema. providerOptions: { executorch: { jsonExample: '{"items":[{"area":"Aisle 2","issue":"Spilled milk","severity":"high"}]}' } }, experimental_repairText: async ({ text }) => text.replace(/"(low|medium|high)"/gi, (m) => m.toLowerCase()), }); 6 out of 10 still isn't good enough to ship, and passing the schema doesn't mean the content is right. I read every valid checklist from the 1B model: - Two of the six copied my example into the store's checklist: "Aisle 2: Spilled milk on floor" was never in the note. - Fields got mixed up: "Back fire exit: Expired yoghurt found in dairy fridge". - Items were duplicated, and every item, in every valid checklist, was marked high. Apple's 20 checklists listed every issue in each note, in sensible areas, and never invented one. It rated a few minor issues too high (a frozen checkout scanner as high), but the fire, rodent and food-safety issues were high every time. Neither engine was good at the summaries. The 1B model opened every one with "Here is a two-sentence summary", then often wrote three or four. It also misread the notes: once it said the torn freezer seal was blocking the fire exit, once that a leaking roof was "not an issue". Apple's summaries were shorter (177 characters against 396), but half came back as Markdown bullet lists rather than two sentences. One left out the wet floor, and another ranked the frozen scanner above expired food. If your feature needs structured output, a 1B model in your app isn't enough. Use the system model, a larger downloaded model (Llama 3.2 3B is in ExecuTorch's catalog), or the cloud. Choosing a model at runtime Here's the picker the lab uses. The order is fixed: Apple's model if it really works, then a downloaded model if the user agreed to the download, then the cloud. The result is cached for the session. src/lab/router.ts // apple.isAvailable() said true in the simulator while every call failed, // so it's only a first filter. A one-token call is the real check. async function appleWorks() { if (Platform.OS !== 'ios' || !apple.isAvailable()) return false; try { await generateText({ model: apple(), prompt: 'Reply with OK.', maxOutputTokens: 2 }); return true; } catch { return false; } } export function pickModel(cloud: LanguageModel, opts: { allowDownload: boolean }): Promise<Route> { return (cached ??= (async (): Promise<Route> => { if (await appleWorks()) return { model: apple(), where: 'on-device (Apple)' }; if (opts.allowDownload) { // DEFAULT only picks backends linked into this build. const et = createExecutorchModel('llama-3.2-1b', models.llm.LLAMA3_2_1B.DEFAULT); try { await et.load(); return { model: et.model, where: 'on-device (downloaded model)' }; } catch {} } return { model: cloud, where: 'cloud' }; })()); } where is for the UI. If people chose your feature because their text stays on the phone, tell them when it doesn't. That applies to the cloud fallback, and to Apple's Private Cloud Compute when iOS 27 sends a request there. This code is type-checked but not benchmarked; the lab measured each engine on its own. Android: Gemini Nano, from the docs I couldn't test this one: Gemini Nano needs a supported Android 14+ phone, and an emulator won't do. On paper it fits the same pattern. @react-native-ai/adk is another AI SDK provider, so it would be one more branch in pickModel. Its availability check comes in steps: isNanoSupported() (can this phone run it?), isAvailable() (is it ready?) and prepareNano(). Given what happened with Apple's flag, I'd still add a probe call. ExecuTorch also runs on Android, using Vulkan for the GPU, so the downloaded-model branch carries over unchanged. What to use, and when Use Apple's Foundation Models first on iOS. There's nothing to download, it doesn't use your app's memory, and guided generation makes structured output reliable. Expect a slow first call, so warm the model up before the user needs it. Use ExecuTorch when there's no system model, for short free-text tasks where a person reads the result: rewording, suggestions, drafts. Check its output before you act on it. Ask before the 1 GB download, show progress, and turn off telemetry. Don't depend on a 1B model for JSON. Keep a cloud fallback, and label it in the UI. Watch expo-ai. It's in review with an Apple provider, streaming and tool calls. If it lands, most of the setup fixes above become Expo's problem rather than yours. Takeaways - Put both engines behind the AI SDK so the calling code stays the same; ExecuTorch needs a small adapter. - Pin ai@6 for the React Native AI providers, and add stream, TextDecoder and structuredClone polyfills for Hermes. - ExecuTorch 0.10.4 needs a one-file patch to build on React Native 0.87 iOS. - Don't trust apple.isAvailable() alone: make a tiny probe call and cache the result. - Use ExecuTorch's .DEFAULT variants; MLX variants download and then fail on the simulator. - A 1B model returned schema-valid JSON 2 times in 20; an example prompt and a repair step got it to 6 in 10. - Apple's guided generation returned valid output 20 times in 20. - Turn off ExecuTorch telemetry, and show users when a request leaves the device. --- I write about React Native in practice, measured and with public code, at praveensingh.co.in.

Achievements

Awards earned by the repositories callstackincubator owns. Select an award to embed its badge.

No awards yet

Repositories earn awards by reaching the top three in a completed trending day or week.

A repository earns an award for finishing first, second or third in a completed trending day or week, ranked by new stars, new forks or pull request authors. Awards follow a repository through renames and transfers and count toward its current owner. Weeks run Monday to Sunday, UTC.