Ek
This page was generated with AI — please accept inaccuracies This is a very very early version..
Ek
A Programming Language for the Agent Era
Strict. Safe. Full-Stack. Agent-First.

The Name

Ek comes from Punjabi/Urdu — meaning "one."

Files use the .ek extension. The language is pronounced "ek" — like the first syllable of "echo." Ek is built to be the global standard for agent-generated safe code.


1.The Core Thesis

Most programming languages were designed around one fundamental constraint: human programmers are slow, error-prone, and have limited working memory. Every abstraction, every framework, every dependency manager exists to compensate for that constraint.

That constraint is gone.

AI agents can write code at infinite scale, with infinite patience, and without fatigue. The reason we needed Rails, npm, pip, and heavyweight frameworks — to shortcut human effort — no longer applies. We can go back to first principles and build something cleaner, safer, and faster than anything that came before.

The Thesis: If you need to dig a tunnel and you have infinite spoons and infinite time, you can build a better tunnel than anyone with a shovel or a machine. Agents are the infinite spoons. Tokens are infinite. The old constraints are dead.

This is not a language for humans to write. It is a language for agents to use as their primary instrument for real work — from kernel modules to browser UIs — with safety guarantees that are mathematically impossible to violate.


2.The Problem

2.1 Every Major Hack Comes From the Same Place

Buffer overflows, null pointer dereferences, use-after-free, integer overflows, unchecked length fields. These are not new problems. They have existed since C was written in the 1970s. They are responsible for virtually every major security breach in history — Heartbleed, WannaCry, and thousands of CVEs you have never heard of.

Existing languages tried to solve this:

  • Rust introduced a borrow checker — but kept an unsafe keyword that developers use to opt out of safety
  • Austral introduced linear types and capability security — but remains academic and human-authored
  • Vercel Zero launched in May 2026 as an agent-first language — but targets only the systems layer, has no internationalization, and no formal verifiability

None of them started from the right assumption: that the programmer is not a human.

2.2 The Agent Code Generation Problem

AI agents today write code in Python, JavaScript, C, and Rust — languages never designed for agent authorship. These languages are loose, ambiguous, and full of escape hatches. An agent can generate unsafe code just as easily as safe code. The language provides no structural guarantee.

The Gap: No language has ever been designed from the ground up with the assumption that the primary author is an AI agent and that unsafe code must be structurally impossible to express — not just unlikely, not just caught in testing, but impossible in the grammar.


3.The Language

3.1 Core Design Philosophy

One canonical way to do everything. No escape hatches. If something cannot be expressed safely, it cannot be expressed at all.

The primary author is an agent. Agents have infinite tokens and infinite patience. They do not need shortcuts. They do not need unsafe. They will write the long safe version every single time because they never get tired.

3.2 Safety Features

FeatureWhat It MeansWhat It Prevents
Linear TypesEvery value used exactly onceMemory leaks, use-after-free, double free
Always-Assigned VariablesEvery variable must have a value at declarationUninitialised memory, null-like crashes
Capability TokensFunctions declare required permissions in their signatureSupply chain attacks, hidden resource access
Bounded MemoryEvery allocation has a declared maximum size, proven at compile timeBuffer overflows, unbounded allocation attacks
No Unsafe KeywordZero escape hatches, everThe entire category of unsafe opt-outs
Effect SystemEvery failure mode enumerated and proven at compile timeSilent failures, unhandled errors, runtime surprises
Formal VerifiabilityCompiler produces a mathematical proof alongside every binaryEntire classes of logic errors
Strict TypingNo implicit casts, everType confusion vulnerabilities
Explicit Error HandlingEvery error must be handled, compiler enforces thisSilent failures and unexpected crashes

3.3 Type System

The type system is the heart of Ek. Every type is either:

  • A primitive — integers with explicit bit width and bounds, floats with explicit precision, booleans, unicode text
  • A composite — records, unions, arrays — all with explicit sizes baked into the type. One deliberate exception: Vector (⦃τ T⦄) is a growable, audited container backed by one reallocation mechanism in the standard library — the only place unbounded allocation is permitted, used for structures like linked lists, trees, and parser ASTs that cannot be sized up front
  • A capability token — an unforgeable linear token required to access any external resource
  • An outcome union — a plain two-or-more-variant union, with one Success variant and one or more named failure variants, for any fallible operation — handled via the verify construct, with no generic Result<T, E> wrapper and no angle-bracket syntax of any kind

