This directory contains the Fedora/Linux-first Avalonia shell for CKAN.
The installed desktop command is ckan-linux. The package launcher lives at
usr/bin/ckan-linux and execs the self-contained Avalonia binary at
usr/lib/ckan-linux/CKAN-LinuxGUI.
The app binary starts in LinuxGUI/Program.cs, which initializes LinuxGUI
logging and starts Avalonia with the classic desktop lifetime. App.axaml.cs
then registers the app services and opens Shell/MainWindow.axaml.
When this repository's Debian package installs /usr/bin/ckan-linux, the
/usr/bin/ckan wrapper uses it as the replacement UI for graphical no-argument
launches. Command line arguments still run through the existing Mono ckan.exe
path, and no-display launches continue to use ckan consoleui.
The Linux GUI app keeps startup files at the LinuxGUI/ root and groups the
desktop surface by role:
Shell/containsMainWindow, its view model partials, and startup shell state.Windows/contains secondary dialogs and utility windows.Models/contains Linux GUI view-model support items used by bindings.Services/contains Linux GUI service adapters and controller glue.
The app starts on the mod browser for the current instance. When no saved
browser filter is active, the default mod list is Installed, so cleanup and
updates are the first view instead of the full catalog. If no installed mods are
detected, the browser falls back to All. Installed startup snapshots are
sorted by mod name from A-Z before the full catalog data is available.
If no active instance is selected, or if the saved/default instance cannot be activated, LinuxGUI opens the pre-browser instance selection surface. That screen uses the same installed app code as normal launches; the dev launcher only makes it easier to hit because it uses isolated dev configuration.
Refreshing the catalog temporarily replaces the browser rows with the matching
skeleton table until the reload finishes. During that work the header action
changes from Reload to Reloading.... On cold start, catalog loading uses
Loading... instead so the first load does not read like a user-triggered
reload.
Actions are queued before they are applied. Use the Preview surface to inspect
what CKAN Linux is about to do:
- direct installs, updates, removals, and downloads
- required dependency installs, which CKAN resolves automatically
- removable auto-installed dependencies that are no longer needed
- conflicts or provider choices that need user input
- optional recommendations, suggestions, and supported integration mods
Optional recommendations, suggestions, and supported mods are informational.
Use the View button on each optional section to open Browse filtered to those
mods, queue any extras you want, then use the Close button in the notice above
the mod list to return to Preview. The Apply Changes button does not require
reviewing optional extras first.
Required virtual dependencies are different. If several mods provide the same required dependency, apply opens a provider-choice dialog. The dialog is capped to a scrollable list and shows the provider identifier, display name, and any available CKAN hints such as version, cache state, download count, and summary so large provider sets do not take over the screen.
The Mods menu includes maintenance actions for large cleanup passes:
Clean up missing installed modsimmediately removes stale CKAN registry entries for CKAN-managed mods whose registered files were manually deleted, prunes stale autodetected DLL records, then reloads the browser.Queue remove all installed modsreplaces the current apply queue with removals for CKAN-managed installed mods.
Removal previews also include auto-removable dependencies where the registry can prove they are no longer required by anything that will remain installed.
Mods > Installation History opens as a non-modal utility window. Keep it open
while browsing the mod list to cross-reference saved snapshots against current
mods without repeatedly closing and reopening the history window.
Build and publish the self-contained desktop shell:
./build.sh LinuxGUI --configuration=ReleaseOutput:
_build/publish/CKAN-LinuxGUI/linux-x64/
Assemble an install-shaped Linux desktop layout with launcher, desktop entry, icons, and documentation:
./build.sh LinuxGUIPackage --configuration=ReleaseOutput:
_build/package/ckan-linux/linux-x64/
The staged layout includes:
usr/bin/ckan-linuxusr/lib/ckan-linux/usr/share/applications/ckan-linux.desktopusr/share/icons/hicolor/*/apps/ckan-linux.pngusr/share/doc/ckan-linux/README.md
Install the Linux GUI into a local prefix so it can be launched as
~/.local/bin/ckan-linux without typing the staged package path:
./scripts/install-linuxgui.sh
~/.local/bin/ckan-linuxBy default this installs under ~/.local, keeping it separate from the upstream
ckan command. If ~/.local/bin is already on your PATH, you can launch it
as ckan-linux. Use --prefix /usr/local to install somewhere else.
Launch the Linux shell with an isolated XDG home so it does not share config, cache, or app-data state with your normal CKAN setup:
./scripts/run-linuxgui-dev.shIf the checked-in LinuxGUI, App, Core, or PluginCompat sources are newer
than the local framework-dependent dev build, the launcher automatically refreshes
_build/out/CKAN-LinuxGUI/Debug/bin/net8.0/ before starting the app. Override
that with CKAN_LINUX_DEV_BUILD_CONFIGURATION=Release if you intentionally want
the dev launcher to track the Release output path.
By default this uses:
~/.ckan-linux-dev/data~/.ckan-linux-dev/config~/.ckan-linux-dev/cache~/.ckan-linux-dev/run
You can override the base directory with:
CKAN_LINUX_DEV_HOME=/path/to/dev-home ./scripts/run-linuxgui-dev.shThe mod browser can optionally use a Rust-generated catalog sidecar for faster catalog/search. Normal LinuxGUI builds and installs do not require Rust, the Rust repository, or a sidecar index; if no valid index is configured, the browser uses CKAN's normal registry/repository cache.
The LinuxGUI sidecar reader is included in this repository. The external
generator source is published at
appaKappaK/ckan-meta-rs.
Sidecar rows include browse-list metadata such as title, summary,
relationships, compatibility, release date, and download count. CKAN's registry
remains authoritative for details, installs, updates, and dependency
resolution.
To use the sidecar, generate the file with ckan-meta-rs and point the GUI at
it:
CKAN_CATALOG_INDEX_PATH=/path/to/catalog-index-latest.json ./scripts/run-linuxgui-dev.shIn dev runs, scripts/run-linuxgui-dev.sh also checks the normal host app-data
location, ${XDG_DATA_HOME:-$HOME/.local/share}/CKAN/catalog-index-latest.json,
and links it into the isolated dev data home when no explicit
CKAN_CATALOG_INDEX_PATH is set.
For repeated local use outside the dev launcher, either keep using
CKAN_CATALOG_INDEX_PATH or symlink the generated file into app data:
mkdir -p ~/.local/share/CKAN
ln -s /path/to/ckan-meta-rs/data/catalog-index-latest.json \
~/.local/share/CKAN/catalog-index-latest.jsonIf the sidecar is missing, invalid, or not configured, the browser uses the normal CKAN metadata loader.
Catalog load timings are written to the dev session/debug logs. Look for these prefixes when comparing normal mode to sidecar mode:
Mod catalog service listMod catalog index direct buildMod catalog registry buildLinuxGUI catalog loadLinuxGUI catalog filter
The browser diagnostics text also includes whether the last load used the Rust catalog-index sidecar or the CKAN registry fallback.
For repeatable local measurements, run:
./scripts/benchmark-linuxgui-catalog.sh --iterations 3On 2026-05-13 against the KSP-Steam instance, 98 installed mods, and the
cached CKAN repository data in ~/.local/share/CKAN/repos, the benchmark
reported:
| Path | Items | First run | Best run | Average |
|---|---|---|---|---|
| Installed snapshot | 98 | 26 ms | 2 ms | 10 ms |
| CKAN registry cache | 3,505 | 6,345 ms | 2,886 ms | 4,057 ms |
| Rust sidecar index | 3,495 | 3,000 ms | 2,956 ms | 2,971 ms |
These numbers are local cache timings, not network update timings. The script does not update repositories and uses read-only registry access so it can be run while comparing catalog load paths.
Skip the automatic rebuild check if you deliberately want to launch the current artifacts as-is:
CKAN_LINUX_DEV_SKIP_BUILD=1 ./scripts/run-linuxgui-dev.shRun deterministic visual tests:
./build.sh LinuxGUIVisualTestsOutput:
_build/visual-tests/actual/
The Linux shell keeps its own UI settings separate from the legacy GUI. By default it writes:
- settings:
~/.local/share/CKAN/linuxgui.settings.json - shared CKAN data:
~/.local/share/CKAN/
The Linux shell initializes logging from log4net.linuxgui.xml. When you use
./scripts/run-linuxgui-dev.sh, the launcher now writes a comprehensive dev
session log and installs a debug-level log4net config in the isolated run/
directory.
The main dev log files are:
- session log:
~/.ckan-linux-dev/run/ckan-linux-session.log - per-run session log:
~/.ckan-linux-dev/run/ckan-linux-session-YYYYMMDD-HHMMSS.log - debug app log:
~/.ckan-linux-dev/run/ckan-linux-debug.log
The session log captures launcher decisions, selected binary, XDG paths, and
all stdout/stderr from the app process. The debug app log captures log4net
output at DEBUG level.
By default, run-linuxgui-dev.sh now keeps the app's stdout/stderr out of the
terminal and writes it only to the session log. If you want the old mirrored
behavior for a debugging session, launch with:
CKAN_LINUX_DEV_STREAM_STDIO=1 ./scripts/run-linuxgui-dev.sh