Welcome. This guide covers environment setup, running the tests, and submitting a
change. See AGENTS.md for the architecture and design invariants.
This project follows the Meshtastic Code of Conduct. Be excellent to one another.
We use the Developer Certificate of Origin,
not a CLA. Sign off every commit with -s:
git commit -s -m "Your message"This appends a Signed-off-by: trailer. Configure it once so you don't forget:
git config format.signOff trueThe org-wide DCO App blocks PRs whose commits aren't
signed off. To fix retroactively: git rebase --signoff HEAD~N && git push --force-with-lease.
- JDK 21 (Temurin recommended). The build pins the Kotlin toolchain to 21.
- Xcode 15+ is only needed to run the iOS/tvOS/macOS targets (macOS host).
- No submodules.
| Task | Command |
|---|---|
| Full check (all 13 targets, tests, API check) | ./gradlew build |
| JVM tests (incl. the zstd-jni interop oracle) | ./gradlew jvmTest |
| API surface check | ./gradlew apiCheck |
| API surface dump (after an intended change) | ./gradlew apiDump |
| Reformat Kotlin (Spotless/ktlint) | ./gradlew spotlessApply |
| Formatting + static-analysis gate | ./gradlew spotlessCheck detekt |
| Regenerate the trained test dictionary | python3 scripts/train_test_dict.py |
Formatting (Spotless/ktlint) and static analysis (detekt) are wired into the build
and gated in CI. ktlint reads .editorconfig, so that file remains the single
source of Kotlin style. Run ./gradlew spotlessApply to auto-format before
committing. Pre-existing findings in the RFC 8878 engine (lifted verbatim from
TAKPacket-SDK) are recorded in config/detekt/baseline.xml; the gate blocks new
issues. Regenerate the baseline after intentionally clearing engine findings with
./gradlew detektBaseline.
The public API is captured in api/kzstd.api by the binary-compatibility-validator
and explicitApi(). After an intentional public-API change, run
./gradlew apiDump and commit the regenerated api/kzstd.api in the same PR.
./gradlew apiCheck (part of build) fails on unintended drift. Never edit the
.api file by hand.
CHANGELOG.md is hand-written in
Keep a Changelog form, and nothing generates an
entry from a commit. scripts/changelog.sh cuts and reads sections without re-rendering
the file, so prose under any heading survives a release.
Add an entry under ## [Unreleased] for anything a consumer would notice — a new or
changed public API, a behaviour change, a fix to something they could have hit, a
security property, a compressed-output or frame-format change. Refactors, test-only
changes and CI work need none.
A change that moves api/kzstd.api or api/kzstd.klib.api always needs an entry,
and it goes under ### Breaking if a consumer has to change code rather than just
recompile. Breaking comes first in a section for that reason: with committed ABI
dumps, the first thing a consumer needs to know is whether recompiling is enough.
The changelog is also what the GitHub Release page says. release.yml puts
scripts/changelog.sh notes X.Y.Z in the release body, and GitHub's own
generate_release_notes is off, so a release is described once. Releasing is in
RELEASING.md.
- Branch off
main. - Make the change; add tests for any new behavior.
- Run
./gradlew buildand fix anything red. If you changed the public API, run./gradlew apiDumpand commit the result. - Add a
CHANGELOG.mdentry under## [Unreleased]if a consumer would notice — see Changelog above. Anapi/*.apimove always needs one. - Sign off every commit (
git commit -s). - Open the PR and describe what changed and why.
kzstd is GPL-3.0, the same license as the other Meshtastic projects, so lifting
code from them is allowed. When you do: keep the SPDX-License-Identifier: GPL-3.0-or-later
header, add a copyright line crediting the source repo, and note the origin in the
commit message (Origin: <repo>/<path> @ <sha>).
Don't open a public issue — follow SECURITY.md.