There is no null. There is no void*. There is no implicit cast between any two types. There is no integer overflow — the compiler rejects operations that could overflow without explicit handling.

Every variable must be assigned a value at the point of declaration. There are no uninitialised variables. Ever. A variable without a value cannot be expressed in the grammar.

// correct — value assigned at declaration § 𝕊 name <- "john"; // this cannot be written in Ek — the grammar rejects it § 𝕊 name;

3.4 Linear Types in Detail

Every value in Ek must be used exactly once. Not zero times. Not twice. Once.

  • If you open a file handle, you must close it. The compiler rejects the program if you forget.
  • If you allocate memory, you must free it. The compiler rejects the program if you forget.
  • If you receive a network connection, you must handle and close it. Impossible to leak.

No garbage collector is needed. No runtime cost. Memory is managed at compile time through math, not at runtime through scanning. Linear types give you memory safety and performance simultaneously.

3.5 Capability Security in Detail

No function in Ek can access the filesystem, network, hardware, or any external resource unless it holds an explicit capability token for that resource.

Tokens are declared in the function signature:

:: readFile(§ 𝕊 path, FileReadCapability cap) -> 𝕊;

Anyone reading this function knows exactly what it is allowed to touch — just from the signature. No surprises hidden inside the body.

Tokens are:

  • Unforgeable — you cannot create one from nothing. The OS hands the root token to the program at startup. Everything flows from there.
  • Linear — they follow the same one-use rules as all values in Ek
  • Passed explicitly — a function that needs filesystem access must receive the token from its caller

The chain of trust is visible and unbreakable:

OS hands FileReadCapability to the program at startup

Main function receives it

Main passes it explicitly to the function that needs it

That function passes it to read_file

read_file uses it — token is consumed

A third-party library physically cannot access your network unless you hand it a NetworkCapability. Supply chain attacks that rely on hidden network calls are structurally impossible in Ek.

Standard capability types:

FileReadCapability — can read files FileWriteCapability — can write files NetworkCapability — can make network calls HardwareCapability — can talk to physical devices MemoryCapability — can request additional memory allocations

3.6 Bounded Memory in Detail

In C you can write:

char buffer[256]; strcpy(buffer, user_input); // what if user_input is 10,000 bytes? // buffer overflow — this is how Heartbleed happened

The programmer said "give me 256 bytes" but placed no enforced limit on what goes in. In Ek, the size is part of the type — not a comment, not a runtime check, but a mathematical contract the compiler reasons about:

§ ⟦τ ℂ, σ 256⟧ inputBuffer; § ⟦τ ℤ, σ 100⟧ numbers; § ⟦τ ℂ, σ 512⟧ username;

When you try to write into a bounded buffer, the compiler checks — can this operation be proven to stay within bounds? If it cannot prove it, the program is rejected at compile time. Not a runtime crash. A compile error before anything runs.

When the data is too large, it becomes an error — not an overflow:

WriteOutcome { Success(), Failure(BufferTooSmall) }; :: writeTo(inputBuffer, data) -> WriteOutcome;

The overflow cannot happen. The error is declared in the effect signature. The caller must handle BufferTooSmall. The compiler enforces this. Three layers of protection, all at compile time.

3.7 No Escape Hatches

This is the most important design decision and the sharpest break from every prior language.

Rust has unsafe {}. Austral has limited foreign function escape. C is entirely unsafe. Every language made concessions because humans needed them — writing 100% safe code manually is exhausting.

Ek has no concessions. No unsafe. No raw pointers. No foreign function interface that bypasses the type system. If you cannot express it safely in Ek, you cannot express it at all.

Agents do not need escape hatches. They have infinite tokens. They will write the safe version.

3.8 Effect System experimental

This is where Ek goes beyond every language in existence — including Austral.

