Dependeasy - Reaktor build control plane

Start with Reaktor Build Tools for the combined Dependeasy + Reaktor CLI map. This page focuses on Dependeasy itself.

Dependeasy should become Reaktor's build control plane.

That does not mean replacing Gradle, Xcode, CMake, Vite, Wrangler, Fastlane, Maestro, Dagger, or Kotlin's own plugins. It means Dependeasy should turn Reaktor's Kotlin build intent into typed facts that those tools, Reaktor CLI, reaktorDesktop, reaktor-mcp, and CI can all consume.

The current plugin is already more than a dependency helper. It centralizes Kotlin/Android/native versions, applies KMP conventions, wires common Android/iOS/JS/JVM source-set shapes, builds Android and iOS CMake sidecars, extracts Android Prefab libraries, generates Kotlin/Native cinterop .def files, emits Kotlin/JS packages, and records release binary sizes. But the next step is the important one: Dependeasy must become the producer of the build graph that Reaktor CLI operates.

Today the CLI discovers a project from package.json, npm scripts, workspaces, settings.gradle.kts, targets/, and target-local package files. That is a good bootstrap, but it is still inference. Dependeasy can give the CLI authoritative build truth: targets, source sets, artifacts, toolchains, generated outputs, native libraries, budgets, tests, deploy descriptors, and host requirements.

1. Product Thesis

Dependeasy's job is to make a Kotlin module describe what it is once, then derive everything needed to build, test, package, publish, deploy, inspect, and operate it.

The target experience should feel closer to cargo, flutter, or next than to a collection of Gradle snippets:

reaktor graph
reaktor doctor appDarwin
reaktor app build iosSimulatorArm64
reaktor app perf jsWeb
reaktor reaktorWeb bundle
reaktor deploy socialServer
reaktor explain reaktor-ffi

Those commands should not scrape shell scripts or guess from directory names when better facts exist. The source of truth should be:

  1. Dependeasy configures the Gradle/KMP build.
  2. Dependeasy emits build facts.
  3. Reaktor CLI reads those facts and renders commands, diagnostics, graphs, budgets, and safe operations.
  4. reaktorDesktop and reaktor-mcp read the same facts.
  5. CI/Dagger/Fastlane/Wrangler consume generated descriptors rather than hand-maintained parallel metadata.

The rule is simple: Dependeasy produces build truth; the CLI operates that truth.

2. What Dependeasy Does Today

Dependeasy lives in reaktor/dependeasy and currently ships three Gradle plugins:

Plugin IDScopeCurrent role
dev.shibasis.dependeasy.settingssettings.gradle.ktsRuns NativeBootstrap, which bootstraps native dependencies such as FlatBuffers and Hermes under .github_modules.
dev.shibasis.dependeasy.libraryKMP library modulesApplies Kotlin Multiplatform, Android library, serialization, KSP, shared opt-ins, buildReleaseBinaries, and generateDocumentation.
dev.shibasis.dependeasy.applicationAndroid app targetsApplies Android application, Kotlin Android, serialization, Crashlytics, and Java desugaring.

The dependeasy {} DSL currently exposes native configuration:

DSL blockCurrent role
androidNative { prefab(...) }Declares Android Prefab dependencies extracted from AARs and passed to CMake.
androidNative { fbjni(); hermes("...") }Convenience declarations for FBJNI and Hermes.
darwinNative { packageName; includeDirs(...); headers(...); compilerOptions(...) }Configures Kotlin/Native cinterop for iOS static libraries.

The KMP helper shape is compact:

kotlin {
    common { }
    droid { }
    darwin { }
    web { }
    server { }
}

The important implementation facts are:

