mirror of
https://github.com/utmapp/UTM.git
synced 2026-10-11 21:59:56 +00:00
agents: add /utm-release for publishing GitHub releases
Cutting a release meant hand-assembling notes that the app parses for "What's New", and Release.md no longer matched the template in use. The skill drafts the notes from the commits and PRs since the last release (carrying the series forward on revisions), waits for approval, then bumps Build.xcconfig, tags, and creates the release and its Releases discussion. Release.md now holds the current template and footer and documents which platform prefixes the in-app parser accepts. Assisted-by: Claude:claude-opus-5-5
This commit is contained in:
@@ -0,0 +1,211 @@
|
||||
---
|
||||
name: utm-release
|
||||
description: Publish a new UTM release on GitHub. Drafts the release notes from the commits and pull requests since the last release, has the user approve them, bumps the version in Build.xcconfig, commits and tags it, pushes, and creates the GitHub release with a discussion in the "Releases" category, which starts the release pipeline. Use this when the user wants to cut, publish, tag, or draft a UTM release or beta, or runs /utm-release.
|
||||
---
|
||||
|
||||
# utm-release
|
||||
|
||||
This is the canonical copy. The per-agent entries in `.claude/commands/` and
|
||||
`.opencode/command/` point here. `$SCRATCH` means your agent's scratch directory,
|
||||
or `mktemp -d` if you don't have one.
|
||||
|
||||
Arguments, both optional and in this order:
|
||||
|
||||
1. **Version** `x.y.z`. The default is the next revision after the current
|
||||
`MARKETING_VERSION` in `Build.xcconfig` (5.0.5 → 5.0.6).
|
||||
2. **Prerelease** `yes` or `no`. The default is `yes`.
|
||||
|
||||
Read `Documentation/Release.md` first. Its "Release notes" section describes how
|
||||
the app parses the notes, and how to version and write them. Its "Release notes
|
||||
template" gives the layout and the footer (from `## Issues` to the end), which
|
||||
you copy verbatim. This skill doesn't repeat those rules, so apply them.
|
||||
|
||||
## Ground rules
|
||||
|
||||
- **Nothing leaves the machine until the user approves the notes.** Pushing
|
||||
the tag and creating the release start the public pipeline, which signs the
|
||||
build and submits it to App Store Connect. It can't be undone cleanly.
|
||||
- The GitHub secrets and variables are already set up. Don't read, change, or
|
||||
check them.
|
||||
- Commit `Build.xcconfig` only. Leave any other changes in the working tree
|
||||
alone.
|
||||
|
||||
## Step 1: Preflight
|
||||
|
||||
```sh
|
||||
git fetch origin --tags
|
||||
git status --short
|
||||
git rev-parse --abbrev-ref HEAD # must be main
|
||||
git rev-list --left-right --count HEAD...origin/main # must be 0 0
|
||||
grep -E '^(MARKETING_VERSION|CURRENT_PROJECT_VERSION)' Build.xcconfig
|
||||
gh release list -R utmapp/UTM -L 10
|
||||
```
|
||||
|
||||
- Stop and ask if you're not on `main`, if `main` differs from `origin/main`, or
|
||||
if `Build.xcconfig` has uncommitted changes. Other dirty files are fine.
|
||||
- If `gh` isn't authenticated, ask the user to run `gh auth login`.
|
||||
- The **previous release** is the newest entry in `gh release list`. Its tag
|
||||
should match the current `MARKETING_VERSION`. If it doesn't, tell the user
|
||||
before you continue.
|
||||
- Work out the new version and check that it is greater than the previous one.
|
||||
If tag `vx.y.z` already exists, locally or on GitHub, stop. The user probably
|
||||
wants a re-release. Point them to "Re-release" in `Release.md` and ask how to
|
||||
proceed.
|
||||
- The new build number is the current `CURRENT_PROJECT_VERSION` + 1.
|
||||
|
||||
## Step 2: Start the notes
|
||||
|
||||
- **Revision** (same `x.y` as the previous release, z > 0): start from the
|
||||
previous release's full notes:
|
||||
`gh release view <prev-tag> -R utmapp/UTM --json body -q .body | tr -d '\r'`.
|
||||
Keep every section, including all the older `## Changes` sections.
|
||||
- **New minor or major version**: start from the template in `Release.md`.
|
||||
Carry nothing over from the previous series.
|
||||
|
||||
Either way, replace the footer with the one in `Release.md`, so the release uses
|
||||
the current template.
|
||||
|
||||
## Step 3: Collect the changes
|
||||
|
||||
List everything that landed since the previous release:
|
||||
|
||||
```sh
|
||||
git log --first-parent --reverse --format='%H %an <%ae>%n %s' <prev-tag>..origin/main
|
||||
```
|
||||
|
||||
Each entry is one of these:
|
||||
|
||||
- **A merge commit** (`Merge pull request #N from owner/branch`): one PR.
|
||||
- **A squash merge** (subject ends in `(#N)`): one PR.
|
||||
- **A direct commit to `main`**: its own change.
|
||||
|
||||
For each PR, fetch its details:
|
||||
|
||||
```sh
|
||||
gh pr view N -R utmapp/UTM --json title,body,author,commits,files,closingIssuesReferences
|
||||
gh api repos/utmapp/UTM/pulls/N --jq '.user.login + " " + .author_association'
|
||||
```
|
||||
|
||||
For a direct commit, read `git show --stat <sha>`, and get the author's GitHub
|
||||
login with `gh api repos/utmapp/UTM/commits/<sha> --jq .author.login`.
|
||||
|
||||
Then write one bullet per PR or direct commit, in the format that `Release.md`
|
||||
gives. Work out each part from the code and the discussion, not only from the
|
||||
title:
|
||||
|
||||
- **What changed.** Describe what users see, and start with a verb (Fixed,
|
||||
Added, Support, …). If several PRs or commits build one feature, merge them
|
||||
into one bullet.
|
||||
- **Platform.** Judge from the files touched and from `#if os(...)`,
|
||||
`WITH_QEMU_TCI`, `@available`, or `#available` checks. The code in
|
||||
`Platform/macOS/`, the Apple Virtualization backend (`UTMAppleVirtualMachine`
|
||||
and `Configuration/UTMAppleConfiguration*`), `QEMUHelper`, `QEMULauncher`, and
|
||||
`utmctl` is macOS-only. If a change only applies from some OS version, add the
|
||||
version: `(macOS 26)`. Use only prefixes that the table in `Release.md` accepts.
|
||||
- **Component.** Use the same names as earlier notes (the list in `Release.md`,
|
||||
and whatever the previous notes used). Translations are always
|
||||
`Localization:`, with each language named in English (`German`, not `de`).
|
||||
Work the language out from the `.lproj` folders that the change touches (for
|
||||
example `Platform/de.lproj` is German, and `zh-HK` plus `zh-Hans` is
|
||||
`Chinese (Hong Kong, Simplified)`).
|
||||
- **Issue.** If the change fixes a bug or resolves a request that has an issue,
|
||||
add `(#N)`. Find it in `closingIssuesReferences` or a `Fixes`, `Resolves`, or
|
||||
`Closes #N` line in the PR body or the commit messages. Don't cite the PR
|
||||
number itself.
|
||||
- **Credit.** If `author_association` isn't `OWNER` or `MEMBER`, add
|
||||
`(thanks @login)`. Do the same for a direct commit by someone other than a
|
||||
maintainer. Don't credit bots.
|
||||
- **Leave out** changes that users can't see: docs, CI, agent skills, tests,
|
||||
refactors, and build scripts that don't change what ships. Keep build fixes
|
||||
that do change the shipped app. For example, a dependency link fix that makes
|
||||
UTM run on older macOS is user-visible. Keep a list of what you left out, to
|
||||
show the user.
|
||||
|
||||
Put the new bullets in `## Changes (vx.y.z)`, directly above the previous
|
||||
`## Changes` section. Sort them into the groups that `Release.md` describes:
|
||||
changes for every platform first, then each platform's own changes, and within
|
||||
each of those, every bullet for the same component next to the others. Check the
|
||||
order again after the user's edits in Step 5. Leave the older sections in the
|
||||
order they were published, but offer to sort any that aren't sorted yet.
|
||||
|
||||
## Step 4: Highlights and notes
|
||||
|
||||
- **Highlights.** Review the list with the whole release, or series, in mind.
|
||||
Add a highlight only for a major feature or change, or a theme that several
|
||||
changes share. Write for a general audience, with marketing terms rather than
|
||||
technical ones. On a revision, keep the earlier highlights, but you may reword
|
||||
or merge them when a new change extends one. If nothing is worth a
|
||||
highlight, don't invent one. Tell the user instead, because the first section
|
||||
is what the app shows up front.
|
||||
- **Notes and Known Issues.** Keep the carried-over entries, but flag any that
|
||||
are now stale, such as a requirement that was reverted or a known issue that
|
||||
this release fixes. Suggest removing them rather than removing them yourself.
|
||||
Propose new notes when a change needs action from users (reinstall a driver,
|
||||
new minimum OS, changed defaults).
|
||||
|
||||
## Step 5: Get the notes approved
|
||||
|
||||
Write the notes to `$SCRATCH/release-notes-vx.y.z.md`. Show the user:
|
||||
|
||||
- the full notes,
|
||||
- the title (`vx.y.z (Beta)` for a prerelease, otherwise `vx.y.z`), the version,
|
||||
the build number, and whether it's a prerelease,
|
||||
- the commits and PRs you left out, and why,
|
||||
- anything you weren't sure about: platform, issue, credit, or stale notes.
|
||||
|
||||
Then **stop and wait**. The user may add notes or highlights, or edit the
|
||||
changelog. Apply their edits to the file and show the result again. Repeat until
|
||||
they approve this exact text. If they change the version or the prerelease
|
||||
setting, go back to Step 1.
|
||||
|
||||
## Step 6: Bump, commit, tag, push
|
||||
|
||||
Once the user has approved:
|
||||
|
||||
1. In `Build.xcconfig`, set `MARKETING_VERSION = x.y.z` and
|
||||
`CURRENT_PROJECT_VERSION` to the new build number. Change nothing else.
|
||||
2. Commit only that file. The title is exactly `project: bumped version`, and it
|
||||
carries the AI-attribution trailer that `AGENTS.md` requires:
|
||||
```sh
|
||||
git add Build.xcconfig
|
||||
git commit -m "project: bumped version" -m "Assisted-by: AGENT:MODEL"
|
||||
```
|
||||
Put your own agent and model in the trailer. Don't add `Co-authored-by` or
|
||||
session links, and remove any that your tools add.
|
||||
3. Tag the commit and push both. Use a lightweight tag, like earlier releases:
|
||||
```sh
|
||||
git tag vx.y.z
|
||||
git push origin main
|
||||
git push origin vx.y.z
|
||||
```
|
||||
If the push to `main` is rejected, stop and tell the user. Don't force-push or
|
||||
rebase over new commits on `main`. If new commits landed, their changes are
|
||||
missing from the notes.
|
||||
|
||||
## Step 7: Create the release
|
||||
|
||||
```sh
|
||||
gh release create vx.y.z -R utmapp/UTM --verify-tag \
|
||||
--title "vx.y.z (Beta)" --prerelease \
|
||||
--notes-file "$SCRATCH/release-notes-vx.y.z.md" \
|
||||
--discussion-category "Releases"
|
||||
```
|
||||
|
||||
For a stable release, use `--title "vx.y.z"` and `--latest` instead of
|
||||
`--prerelease`. Don't create a draft. The pipeline runs on the release's
|
||||
`created` event, and a published release is what the app downloads its notes
|
||||
from.
|
||||
|
||||
Then check the result, and fix what you can:
|
||||
|
||||
```sh
|
||||
gh release view vx.y.z -R utmapp/UTM --json name,isPrerelease,url
|
||||
gh api graphql -f query='{repository(owner:"utmapp",name:"UTM"){discussions(first:3,orderBy:{field:CREATED_AT,direction:DESC}){nodes{title url category{name}}}}}'
|
||||
gh run list -R utmapp/UTM --workflow Build --event release -L 1 # not "build.yml": that filter returns stale runs
|
||||
```
|
||||
|
||||
- The discussion must be titled like the release and be in "Releases".
|
||||
- A `Build` run titled like the release should have started for the release event.
|
||||
|
||||
Report the release URL, the discussion URL, and the pipeline run URL. Don't wait
|
||||
for the pipeline to finish unless the user asks.
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
description: Publish a new UTM GitHub release — drafts release notes since the last release, asks for approval, then bumps Build.xcconfig, tags, and creates the release + Releases discussion.
|
||||
argument-hint: [version x.y.z (default next revision)] [prerelease yes|no (default yes)]
|
||||
allowed-tools: Bash, Read, Grep, Glob, Edit, Write, AskUserQuestion
|
||||
---
|
||||
|
||||
Read and follow `.agents/skills/utm-release/SKILL.md`. Use your scratchpad
|
||||
directory as `$SCRATCH`. At the approval step, show the full notes as text,
|
||||
then use AskUserQuestion to ask whether to publish, and treat any edits the user
|
||||
asks for as another round. The trailer is `Assisted-by: Claude:<your model ID>`.
|
||||
|
||||
Arguments (version, then prerelease): $ARGUMENTS
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
description: Publish a new UTM GitHub release — drafts release notes since the last release, asks for approval, then bumps Build.xcconfig, tags, and creates the release + Releases discussion.
|
||||
---
|
||||
|
||||
Follow this UTM release workflow. Arguments (version x.y.z, then prerelease
|
||||
yes|no; both optional): $ARGUMENTS
|
||||
|
||||
@.agents/skills/utm-release/SKILL.md
|
||||
+85
-33
@@ -1,67 +1,119 @@
|
||||
# Release Guide
|
||||
|
||||
This document details the release procedure for UTM team members. The release procedure is mostly automated by GitHub Actions. In short, when you submit a new "release" on the GitHub repository, the following happens:
|
||||
This document details the release procedure for UTM team members. The release procedure is mostly automated by GitHub Actions. In short, when you create a new release on the GitHub repository, the following happens:
|
||||
|
||||
1. If UTM dependencies are not cached from a previous run, build it for {iOS,macOS,iOS-TCI,iOS Simulator} X {arm64,x86_64}.
|
||||
2. Build UTM for all configurations and architectures.
|
||||
3. Take the {iOS-arm64,iOS-TCI-arm64} build and package it into a fakesigned IPA and post it as a release asset.
|
||||
4. Take the iOS-arm64 build and package it into a Cydia DEB and post it as a release asset.
|
||||
5. Update the Cydia repository.
|
||||
6. Update the AltStore repository.
|
||||
7. Combine dependencies for macOS-arm64 and macOS-x86_64 into universal binaries.
|
||||
8. Build UTM as a macOS universal binary.
|
||||
9. Take the universal binary and sign and package it into a DMG.
|
||||
10. Notarize the DMG with App Store Connect and post it as a release asset.
|
||||
11. Take the universal binary and sign and package it for the Mac App Store.
|
||||
12. Submit the signed package to App Store Connect.
|
||||
1. If UTM dependencies are not cached from a previous run, build them for every platform (iOS, iOS TCI, iOS Simulator, visionOS, visionOS TCI, visionOS Simulator, macOS) and architecture.
|
||||
2. Build UTM for every scheme (iOS, iOS SE, iOS Remote, macOS) on each platform and architecture.
|
||||
3. Package the iOS and visionOS builds into fakesigned IPAs (`UTM.ipa`, `UTM-HV.ipa`, `UTM-SE.ipa`, `UTM-Remote.ipa`, and the `-visionOS` variants) and a jailbreak DEB (`UTM.deb`) and post them as release assets.
|
||||
4. Dispatch updates to the AltStore and Cydia repositories.
|
||||
5. Combine dependencies for macOS-arm64 and macOS-x86_64 into universal binaries and build UTM as a macOS universal binary.
|
||||
6. Sign, package, and notarize the universal build into a DMG and post it as a release asset.
|
||||
7. Sign and package the universal build for the Mac App Store and submit it to App Store Connect.
|
||||
8. Sign UTM SE and UTM Remote (iOS and visionOS) and submit them to App Store Connect.
|
||||
|
||||
For more details see the [build.yml](../.github/workflows/build.yml) file.
|
||||
|
||||
## Making a release
|
||||
|
||||
Once you are ready to make a new release:
|
||||
Agents can do all of this with the `/utm-release` skill ([`.agents/skills/utm-release/SKILL.md`](../.agents/skills/utm-release/SKILL.md)), which drafts the release notes and asks for approval before publishing. To do it by hand:
|
||||
|
||||
1. Modify [Build.xcconfig](../Build.xcconfig) and bump `MARKETING_VERSION` following [semantic versioning][5] and `CURRENT_PROJECT_VERSION` by 1.
|
||||
2. Commit the change with the commit message `project: bumped version`. Tag the release with `git tag vx.y.z` corresponding to `MARKETING_VERSION`.
|
||||
2. Commit only that change with the commit message `project: bumped version`. Tag the commit with `git tag vx.y.z` corresponding to `MARKETING_VERSION`.
|
||||
3. Push the commit and tag.
|
||||
4. In GitHub, draft a new release with the template below. Use the title `vx.y.z` or `vx.y.z (Beta)`. Select the tag you just created. Check "This is a pre-release" if it is a beta. Check "Create a discussion for this release" and the "Release" category.
|
||||
5. When the release is published, the pipeline will run and do everything else.
|
||||
4. In GitHub, draft a new release with the template below. Use the title `vx.y.z` or `vx.y.z (Beta)`. Select the tag you just created. Check "Set as a pre-release" if it is a beta. Check "Create a discussion for this release" and select the "Releases" category.
|
||||
5. When the release is created, the pipeline will run and do everything else.
|
||||
|
||||
### Release notes
|
||||
|
||||
The app downloads the notes for its own version from the GitHub release and shows them as "What's New" the first time it launches, so the notes are parsed as well as read. See [UTMReleaseHelper.swift](../Platform/UTMReleaseHelper.swift) and [VMReleaseNotesView.swift](../Platform/Shared/VMReleaseNotesView.swift).
|
||||
|
||||
* Each `## ` heading starts a section. The **first** section is shown up front without its title, so it must be `## Highlights`. "Highlights" and "Installation" are skipped when the user taps "Show All"; every other section is shown.
|
||||
* Every line is a `* ` bullet. Other lines (including `### ` headings) are shown as raw text, so do not use sub-headings. Inline Markdown (bold, links, code) is rendered.
|
||||
* A bullet that starts with a parenthesized prefix, `* (prefix) text`, is shown only on matching builds, with the prefix stripped:
|
||||
|
||||
| Prefix | Shown in |
|
||||
|--------|----------|
|
||||
| starts with `macOS`, e.g. `(macOS)`, `(macOS 26)` | macOS |
|
||||
| starts with `iOS`, e.g. `(iOS)`, `(iOS 17)`, `(iOS Remote)` (but not `(iOS SE)`) | all iOS and visionOS builds, including UTM SE and UTM Remote |
|
||||
| `(iOS SE)` exactly | UTM SE only |
|
||||
| starts with `visionOS` | visionOS builds only |
|
||||
|
||||
Any other parenthesized prefix, such as `(iPadOS)`, `(AVF)`, or `(iOS, macOS)`, hides the line on **every** platform. Put components after the platform instead: `* (macOS) Settings: ...`. GitHub still shows every line.
|
||||
|
||||
#### Versioning the notes
|
||||
|
||||
* **New minor or major version (`x.y.0`)**: start fresh notes from the template below.
|
||||
* **Revision (`x.y.z`, z > 0)**: copy the full notes of the previous release in the same `x.y` series, then add or update highlights and notes, and add a new `## Changes (vx.y.z)` section above the previous ones. The changes for every release in the series stay in the notes, newest first.
|
||||
|
||||
#### Writing the notes
|
||||
|
||||
* **Highlights** are the first thing users see, so use them sparingly: major features or changes only, or a theme that several changes share. Write them for a general audience, in marketing terms rather than technical ones: `* **Feature name**: One or two sentences.` Put a platform prefix before the bold title if the feature is only on one platform.
|
||||
* **Notes** are for anything users must know or do: changed behaviour, requirements, migration steps, recommendations.
|
||||
* **Known Issues** list major problems in this release, with a workaround if there is one.
|
||||
* **Changes** list one bullet per commit, or one per pull request if the commits came from a PR. If several commits make up one feature, write one bullet. Leave out changes users can't see (documentation, CI, agent tooling, refactoring). Format each bullet as:
|
||||
|
||||
`* (Platform) Component: What changed (#issue) (thanks @contributor)`
|
||||
|
||||
* `(Platform)` only if the change affects one platform, or one version of it (`(macOS 26)`); see the prefix table above.
|
||||
* `Component:` when the change belongs to one area. Commonly used: Home, Config, Wizard, Settings, Toolbar, Scripting, utmctl, AVF, QEMU, SPICE, CocoaSpice, ANGLE, USB, Downloader, Localization.
|
||||
* `(#issue)` is the issue the change fixes or resolves, not the PR number.
|
||||
* `(thanks @login)` credits a PR or commit author who is not a UTM maintainer.
|
||||
* Translation changes use the `Localization:` component and name each language in English, not by its code: `* Localization: Updated German (thanks @contributor)`, not `de`. Add the region or script in parentheses when it matters: `Chinese (Hong Kong, Simplified)`.
|
||||
* Sort each `## Changes` section into groups:
|
||||
1. Changes for every platform, then `(iOS…)` changes, then `(visionOS…)` changes, then `(macOS…)` changes. Keep a versioned prefix such as `(macOS 26)` next to the others for that platform.
|
||||
2. Within each platform group, bullets with no component first, then one run of bullets per component, so every change for the same component on the same platform sits together.
|
||||
|
||||
### Release notes template
|
||||
|
||||
Make sure to copy all the changes for all beta releases after the last non-beta release.
|
||||
`## Notes` and `## Known Issues` are optional; remove them if they are empty. Use the footer (from `## Issues` to the end) verbatim.
|
||||
|
||||
```
|
||||
## Installation
|
||||
Visit [https://getutm.app/install/][1] for the most up to date installation instructions.
|
||||
|
||||
## Highlights
|
||||
* Key features
|
||||
* Keep these bullets short
|
||||
* **Feature name**: One or two sentences for a general audience.
|
||||
* (macOS) **Platform-only feature**: Prefix the line if the feature is only on one platform.
|
||||
|
||||
## Notes
|
||||
* List any important changes here
|
||||
* Include anything that deviates significantly from previously defined behaviour
|
||||
* List any important changes here.
|
||||
* Include anything that deviates significantly from previously defined behaviour.
|
||||
|
||||
## Known Issues
|
||||
* List any known major issues here.
|
||||
|
||||
## Changes (vx.y.1)
|
||||
* Third change
|
||||
* (iOS) iOS only change
|
||||
* (iOS) Another iOS only change
|
||||
* (macOS) A macOS only change
|
||||
* A change on every platform (#1234)
|
||||
* Component: A change in one component (thanks @contributor)
|
||||
* Component: Another change in the same component
|
||||
* Localization: Updated German (thanks @contributor)
|
||||
* (iOS) An iOS-only change
|
||||
* (macOS) A macOS-only change
|
||||
* (macOS) Component: A macOS-only change in one component
|
||||
|
||||
## Changes (vx.y.0)
|
||||
* One change
|
||||
* Another change
|
||||
|
||||
## Issues
|
||||
Please check the full list on [Github][2] and help report any bug you find that is not listed.
|
||||
Please check the full list on [Github](https://github.com/utmapp/UTM/issues) and help report any bug you find that is not listed.
|
||||
|
||||
### Known Issues
|
||||
## Installation
|
||||
|
||||
* Optional section. List any known major issues here in bullet points.
|
||||
* [iOS](https://docs.getutm.app/installation/ios/)
|
||||
* [macOS](https://docs.getutm.app/installation/macos/)
|
||||
|
||||
| File | Description | Installation | JIT | Hypervisor | USB |
|
||||
|------|------------|--------------|-----|-----------|-----|
|
||||
| UTM.deb | Jailbroken iOS version | Open in Cydia, dpkg, or Sileo | Yes | Yes(1) | Yes |
|
||||
| UTM.dmg | macOS version | Mounting and copying UTM.app to /Applications | Yes | Yes | Yes |
|
||||
| UTM.ipa | Non-jailbroken iOS version (sideloading) | AltStore, etc (see guide) | Yes(2) | No | No |
|
||||
| UTM-HV.ipa | Non-jailbroken iOS version (TrollStore) | TrollStore | Yes | Yes(1) | Yes |
|
||||
| UTM-SE.ipa | Non-jailbroken iOS version (sideloading) | AltStore, enterprise signing, etc | No | No | No |
|
||||
| UTM-Remote.ipa | Remote client | Any | No | No | No |
|
||||
|
||||
1. Hypervisor on iOS requires an M1 iPad or newer.
|
||||
2. Enabling JIT may require a separate JIT enabler such as [Jitterbug][2] or Jitstreamer.
|
||||
|
||||
[1]: https://getutm.app/install/
|
||||
[2]: https://github.com/utmapp/UTM/issues
|
||||
[2]: https://github.com/osy/Jitterbug
|
||||
```
|
||||
|
||||
### Beta release
|
||||
|
||||
Reference in New Issue
Block a user