feat(mods): add native modification manager - #230
Open
flathead wants to merge 18 commits into
Open
Conversation
Add declarative mod packages that can be installed from local directories, archives, or Git repositories. Enabled packages are composed onto a clean shell source tree and activated through immutable generations, with compatibility checks, conflict detection, rollback, and startup recovery. Expose the same operations through the ambxst mods CLI and a lazy-loaded Settings panel. The manager performs no polling or background update checks; repository access and generation builds happen only after explicit user actions.
Several focused mods need to register against the same Ambxst integration files. Rejecting shared filenames prevented otherwise independent patches from being enabled together. Apply operations in load order and let the existing patch preflight reject overlapping hunks. Failed composition still leaves the active generation unchanged.
Expose an exact-position move operation and add a native drag handle when the list is sorted by load order. Reordering enabled packages rebuilds the immutable generation in the chosen order. Disabled-only moves update state without rebuilding, and failed composition leaves the active generation untouched.
This was referenced Aug 31, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I noticed a lot of useful improvements, including a few of mine (hehe), sitting in the review queue. To take some pressure off the maintainer, I built a native mod manager for Ambxst.
The manager gives community work a practical route to users while it is under review. People can install, configure, update, reorder, disable, and remove mods from Settings instead of maintaining a separate fork. That should make it easier for contributors to test focused changes and share them with other Ambxst users.
If a mod belongs in the main project, it remains ordinary Ambxst source code. Its patch or overlay can be reviewed and merged as a normal feature. The package format records compatibility, tested base revisions, affected files, dependencies, and conflicts, so packages do not create a parallel architecture.
What this PR adds:
ambxst modsCLIThe manager has no polling loop, repository watcher, or background update worker. Network access and generation builds happen only after an explicit action. A newly built generation gets an eight-second startup check; if Quickshell exits during that window, Ambxst restores the last known-good generation.
Installed QML runs with the user's permissions. The UI states this clearly, and packages never run installer scripts.
Trying this branch
This PR changes both QML and the Go backend. The
modsservice lives in the binary, andinstall.shdownloads a prebuilt one, so testing the branch needs a local build:That step exists only while the manager is a pull request. After a release carries it,
ambxst updatebrings the binary, and installing, updating, or reordering a mod never compiles Ambxst.Installing community mods
The first converted packages are in flathead/ambxst-mods. Paste a package-directory link directly into Package source:
The manager recognizes GitHub
/tree/<branch>/<path>links and uses a shallow sparse checkout. A local clone and the CLI work too:git clone https://github.com/flathead/ambxst-mods.git ambxst mods install ./ambxst-mods/packages/volume-scroll ambxst mods enable community.volume-scroll ambxst reloadPackages install disabled, leaving time to review the manifest and patch. Updates, removal, rollback, and the same install flow are available from Settings.
Required mods and i18n
A manifest lists required IDs in
dependenciesand may publish their package URLs independencySources. The details pane marks each requirement as missing, disabled, or ready. Install required mods validates exact IDs, installs missing packages, enables the dependency chain in topological order, and rebuilds once. A failed download, validation, or composition leaves the previous state and active generation intact. The selected package stays disabled until the user enables it.This supports shared packages such as
community.i18n, which lives in its own repository at flathead/ambxst-mod-i18n and is pulled in by the packages that declare it. The Mods panel uses that translator only while the i18n mod is active and keeps complete English fallbacks, so Settings still opens when i18n is absent, disabled, or broken.Load order and runtime cost
Switch the list to Sort: Load order to drag packages into an exact position. Dependencies still load before dependents.
Composition does not depend on exact patch context. A patch is tried verbatim first, then merged three-way against the pre-image blob recorded in its diff, so an earlier mod or an Ambxst update can move the lines it was written against. The merge runs in a temporary Git repository that borrows the base object store and is deleted before activation, so a generation stays plain source. When two mods only insert new lines at the same anchor — two bar widgets registering next to each other — both blocks are kept and load order decides which comes first. Two mods rewriting the same existing lines still stop the build and leave the active generation untouched.
compatibility.ambxstis enforced.compatibility.testedBaseCommitsis advisory: the base moves with every Ambxst update, so an unlisted revision only marks the package as untested in Settings.The manager is not a runtime plugin host. It composes ordinary Ambxst source into an immutable generation, then Quickshell loads that tree normally. Moving disabled packages only updates state and does not rebuild. Ongoing resource use comes from the enabled feature itself, as it would after merging the same code into core.
After an Ambxst update
A generation records the base version and revision it was built from. On launch, Ambxst compares them with the current base and skips a stale generation, starting the clean base instead. Settings then shows
Rebuild requiredwith the reason and a Rebuild button. Rebuilding re-composes the same packages onto the new base; a patch that can no longer be merged stops the build and leaves the running shell alone. An update therefore costs the mods until a rebuild, never a broken desktop.Writing a package or moving it into core
A package needs an
ambxst.mod.jsonplus patch or overlay files.docs/mods/README.mddocuments the format, dependency sources, GitHub directory installs, settings, and the QML settings API.A package patch is generated against a tree that already carries this manager, since that is the only tree a mod can be installed on. To promote a mod into Ambxst, review the feature's own branch as normal project code, or reproduce the packaged source and diff it against
dev:git switch -c mods/example feature/mod-manager git apply --3way /path/to/feature.patch go test ./... go vet ./...There is no second implementation to port: the generated tree and the upstream change use the same QML, JavaScript, Go, and configuration files.
Checks
go test ./...go vet ./...Screenshots