AreaWhat exists
Version policyVersion.kt centralizes Kotlin, AGP, Java, Android SDK/NDK/CMake, Ktor, Spring, Koin, KSP, serialization, coroutines, Firebase, SQLDelight, Exposed, Kotlin JS wrappers, Android ABIs, and native packaging policies.
Common source setsCommon opt-ins, expect/actual support, JS suspend export flags, Kotlin test, coroutines test, Turbine, serialization, networking, logging, Arrow, and Koin helpers.
AndroidandroidTarget, debug/release publication, Java/Android target policy, instrumented tests, generated JNI libs, FBJNI, app/library defaults, desugaring, and native packaging.
Darwin/iOSKotlin CocoaPods, iosSimulatorArm64, iosArm64, static frameworks, pod dependencies, CMake task dependencies, generated cinterop .def files, headers, and static library paths.
JSKotlin/JS IR, ES modules, browser/node library binaries, TypeScript declarations, ts/export, ts/import, generated webpack/Terser config, and stable class/function names.
JVM/serverJVM target, Java 25 policy, -Xjvm-default=all, WebFlux/Ktor/coroutines helpers.
Native/C++cpp/CMakeLists.txt discovery, native library-name detection, Android ABI CMake tasks, iOS device/simulator CMake tasks, Prefab extraction, native dependency scanning across Gradle project dependencies.
Size/docsbuildReleaseBinaries appends AAR/XCFramework size data; generateDocumentation copies Dokka output.

That is a strong base. The missing layer is a stable build model above these conventions.

3. Reaktor CLI Integration Contract

The CLI is where Dependeasy's next value becomes visible.

Current reaktor-cli behavior is already pointed in the right direction:

  • ReaktorProject discovers a project from an existing package.json with a reaktor key.
  • It reuses scripts, workspaces, settings.gradle.kts, concrete targets/ folders, target-local package.json files, and Gradle modules.
  • Bare reaktor renders targets, libraries, toolchains, and global operations.
  • reaktor <target> renders a target dashboard.
  • reaktor explain <name> explains targets, Gradle modules, scripts, and script families.
  • reaktor graph renders the discovered project model.
  • reaktor deploy resolves declared targets, workspace names, deploy<Name> scripts, and targets/<name>/deploy.sh.

That works, but it is a C1 discovery model. Dependeasy should upgrade it into a C2/C3 build-graph model.

Build Manifest

Each Dependeasy-enabled module should emit a versioned manifest:

{
  "schema": "dev.shibasis.dependeasy.manifest.v1",
  "module": "reaktor-ffi",
  "gradlePath": ":reaktor-ffi",
  "sourceSets": ["commonMain", "androidMain", "iosArm64Main", "iosSimulatorArm64Main", "jsMain", "jvmMain"],
  "targets": [
    {
      "id": "android",
      "family": "android",
      "kind": "library",
      "host": "any",
      "toolchains": ["java:21", "agp", "android-sdk", "ndk", "cmake"],
      "artifacts": ["aar", "jniLibs:arm64-v8a", "jniLibs:x86_64"],
      "tasks": {
        "build": ":reaktor-ffi:assembleRelease",
        "test": ":reaktor-ffi:testDebugUnitTest",
        "native": ":reaktor-ffi:buildAndroidArm64V8aCMake"
      },
      "budgets": {
        "aarKb": 1024,
        "jniKb": 2048
      }
    },
    {
      "id": "iosSimulatorArm64",
      "family": "apple",
      "kind": "framework",
      "host": "macos",
      "toolchains": ["xcode", "cocoapods", "cmake"],
      "artifacts": ["framework", "staticLib", "cinterop"],
      "tasks": {
        "build": ":reaktor-ffi:linkReleaseFrameworkIosSimulatorArm64",
        "native": ":reaktor-ffi:buildIosSimulatorArm64CMake"
      }
    },
    {
      "id": "jsWeb",
      "family": "js",
      "kind": "package",
      "host": "any",
      "artifacts": ["esm", "typescriptDeclarations"],
      "tasks": {
        "build": ":reaktor-ffi:jsBrowserProductionLibraryDistribution"
      }
    }
  ],
  "nativeLibraries": [
    {
      "name": "reaktorffi",
      "buildSystem": "cmake",
      "headers": ["cpp/include/reaktor_ffi.h"],
      "dependsOn": [":reaktor-flexbuffer"]
    }
  ],
  "generatedOutputs": [
    { "kind": "typescript", "path": "build/compileSync/js/main/productionLibrary/kotlin" },
    { "kind": "cinteropDef", "path": "build/dependeasy/def/reaktor.def" }
  ]
}

