For human contributors. If you're an AI agent, read AGENTS.md instead.
Thank you for your interest in contributing to the Aether OS! This is a from-scratch x86_64 operating system built with the Aether 4GL language. The kernel is the smallest possible substrate — all features are loadable modules.
# Clone the repository
cd /Volumes/Backup/Development/Project_Aether/os
# Build the disk image
make
# Run in QEMU (headless, serial console)
make run
# Run in QEMU (graphic mode)
make run-graphic
# Test boot
make test- Aether compiler: Must be installed (
aetherin PATH) - NASM: Netwide Assembler
- x86_64-elf-objcopy: ELF64 binary conversion
- QEMU: System emulator (x86_64)
- Python 3: For build tools
- make: Build system
On macOS:
brew install nasm x86_64-elf-binutils qemuOn Linux:
sudo apt-get install nasm binutils-x86-64-linux-gnu qemu-system-x86Aether OS is built on three principles:
- The kernel does almost nothing — boot, serial I/O, physical memory management, ELF loading, syscall layer, module loader
- Every feature is a loadable module — filesystem, compression, qubits, GUI, device drivers — all
.kofiles - Every command is a standalone binary —
ls,cat,echo,reboot— all ELF executables in/bin/
BIOS → stage1.ae (512B MBR, INT 13h)
→ stage2.ae (ATA PIO, loads kernel to 0x1000000)
→ boot.ae (GDT, PAE, long mode, page tables)
→ kernel_main (init → shell)
main()
→ serial_init() # COM1 serial port (115200 8N1)
→ page_allocator_init() # Bitmap-based physical page allocator
→ syscall_page_init() # 0x5000 function table
→ module_registry_init() # 0x4000 service table
→ boot_fs_init() # In-memory filesystem
→ compute_kernel_end_sector() # Calculate kernel size
→ load_binary_index() # Read binary index from disk
→ register_commands() # Register built-in commands
→ shell_main() # Prompt → readline → exec → loop
| File | Size | Purpose |
|---|---|---|
stage1.ae |
512 bytes | MBR boot sector — loads stage2 via INT 13h |
stage2.ae |
16KB | ATA PIO kernel loader — reads kernel sectors to 0x1000000 |
boot.ae |
16KB | Long mode entry — GDT, PAE, page tables, calls kernel_main |
Key constraints:
- stage1 must fit in exactly 512 bytes with 0xAA55 signature
- stage2 and boot are compiled as flat binaries with
@layoutdirectives - boot.ae is padded to 16KB (0x4000) so the kernel ELF (linked at 0x1004000) aligns correctly
| File | Lines | Purpose |
|---|---|---|
main.ae |
1559 | Kernel main — serial I/O, shell, ATA PIO, FS, ELF loader |
data.ae |
~100 | Data structures — inode table, binary index |
elf.ae |
~80 | ELF64 loader — flat-offset, cross-module safe |
| File | Purpose |
|---|---|
libaether.ae |
Userspace runtime library (syscall wrappers) |
help.ae |
Help command |
ls.ae |
Directory listing |
echo.ae |
Echo command |
cat.ae |
File viewer |
clear.ae |
Clear screen |
reboot.ae |
Reboot command |
shutdown.ae |
Shutdown command |
uptime.ae |
Uptime display |
mem.ae |
Memory info |
ver.ae |
Version info |
ps.ae |
Process list |
modules.ae |
Module list |
date.ae |
Date/time |
booleval.ae |
Boolean evaluation (quantum-aware) |
qubit.ae |
Qubit simulation |
| File | Purpose |
|---|---|
kernel.ld |
Kernel linker script (links at 0x1004000) |
bin.ld |
Binary linker script (links at 0x2000000) |
build_image.py |
Builds the final disk image |
pad_and_combine.py |
Pads boot.bin to 16KB and combines with kernel.bin |
- Add the function in
src/kernel/main.ae - Wire into init by calling it from
main()at the appropriate point - Add data structures in
src/kernel/data.aeif needed - Update documentation:
STATUS.md— mark phase items as completePHASE_02.md— add checkmarksAGENTS.md— update key files reference
- Build and test:
make clean && make && make run
- Create
src/bin/<name>.ae - Use libaether.ae for syscall wrappers:
import "libaether.ae" @entry(0x2000000) func main() { puts("Hello from my command!\n") exit_bin() } - Build: The Makefile automatically picks up new
.aefiles insrc/bin/ - Test:
make binsto compile just the binaries, or fullmake
- Add handler in
src/kernel/main.ae:func my_syscall_handler(arg1: u64): u64 { // implementation return result } - Register in
syscall_page_init()at the next available slot - Add wrapper in
src/bin/libaether.ae:func my_syscall(arg1: u64): u64 { asm { mov rax, arg1 call [0x5048] // next available slot } } - Update documentation — syscall table in AGENTS.md and REQUIREMENTS.md
- Create a
.aefile that usesmodulekeyword:module my_driver { @export func mod_init(): int { reg_cmd("mycmd", my_handler) return 0 } @export func mod_fini() { unreg_cmd("mycmd") } } - Compile with
aether --target module - Place the
.kofile in/lib/enabled/on the disk image
- Reproduce the bug in QEMU
- Check serial output for error messages
- Identify the root cause (serial? memory? ELF loader? shell?)
- Fix in the appropriate source file
- Build and test:
make clean && make && make run - Update STATUS.md if applicable
- Language: Aether (
.ae) — Python-style indentation, 4 spaces - Naming:
snake_casefor functions and variables - Comments:
#for line comments - Asm blocks: Full NASM syntax, use SysV ABI registers (rdi=arg1, rsi=arg2)
- No
retin asm blocks: The compiler handles function prologue/epilogue - Error handling: Return error codes, print error messages via serial
# Build and test boot
make test # Boots QEMU, checks for "Aether OS" in serial output
# Interactive testing
make run # Headless QEMU with serial console
make run-graphic # Graphic mode QEMU
# Full rebuild
make clean && makeThe kernel outputs debug information over serial (COM1 at 115200 8N1):
# Capture serial output to file
qemu-system-x86_64 -m 256M -smp 2 -nographic -no-reboot \
-M pc -drive file=build/aether.img,format=raw -serial file:/tmp/aether.log
# Or use the Makefile test target
make test
cat /tmp/aether_test.logUse descriptive multi-line commit messages:
os/component: Brief description of change
Detailed explanation of what was changed and why.
Include any relevant context, trade-offs, or alternatives considered.
Fixes #123
- The OS is written in the same language it's designed to run
- No libc dependency — everything is freestanding
- Full control over code generation and memory layout
- Automatic memory management without GC
- Smaller trusted code base = fewer bugs
- Features as modules = hot-pluggable, crash-isolated
- Easier to reason about and debug
- Forces clean interfaces (syscall page, module registry)
- Simple, well-understood protocol
- No driver needed (works on real hardware and QEMU)
- Sufficient for boot and development
- Can be replaced with AHCI/ NVMe later
- Simplest possible I/O (no framebuffer, no keyboard driver needed)
- Works on real hardware (COM port) and QEMU
- Easy to capture and log
- Can be extended to a full terminal later
- Read REQUIREMENTS.md for OS requirements
- Read STATUS.md for implementation status
- Read AGENTS.md for AI agent guide (also useful for humans)
- Read the source code — it's well-commented
- Read the Aether Compiler documentation for language reference