Architecture¶
ELMOS follows a layered, domain-driven architecture in Go with strict separation of concerns.
Visual Overview¶
For detailed diagrams, see the Architecture Diagrams page:
- Component Diagram - Package relationships
- Sequence Diagram - Build workflow
- Class Diagram - Domain types
- State Diagram - Workspace lifecycle
- Deployment Diagram - Runtime view
Layer Overview¶
| Layer | Package | Purpose |
|---|---|---|
| App | core/app/ |
CLI commands, dependency injection |
| Domain | core/domain/ |
Business logic, platform-agnostic |
| Infra | core/infra/ |
System interactions, external deps |
| Config | core/config/ |
Configuration types and loading |
| Context | core/context/ |
Build state and environment |
| UI | core/ui/ |
TUI and output formatting |
App Layer (core/app/)¶
The application entry point and command registration.
App Struct¶
// core/app/app.go
type App struct {
Exec executor.Executor
FS filesystem.FileSystem
Config *config.Config
Context *elcontext.Context
KernelBuilder *builder.KernelBuilder
ModuleBuilder *builder.ModuleBuilder
AppBuilder *builder.AppBuilder
QEMURunner *emulator.QEMURunner
HealthChecker *doctor.HealthChecker
AutoFixer *doctor.AutoFixer
RootfsCreator *rootfs.Creator
PatchManager *patch.Manager
ToolchainManager *toolchain.Manager
Printer *ui.Printer
}
Key Functions:
New()- Creates App with all dependencies wiredBuildRootCommand()- Returns the root Cobra command
Commands Context¶
Commands receive a shared context:
// core/app/commands/context.go
type Context struct {
Exec executor.Executor
FS filesystem.FileSystem
Config *config.Config
AppContext *elcontext.Context
KernelBuilder *builder.KernelBuilder
// ... all domain services
Printer *ui.Printer
}
Domain Layer (core/domain/)¶
Platform-independent business logic.
Modules¶
| Module | Purpose | Key Types |
|---|---|---|
builder/ |
Kernel, module, app builds | KernelBuilder, ModuleBuilder, AppBuilder |
doctor/ |
Environment health checks | HealthChecker, AutoFixer |
emulator/ |
QEMU execution | QEMURunner, RunOptions |
patch/ |
Kernel patch management | Manager, PatchInfo |
rootfs/ |
Root filesystem creation | Creator |
toolchain/ |
Cross-compiler management | Manager |
Example: KernelBuilder¶
// core/domain/builder/kernel.go
type KernelBuilder struct {
exec executor.Executor
fs filesystem.FileSystem
cfg *config.Config
ctx *elcontext.Context
tm *toolchain.Manager
}
// Key methods
func (b *KernelBuilder) Build(ctx context.Context, opts BuildOptions) error
func (b *KernelBuilder) Configure(ctx context.Context, configType string) error
func (b *KernelBuilder) Clean(ctx context.Context) error
Infra Layer (core/infra/)¶
External system interactions with mockable interfaces.
Interfaces¶
| Package | Interface | Purpose |
|---|---|---|
executor/ |
Executor |
Run shell commands |
filesystem/ |
FileSystem |
File I/O operations |
homebrew/ |
Resolver |
Homebrew path resolution |
printer/ |
Printer |
Formatted output |
Executor Interface¶
// core/infra/executor/executor.go
type Executor interface {
Run(ctx context.Context, name string, args ...string) error
RunWithEnv(ctx context.Context, env []string, name string, args ...string) error
Output(ctx context.Context, name string, args ...string) ([]byte, error)
// ... more methods
}
Context Layer (core/context/)¶
Build state and environment management.
Context Struct¶
// core/context/context.go
type Context struct {
Config *config.Config
Exec executor.Executor
FS filesystem.FileSystem
Brew *homebrew.Resolver
Verbose bool
}
Key Methods:
| Method | Purpose |
|---|---|
IsMounted() |
Check if workspace volume is mounted |
EnsureMounted() |
Verify mount or return error |
GetKernelImage() |
Path to built kernel image |
GetMakeEnv() |
Environment variables for make |
HasConfig() |
Check if .config exists |
Data Flow¶
User → CLI (Cobra) → App.BuildRootCommand()
↓
Command Handler
↓
Domain Service (e.g., KernelBuilder)
↓
Infra Interface (e.g., Executor.Run())
↓
External System (make, qemu, etc.)
- User runs
elmos kernel build - Cobra parses args, calls command handler
- Handler uses
Context.KernelBuilder.Build() - KernelBuilder calls
Executor.RunWithEnv()with make args - Output streamed back to user
Key Patterns¶
Dependency Injection¶
All domain services receive dependencies via constructors:
// app.go - wiring
func New(exec executor.Executor, fs filesystem.FileSystem, cfg *config.Config) *App {
ctx := elcontext.New(cfg, exec, fs)
tm := toolchain.NewManager(exec, fs, cfg, printer)
return &App{
KernelBuilder: builder.NewKernelBuilder(exec, fs, cfg, ctx, tm),
// ...
}
}
Interface Abstraction¶
Domain defines interfaces, infra implements:
// Domain uses:
type Executor interface { Run(...) error }
// Infra provides:
type ShellExecutor struct { /* implements Executor */ }
type MockExecutor struct { /* for testing */ }
Directory Structure¶
core/
├── app/
│ ├── app.go # App struct, New(), BuildRootCommand()
│ ├── commands/ # CLI command handlers
│ │ ├── context.go # Shared command context
│ │ ├── kernel.go # elmos kernel *
│ │ ├── qemu.go # elmos qemu *
│ │ └── ...
│ └── version/ # Version info
├── config/
│ ├── arch.go # Architecture configs (arm64, riscv)
│ ├── defaults.go # Default values
│ ├── loader.go # YAML config loading
│ └── types.go # Config struct definitions
├── context/
│ └── context.go # Build context, mount checks
├── domain/
│ ├── builder/ # Kernel/module/app builders
│ ├── doctor/ # Health checks
│ ├── emulator/ # QEMU runner
│ ├── patch/ # Patch management
│ ├── rootfs/ # RootFS creation
│ └── toolchain/ # Toolchain management
├── infra/
│ ├── executor/ # Command execution
│ ├── filesystem/ # File operations
│ ├── homebrew/ # Homebrew paths
│ └── printer/ # Output formatting
└── ui/
├── printer.go # Styled output
└── tui/ # Interactive TUI