A root aggregation task should then merge module manifests into a project-level file, for example .reaktor/build-graph.json.

CLI Consumers

CLI surfaceWhat Dependeasy should feed it
reaktor graphModules, source sets, targets, artifacts, generated outputs, native libraries, dependencies, and publication nodes.
`reaktor explain <moduletarget>`
reaktor doctorRequired JDK, Android SDK, NDK, CMake, Ninja, Xcode, CocoaPods, SwiftPM, Node, npm, Wrangler, Fastlane, and host-target compatibility.
reaktor <target> dashboardsBuild/test/perf/deploy commands derived from facts, not guessed from scripts.
reaktor build/test/perfTarget-aware execution with the right Gradle task, npm script, native task, or external harness.
reaktor deployGenerated deploy descriptors that point to Wrangler, Fastlane, k3s, Dagger, desktop packaging, or publication tasks.
reaktor addModule and target scaffolding from Dependeasy target templates.
reaktorDesktop / MCPThe same graph as clickable nodes and agent-readable operations.

Integration Rules

  1. Dependeasy emits facts; the CLI does not reverse-engineer them when facts exist.
  2. Every fact has provenance: Gradle plugin, package file, CMake file, generated task, or external descriptor.
  3. Every command has a backing task: Gradle path, npm script, shell script, Dagger function, Wrangler command, Fastlane lane, or generated operation.
  4. Every mutating operation has a safety class: build, test, local run, deploy, migrate, publish, sign, rotate, delete.
  5. The manifest schema is versioned and test-covered: old CLI versions fail clearly, not silently.
  6. Generated descriptors are inspectable: no hidden side effects; users can see what Dependeasy generated and why.

This is the deepest improvement area: without it, Dependeasy remains useful build glue. With it, Dependeasy becomes the build fact layer underneath Reaktor's CLI, workbench, agents, and CI.

4. Ecosystem Scan

The local Reaktor and BestBuds workspaces explain why Dependeasy needs to own more than KMP source sets.

