Skip to content

Conversation

@ahmedadan
Copy link
Contributor

@ahmedadan ahmedadan commented Nov 17, 2025

  • Have you followed the guidelines in our Contributing document?
  • Have you checked to ensure there aren't other open Pull Requests for the same change?
  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes? Here's an example.
  • Have you successfully run brew lgtm (style, typechecking and tests) with your changes locally?

Adds support for Flatpak applications and remotes in Brewfile. This change extends Brewfile to support managing Flatpak applications and remotes, making it easier to maintain a consistent set of installed applications across Linux systems.

Sample Brewfile

brew "git"
brew "neovim"

# Add Flatpak custom remotes
flatpak_remote "flathub-beta", "https://flathub.org/beta-repo/flathub-beta.flatpakrepo"

# Install Flatpak applications
flatpak "org.gnome.Calculator"
flatpak "org.mozilla.firefox"
flatpak "com.spotify.Client"
flatpak "org.godotengine.Godot", remote: "flathub-beta"

Bundle Commands

All Brewfile commands now support Flatpak operations:

  • brew bundle install - Installs Flatpak applications and adds remotes
  • brew bundle dump - Exports installed Flatpak applications and remotes to Brewfile
  • brew bundle check - Verifies Flatpak applications are installed
  • brew bundle cleanup - Removes Flatpak applications and remotes not in Brewfile

Implementation Details

  • macOS handling: Flatpak entries are automatically skipped on macOS with appropriate warnings
  • Bundle modules: Adds installer, dumper, and checker modules for both Flatpak applications and remotes
  • Remote support: Flatpak applications can specify which remote to install from (defaults to "flathub")

Closes #21029

@gromgit
Copy link
Contributor

gromgit commented Nov 18, 2025

flatpak_remote "flathub", "https://flathub.org/repo/flathub.flatpakrepo"

Is this the default Flatpak repo? If so, I think it should not have to be specified, especially since most of your flatpak examples have no explicit remote refs.

@ahmedadan
Copy link
Contributor Author

flatpak_remote "flathub", "https://flathub.org/repo/flathub.flatpakrepo"

Is this the default Flatpak repo? If so, I think it should not have to be specified, especially since most of your flatpak examples have no explicit remote refs.

Good call, that is the default. I'll remove it from the example.

Copy link
Member

@MikeMcQuaid MikeMcQuaid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR!

Some more questions:

  • do you have example Brewfiles for this?
  • can you describe why you're building this? Is it just for your personal use, your company's use, your distro's use, etc.? Just trying to get an understanding of how many people are wanting to use this and why. Hopefully you appreciate that adding ~1300 lines of code if it's mainly for your personal usage isn't going to work for us.

I do wonder if there's room for brew bundle to have its own extension system so it's easier/possible to maintain things like this in a Homebrew tap instead of in Homebrew/brew. Thoughts?

@botantony
Copy link
Member

Does it really need flatpak_remote? I think having flatpak <package>, remote: where remote is a URL should be enough

@ahmedadan
Copy link
Contributor Author

I do wonder if there's room for brew bundle to have its own extension system so it's easier/possible to maintain things like this in a Homebrew tap instead of in Homebrew/brew. Thoughts?

I'd have to refer to your expertise here, I can see the value of an abstraction like this especially for smaller or more niche tools, I think with a system like Flatpaks and their universality on Linux distributions I think it's at the scale where this could be warranted.

If your hesitation is with maintaining this moving forward I'd definitely volunteer to do so if that would be any help. This also enables a level of curation for our family of distributions that would be invaluable.

@MikeMcQuaid
Copy link
Member

Does it really need flatpak_remote? I think having flatpak <package>, remote: where remote is a URL should be enough

Yeh, I agree here. I think it makes sense for taps because they are Homebrew primitives and some people would/do use them in Brewfiles without a formula or cask. What would you think about just specifying the format like suggested by @botantony?

If your hesitation is with maintaining this moving forward I'd definitely volunteer to do so if that would be any help. This also enables a level of curation for our family of distributions that would be invaluable.