The hierarchy of error handling across languages:

  • JavaScript — errors are silent. You find out at runtime, maybe.
  • Python — errors crash loudly, but you can ignore them entirely.
  • Rust — errors are tracked, but .unwrap() lets you bypass the system.
  • Austral — errors must be handled, no bypass. The strictest thing that exists today.
  • Java — tried to enumerate errors with checked exceptions in 1995. Human developers found it tedious and worked around it constantly with empty catch blocks. The idea was right. The execution failed because humans get tired.
  • Ek — errors are proven at compile time. Every failure mode is enumerated. Impossible errors are eliminated before the program runs. It works where Java failed because agents never get tired.

What the Ek effect system does:

Every function declares not just what it returns but exactly what can go wrong:

ReadOutcome { Success(𝕊), FileNotFound, PermissionDenied, Corrupted }; :: readFile(§ 𝕊 path, FileReadCapability cap) -> ReadOutcome;

The compiler knows at compile time: every failure mode this function can produce; whether the caller has handled all of them; whether any failure mode is impossible given the current capability context — and eliminates it.

What Ek proves: no matter what happens at runtime, every possible outcome has been handled in the code. The file might not be there. But you already handled that case because the compiler made you. Runtime surprises are impossible — not because the world is predictable, but because every possible outcome is accounted for.

3.9 Formal Verifiability experimental

Normal testing says: "I ran the code 1000 times and it worked."

Formal verification says: "I can mathematically prove this code is correct for all possible inputs, forever."

The Ek compiler produces a formal proof alongside every binary. Before a single line of agent-generated code runs, the agent can verify the proof. Not test it. Prove it.

The proof covers not just "does this logic compute the right answer" but "can this program access anything it should not, overflow any buffer, or encounter any unhandled failure mode." The answer to all three is mathematically proven to be no.

3.10 Speed

All of these safety features — do they make Ek slow? No. And the reason is specific and important.

Every safety feature in Ek is enforced at compile time, not at runtime.

The compiler does the work. The binary does not. By the time a .ek file becomes a running program, every safety check has already happened and been proven. The binary contains none of that checking machinery — it just runs.

  • Python, JavaScript — runtime type checking, garbage collection, bounds checking as the program runs.
  • Java — garbage collector pauses your program to scan and free memory.
  • Rust — adds runtime bounds checks on array accesses in safe code.

Ek has none of this at runtime. Linear types manage memory at compile time through math — no garbage collector, no pauses, no hidden overhead. Ek binaries are comparable in speed to C and Rust. All of the safety. None of the runtime cost.

3.11 Internationalized Syntax

Ek keywords are not locked to English. The syntax is designed to be language-neutral in structure — readable and writable regardless of what human language the author thinks in. Keywords can be expressed in any language. The grammar does not assume left-to-right or subject-verb-object thinking.

Ek is the first systems language to treat internationalization as a first-class design requirement, not an afterthought. A developer in Lahore, Lagos, or Tokyo should be able to read Ek code without thinking in English first.

3.12 The Lens System experimental

Ek has one truth and multiple readable forms.

Real Code

What agents write and what the compiler sees. Mathematical, symbolic, and language-neutral. No English keywords. No ceremony. Just symbols and names. A model that learns a small, fixed set of mappings can write any Ek program correctly.

Dev Lens

A readable form aimed at people with a programming background. It keeps familiar structure — brackets, indentation, short keywords — close to what a developer coming from C, Rust, or Python would expect to see.

Normie Lens

A readable form aimed at people with no programming background. It spells things out in full English words rather than short keywords or symbols, trading brevity for clarity.

All three are generated from and convert back to the same underlying program. Real Code is the only form agents write or the compiler natively reasons about. Dev Lens and Normie Lens are views generated from Real Code — never written directly — and can themselves be generated in any human language. The underlying program does not change between forms. The view does.

Why symbols make agent authorship more reliable: Every English keyword carries ambiguity. The word function appears in millions of non-code documents the model was trained on. A dedicated Real Code symbol means exactly one thing in Ek, always. No ambiguity to resolve. The model learns one mapping and applies it perfectly.

This is the experimental bet behind the Lens System: that a small, fixed set of unambiguous symbols produces more reliable agent-authored code than reusing the same overloaded keywords every other language already uses. It has not yet been tested against models head-to-head — that test is part of Phase 1.

Lens Identification

Every .ek file declares its lens at the top:

@lens: dev