EcosystemLocal evidenceDependeasy responsibilityCLI unlock
Composite Gradlebestbuds/settings.gradle.kts includes ../reaktor/dependeasy and ../reaktor; Reaktor modules are dependency-substituted into BestBuds.Source-build vs published-build policy, included-build metadata, module graph, version alignment.reaktor graph, reaktor explain :module, safer source/published switching.
Multi-module KMPReaktor modules repeatedly use common/droid/darwin/web/server; BestBuds app and engine consume many Reaktor modules.Declarative target matrix, source-set hierarchy, dependency rules, per-module target manifests.reaktor <module> build <target>, target dashboards.
Androidtargets/appAndroid, Android KMP modules, SDK/NDK/CMake defaults, Firebase, signing and Fastlane scripts.App/library conventions, SDK/NDK/CMake, ABI policy, JNI packaging, signing inputs, instrumentation and bundle budgets.reaktor appAndroid doctor/build/test/perf/release.
Apple / CocoaPodsGenerated podspecs; targets/appDarwin/Podfile; Firebase pod workarounds in module build files.CocoaPods config, pod dependency normalization, Xcode diagnostics, framework/XCFramework output, deployment-target policy.reaktor appDarwin doctor/build/test/release.
SwiftPMExternal dependencies such as FlatBuffers and Hermes have Package.swift; Kotlin supports SwiftPM import/export flows.Swift package import/export, Package.resolved, generated Package.swift, checksums, XCFramework zip publication.reaktor appDarwin swiftpm doctor/export/publish.
CMake / C++root.cmake, module cpp/ folders, Hermes/FlatBuffers bootstrapping, FBJNI/Hermes/OpenSSL Prefab extraction.Variant-aware native graph, CMake cache keys, compile commands, symbols, headers, native artifact publication.reaktor native graph/build/clean/symbols.
Kotlin/JSModules emit ts/export; BestBuds generates bestbuds-kt and engine-kt; Dependeasy controls webpack/Terser details.npm package metadata, export maps, declarations, source maps, minification policy, JS test hooks.reaktor appWeb package, reaktor explain bestbuds-kt.
Vite / Reacttargets/appWeb, targets/reaktorWeb, targets/companyOS use manual aliases for generated Kotlin JS packages.Generated alias maps and consumer metadata from KMP outputs.reaktor appWeb doctor catches stale aliases and missing generated packages.
Cloudflare WorkersMany target workspaces use package.json, wrangler.json, D1/R2/Hyperdrive bindings, and deploy scripts.Worker descriptors, binding facts, route metadata, bundle budgets, deploy/test hooks.reaktor <worker> deploy/logs/bindings/doctor.
JVM servertargets/reaktorServer is Spring Boot on Java 25.JVM toolchain, server build/test/deploy descriptors, container/image facts, health checks.reaktor reaktorServer build/deploy/logs/health.
Desktop JVMtargets/reaktorDesktop packages Compose Desktop and local MCP HTTP behavior.Desktop packaging, runtime image metadata, launcher ports, local health checks.reaktor reaktorDesktop build/run/package.
Tests and perfKotlin test, JMH, Playwright, Maestro, Karate, k6, Lighthouse, bundle budgets, performance collectors.Unified harness descriptors, budgets, reports, and regression gates keyed by module/target.reaktor test, reaktor perf, budget dashboards.
Release/deploynpm scripts, Fastlane, Wrangler, k3s scripts, Dagger direction, deployReaktor.Deployable target descriptors, artifact provenance, environment mapping, operation safety classes.reaktor deploy, reaktor release, desktop Deploy pane.

5. Current KMP Target Coverage

Kotlin Multiplatform covers Android, JVM, JavaScript, Kotlin/Wasm (wasmJs and wasmWasi), and Kotlin/Native targets across Apple, Linux, Windows/MinGW, and Android NDK families. Kotlin/Native target support is tiered. Current official docs list macosArm64, iosSimulatorArm64, and iosArm64 as Tier 1; linuxX64, linuxArm64, watchOS, and tvOS targets as Tier 2; and Android Native, mingwX64, iosX64, and other lower-guarantee targets as Tier 3. The docs also call out host limits: final Apple binaries require macOS, and Apple targets with cinterop or CocoaPods have extra host constraints.

Dependeasy's current coverage is narrower:

Target familyCurrent supportGap
Android app/libraryStrong for JVM-bytecode Android, Android library/app defaults, NDK CMake, JNI packaging.ABI splits, Android Native KMP targets, signing/secrets facts, artifact budgets per ABI.
JVMGood Java 25 server target conventions; desktop/server targets exist in BestBuds.Dedicated server/desktop manifests, containers, health checks, Compose Desktop packaging facts.
Kotlin/JSGood ES module output, browser/node library binaries, TypeScript definitions, stable names.Vite/Wrangler/npm workspace contracts, package export maps, Worker bundle budgets.
iOSGood iosArm64 and iosSimulatorArm64, CocoaPods, static framework, CMake, cinterop.iosX64, explicit XCFramework policy, SwiftPM import/export, Xcode diagnostics.
macOSNot first-class despite macosArm64 being Tier 1.macOS target block, binaries, CMake flags, tests, packaging/export.
LinuxNot first-class despite linuxX64/linuxArm64 being Tier 2.Native executable/static/shared library support, CI host policy.
Windows/MinGWNot first-class.mingwX64, host constraints, executable packaging, CMake generator selection.
tvOS/watchOSNot first-class.Apple target declarations, simulator/device test policy, CocoaPods/SwiftPM constraints.
Wasm JS/WASINot supported yet.wasmJs, wasmWasi, browser/WASI packaging, Compose/Wasm hooks, Wasm budgets.
Android Native KMPNot modeled as native KMP targets; native is currently Android library + NDK CMake sidecars.Decide where androidNativeArm32/Arm64/X86/X64 are first-class versus sidecar outputs.

