Pencil Research has acquired Petey, an AI assistant for your Apple Watch, iPhone, and iPad. Petey’s creator, Hidde van der Ploeg, is well known for his high-quality apps, and Petey reflects this. As the acquirer, we wanted to respect the work Hidde put into his app – and also the well-deserved trust in Hidde by the app’s users – by making the transfer process seamless.
With the transfer behind us now, we can share what we’ve learned. The process was painless, but still surprising – some parts that we expected to be difficult were very easy, and some things we took for granted turned out to be impossible.
The services Petey uses that matter for the purposes of transferring it are:
- 🛫 TestFlight, for its beta program and tester management
- 🔐 Keychain sharing, for sharing a user’s private information and subscription status across the user’s devices
- 📱📲 App Groups, to facilitate information sharing between its different targets (iOS/iPadOS, watchOS, iOS widgets, watchOS widgets)
- ☁️ iCloud, specifically iCloud key-value storage and CloudKit
- 💁♂️ Its own backend, for facilitating communication between end user devices and third-party APIs
Preparing the app for transfer
Apple’s approach to app transfers protects users’ privacy while minimizing the bureaucracy imposed on the app developers. Their full documentation covers many corner cases - definitely worth reading in its entirety before attempting this yourself.
🛫TestFlight: Starting over
Petey had a successful beta program, but TestFlight groups and users are not transferable. To make Petey eligible for transfer, all TestFlight testers and groups needed to be deleted. Testers added by email can always be re-added, of course, but testers who joined the beta program via anonymous link are lost.
🔐Keychain sharing: Minor for us, maybe worse for you
Transferred apps like Petey lose their existing keychain access groups when the buyer releases their first update. Petey handles this without a hiccup, but it’s easy to imagine an app that stores critical information in keychain – this would require a coordinated migration of user data between the seller and buyer, starting before the transfer is initiated. See DTS’s comments in the developer forum thread ITMS-90076: Potential Loss of Keychain Access.
Post-transfer
With Petey transferred into our account, we needed to release a minor update to make sure we had everything we needed to update the app. Attempting to build the app showed a few issues in each target in the ‘Signing and Capabilities’ tab.
📱📲 Moving over missing bundle and app group IDs
First, we changed the Team for each target from the seller’s team to our team. This revealed that, with the exception of the bundle ID for the iOS/iPadOS target, all the required identifiers for the app were not available for us to use. Xcode reported this as:
Failed to register bundle identifier. The app identifier (some bundle ID) cannot be registered to your development team because it is not available. Change your bundle identifier to a unique string to try again.
The cause of this is that the app transfer process only transferred the bundle ID for the iOS/iPadOS target to our account, leaving the bundle IDs for the other targets behind. It also left the app group ID in the seller’s account.
The fix was simple enough: the seller deleted the bundle IDs and the App Group ID from their developer account, and we registered them in ours.
☁️ Tweaking the iCloud KV storage entitlement
Attempting a build then revealed another issue, which Xcode reported as:
Provisioning profile “iOS Team Provisioning Profile: (some bundle ID) doesn’t match the entitlements file’s value for the com.apple.developer.ubiquity-kvstore-identifier entitlement.
This is caused by iCloud KVS using, by default, a dynamic value for one of the app’s entitlements.
The fix was to edit the app’s .entitlements
file. Find the com.apple.developer.ubiquity-kvstore-identifier
key, and change the value from:
$(TeamIdentifierPrefix)$(CFBundleIdentifier)
to:
SellerTeamID.com.company.app
Hardcoding the seller’s team ID here will resolve the error. (If you’re using Xcode to edit your .entitlements
file, the key will be shown as “iCloud Key-Value Store”.)
💁♂️ Moving the backend
Petey’s backend carries a lot of the app’s value, since the app’s functionality is largely dependent on the third-party API access intermediated by the backend. By coordinating carefully on transferring first the domain, and then the services, we were able to avoid downtime.
To transfer the domain without downtime, the buyer needs to add DNS records as soon as they’re able – ideally, before the domain transfer is finished. Here’s what we did:
- Seller gives buyer the complete DNS records for the domain
- Seller unlocks the domain
- Seller requests an authorization code (< 24 hours)
- Buyer uses authorization code to initiate the domain transfer
- Buyer adds the DNS records from step 1 to the buyer’s registrar’s DNS settings as soon as possible (even if you want to eventually use a real DNS service)
- Wait. (The seller’s registrar will likely enforce a one- to five-day delay on the transfer.)
When transferring a domain in, most registrars will either preserve the seller’s nameserver records for the domain, or set the domain to use the registrar’s own nameserver. Our registrar (Hover) preserved the seller’s nameservers (Squarespace), and Squarespace kept answering DNS requests for the domain even after transferring it out. That gave us time to manually switch the nameservers to our own. The domain’s records were available throughout the process.
With the domain safely moved, it was time to move the services. For Petey, that meant transferring some Vercel projects and GitHub repositories. Rather than inviting the seller to our existing team, which involved some security and billing complexity, the seller transferred the projects to one of our admins who then transferred it to the team.
Welcome, Petey!
We acquired Petey because we believe in Hidde’s app design philosophy, the app’s quality, the taste of its users, and the future potential of apps that make AI tools accessible to everyday users. We’re excited to get to work.