Declare intent.
Generate the wiring.
Elarion turns modules, handlers, and attributes into deterministic, compile-time wiring. One annotated class becomes a use case, a service, a JSON-RPC method, an MCP tool, an HTTP endpoint, and a typed client — with no runtime reflection scanning.
[RpcMethod("clients.get")] public sealed class GetClient(IAppDbContext db) : IHandler<GetClient.Query, Result<Response>> { public sealed record Query(Guid Id); public sealed record Response(Guid Id, string Name); public async ValueTask<Result<Response>> HandleAsync(Query q, CancellationToken ct) { var client = await db.Clients .Where(c => c.Id == q.Id) .Select(c => new Response(c.Id, c.Name)) .FirstOrDefaultAsync(ct); return client is null ? AppError.NotFound($"Client {q.Id} not found.") : client; } }
One class. Every surface.
Your application assemblies declare modules and handlers. Source generators emit the registrations, transports, and contracts as ordinary DI code at build time. Nothing is discovered at startup, so missing wiring is a build error — never a runtime surprise.
- No registration lists to keep in sync
- Deterministic, AOT-friendly startup
- The same handler, surfaced to humans and AI agents
A thin host. A rich application surface.
Auto-detect application patterns, explicitly wire platform capabilities. Everything that can be derived from your code is generated for you.
Build-time, not runtime
- Wiring discovered by scanning the classpath at startup
- Missing registration surfaces as a runtime exception
- Reflection undermines trimming and AOT
- A parallel registration list drifts from your code
- Wiring emitted as inspectable DI code at compile time
- Missing wiring is a build error, caught in CI
- Trim- and AOT-friendly by construction
- Intent declared next to the type — one source of truth
The philosophy in one line
“Auto-detect application patterns, explicitly wire platform capabilities.”
Repeating what your code already states — “I handle this request”, “I validate this command” — in a separate registration list creates a parallel model that drifts. Elarion declares intent next to the type and generates the wiring.
Read the full design rationaleLayered, domain-neutral packages
A clean dependency direction: abstractions at the base, a reusable runtime above, and opt-in transports and data layers at the edge. The host stays a thin composition shell.
Ship your first module in minutes
Add the packages, declare a module, write a handler. The generators take care of the wiring, the transports, and the typed client.