References: Kotlin/Native supported targets, Kotlin/Wasm, KMP Gradle DSL, native binaries, CocoaPods integration, SwiftPM import, and SwiftPM export.

6. How This Helps Complex KMM Builds

Complex KMM builds fail because every platform asks a different question:

  • Android asks for AGP, SDK/NDK/CMake, ABI packaging, manifests, desugaring, signing, Google services, instrumentation, APK/AAB/AAR output.
  • iOS asks for CocoaPods or SwiftPM, Xcode settings, frameworks/XCFrameworks, cinterop, deployment targets, signing, simulator/device splits, and macOS-only build paths.
  • JS asks for ESM, package metadata, TypeScript declarations, bundler aliases, minification, source maps, browser/Node/Worker distinctions.
  • JVM/server asks for toolchains, server dependencies, containers, health checks, service config, deploy metadata.
  • Native asks for CMake, headers, static/shared libraries, linker flags, generated .def files, symbols, sanitizers, and architecture-specific outputs.
  • Reaktor adds graph stability: generated JS/native artifacts need to be discoverable by the CLI, desktop, MCP, CI, and agents.

Dependeasy helps when it turns those platform-specific questions into one typed declaration:

dependeasy {
    module("reaktor-ffi") {
        targets {
            androidLibrary {
                nativeLibrary("reaktorffi")
                prefab("fbjni")
                prefab("hermes")
            }
            apple {
                ios()
                cinterop("reaktor")
                integration = cocoaPodsAndSwiftPM()
            }
            jsWeb {
                packageName = "reaktor-ffi"
                typescript = true
            }
            jvm()
        }
        budgets {
            artifact("aar", maxKb = 1024)
            artifact("xcframework", maxKb = 2048)
            artifact("npmPackage", maxKb = 512)
        }
    }
}

The module author should not have to remember every task name and output path. Dependeasy should derive them, publish them as facts, and let the CLI render the workflow:

reaktor explain reaktor-ffi
reaktor reaktor-ffi doctor
reaktor reaktor-ffi build android
reaktor reaktor-ffi build iosSimulatorArm64
reaktor reaktor-ffi native symbols android
reaktor reaktor-ffi perf

For reaktor-ffi, this matters because the module spans common Kotlin, Android bytecode, Kotlin/JS, JVM, iOS framework code, Hermes/JSI C++, FBJNI, Android Prefab, and Kotlin/Native cinterop. Without Dependeasy, each surface is hand-wired. With the control-plane version of Dependeasy, each surface is a target node with tasks, artifacts, dependencies, budgets, and diagnostics.

For BestBuds, this matters because modules/app and modules/engine compile shared product/runtime code to Android, iOS, JVM, and generated JS packages. Then targets/appAndroid, targets/appDarwin, targets/appWeb, Workers, desktop packages, and Spring Boot servers wrap those outputs. The current workflow spans Gradle, npm, Vite, Wrangler, Fastlane, Xcode, shell scripts, Playwright, Maestro, Karate, k6, and Dagger. Dependeasy should not erase those tools. It should make their relationships visible and executable.

7. Improvement Programs

These are not generic "areas." They are product programs. Each should produce code, manifests, fixtures, CLI behavior, and docs.

P0. Build Manifest and Graph API

Build: per-module build/dependeasy/manifest.json, root .reaktor/build-graph.json, Gradle tasks to validate/aggregate them, and a small Kotlin data model shared with Reaktor CLI.

CLI unlock: reaktor graph, reaktor explain, target dashboards, and desktop/MCP stop guessing when manifest facts exist.