Ok, good to know, I will CC you on relevant issues/PRs ❤️

@ahmedadan
Copy link
Contributor Author

Does it really need flatpak_remote? I think having flatpak <package>, remote: where remote is a URL should be enough

Yeh, I agree here. I think it makes sense for taps because they are Homebrew primitives and some people would/do use them in Brewfiles without a formula or cask. What would you think about just specifying the format like suggested by @botantony?

If your hesitation is with maintaining this moving forward I'd definitely volunteer to do so if that would be any help. This also enables a level of curation for our family of distributions that would be invaluable.

Ok, good to know, I will CC you on relevant issues/PRs ❤️

Does it really need flatpak_remote? I think having flatpak <package>, remote: where remote is a URL should be enough

That can definitely be done. What I was trying to avoid was the example below, which I find difficult to parse if each and every line needs to mention the remote by URL.

brew "git"
brew "neovim"

# Install Flatpak applications
flatpak "org.gnome.Calculator", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "org.mozilla.firefox", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "com.spotify.Client", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "org.godotengine.Godot", remote: "https://flathub.org/beta-repo/flathub-beta.flatpakrepo"
flatpak "io.github.dvlv.boxbuddyrs", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "io.github.flattool.Ignition", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "io.github.flattool.Warehouse", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "io.github.gaheldev.Millisecond", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "io.github.getnf.embellish", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "io.github.kolunmi.Bazaar", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "io.gitlab.adhami3310.Impression", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "io.missioncenter.MissionCenter", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "io.podman_desktop.PodmanDesktop", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "me.iepure.devtoolbox", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "org.gnome.Calculator", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "org.gnome.Calendar", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "org.gnome.Characters", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "org.gnome.Connections", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "org.gnome.Contacts", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "org.gnome.DejaDup", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "org.gnome.FileRoller", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "org.gnome.Firmware", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "org.gnome.Logs", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "org.gnome.Loupe", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "org.gnome.Maps", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "org.gnome.NautilusPreviewer", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "org.gnome.Papers", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "org.gnome.SimpleScan", remote: "https://flathub.org/repo/flathub.flatpakrepo"
flatpak "org.gnome.TextEditor", remote: "https://flathub.org/repo/flathub.flatpakrepo"

Would either of you be open to FlatHub remaining the default and then only custom remotes using remote:?

We then could have something like:

flatpak "org.gnome.Calculator"
flatpak "org.mozilla.firefox"
flatpak "com.spotify.Client"
flatpak "org.godotengine.Godot", remote: "https://flathub.org/beta-repo/flathub-beta.flatpakrepo"
flatpak "io.github.dvlv.boxbuddyrs"
flatpak "io.github.flattool.Ignition"
flatpak "io.github.flattool.Warehouse"
flatpak "io.github.gaheldev.Millisecond"
flatpak "io.github.getnf.embellish"
flatpak "io.github.kolunmi.Bazaar"
flatpak "io.gitlab.adhami3310.Impression"
flatpak "io.missioncenter.MissionCenter"
flatpak "io.podman_desktop.PodmanDesktop"
flatpak "me.iepure.devtoolbox"
flatpak "org.gnome.Calculator"
flatpak "org.gnome.Calendar"
flatpak "org.gnome.Characters"
flatpak "org.gnome.Connections"
flatpak "org.gnome.Contacts"
flatpak "org.gnome.DejaDup"
flatpak "org.gnome.FileRoller"
flatpak "org.gnome.Firmware"
flatpak "org.gnome.Logs"
flatpak "org.gnome.Loupe"
flatpak "org.gnome.Maps"
flatpak "org.gnome.NautilusPreviewer"
flatpak "org.gnome.Papers"
flatpak "org.gnome.SimpleScan"
flatpak "org.gnome.TextEditor"

Thoughts? @MikeMcQuaid @botantony

@MikeMcQuaid
Copy link
Member

Would either of you be open to FlatHub remaining the default and then only custom remotes using remote:?

