Add Action Extension to Expo App without Ejecting

I would like to add an Action Extension to my Expo app but I would like to avoid to eject.

I was wondering if it’d be possible to create the AE and upon release (build) eject the Expo app, link the module, export the assets and build the app with turtle-cli.

In development I wouldn’t need the AE and can continue to develop using the expo-cli without ejecting (maybe aliasing the import to a noop). Has anybody done anything like this? Is it even possible? If so can I get some guidance (noob here)?

Update I did manage to get this to work in development.

The workflow looks like the following:

  • I clone the app in a temporary folder
  • yarn && expo eject
  • cd ios && pod install && cd …

Creating the Extension

  • Open ios/YourApp.xcworkspace
  • Select the App from the left sidebar
  • You’d get another column TARGET, click + at the bottom left
  • Create the Extension

Running the app in development

  • run node_modules/react-native/scripts/launchPackager.command
  • yarn ios (it’ll open the simulator and fail - close it)
  • expo start (open the app in the simulator and it’ll work)

Now I am trying to figure out how to build it for distribution (or simulator) with turtle-cli.

I have ejected my expo app to add an Action Extension (I actually eject only at build time because in development I want to keep using Expo).

I build the app (I use turtle-cli with -t simulator ) and when I run the app the extension is not available in Safari. I assume that turtle builds my parent app but not the extension. Is there anything I need to do (linking or something) to get this to work?

Hi. Sorry, I can’t answer your questions about turtle-cli etc., but have you seen this documentation about using the Expo client despite having ejected?

Thank you for replying! I am thinking that the following bit might apply

Avoid importing the expo package in bare apps

Using the approaches above, you should avoid importing the expo package in bare environments. If you import anything from the expo package it will run code that assumes you are within the client runtime environment and throw an error.

This is relevant when I run yarn ios and probably why I get the following error in the simulator after that:

The Expo SDK requires Expo to run. It appears the native Expo modules are unavailable and this code is not running on Expo.

Unfortunately the docs are not that informative nor suggest a solution or actions to take.

In any case I would like to know how I can build my container app to include the Action Extension when I eject.

I assume the build information for the main app (generated by Expo) are in its Info.plist file and turtle-cli builds the app using those information. If that’s the case maybe it can build the Action Extension as well?


I’m not sure if turtle-cli can be used to build a Bare Workflow app. The documentation says it’s for building Standalone apps, which implies to me that it’s for the Managed Workflow. Perhaps someone who knows the answer will post a comment in this thread.

Yes, this error is because you’ve got some code that does:

import ... from 'expo';

I’m a bit confused, though. I don’t think you can import stuff from expo in ejected apps, but you say you’re able to eject and build your app? If so then I don’t understand where/when you’re seeing this error.

Anyway make sure you’re on the latest SDK version (36 at the moment) because the Expo team is moving more and more stuff out of the expo package into separate modules.

I’m a bit confused, though. I don’t think you can import stuff from expo in ejected apps, but you say you’re able to eject and build your app? If so then I don’t understand where/when you’re seeing this error.

I am able to run the ejected app with expo start but I get the error when I use yarn ios which I believe builds and runs the app with expo start --ios.

I assume that the latter is compiling the action extension as well but then it cannot run the container (main) app because it imports from expo. That might be the reason why, when I run the container app with expo start, the action extension is available in Safari but also why when I try to package/build the app with turtle-ci the app extension is not bundled.

Hey @giu, unfortunately right now you can’t use either the expo-cli or turtle-cli to build bare react native apps. To build, you’ll need to go through xcode or Android studio (or check out fastlane, that’s a pretty popular command line tool for building android/ios apps)

Also- you can’t import from expo in a bare app. However, we are going to provide replacements for these modules come SDK 37!

Actually now rereading the thread it’s not clear- did you eject to Expokit or to bare?

Hi @charliecruzan thank you for looking into this! That’s what I figured, it seems that turtle-cli can’t build my “enhanced” bare app - I basically have an expo-cli powered app which I am ejecting only to add an Action Extension.

When I build it with turtle-cli the app builds just fine but the Action Extension is not built and bundled.

I am a total noob to be honest and I wouldn’t know how to build the app with xcode or fastlane in the same way as turtle-cli does i.e. make it so it references the assets, including ios-index.json hosted on my servers (basically to get js updates). I’d really appreciate if you could give me any pointer.

I started to look into the implementation of turtle-cli and I guess it won’t be that hard for somebody who knows what’s going on to have it pick up and build anything in the main (container) app workspace (in my case the ejected expo app + action extension).

Do you think it makes sense to open an issue?

Fwiw I am looking at the modules below. Please let me know in case you have any idea about how to patch turtle-cli to achieve what I am trying to do, I’d be happy to contribute back once I have figured all this out.

I found this but couldn’t figure out where it is used

By the way thanks for the tip: replacing the imports from expo (I was only using Linking) works and I can run the app with react-native run-ios - and my action extension works!