CocoaPods Trunk is a server-side service of the CocoaPods ecosystem designed for publishing, hosting and managing pod libraries. Trunk replaced the outdated publishing mechanism through GitHub repositories and forks by providing a centralized infrastructure with authentication, session management, versioning and validation before publishing. iOS and macOS developers use pod trunk push to submit libraries to the public registry.
Key Takeaways
pod trunk register with email confirmationpod trunk push command goes through validation, linting and upload to the registrypod trunk me, pod trunk add-owner, pod trunk deprecate for pod administrationCocoaPods Trunk is a server infrastructure launched in 2015 for centralized publishing of pod libraries. Before Trunk, each pod was distributed through a Git repository: developers had to create a public repository, add a podspec file, and submit a Pull Request to the central repository CocoaPods/Specs. This approach required manual moderation and created delays when publishing updates.
Trunk solved these problems by providing a unified API for publishing, updating, and managing pods. The service includes four key components:
Trunk's architecture is built on the Ruby on Rails stack with a PostgreSQL database. The service uses HTTP API with JSON format for all operations, and the CLI client pod trunk is part of the CocoaPods distribution, installed along with the main cocoapods gem.
As of today, over 100,000 pods have been published through Trunk, with total downloads exceeding 50 billion. The service processes thousands of publishing and update requests daily from developers around the world.
Before publishing a pod, you must register with Trunk. The process consists of a single step — the pod trunk register command:
pod trunk register your@email.com 'Your Name' --description='MacBook Pro, iOS Development'After running the command, a confirmation link is sent to the specified email. Clicking the link activates the account and creates a session token that is stored in the system keychain (Keychain on macOS, gnome-keyring or equivalent on Linux). The token is automatically used for all subsequent pod trunk operations.
The --description parameter is optional but recommended — it helps identify the session when viewing active sessions via pod trunk me. If you work from multiple machines (workstation, CI server), the description helps distinguish one session from another.
To check authentication status, use the command:
pod trunk meThe output shows email, name, your pod list (if you have published any) and active sessions. Example output:
- Name: Your Name
- Email: your@email.com
- Since: 2024-03-15 10:30 UTC
- Pods:
- MyLibrary
- AnotherPod
- Sessions:
- 2024-03-15 10:30 UTC - MacBook Pro, iOS developmentOn CI servers (GitHub Actions, GitLab CI, Jenkins), authentication is done via a token passed through the COCOAPODS_TRUNK_TOKEN environment variable. The token can be obtained with the command:
pod trunk me --token-onlyThis token is stored in CI settings as a secret variable and is used during the publishing step without repeated registration. Example for GitHub Actions:
env:
COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}Important: the token provides full access to managing pods linked to the account. Never publish it in public repositories or share it with third parties. If compromised, the token can be revoked via pod trunk remove-session or by deleting all sessions through the CocoaPods website control panel.
A podspec file (.podspec or .podspec.json) is the library manifest containing metadata, dependencies, platform information, and source code details. Trunk uses this file for validation and pod registration. A minimal podspec for publishing looks like this:
Pod::Spec.new do |s|
s.name = 'MyLibrary'
s.version = '0.1.0'
s.summary = 'Brief description of the library'
s.description = 'Detailed description with explanation of features'
s.homepage = 'https://github.com/username/MyLibrary'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'Your Name' => 'your@email.com' }
s.source = { :git => 'https://github.com/username/MyLibrary.git', :tag => s.version.to_s }
s.source_files = 'Sources/**/*.{swift,h,m}'
s.platform = :ios, '12.0'
s.swift_version = '5.7'
endKey podspec fields:
MAJOR.MINOR.PATCH format. Trunk does not accept re-publishing the same version — you must increment the number.MIT, Apache-2.0, BSD or another open-source license.Before publishing, validate the podspec with the linter:
pod lib lint MyLibrary.podspecThe linter checks syntax, required fields, file path correctness, and dependency resolution. If the linting process uses private sources, add the --sources flag. To skip network downloads (local-only check), use the --local-only flag.
The main command for publishing a pod is pod trunk push. It sends the podspec file to the Trunk server, where it undergoes full validation and is registered in the public registry. Syntax:
pod trunk push MyLibrary.podspecThe --allow-warnings flag allows publishing with warnings. By default, any warnings block publishing. If your library has known warnings that do not affect functionality, you can use this flag. Important: errors always block publishing regardless of flags.
The --synchronous flag makes the request synchronous — the terminal waits for server-side validation to complete. By default, the command returns control immediately after submission, and the server processes publishing asynchronously. Synchronous mode is useful in CI/CD when the next pipeline step depends on successful publishing.
The --skip-import-validation flag skips checking library import into a test project. This speeds up publishing but does not guarantee the library actually compiles. Use this flag only if you are confident in build correctness.
Example of publishing with typical options:
pod trunk push MyLibrary.podspec \
--allow-warnings \
--synchronous \
--skip-import-validationAfter successful publishing, Trunk returns JSON with details:
Congrats
MyLibrary (0.1.0) successfully published
Pod URL: https://cocoapods.org/pods/MyLibraryThe library becomes available for installation via Podfile in any iOS or macOS project. Typically, CocoaPods search index updates within a few minutes, but in rare cases indexing may take up to an hour.
Important limitation: once a pod version is published, it cannot be deleted. This is to prevent breaking projects that already depend on this version. If a publication was erroneous, you can publish the next version with a fix, but rollback is impossible. The exception is pod trunk delete, which is only available to CocoaPods staff and is used in extreme cases (license violations, malicious code).
CocoaPods Trunk provides several commands for administering published pods:
To transfer publishing rights to another developer, use the command:
pod trunk add-owner MyLibrary developer@email.comAfter execution, the new owner gets full access to pod management: publishing new versions, adding and removing other owners, marking the pod as deprecated. Any registered Trunk user can be an owner — prior registration is required.
If a developer has left the project or should no longer have access to the pod:
pod trunk remove-owner MyLibrary developer@email.comOnly a current owner can remove an owner. You cannot remove the last owner of a pod — you must first add a new one. This prevents a pod from becoming ownerless and abandoned.
If a library is no longer maintained, you can mark it as deprecated. This does not remove the pod from the registry but adds a warning for users during installation:
pod trunk deprecate MyLibraryOptionally, you can specify a replacement pod:
pod trunk deprecate MyLibrary --in-favor-of=NewLibraryWhen installing a deprecated pod, CocoaPods displays a warning in the terminal and recommends switching to the specified replacement. This is the correct way to end library support without breaking existing project builds.
Pod information is available via the pod trunk info command:
pod trunk info MyLibraryThe command shows all pod versions, publication dates, owner list, and status (active/deprecated). To view details of a specific version, use pod spec cat MyLibrary 0.1.0.
When working with Trunk, developers often encounter typical errors. Let's review the most common ones:
Symptom: [!] Authentication failed. You need to register a session first.
Cause: Missing or expired session token. Tokens have a limited validity period (30 days without activity by default).
Solution: Re-run pod trunk register your@email.com 'Your Name'. If you are using CI, check the COCOAPODS_TRUNK_TOKEN environment variable is up to date and generate a new token if needed.
Symptom: [!] You have already pushed version 0.1.0 for MyLibrary.
Cause: Attempt to re-publish an existing version. Trunk does not allow overwriting versions.
Solution: Increment the version in podspec according to semantic versioning. If you made a mistake in the podspec, publish the next version with the fix.
Symptom: [!] The spec did not pass validation. ERROR | [iOS] file patterns: Source files did not match any file.
Cause: Incorrect path to source files in the source_files field.
Solution: Check paths in the podspec, run pod lib lint locally until all errors are resolved, then repeat publishing. Use glob patterns: Classes/**/*.{h,m}, Sources/MyLibrary/**/*.swift.
Symptom: [!] Connection to trunk.cocoapods.org failed. Timeout.
Cause: Network issues or temporary Trunk server unavailability.
Solution: Check server availability: curl -I https://trunk.cocoapods.org. If the server responds, retry the command in a few minutes. Your IP may be blocked — try from a different connection or via VPN.
Symptom: [!] You do not have permission to push to MyLibrary.
Cause: You are not an owner of the pod. This happens if someone has already registered a pod with that name.
Solution: Contact the current pod owner (find out via pod trunk info MyLibrary) and ask them to add you via pod trunk add-owner. If the pod name is taken, consider an alternative name.
Frequently Asked Questions
The old method required a manual Pull Request to the CocoaPods/Specs repository. Trunk automates the process: you run a single pod trunk push command, and the server validates the podspec, adds it to the registry, and updates the search index. Trunk also added access management (multiple owners), session tokens, and centralized metadata storage.
This is not possible — Trunk prohibits deleting published versions to maintain dependency integrity. If a version has a critical bug, publish a new version with the fix and mark the problem version as deprecated via pod trunk deprecate. Full deletion is only available to CocoaPods administrators in exceptional cases.
No, the s.author field must include an email. Trunk uses it to link the pod to the owner's account. The address must match the email used during pod trunk register. If the email in the podspec differs, publishing will be rejected.
Typically, the pod appears in CocoaPods search within 5–15 minutes. In rare cases, indexing may take up to an hour. However, the pod is available for installation via Podfile immediately after a successful response from Trunk — you just need to specify the exact version or range in the Podfile.
If you have an active session (token not expired), change your email via pod trunk register new@email.com — the new registration will link pods to the new address. If the session has expired, contact CocoaPods support via GitHub Issues. Proof of pod ownership could be the ability to create a commit in the pod's Git repository.
Summary
pod trunk register with email confirmation and automatic session token storagepod trunk push command goes through server-side validation; once published, a version cannot be deletedpod trunk add-owner and pod trunk remove-ownerCOCOAPODS_TRUNK_TOKEN environment variable for automated publishing in pipelinesWe will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also