Yeh, this seems good/appropriate for now 👍🏻

@ahmedadan ahmedadan force-pushed the feat/add-flatpak-to-brewfile branch 2 times, most recently from ef17a37 to be20d8e Compare November 20, 2025 03:48
Copy link
Member

@MikeMcQuaid MikeMcQuaid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Almost there.

@ahmedadan ahmedadan force-pushed the feat/add-flatpak-to-brewfile branch from be20d8e to 02412e8 Compare November 21, 2025 16:52
@ramcq
Copy link

ramcq commented Nov 22, 2025

Hey folks, Flatpak / Flathub person here - this is super exciting to see, and a very cool addition to brew! If you can excuse the driveby, I did have a couple of pieces of feedback. Of course, your project your choice, feel free to take or leave. 🙇

  1. It's really non-idiomatic to refer to remotes by URL in Flatpak land. You use a URL typically once to add a remote - think git - and then Flatpak has to pull and cache a bunch of metadata, verify GPG keyring, etc - and then you use your local name for it after that. If you don't want a separate verb to add a remote, could you perhaps consider a way to use a named remote with a fallback URL, and then use it after that? This would echo the semantic of flatpak remote-add --if-not-exists, e.g.
# defines the flathub-beta remote if it's not defined
flatpak "org.godotengine.Godot", remote: flathub-beta, repo: "https://flathub.org/beta-repo/flathub-beta.flatpakrepo"
# then use it for these ones
flatpak "io.github.dvlv.boxbuddyrs", remote: flathub-beta
flatpak "io.github.flattool.Ignition", remote: flathub-beta

There's one counter-example: if you use a .flatpakref file it basically encodes a remote + app tuple; in this case if you don't have that remote already, Flatpak adds the remote as app.name-origin which has a semantic of filtering the remote, and only using it for that app ID only. This would be maybe a less surprising way to support the "add just this one app from this URL" semantic, without the side-effect of installing or redefining a remote that's used for other apps.

# add this repo as a remote named org.nottrustworthy.CrazyApp-origin, which won't be used for other apps
flatpak "org.nottrustworthy.CrazyApp", repo: "https://repo.nottrustworthy.org/repo"
  1. If it's possible I'd also recommend trying to bunch up the installs from the same remote and issue them as one flatpak install invocation; each flatpak install transaction contains a number of one-time housekeeping & metadata update operations, which are very IO intensive. Issuing all of the flatpak installs in one process will speed things up by avoiding repeating these housekeeping tasks dozens of times.

Thanks for reading! Hopefully you find this helpful. -Rob

@MikeMcQuaid
Copy link
Member

Thanks for the input Rob!

  1. It's really non-idiomatic to refer to remotes by URL in Flatpak land. You use a URL typically once to add a remote - think git - and then Flatpak has to pull and cache a bunch of metadata, verify GPG keyring, etc - and then you use your local name for it after that.

In the case of brew bundle, though, a remote is not useful by itself. git is a good example; for 99% of use no-one ever has to care about non-origin remotes and the more this is forced into user's experience the more confused they are (citation: I authored a published Git book, I have taught 10+ in-person workshops).

We don't want something added here that will make the Brewfile hard to e.g. remove one line. As a result, using the same URL and deduping internally makes more sense to me here.

2. If it's possible I'd also recommend trying to bunch up the installs from the same remote and issue them as one flatpak install invocation

This doesn't really work for us as 1) it will not be possible to identify easily which invocation failed without output parsing and 2) this is different to how all other brew bundle tool invocations are.

The common theme in the above: it's less important to map to how Flatpak does things as how brew bundle does things.

@ramcq
Copy link

ramcq commented Nov 24, 2025

In the case of brew bundle, though, a remote is not useful by itself. git is a good example; for 99% of use no-one ever has to care about non-origin remotes and the more this is forced into user's experience the more confused they are (citation: I authored a published Git book, I have taught 10+ in-person workshops).

No objections here! 😆 My team ends up teaching Git to highschoolers, and when there is more than one repo, things go south very quickly.