This resolves ambiguity at the file level. Some snippets are genuinely indistinguishable between Dev and Normie — a bare conditional like if (x > 0) then {} else {} is identical token-for-token in both lenses. This is an accepted tradeoff: closeness between the lenses is what makes them easy to learn side by side.

3.13 Comparison to Existing Languages

FeatureCRustAda/SPARKAustralVercel ZeroEk
No unsafe keywordunsafe{}Partial✅ never
Linear types
Always-assigned variablesPartialPartial
Capability tokensPartial✅ full
Bounded memory (compile-time proven)Runtime only✅ SPARK onlyPartial✅ full
Effect system (compile-time)
Formal verifiability✅ SPARK onlyPartial
Full stack coveragePartialPartial
Internationalized syntax
Agent-first designPartial
No escape hatches ever
Zero runtime safety overheadPartial
Lens System✅ experimental

Against Vercel Zero: Zero is safe at the bottom of the stack. Ek is safe everywhere. Zero is English-only. Ek is internationalized. Zero has no formal verifiability. Ek proves correctness mathematically. Zero validated the market timing. Ek is the complete answer.

Against Austral: Austral requires error handling. Ek proves at compile time every failure mode that can reach a function — and eliminates failure modes that cannot occur. Austral knows at runtime. Ek knows at compile time.

Against Ada/SPARK: SPARK proved that bounded memory and formal verification work in production — jet engines and medical devices run on it. Ek takes that proven foundation and adds capability tokens, an effect system, agent-first design, full-stack coverage, and internationalized syntax. SPARK is the proof the ideas work. Ek is the complete version of those ideas.

3.14 Deliberate Omissions

Every feature below exists in at least one mainstream language. Ek omits all of them — not because they are hard to implement, but because they exist for a reason that no longer applies: human programmers got tired of typing things, so languages built shortcuts. Agents do not get tired.

No Pointers

Ek has no raw pointers, no memory addresses exposed to the programmer, and no pointer arithmetic. There is no *p, no &x for taking an address, no dereference operator. Linear types are the replacement. Every value has exactly one owner and is used exactly once — the compiler tracks this at compile time the same way a pointer would be tracked at runtime, but without the danger of a dangling reference, a double free, or a use-after-free. This is the same approach Rust takes with ownership and borrowing, except Ek's linear types are stricter — a value is not just borrowed under rules, it is consumed exactly once. No pointer primitive is needed in the grammar. Memory safety comes from the type system, not from manual address management. Self-referential structures (linked lists, trees, graphs) are expressed using integer indices into a Vector rather than pointers — a record's "next" or "children" field is a plain slot number, not a memory address, so no dangling reference is possible.

Type Conversion, Not Type Casting

There is no implicit cast between any two types — and no casting syntax either. Ek has no (int)x, no as, no special conversion grammar of any kind. Type conversion is just a function call, like any other operation:

ConversionOutcome { Success(), Failure(ConversionError) }; :: toInteger(§ x) -> ConversionOutcome; :: toFloat(§ x) -> ;

If the conversion can fail or lose information — converting a float to an integer can lose precision or overflow — the function returns a plain two-variant union that the caller handles with verify. If the conversion is always safe — converting an integer to a float — the function returns the value directly. Agents need no new grammar to convert between types. Type conversion is not a language feature. It is a library feature, expressed entirely through the function and effect system that already exists.

No Preprocessor, No Macros

Ek has no preprocessor and no macro system of any kind. No #define. No macro_rules!. No text substitution step before compilation. No code that generates other code before the type checker, capability verifier, or effect system ever sees it. Macros break Ek's core promise — a macro means the code you read is not the code that runs, the opposite of formal verifiability. This is not the same as the Lens notation system: Lens does not generate new code or new logic, it renders the exact same program in a different visual representation, the way the same number can be written in decimal or binary. A macro produces a different program. Ek allows the former and forbids the latter.

No Multiple Return Values

Ek has no syntax for returning multiple values from a function — no tuple type, no comma-separated return. A function that needs to return more than one piece of information returns a record, which carries it explicitly and by name:

Point { x, y }; :: get_point() -> Point { Point { x: 3, y: 4 }; }