Done when: a module like reaktor-ffi can show Android/iOS/JS/JVM/native artifacts, CMake outputs, cinterop files, and budget tasks from manifest data alone.

P1. Target Matrix DSL

Build: a real target DSL that covers Android app/library, JVM server, desktop JVM, JS web, JS worker, Wasm JS, Wasm WASI, iOS, macOS, tvOS, watchOS, Linux, MinGW, and Android Native.

CLI unlock: reaktor <module> build <target> becomes deterministic, and unsupported host/target combinations fail before a build starts.

Done when: the current common/droid/darwin/web/server helpers are expressible as a compatibility layer over the matrix.

P2. Source-Set and Dependency Governance

Build: source-set hierarchy facts, target-specific dependency rules, generated/validated Gradle version catalogs, npm constraints, CocoaPods/SwiftPM locks, Maven publication coordinates, SBOM/license/vulnerability reports.

CLI unlock: reaktor doctor dependencies, reaktor explain dependency <name>, and graph-visible dependency drift.

Done when: a version bump can be checked across Gradle, npm, CocoaPods, SwiftPM, Android Prefab, and CMake source dependencies without manual search.

P3. Native/C++ Build Engine

Build: variant-aware CMake model with build type, architecture, output kind, dependency kind, headers, compile commands, symbols, sanitizer mode, and cache keys.

CLI unlock: reaktor native graph, reaktor native build <module> <target>, reaktor native symbols, reaktor native clean, and native diagnostics inside reaktor doctor.

Done when: Android ABI outputs and iOS simulator/device outputs are represented by the same model, and macOS/Linux/MinGW can be added without duplicating the task architecture.

P4. Apple Packaging: CocoaPods and SwiftPM

Build: CocoaPods and SwiftPM as peer integration modes; Package.resolved and .swiftpm-locks; generated Package.swift; XCFramework zip/checksum publication; Xcode diagnostic checks; deployment-target policy.

CLI unlock: reaktor appDarwin doctor, reaktor appDarwin pods, reaktor appDarwin swiftpm export, and reaktor appDarwin release.

Done when: a Reaktor KMP module can be consumed through either CocoaPods or SwiftPM with the same cinterop package names and framework identity.

P5. JS, Vite, Wasm, and Worker Pipeline

Build: npm package descriptors, export maps, TypeScript declaration facts, Vite alias maps, Worker descriptors, Wrangler binding facts, JS/Wasm bundle budgets, wasmJs and wasmWasi conventions.

CLI unlock: reaktor appWeb doctor, reaktor appWeb bundle, reaktor <worker> bindings, reaktor <worker> deploy, and Wasm target builds.

Done when: Vite aliases and Worker package inputs are generated from KMP outputs instead of being hand-maintained.

P6. Toolchain Doctor and Bootstrap

Build: actionable checks for Java 25/21, Android SDK, NDK, CMake, Ninja, Xcode, iOS SDKs, CocoaPods, Ruby path, SwiftPM, Node/npm, Vite, Wrangler, Fastlane, Dagger, host support, signing inputs, and secret references.

CLI unlock: reaktor doctor, reaktor doctor <target>, and preflight gates before build/deploy/release.

Done when: a missing NDK, stale CocoaPods install, unsupported Apple build host, missing Wrangler binding, or wrong Java toolchain is reported with the value found, the value expected, and the exact next fix.

P7. Performance and Build-Size Harness

Build: one budget model for AAR, APK/AAB, XCFramework, static/shared native libs, npm packages, JS chunks, Wasm files, Worker bundles, JVM jars, desktop packages, containers, JMH, Native benchmarks, JS benchmarks, Lighthouse, Playwright, Maestro, Karate, k6, Gradle task timing, CMake timing, and cache hit rates.

CLI unlock: reaktor perf, reaktor budget, reaktor <target> perf, and CI trend reports.

Done when: buildReleaseBinaries is replaced by structured reports and thresholds that cover every artifact family Reaktor ships.

P8. Publication, Release, and Provenance