We don't want something added here that will make the Brewfile hard to e.g. remove one line. As a result, using the same URL and deduping internally makes more sense to me here.

This makes sense. With that as the criteria, and expecting that 99.999% of installs will just want the apps off Flathub, maybe the least worst semantic is:

  • no URL ⇒ use Flathub
  • URL ⇒ define it as a single-app remote (safest)
  • URL + a name ⇒ define it as a named remote if this URL isn't already available (unambiguous)
  1. If it's possible I'd also recommend trying to bunch up the installs from the same remote and issue them as one flatpak install invocation

This doesn't really work for us as 1) it will not be possible to identify easily which invocation failed without output parsing and 2) this is different to how all other brew bundle tool invocations are.

Fair enough! Just an optimization in any case. At the API level, you definitely can do discrete install operations without the hooks/pruning, but I'm not immediately seeing that on the CLI. And I entirely appreciate that accessing the Flatpak API is not a practical approach here!

The common theme in the above: it's less important to map to how Flatpak does things as how brew bundle does things.

👌

@MikeMcQuaid
Copy link
Member

My team ends up teaching Git to highschoolers, and when there is more than one repo, things go south very quickly.

Ooof, good job, rather you than me!

  • no URL ⇒ use Flathub
  • URL ⇒ define it as a single-app remote (safest)
  • URL + a name ⇒ define it as a named remote if this URL isn't already available (unambiguous)

This makes sense to me. @ahmedadan thoughts?

@ahmedadan
Copy link
Contributor Author

Thanks for the thoughtful discussion @ramcq @MikeMcQuaid! I really like where this landed. The 3-tier approach makes a lot of sense, just to make sure I understand we're looking at the following:

# Tier 1: Flathub (default)
flatpak "org.gnome.Calculator"

# Tier 2: Single-app remote - creates "org.godotengine.Godot-origin"
flatpak "org.godotengine.Godot", remote: "https://dl.flathub.org/beta-repo/"

# Tier 3: Named shared remote - creates "flathub-beta" if not exists
flatpak "org.godotengine.Godot", remote: "flathub-beta", url: "https://dl.flathub.org/beta-repo/"
flatpak "io.github.dvlv.boxbuddyrs", remote: "flathub-beta"  # reuses existing remote

The dumper will detect the remote type and output the appropriate format:

  • Flathub packages → flatpak "app" (clean, no remote needed)
  • Single-app remotes (*-origin) → flatpak "app", remote: "https://..."
  • Named remotes → flatpak "app", remote: "name", url: "https://..." (first occurrence) then flatpak "app", remote: "name" (subsequent)

One question: for Tier 3, should we validate that the url: matches if the named remote already exists?

Options:

  1. Warn only - "Remote 'flathub-beta' exists with different URL, using existing"
  2. Error - "Remote 'flathub-beta' exists with different URL, please resolve"
  3. Silent - Trust the user, use whatever's there

I'm leaning toward (1) for safety with flexibility. Thoughts?

@MikeMcQuaid
Copy link
Member

@ahmedadan All sounds good to me!

@ahmedadan ahmedadan force-pushed the feat/add-flatpak-to-brewfile branch from 02412e8 to 8f037d0 Compare November 26, 2025 00:58
Copy link
Member

@MikeMcQuaid MikeMcQuaid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost there, a little more cleanup needed!

Copy link
Member

@MikeMcQuaid MikeMcQuaid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks so much for your contribution! Without people like you submitting PRs we couldn't run this project. You rock, @ahmedadan!

@MikeMcQuaid MikeMcQuaid added this pull request to the merge queue Nov 27, 2025
Merged via the queue into Homebrew:main with commit 5d630cc Nov 27, 2025
72 of 75 checks passed
@ahmedadan
Copy link
Contributor Author

Thanks for the guidance and patience @MikeMcQuaid I know I learned a lot and will hopefully have the opportunity to contribute again in the future!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

brew bundle: Add support for Flatpak packages and remotes

6 participants