This needs no new grammar, no new primitive, and no special case. One function, one return value, always — and when that value needs to carry multiple pieces of data, a record carries it clearly by name rather than an unnamed tuple position like result.0 or result.1.

No Generics

Ek has no generic types and no type parameters. There is no <T>, no [T], no placeholder-type syntax of any kind. Every function signature names concrete, specific types. Agents have infinite tokens — writing maxInt, maxFloat, and maxString as three separate, fully explicit, separately provable functions costs an agent nothing. The standard library ships fully-typed, formally verified functions for every common type and common operation — written and proven once by whoever maintains the standard library. Generics also add real complexity to the type system, the effect system, and the formal verifier — every generic feature is more surface area where soundness can break. Ek trades a small amount of stdlib-level duplication for a simpler, more reliably verifiable type system everywhere else.

Excluded Features

Ek has no operator overloading, no default or optional parameters, no variadic functions, no global mutable state, no inheritance or polymorphism, and no exceptions or try/catch — the plain two-variant Success/Failure union, handled via the verify construct, and the effect system replace all error handling, and every value, behavior, and signature is explicit and unambiguous by construction.

3.15 Further Resolved Decisions

  • No separate mutability concept. Ek has no mut, no const, no distinction between a mutable and an immutable variable. Linear types already mean every value is used exactly once and never reassigned — there is no "change this value later" operation in the grammar to begin with. This makes the question moot rather than answered by a rule: every Ek variable is, by construction, stricter than even Rust's default-immutable binding, since Rust's immutable bindings can still be read many times, while Ek's linear values are consumed exactly once.
  • Void, not a unit type. A function that returns nothing uses void — a deliberate, familiar exception to Ek's "no special cases" rule, rather than Rust's approach of treating "nothing" as an ordinary, real type with exactly one value. The two approaches produce identical runtime performance; this was a familiarity-over-consistency tradeoff, made explicitly rather than by default, since void is the term developers coming from C-family languages already expect.
  • A distinct Char type. Ek has a dedicated Char type, separate from String. The justification is specific: Ek claims coverage down to kernel modules, device drivers, and firmware, and at that layer, single-byte-level precision is a real, recurring need. Outside that tier, Char will rarely appear in ordinary application code.
  • A universal statement terminator. Every Ek statement ends with ;. Only two constructs are exempt, because they are definitions rather than statements: a function declaration and a standalone control-flow block (if/while/for/verify/match) used in statement position — both are self-terminating at }, with no additional ;. Everything else that is a statement ends in ; even when its last token happens to be } — this includes record/union declarations and any statement whose right-hand side is itself a brace-delimited expression. This is the same statement/definition distinction C, Rust, and Java already make. An explicit terminator removes a standing constraint on every future grammar addition and gives the model one fewer judgment call to make per statement.
  • Declaration before use. A function or type must be declared before any point in the file where it is referenced — matching C's convention, not Rust's order-independence. This is a deliberate departure from otherwise following Rust's lead on most safety-oriented choices, made for simplicity of the compiler's first pass rather than for any safety reason.
  • Short-circuit logical evaluation. Ek's & and | short-circuit, matching C and Rust: the right-hand side of & is never evaluated if the left-hand side is already false, and likewise for | when the left-hand side is already true. This is a deliberate concession to universal convention over Ek's stricter "no implicit behavior" instinct — short-circuiting is itself a form of implicit, hidden control flow — and is flagged as revisitable later if the tension ever causes a real design conflict.

3.16 Open Research Questions

Capturing closures. A named, top-level, capability-free function can already be passed as a value — no new syntax needed. What remains unresolved is a closure that captures a variable from its enclosing scope: it is not yet clear whether a captured linear value or capability token should be considered consumed when the closure is created, or each time the closure is called. Deferred pending further design work, not excluded by decision.


4.The Trusted Computing Base

Every computer starts in Assembly. At the very bottom of every Ek deployment is a Trusted Computing Base — a minimal layer written once in C or Assembly that handles the bare metal boot sequence, first syscall primitives, and hardware access. Everything above it is pure Ek.

  • Target size: under 500 lines of C or Assembly
  • Written once, formally audited by external security researchers, never touched again
  • Published in full — the surface area of trust is completely visible
  • Smaller than any operating system, runtime, or language foundation in existence

