# Odevio CLI decides your iOS output with one of three build types

> A Python command line tool that builds, signs and ships Flutter apps for iOS on remote Macs, aimed at people who do not own one. The whole surface is small: an account, an optional Apple developer link, and a build type that determines whether you get a simulator configuration, an ad-hoc IPA, or a publication build.

**Odevio/Odevio-CLI** — Build, sign and publish iOS apps from any OS - no Mac, no Xcode. Driven by your AI agent

- Repository: https://github.com/Odevio/Odevio-CLI
- Website: https://www.odevio.com
- Stars: 423 · Forks: 18
- Language: Python
- License: MIT
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/odevio-odevio-cli

## One flag decides whether you get a simulator config, an IPA, or a submission

Everything in the build path reduces to a single option, --build-type, with three accepted values and a different command sequence for each.

The configuration mode is the entry point for a new account. It starts a build machine in configuration mode so you can configure Xcode or test the app in the iOS simulator, without needing a signing identity at all.

The ad-hoc path produces something installable on a physical device for testing:

```bash
odevio build start --build-type ad-hoc
odevio build ipa
```

The publication path is the App Store route:

```bash
odevio build start --build-type publication
```

Note what is missing from the last one. There is no separate upload command in the documented flow, so publication covers the build stage, and the release step is described in prose rather than as a command.

When a build fails there is one diagnostic command, odevio build logs.

## Linking an Apple account takes four identifiers and a path to a private key

Signing is opt-in. Without it you can configure Xcode and use the simulator, but producing an IPA or a submission needs your Apple Developer Account attached first.

The command takes five arguments, four of them identifiers:

```bash
odevio apple add --apple-id APPLE_TEAM_ID --name TEXT --key-id APPLE_KEY_ID --issuer-id APPLE_ISSUER_ID --private-key LOCATION_APPLE_PRIVATE_KEY
```

Once the account is linked, the app itself is created separately, with a display name and a bundle identifier:

```bash
odevio app mk --name MY_APP_NAME --bundle-id COM.COMPANY.APP_NAME
```

The split matters for anyone scripting this. The Apple account is a machine-level attachment with a lifetime, while the app identifier is a per-project artefact, and a project that has never been through `odevio app mk` has no identity for signing to target.

The private key is passed as a file location rather than as its contents, which is the safer of the two conventions available.

## The remote Mac is reached over SSH, a QR code and a server-sent event stream

The dependency list explains the architecture better than the prose does, because the three libraries are unusual for a command line tool.

paramiko 3.0.0 is an SSH client. It is the mechanism by which a machine on Odevio's side is started, configured and driven, which is what makes no local Mac a requirement rather than a simplification.

qrcode 7.4.2 generates a barcode, which is how a physical device or a logged-in session gets paired without typing a long token.

sseclient-py 1.8.0 is a client for server-sent events, which is how a build stream is followed rather than polled. The documented way to read a failure, odevio build logs, fits that pattern.

The remaining five are ordinary: click 8.0.4 for the command surface, rich 11.2.0 for terminal output, requests 2.27.1 for HTTP, pyjwt 2.4.0 for token handling and questionary 1.10.0 for the interactive prompts behind signup.

So the tool is a thin local client. Nearly all of the iOS knowledge lives on the remote machine.

## Eight exact pins frozen in 2022, on a package labelled production stable

Dependencies are pinned to exact versions, which is correct for a build tool. The versions themselves are the interesting part.

```text
click==8.0.4
rich==11.2.0
requests==2.27.1
pyjwt==2.4.0
questionary==1.10.0
paramiko==3.0.0
qrcode==7.4.2
sseclient-py==1.8.0
```

Every one of those is a 2022 release, while the package metadata declares requires-python of 3.9 or newer and the classifier Development Status :: 5 - Production/Stable. A stable classifier and a dependency set that has not moved in four years are two different claims, and the second is what you install.

The list is also duplicated. pyproject.toml declares the same eight pins as dependencies, and requirements.txt repeats them identically, which means a change has to be made in two places and nothing enforces that they match.

Packaging itself is straightforward: hatchling as the build backend, a src/ layout, an entry point declared as odevio="odevio.__main__:odevio", and classifiers marking it operating-system independent.

## Three version numbers disagree, and the newest tag is from February 2024

The version of this tool is stated in three places and the three do not agree.

The newest GitHub release is v1.2.2, published on 2024-02-02, after v1.2.1 in December 2023 and v1.2.0 in November 2023. The build metadata in pyproject.toml declares version 1.3.0. The badge at the top of the readme points at 1.3.1.

So the released artefact anyone can pip install by tag is older than the source, and the source is older than the badge. None of the three lines describe the same build.

The repository is not archived and the last push is dated 2026-09-24, so this is not an abandoned project. It is one where the release process stopped two and a half years ago while development continued.

There is a changelog.txt at the root, which would settle the question, but it is not part of what the readme summarises. Pinning a commit is the safer reference than any of the three numbers.

## Claude Code is the first agent supported, but the contract is Agent Skills

