Thank you for your interest in contributing to kore. This document describes how to set up your development environment, the coding standards we follow, and the process for submitting changes.
Prerequisites:
- JDK 21 (LTS)
- Gradle 9.x is included via the Gradle wrapper — no separate installation needed
Clone and build:
git clone https://github.com/UnityInFlow/kore-runtime.git
cd kore-runtime
./gradlew buildRun tests:
./gradlew testRun a specific module's tests:
./gradlew :kore-core:test
./gradlew :kore-llm:test
./gradlew :kore-mcp:test
./gradlew :kore-test:testAll Kotlin code is formatted with ktlint via the kotlinter-gradle plugin.
Check for violations (runs in CI):
./gradlew lintKotlinAuto-fix formatting violations:
./gradlew formatKotlinRun formatKotlin before committing. CI runs lintKotlin — a formatting violation will fail the build.
These rules apply to all contributions. They are enforced in code review.
valeverywhere —varis not permitted. Refactor to avoid mutation.- No
!!(non-null assertion) without a comment explaining why it is safe. - No
Thread.sleep()or raw threads — use coroutines (delay(),withContext(),async { }). - Sealed classes for domain modelling (results, errors, states) — not exceptions for expected failures.
- Coroutines for all async work — the agent loop is coroutine-based throughout.
- Immutable data classes for value objects.
- KDoc on all
publicandinternalAPIs. - No secrets in source code — all credentials via environment variables.
- Port interfaces in
kore-coremust have zero external dependencies (the module carries onlykotlinx-coroutines-core).
- New features and bug fixes must include tests.
- Tests use JUnit 5 as the runner and Kotest assertions (
shouldBe,shouldBeInstanceOf, etc.). - Coroutine tests use
runTestfromkotlinx-coroutines-test. - No network calls in unit tests — use
MockLLMBackendfromkore-test. - Coverage target: >80% on core logic (
kore-coreandkore-mcp).
| Type | Pattern | Example |
|---|---|---|
| Feature | feat/short-description |
feat/skills-yaml-loader |
| Bug fix | fix/short-description |
fix/budget-exceeded-not-returned |
| Documentation | docs/short-description |
docs/mcp-client-guide |
| Chore / tooling | chore/short-description |
chore/upgrade-coroutines |
Branch from main. Keep branches focused — one feature or fix per PR.
Follow conventional commits:
feat: add S003 no-secrets rule
fix: budget exceeded returns wrong token count
test: add edge cases for empty tool call arguments
docs: update README with fallback chain example
chore: upgrade kotlinx-coroutines to 1.10.2
refactor: extract retry logic into RetryPolicy
- Use present tense ("add" not "added")
- Keep the subject line under 72 characters
- Mention the module in the body if the change is module-specific
Before opening a PR, confirm:
-
./gradlew testpasses — all tests green -
./gradlew lintKotlinpasses — no formatting violations - New public APIs have KDoc comments
- No secrets, API keys, or tokens in any committed file
- No new
vardeclarations - No new
!!assertions without explanatory comments
PR description should include:
- What changed and why
- Which modules are affected
- Any decisions made that are not obvious from the code
Open a GitHub issue with:
- A minimal reproducible example (a failing test is ideal)
- Expected vs actual behavior
- Kotlin version, JVM version, and kore version
By contributing to kore, you agree that your contributions will be licensed under the MIT License.