Developers
Getting Started
Set up the workspace, build core modules, and create a small ECHO-compatible module.
Purpose
Start here when you want to build an ECHO module or addon against the public SDK instead of copying internal implementation details from another module.
The current public developer path is concrete:
- Use
ECHO-SDKfor schemas, templates, validation tooling, Gradle task names, and publicdev.echo.api.*samples. - Use
ECHO-Modulesfor first-party module source andMETA-INF/echo.mod.jsondescriptors. - Use
ECHO-Release-Indexfor public release metadata, asset families, checksums, and launcher download truth. - Use ECHO Launcher as the normal player delivery path.
ECHO still supports the Minecraft/NeoForge lane while Native and Standalone lanes mature. Keep runtime-specific code behind AdapterCore or generated adapters, and keep public addon code on the SDK contracts.
Before You Build
Read these pages first:
- Platform Overview for launcher, PackOS, modules, contracts, adapters, and runtime lanes.
- Module System for how first-party modules relate to each other.
- Service Contracts for the boundary between module behavior and runtime implementation.
- Native SDK Artifacts for Maven coordinates and the Gradle plugin.
- Native Addon Guide for
.echo-addonpackaging.
You do not need to understand every module before writing a first addon. You do need to know which layer owns your feature, which runtime targets it supports, and which contract IDs it provides or consumes.
Install And Validate The SDK
Run SDK validation from ECHO-SDK:
python tools/echo_sdk.py validate templates --json
python tools/validate_echo_contracts.py --json
For a Gradle addon project, apply the SDK plugin and use the current task names:
plugins {
id 'dev.echo.native.echo-sdk-gradle-plugin' version '1.0.0-RC'
}
dependencies {
implementation 'dev.echo.native:echoaddonapi:1.0.0-RC'
implementation 'dev.echo.native:echo-native-contracts:1.0.0-RC'
testImplementation 'dev.echo.native:echo-native-testkit:1.0.0-RC'
}
Useful SDK tasks:
echoInitAddonechoValidateManifestechoValidateSchemasechoValidateImportsechoValidatePermissionsechoValidateRuntimeTargetsechoValidateechoGenerateAdaptersechoPackageNativeAddonechoPackageNeoForgeechoPackageStandaloneechoParityTestechoBuildReleaseBundle
Workspace To First Addon
Use this flow for the first pass:
- Validate
ECHO-SDKtemplates and contracts. - Pick a target from Native Addon Guide, NeoForge Module Guide, or Standalone Module Guide.
- Create an addon from a template or mirror the sample structure in
ECHO-SDK/samples/hello-content-addon. - Define
META-INF/echo.mod.json. - Define
META-INF/echo-addon-package.jsonwhen producing.echo-addonpackages. - Implement the addon through
dev.echo.api.*and JDK imports. - Register content, services, events, or optional integrations through SDK and module contracts.
- Run
echoValidateand focused tests. - Package the selected runtime families.
- Publish release metadata through the Release Index path when the artifact is player-facing.
Current Addon Shape
The SDK sample addon uses dev.echo.api.* public types and a registry context. This is the public shape developers should copy before reaching for first-party internals.
package dev.echo.samples.hello;
import dev.echo.api.addon.EchoAddon;
import dev.echo.api.addon.EchoAddonDescriptor;
import dev.echo.api.addon.EchoAddonId;
import dev.echo.api.addon.EchoAddonKind;
import dev.echo.api.addon.EchoAddonRole;
import dev.echo.api.addon.EchoAddonRuntimeTarget;
import dev.echo.api.addon.EchoAddonVersion;
import dev.echo.api.context.EchoRegistryContext;
import java.util.Set;
public final class HelloContentAddon implements EchoAddon {
private static final EchoAddonDescriptor DESCRIPTOR = new EchoAddonDescriptor(
new EchoAddonId("hello_content_addon"),
new EchoAddonVersion("0.1.0"),
"Hello Content Add-on",
EchoAddonKind.CONTENT,
EchoAddonRole.SAMPLE,
Set.of(
EchoAddonRuntimeTarget.ECHO_NATIVE,
EchoAddonRuntimeTarget.NEOFORGE,
EchoAddonRuntimeTarget.ECHO_RUNTIME_STANDALONE
)
);
@Override
public EchoAddonDescriptor descriptor() {
return DESCRIPTOR;
}
@Override
public void register(EchoRegistryContext context) {
// Register items, blocks, recipes, services, or providers through SDK contexts.
}
}
The matching module manifest is META-INF/echo.mod.json:
{
"schema": "echo.mod.v1",
"id": "hello_content_addon",
"name": "Hello Content Add-on",
"version": "0.1.0",
"kind": "content",
"role": "sample",
"runtimeTargets": ["echo_native", "neoforge", "echo_runtime_standalone"],
"domains": ["items", "blocks", "recipes"],
"permissions": ["registry.items", "registry.blocks", "registry.recipes"],
"entrypoint": "dev.echo.samples.hello.HelloContentAddon"
}
Good First Addons
A good first addon does one thing clearly:
- Adds registry content through
EchoRegistryContext. - Publishes data-driven Index, Lens, Terminal, or HoloMap resources.
- Registers one service contract through
EchoNativeAddonRuntime. - Adds a small NetCore action with explicit server validation.
- Adds PackOS-aware metadata for an existing module or pack.
Avoid starting with an addon that owns networking, persistent saves, custom UI, and world generation at the same time. That hides the contract boundaries you are trying to learn.
Implementation Checklist
META-INF/echo.mod.jsonexists and usesschema: "echo.mod.v1".- The addon ID is lowercase and stable.
runtimeTargetsmatch the artifacts you actually build.permissionsmatch the registries, networking, data, or UI surfaces the addon uses.- Public sample code imports
dev.echo.api.*and JDK types only. - Optional integrations use service lookup or no-op behavior.
- Runtime-specific code is isolated in AdapterCore, generated adapters, or runtime entrypoints.
- Tests cover the service or registry behavior before release.
- Docs and release notes are present before the addon is public.
Common Mistakes
- Copying
com.knoxhack.*internals into third-party SDK samples. - Declaring
echo_native,neoforge, andecho_runtime_standalonewhen only one artifact builds. - Publishing a
.jarwithoutMETA-INF/echo.mod.json. - Hard-requiring an optional module instead of using
EchoOptionalServices. - Treating GitHub release assets as the normal player install path instead of routing players through ECHO Launcher.
Next Step
Create the module descriptor first, then choose one integration surface. If the addon is mostly content or discovery, start with Index or Lens. If it is mission or route related, start with Terminal and MissionCore through service contracts.