SkillAgentSearch skills...

Kayan

Kotlin Multiplatform Gradle plugin for generating typed BuildConfig-style objects from layered JSON configs.

Install / Use

/learn @MohamadJaara/Kayan
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<p align="center"> <img src="site/public/kayan-icon.png" alt="Kayan icon" width="144"> </p> <h1 align="center">Kayan</h1> <p align="center">Typed layered JSON and YAML config for Kotlin Multiplatform, JVM, and Android.</p> <p align="center"> <a href="https://github.com/MohamadJaara/Kayan/actions/workflows/gradle.yml"><img src="https://github.com/MohamadJaara/Kayan/actions/workflows/gradle.yml/badge.svg" alt="CI"></a> <a href="https://codecov.io/github/MohamadJaara/Kayan"><img src="https://codecov.io/github/MohamadJaara/Kayan/graph/badge.svg?branch=main" alt="Codecov coverage"></a> <a href="https://central.sonatype.com/artifact/io.github.mohamadjaara/kayan-gradle-plugin"><img src="https://img.shields.io/maven-central/v/io.github.mohamadjaara/kayan-gradle-plugin" alt="Maven Central"></a> <a href="https://github.com/MohamadJaara/Kayan/releases"><img src="https://img.shields.io/github/v/release/MohamadJaara/Kayan" alt="Release"></a> <a href="https://github.com/MohamadJaara/Kayan/blob/main/LICENSE"><img src="https://img.shields.io/github/license/MohamadJaara/Kayan" alt="License"></a> <a href="https://mohamadjaara.github.io/Kayan/"><img src="https://img.shields.io/badge/docs-GitHub%20Pages-blue" alt="Docs"></a> </p>

Kayan is a Kotlin Gradle plugin that generates a typed Kotlin object from layered JSON and YAML config files. It works with Kotlin Multiplatform, Kotlin/JVM, and Kotlin Android projects, so shared code can read config directly without platform-specific BuildConfig wiring.

The name comes from the Arabic word كيان (Kayan), which means "entity", "structure", or "being". JSON is valid YAML, but Kayan still makes the format choice explicit so your builds do not develop a split personality.

Why Kayan

  • Keep config in JSON or YAML while exposing a typed Kotlin API.
  • Let the consuming app own the schema and generated property names.
  • Resolve layered defaults and overrides deterministically at build time.
  • Work in shared Kotlin across KMP, JVM, and Android modules.
  • Reuse resolved values inside Gradle itself with buildValue("key").

Quick start

Add Maven Central to Gradle plugin resolution when consuming the published plugin:

pluginManagement {
    repositories {
        gradlePluginPortal()
        mavenCentral()
    }
}

Add a config file:

{
  "flavors": {
    "prod": {
      "api_base_url": "https://api.example.com",
      "feature_search_enabled": false
    },
    "dev": {
      "api_base_url": "https://dev.example.com",
      "feature_search_enabled": true
    }
  },
  "brand_name": "Example App"
}

YAML works too:

flavors:
  prod:
    api_base_url: https://api.example.com
    feature_search_enabled: false
  dev:
    api_base_url: https://dev.example.com
    feature_search_enabled: true
brand_name: Example App

Apply the plugin and declare your schema:

plugins {
    kotlin("multiplatform") version "<kotlin-version>"
    id("io.github.mohamadjaara.kayan") version "<kayan-version>"
}

kayan {
    packageName.set("sample.generated")
    flavor.set("prod")

    schema {
        string("api_base_url", "API_BASE_URL", required = true)
        boolean("feature_search_enabled", "FEATURE_SEARCH_ENABLED")
        string("brand_name", "BRAND_NAME")
    }
}

Generate the config source:

./gradlew generateKayanConfig

Use the generated object from shared code:

import sample.generated.SampleConfig

val baseUrl = SampleConfig.API_BASE_URL
val searchEnabled = SampleConfig.FEATURE_SEARCH_ENABLED
val brandName = SampleConfig.BRAND_NAME

Generated source lands in build/generated/kayan/kotlin and is wired into the appropriate source set automatically.

Target-specific overrides

For Kotlin Multiplatform projects that need one config API in shared code but different values per target, add targets in the config file and configure Kayan targets:

brand_name: Example App

flavors:
  prod:
    targets:
      android:
        bundle_id: com.example.android
      ios:
        bundle_id: com.example.ios
kayan {
    packageName.set("sample.generated")
    flavor.set("prod")

    targets("android", "ios")
}

Kayan generates an expect object into commonMain and matching actual object declarations into the configured target source sets.

For non-standard source set names or custom target labels, use the DSL form:

kayan {
    targets {
        ios()
        jvm("desktop")
        sourceSet("appleMain", "ios-shared")
    }
}

By design, Kayan is a fit for non-sensitive build and app configuration. Values declared in the schema can be generated into source or consumed by Gradle during the build, so secrets such as API keys, passwords, and tokens should stay in dedicated secret-management or environment-specific secure storage.

buildValue() is experimental. Opt in with @file:OptIn(io.kayan.gradle.ExperimentalKayanGradleApi::class) when using the Gradle build-time API from build.gradle.kts.

Build-time config access

When Gradle logic needs the same resolved config, use buildValue() directly in build.gradle.kts:

@file:OptIn(io.kayan.gradle.ExperimentalKayanGradleApi::class)

val isSearchEnabled =
    kayan.buildValue("feature_search_enabled")
        .asBoolean()

dependencies {
    if (isSearchEnabled) {
        implementation("com.example:search-sdk:1.0.0")
    }
}

This is useful for conditional dependencies, task inputs, and other configuration-time decisions. Provider variants such as asStringProvider() are also available for lazy task wiring.

Learn more

Development

Build everything:

./gradlew build

Run plugin tests:

./gradlew :gradle-plugin:test

Install the local git hooks:

pre-commit install --install-hooks

Sample app

The sample app in sample/ demonstrates local plugin consumption, generated config usage, and Compose Multiplatform targets for desktop, web, and Apple platforms.

Run the desktop sample:

./gradlew -p sample run

Run the web sample:

./gradlew -p sample wasmJsBrowserDevelopmentRun

More sample details are in sample/README.md.

View on GitHub
GitHub Stars9
CategoryDevelopment
Updated11h ago
Forks0

Languages

Kotlin

Security Score

90/100

Audited on Mar 31, 2026

No findings