Build: artifact identity and provenance for Maven, npm, CocoaPods, SwiftPM, Android APK/AAB/AAR, Apple archives/XCFrameworks, desktop installers, Worker bundles, JVM jars, container images, native libraries, signatures, checksums, SBOMs, and release channels.

CLI unlock: reaktor release, reaktor publish, reaktor artifact explain <id>, and graph-backed rollback planning.

Done when: Reaktor can answer: what artifact came from this revision, what inputs shaped it, what tests/budgets gated it, and where it was published?

P9. CLI-Driven Scaffolding and Migration

Build: target templates and migration recipes that reaktor add can invoke: add JS target, add Worker target, add C++ sidecar, add SwiftPM export, add Wasm target, add perf budget, add deploy descriptor.

CLI unlock: reaktor add target wasmJs, reaktor add native-library, reaktor add swiftpm-export, reaktor add worker.

Done when: adding a target creates Gradle config, generated descriptors, tests, budgets, and docs entries in one operation.

P10. Plugin Fixtures and Conformance Lab

Build: Gradle TestKit fixtures for pure common/JVM, Android app, Android library, common+Android+iOS+JS, native module, native dependency chain, CocoaPods, SwiftPM, JS/Vite consumer, Wasm, build-size/perf budgets, and failure cases.

CLI unlock: regression confidence before CLI starts depending on manifest details.

Done when: every manifest schema field has at least one fixture proving how it is produced and consumed.

P11. Reproducibility, Caches, and Remote Execution

Build: toolchain fingerprints, Gradle cache policy, Kotlin/Native cache policy, npm lock policy, CMake/Ninja cache keys, Xcode derived-data rules, CocoaPods cache policy, Dagger/CI task definitions, and remote-runner environment reports.

CLI unlock: reaktor doctor cache, reaktor build --remote, reaktor explain environment, and reproducible CI failures.

Done when: a build can be compared across laptop, CI, and Reaktor-managed runner with clear toolchain diffs.

P12. Desktop and MCP Operations

Build: operation descriptors for desktop panes and MCP tools: build, test, perf, deploy, publish, logs, open artifact, open report, inspect dependency, inspect binding, explain failure.

CLI unlock: CLI, desktop, and agent surfaces share one operation catalog instead of three hand-maintained adapters.

Done when: a build target shown in reaktorDesktop is backed by the same Dependeasy manifest and command definition that reaktor explain prints.

8. First Slice

The first implementation slice should be narrow and real:

  1. Add manifest data classes in Dependeasy and emit build/dependeasy/manifest.json for one library module.
  2. Include current common/droid/darwin/web/server targets, Gradle task names, JS output paths, Android AAR path, iOS framework path, native CMake tasks, cinterop .def path, and size task outputs.
  3. Add a root aggregation task that writes .reaktor/build-graph.json.
  4. Teach Reaktor CLI to read the manifest if present and show it in reaktor explain <module>.
  5. Add reaktor doctor <module> checks for Java, Android SDK/NDK/CMake, Xcode/CocoaPods, and Node/npm based on the manifest.
  6. Replace buildSize.csv with a structured JSON report while still writing the CSV for compatibility.
  7. Add TestKit fixtures for one no-native module and one native module with a native dependency.

That slice makes the direction concrete without trying to solve every target at once.

9. Non-Goals

Dependeasy should not become a custom build system. Gradle remains the Kotlin build system. CMake remains the native build system where native code needs it. Xcode, CocoaPods, SwiftPM, Vite, Wrangler, Fastlane, Maestro, Karate, k6, Dagger, and Pulumi remain proven executors.

Dependeasy's job is to standardize the contract between those tools, generate the repetitive glue, emit authoritative facts, and let Reaktor CLI/desktop/MCP operate those facts safely.

The long-term target is straightforward: a Reaktor project should be able to use Kotlin anywhere Kotlin can reasonably run, and Dependeasy should make that environment understandable, repeatable, measurable, and operable.