Building and testing
Runesmith is one solution, Runesmith.slnx, with the projects in src/, the build tools in tools/, the template in templates/,
the test projects in tests/ and the benchmarks in benchmarks/. The official plugins live in their own repositories in the
RunesmithHub organization. This page covers the tools you need and the commands CI runs, so a change
that passes here passes there.
Tools
- The .NET 10 SDK.
global.jsonpins the feature band and rolls forward to newer ones. - Node.js 22, only for the documentation site in
website/.
On NixOS
Avalonia and SkiaSharp load the system's font and X11 libraries by name when the app starts. NixOS keeps those out of the default library
path, so running the app fails with Unable to load shared library 'libSkiaSharp' and libfontconfig.so.1: cannot open shared object file. The repository's flake.nix has a development shell with the .NET SDK, Node.js, xvfb-run and those libraries on
LD_LIBRARY_PATH:
nix develop
dotnet run --project src/Runesmith.App
An IDE has to start in that environment too, or the app it runs fails the same way:
- Start it from the shell, such as
nix develop -c <ide> Runesmith.slnx. - Or use direnv:
.envrcloads the shell when you enter the folder (direnv allowonce), and an IDE plugin for direnv passes it on to the IDE.
HammerUI
Runesmith's user interface comes from HammerUI. The projects that use it set UsesHammerUI, and Directory.Build.targets decides where it
comes from:
| When | HammerUI comes from |
|---|---|
A HammerUI checkout next to the Runesmith checkout, at ../HammerUI | That checkout, as a project reference, so both can change together. |
| There is none | The HammerUI package from the Runesmith Hub feed, https://nuget.runesmith.dev/index.json, with no sign-in. |
For the checkout, clone both repositories into the same folder:
git clone https://github.com/RunesmithHub/HammerUI.git
git clone https://github.com/RunesmithHub/Runesmith.git
nuget.config maps HammerUI and RunesmithHub.* to the hub feed only. The hub library, RunesmithHub.Protocol, works the same way, from
a checkout of RunesmithHub/hub at ../hub.
Build
dotnet build Runesmith.slnx -warnaserror
The build has no warnings, and CI treats any warning as an error. Analyzers run at the latest-recommended level, and BannedSymbols.txt
rejects calls that are easy to get wrong; each entry says why and what to use instead.
Building src/Runesmith.App also brings in the bundled plugins; see Bundled plugins.
Bundled plugins
Runesmith ships the official Git and GitHub plugins as published on the plugin hub; the other official plugins, such as C# and Java, are
installed from the hub by the users who want them. bundled-plugins.json at the repository root pins each shipped plugin by id, version
and the SHA-256 of its package:
{
"index": "https://runesmithhub.github.io/registry/",
"plugins": [
{ "id": "runesmith.git", "version": "0.1.0", "sha256": "aa827f72..." }
]
}
After src/Runesmith.App builds, tools/Runesmith.BundledPlugins runs. It updates its copy of the hub's signed index, starting from the
root in src/Runesmith.App/Hub/root.json, and checks that each pinned version is published, not blocked or frozen, and published with the
pinned SHA-256. It downloads each package, checks its length and hash, and unpacks it into plugins/<id> next to the executable, in the
same layout as a plugin the hub installs. Publishing copies the same folders.
The index and the packages are kept under src/Runesmith.App/obj/bundled-plugins, packages by their hash, so later builds work without a
network connection. Without a connection and without that cache, Debug builds warn and leave the plugins out; Release builds and
publishing fail. The tool never uses a package the signed index does not pin.
To update a bundled plugin, set its version and sha256 to those of a published version in the hub's index. The build checks both
and fails when they do not match.
Work on an official plugin
Each official plugin has its own repository, such as RunesmithHub/plugin-csharp, built against the SDK and language packages from the hub feed. To run your changes in Runesmith, build the plugin and install it as a local plugin from the plugin's repository:
dotnet build src/Runesmith.CSharp -t:InstallPlugin
InstallPlugin writes the plugin into the user's plugins folder, under RUNESMITH_HOME when it is set. Bundled plugins live next to the
executable and updates from the hub in hub/plugins in Runesmith's data folder, so the local copy sits beside them and never changes
their files (see Where plugins live). A local copy of a plugin that comes with Runesmith or from the hub
does not load until you allow it; until then the plugin manager marks it Not loaded and says why. To run the local copy:
- Turn on Local copies replace plugins in Settings, under Plugins, or add
"plugins.allowLocalOverrides": trueto your ownsettings.json. A folder's.runesmith/settings.jsoncannot turn it on. - Restart Runesmith. The local copy runs in place of the bundled or hub copy, whatever its version.
- Sign in again where the plugin asks. The local copy has its own secrets and storage, so it never sees the bundled copy's sign-ins or files, and they stay as they were.
While a local copy runs, Runesmith shows a notice at each start, and the plugin manager's Installed tab marks it Replaces the installed plugin. Remove the local copy, or turn the setting off, to go back to the bundled or hub copy, which stayed as it was.
Test
dotnet test --solution Runesmith.slnx -- --ignore-exit-code 8
Tests run on Microsoft.Testing.Platform with xUnit v3, as global.json sets. A test project that has
no tests yet ends with exit code 8, which --ignore-exit-code 8 accepts.
Benchmarks
benchmarks/Runesmith.Benchmarks is a BenchmarkDotNet project, with benchmarks such as completion ranking and the C# analyzer's answer
times. Run it in Release:
dotnet run --project benchmarks/Runesmith.Benchmarks --configuration Release
benchmarks/Runesmith.TypingBenchmark types into the running editor and measures how fast it responds; see
Language services.
Formatting
dotnet format whitespace Runesmith.slnx
dotnet format style Runesmith.slnx
The Checks workflow runs both with --verify-no-changes on every pull request.
The documentation site
The site is a Docusaurus project in website/:
cd website
npm ci
npm start
npm run build checks the prose against website/STYLE.md first, then fails on broken links and anchors. npm run typecheck checks the
site's TypeScript. The site's README.md has the details.