Ek's trusted computing base is the smallest in existence. Everything above it is formally proven safe. There is nowhere to hide a vulnerability.

The first Ek compiler is written in Rust. Once Ek exists and runs, the compiler is rewritten in Ek itself — the self-hosting milestone. The original Rust compiler is retired. The TCB remains, but everything above it — including the compiler — is Ek.


5.Full Stack Coverage

Ek operates at every layer of the stack. Agents do not switch languages or contexts. The same .ek file that writes a kernel module writes a web server writes a browser component.

LayerExamples
Browser UIComponents, DOM, WebAssembly
Mobile / DesktopiOS, Android, native apps
Web ServerHTTP, REST, GraphQL, WebSockets
Business LogicServices, workflows, auth
OS InterfaceSyscalls, processes, filesystem
Device DriversHardware, network stack, interrupts
FirmwareEmbedded, IoT, RTOS, bootloaders
Kernel ModulesCore OS code, memory, scheduler

This is not a claim that Ek is convenient at every layer. It is a claim that Ek is capable at every layer — that the same grammar, the same type system, the same safety rules apply whether you are writing a pixel renderer or a memory allocator. The human does not hold this complexity. The agent does.


6.Compilation

Ek compiles to LLVM IR, then to native machine code for any target platform.

source.ek

Ek Compiler
(type checker + capability verifier + bounds checker + effect system + formal verifier)

Formal proof of correctness
(covers memory safety, capability bounds, effect completeness, logic correctness)

LLVM IR

Native binary — any platform: x86, ARM, RISC-V, WASM
(no runtime safety overhead — all checks already proven at compile time)

Why LLVM: Compiling to C means inheriting C's undefined behavior. Compiling to Assembly means writing a separate backend for every CPU architecture. Compiling to LLVM means one compiler, every platform, all of LLVM's decades of optimizations, and none of C's problems.


7.What Ek Is Not

  • It is not a language for humans to hand-write
  • It is not a faster Python
  • It is not a safer JavaScript
  • It is not a compiler wrapper around C
  • It is not a coding assistant
  • It is not a framework
  • It is not Vercel Zero — Zero lives only at the systems layer. Ek owns the entire stack.
  • It is not Ada — Ada proved the ideas work in production. Ek is the complete version for the agent era.

8.Evergreen Compilation

When the Ek compiler improves — better optimizations, faster codegen, smarter memory layout — every existing .ek file benefits automatically. No code changes required. Just recompile.

parser.ek written in Ek v1

Ek v2 compiler released — 30% faster codegen, better LLVM optimization passes

Recompile parser.ek with Ek v2

Binary is automatically faster and safer. Zero changes to source code.

This is possible because Ek separates the language spec from the compiler implementation. The spec is the contract — it never breaks old code. The compiler improves underneath it. Your .ek files stay valid forever because the rules never change — only the compiler gets smarter at enforcing and optimizing them.


9.Living Codebase

This is the feature that has no equivalent anywhere in software.

In every other language, when a new version releases with better libraries, safer primitives, or improved patterns — someone has to manually migrate the codebase. Most production codebases are stuck on old versions forever.

Because every Ek program has a formal proof of what it does — not just what it says — an agent can:

  1. Read the formal proof of existing code
  2. Rewrite the implementation using new Ek features and better libraries
  3. Formally verify the new version has exactly the same guarantees as the old version
  4. Ship it
Ek v1 — parser.ek written by agent
Formal proof: reads file, counts words, never crashes, bounded 64kb,
             can fail: FileNotFound, Corrupted

Ek v2 releases — better string library, improved bounds primitives, faster I/O

Agent reads formal proof of parser.ek
Agent rewrites parser.ek using Ek v2 features
Formal verifier proves new version === old proof

parser.ek is now on Ek v2.
Faster. Safer. Better. Zero human involvement. Zero risk of regression.

A company with 10 million lines of Ek code never has a legacy codebase. Every time Ek improves, every line of code improves. Automatically. Overnight. For free.


10.Origin

Ek was conceived in Graz, Austria by Faisal Ahmad who isxs from Lahore, Pakistan. The name comes from the Punjabi word meaning "one." The strictest language ever designed. One way. One standard. From the kernel to the browser.