The headline feature is that an AI agent drives the tool. Installation is a single command:

```bash
pip install odevio
```

Onboarding then depends on who is driving. For the agent path, one command installs the skill:

```bash
odevio skill install
```

The readme states that this sets up Claude Code, described as the first AI agent supported, while the package description in pyproject.toml makes a broader claim and says it works with any AI agent that supports the Agent Skills standard. Those two statements are consistent if you read Claude Code as the first implementation rather than the only one, and it is worth testing your own agent before assuming.

The described flow is that the agent writes the code, Odevio builds and signs it on a real Mac, fixes what breaks, and ships it to TestFlight. The fixing step is the part that distinguishes this from a build service: a failing Xcode build is something the agent is expected to repair.

## The readme is reStructuredText because it doubles as the PyPI description

The readme is Readme.rst, not markdown, and the reason is packaging. pyproject.toml sets readme to Readme.rst, which means the same file is the long description on PyPI.

That choice explains the formatting. The header is a full set of RST image directives rather than markdown badges: a logo image at two hundred pixels high, a version badge, a licence badge, a libraries.io release badge, a PyPI downloads badge, an UptimeRobot status badge and a CodeFactor badge.

It also explains the code blocks, which use RST code-block directives with the commands indented beneath them. Sphinx renders both correctly, and the same source then works on PyPI.

Documentation is built with .readthedocs.yaml and published at odevio-cli.readthedocs.io, with a suggested order: the installation guide first, then the tutorial on using Odevio with an AI agent, then the reference guide for every option.

## The issue tracker is explicitly not a support channel

Contributing is described with one unusual boundary drawn in bold: the GitHub issue tracker is not intended to provide help or support, and the documentation is the place for that.

What the tracker is for is bugs and improvements, with pull requests linked to open issues described as more appreciated still. Larger changes are expected to start as a discussion first.

The list of wanted contributions is broader than code. Documentation updates, enhancements, designs or bugfixes all count, as do spelling and grammar fixes, and the readme explicitly welcomes blogging, speaking about, or writing tutorials about the project.

The project also asks for GitHub stars directly, with the stated reasoning that sharing it with other Flutter developers is the point. That is an unusual line to find in a contributing guide, and it tells you something about how the project expects to grow.

## Conclusion

This fits a Flutter developer on Linux or Windows who needs a signed iOS artefact without a Mac and is willing to hand an agent the run. It does not fit someone who wants to understand what happened during the build, because the signing, provisioning and Xcode configuration are all deliberately abstracted away. Two things to check before you trust it with an app. First, the dependency list is pinned to versions from 2022 while the package classifier claims production stability, so review those pins yourself. Second, three different version numbers are in play, and the newest published release is v1.2.2 from February 2024 even though the last push is dated 2026-09-24. Treat the private key path argument as the sensitive part of `odevio apple add`.

## FAQ

### What build types does Odevio CLI support?

Three, chosen with --build-type. Configuration mode configures Xcode or tests in the iOS simulator, ad-hoc produces an IPA for a physical device via odevio build start --build-type ad-hoc followed by odevio build ipa, and publication is the App Store path.

### Do I need a Mac to build an iOS app with Odevio CLI?

No. The build and signing run on remote Macs, so the project states you need no Mac, no Xcode and no iOS knowledge. Certificates, devices, provisioning profiles, bundle IDs and Xcode configuration are all managed by the tool.

### How is an Apple Developer Account connected to Odevio CLI?

With odevio apple add, passing --apple-id APPLE_TEAM_ID, --name TEXT, --key-id APPLE_KEY_ID, --issuer-id APPLE_ISSUER_ID and --private-key LOCATION_APPLE_PRIVATE_KEY. The private key is supplied as a file path rather than as its contents. The app itself is then created separately with odevio app mk.

### Which AI agents can drive Odevio CLI?

Claude Code is described as the first AI agent supported and is what odevio skill install sets up. The package description makes the broader claim that it works with any AI agent supporting the Agent Skills standard.

### What dependencies does Odevio CLI have?

Eight exact pins: click 8.0.4, rich 11.2.0, requests 2.27.1, pyjwt 2.4.0, questionary 1.10.0, paramiko 3.0.0, qrcode 7.4.2 and sseclient-py 1.8.0. They are declared twice, in pyproject.toml and again in requirements.txt, and all eight are 2022 releases.

### How do I check a failed Odevio build?

Run odevio build logs. The remote machine is driven over SSH through paramiko and its output is consumed with a server-sent events client, so the build log is streamed rather than polled.

## Sources

- [License: MIT](https://github.com/Odevio/Odevio-CLI/blob/master/LICENSE)
- [Odevio/Odevio-CLI on GitHub](https://github.com/Odevio/Odevio-CLI)
- [Project website](https://www.odevio.com)
- [README](https://github.com/Odevio/Odevio-CLI/blob/master/README.md)
- [Releases](https://github.com/Odevio/Odevio-CLI/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/odevio-odevio-cli
