
SDK for apps with a prebuilt shell UI (nav, tabs, status, settings), document persistence, accessibility drivers, conformance testing and a Gradle plugin for packaging and test tiers.
An SDK for building Compose Multiplatform desktop applications: a framework, a Gradle plugin, a conformance kit, and a reference app.
Hiro is the frame an application is built inside, so that the application writes its own subject matter and nothing else. It supplies the nav bar, tab strip, status bar, settings screens, brands, navigation and toasts, along with the document, persistence and platform machinery underneath them.
| module | what it is |
|---|---|
hiro-framework |
the shell itself — documents, settings, persistence, platform seams, and the Compose UI those drive |
hiro-accessibility |
macOS accessibility driver and portable acceptance scenarios for driving a packaged application |
hiro-conformance |
a TestKit an application runs against its own objects to prove it wired the shell up correctly |
hiro-gradle-plugin |
build logic every Hiro application would otherwise hand-copy: the four test tiers, single-source version generation, and the whole macOS packaging concern |
hiro-gradle-plugin is a separate Gradle build, not a module. It has to be: Hiro's own build
applies plugins this build produces, and a plugin must be on the settings classpath before any
project is configured. The root settings.gradle.kts pulls it in with
pluginManagement { includeBuild("hiro-gradle-plugin") }.
Published on Maven Central under com.strangeparticle. The current release is 0.4.0.
dependencies {
implementation("com.strangeparticle:hiro-framework:0.4.0")
testImplementation("com.strangeparticle:hiro-conformance:0.4.0")
}plugins {
id("com.strangeparticle.hiro.test-tiers") version "0.4.0" // root project
id("com.strangeparticle.hiro.version") version "0.4.0" apply false // the module that wants a version object
id("com.strangeparticle.hiro.desktop-packaging") version "0.4.0" apply false // a :desktopApp module
}Declare all three plugin ids once, in the root build, and request them without a version in the modules that apply them — repeating it there fails with "the plugin is already on the classpath with an unknown version", because the root's request already put the implementation there.
hiro-accessibility arrives transitively with hiro-framework; you only name it directly from an
acceptance-test module that drives a packaged application.
Acorn is a complete application built on Hiro, in its own repository. It consumes this one exactly the way any other application does — by coordinate, substituted from source during development — so it demonstrates the real integration path rather than a privileged in-tree shortcut. Every part of the documentation points at it.
docs/VERSIONING.md — how a project declares its version, what the two
build identifiers answer, and what a consuming application has to wire up.docs/TESTING.md — the four-tier test model Hiro owns and every consumer
inherits, and why the acceptance tier cannot run in CI.docs/MINIFICATION.md — why release minification defaults to off, what
the keep rules cover, and what leaving it off costs.Three behaviours a consuming application inherits, none of them accidental, all worth knowing.
Two dependencies arrive from beta releases. navigation-compose and
lifecycle-viewmodel-compose are pinned to the beta Compose Multiplatform set this project builds
against, and they reach your build transitively. That is deliberate — the stable line lags the
Compose version Hiro targets — but it is worth knowing before you pin a production release on it.
A packaged application honours HIRO_ACCEPTANCE_HOME_DIRECTORY. Desktop persistence reads that
environment variable on every launch, not only under test, and when it is set the whole config
directory moves there. That is what lets an acceptance run drive a real .app without touching a
developer's own ~/.yourapp — see docs/TESTING.md. It is read in release
builds too, and there is no way to opt out today, so anything that can set an environment variable
on your process can choose where it reads and writes its settings.
Toasts broadcast through a process-wide singleton. ToastBroadcaster is a Kotlin object with
one shared flow, and toast ids come from an unsynchronised counter. That is fine for one shell in
one process, which is every application built on Hiro today. Two shells in one process, or
broadcasts from several threads, are outside what it is built for.
The save API's suspend markers do not track the work. HiroDocumentHost.saveTab is suspend
and saveActiveTabAs is not, but both reach the same non-suspending write, which does blocking file
I/O on whatever thread calls it. Treat every save as blocking and launch it accordingly.
Hiro's own source is BSD 3-Clause -- see LICENSE.
The built artifacts also carry the Inter typeface, which the built-in Strange Particle brands use
for every Material 3 type role. Inter is licensed separately under the SIL Open Font License 1.1;
its terms ship beside the font itself, in
hiro-framework/src/commonMain/composeResources/files/Inter-OFL.txt,
so every copy of the font carries its licence as the OFL requires. NOTICE is the
third-party inventory.
An application redistributing Hiro inherits that obligation: if you show licences to your users, Inter belongs in that list.
An SDK for building Compose Multiplatform desktop applications: a framework, a Gradle plugin, a conformance kit, and a reference app.
Hiro is the frame an application is built inside, so that the application writes its own subject matter and nothing else. It supplies the nav bar, tab strip, status bar, settings screens, brands, navigation and toasts, along with the document, persistence and platform machinery underneath them.
| module | what it is |
|---|---|
hiro-framework |
the shell itself — documents, settings, persistence, platform seams, and the Compose UI those drive |
hiro-accessibility |
macOS accessibility driver and portable acceptance scenarios for driving a packaged application |
hiro-conformance |
a TestKit an application runs against its own objects to prove it wired the shell up correctly |
hiro-gradle-plugin |
build logic every Hiro application would otherwise hand-copy: the four test tiers, single-source version generation, and the whole macOS packaging concern |
hiro-gradle-plugin is a separate Gradle build, not a module. It has to be: Hiro's own build
applies plugins this build produces, and a plugin must be on the settings classpath before any
project is configured. The root settings.gradle.kts pulls it in with
pluginManagement { includeBuild("hiro-gradle-plugin") }.
Published on Maven Central under com.strangeparticle. The current release is 0.4.0.
dependencies {
implementation("com.strangeparticle:hiro-framework:0.4.0")
testImplementation("com.strangeparticle:hiro-conformance:0.4.0")
}plugins {
id("com.strangeparticle.hiro.test-tiers") version "0.4.0" // root project
id("com.strangeparticle.hiro.version") version "0.4.0" apply false // the module that wants a version object
id("com.strangeparticle.hiro.desktop-packaging") version "0.4.0" apply false // a :desktopApp module
}Declare all three plugin ids once, in the root build, and request them without a version in the modules that apply them — repeating it there fails with "the plugin is already on the classpath with an unknown version", because the root's request already put the implementation there.
hiro-accessibility arrives transitively with hiro-framework; you only name it directly from an
acceptance-test module that drives a packaged application.
Acorn is a complete application built on Hiro, in its own repository. It consumes this one exactly the way any other application does — by coordinate, substituted from source during development — so it demonstrates the real integration path rather than a privileged in-tree shortcut. Every part of the documentation points at it.
docs/VERSIONING.md — how a project declares its version, what the two
build identifiers answer, and what a consuming application has to wire up.docs/TESTING.md — the four-tier test model Hiro owns and every consumer
inherits, and why the acceptance tier cannot run in CI.docs/MINIFICATION.md — why release minification defaults to off, what
the keep rules cover, and what leaving it off costs.Three behaviours a consuming application inherits, none of them accidental, all worth knowing.
Two dependencies arrive from beta releases. navigation-compose and
lifecycle-viewmodel-compose are pinned to the beta Compose Multiplatform set this project builds
against, and they reach your build transitively. That is deliberate — the stable line lags the
Compose version Hiro targets — but it is worth knowing before you pin a production release on it.
A packaged application honours HIRO_ACCEPTANCE_HOME_DIRECTORY. Desktop persistence reads that
environment variable on every launch, not only under test, and when it is set the whole config
directory moves there. That is what lets an acceptance run drive a real .app without touching a
developer's own ~/.yourapp — see docs/TESTING.md. It is read in release
builds too, and there is no way to opt out today, so anything that can set an environment variable
on your process can choose where it reads and writes its settings.
Toasts broadcast through a process-wide singleton. ToastBroadcaster is a Kotlin object with
one shared flow, and toast ids come from an unsynchronised counter. That is fine for one shell in
one process, which is every application built on Hiro today. Two shells in one process, or
broadcasts from several threads, are outside what it is built for.
The save API's suspend markers do not track the work. HiroDocumentHost.saveTab is suspend
and saveActiveTabAs is not, but both reach the same non-suspending write, which does blocking file
I/O on whatever thread calls it. Treat every save as blocking and launch it accordingly.
Hiro's own source is BSD 3-Clause -- see LICENSE.
The built artifacts also carry the Inter typeface, which the built-in Strange Particle brands use
for every Material 3 type role. Inter is licensed separately under the SIL Open Font License 1.1;
its terms ship beside the font itself, in
hiro-framework/src/commonMain/composeResources/files/Inter-OFL.txt,
so every copy of the font carries its licence as the OFL requires. NOTICE is the
third-party inventory.
An application redistributing Hiro inherits that obligation: if you show licences to your users, Inter belongs in that list.