Use Your AI
Aria was designed for AI code generation. This page provides ready-to-use configuration files and prompts so your AI assistant can write Aria code today.
Universal AI Guide
This guide works with any LLM — ChatGPT, Claude, Gemini, or any other assistant. Paste it into a new conversation or attach it as a system prompt.
Copy: Aria AI Assistant Guide (full reference)
What is Aria?
Aria is a statically typed, compiled programming language designed for clarity, safety, and performance. It compiles to native code via LLVM. Think of it as a blend of Rust's safety, Go's simplicity, and Swift's expressiveness — but with its own distinct design.
The 5 Design Pillars
- Every token carries meaning — no boilerplate, no ceremony
- The type system is the AI's pair programmer — sum types, exhaustive matching, effects
- Compilation is instantaneous — unambiguous grammar, minimal lookahead
- Performance is opt-in granular — GC default, manual per-block
- No implicit behavior ever — no implicit conversions, no hidden exceptions, no null
Critical Syntax Rules
- No semicolons — newline terminates statements
- No parentheses around conditions —
if x > 0 { }notif (x > 0) { } - No null — use
Option[T](sugar:T?) - No unchecked exceptions — use
Result[T, E](sugar:T ! E) - No inheritance — use composition and traits
mutis on bindings, not types —mut x := Foo{}makesxreassignable- Last expression is the return value — no
returnneeded for final expression =for expression-body functions —fn add(a: i64, b: i64) -> i64 = a + b
Quick Reference
Variables and Constants
// Immutable (default)
x := 42
name := "Aria"
// Mutable
mut count := 0
count = count + 1
// Type annotation
age: i64 = 25
// Constants
const MAX_SIZE: i64 = 1024 Primitive Types
| Type | Description | Example |
|---|---|---|
i64 | 64-bit signed integer (default) | 42 |
i32, i16, i8 | Smaller signed integers | i32(100) |
u64, u32, u16, u8 | Unsigned integers | u8(255) |
f64 | 64-bit float (default) | 3.14 |
f32 | 32-bit float | f32(1.5) |
bool | Boolean | true, false |
str | UTF-8 string | "hello" |
char | Unicode codepoint | 'A' |
Number Literals
decimal := 1_000_000
hex := 0xFF
octal := 0o77
binary := 0b1010_1010 Strings
// Interpolation
name := "Aria"
msg := "Hello, {name}!"
expr := "Result: {x * 2 + 1}"
// String methods
s := "Hello, World"
s.len() // byte length
s.contains("World") // true
s.split(", ") // ["Hello", "World"]
s.trim() // remove whitespace
s.replace("World", "Aria")
s.toLower()
s.toUpper() Functions
// Block body
fn greet(name: str) -> str {
"Hello, {name}!"
}
// Expression body
fn add(a: i64, b: i64) -> i64 = a + b
fn square(x: f64) -> f64 = x * x
// With effects
fn read_config(path: str) -> str ! IoError with [Io, Fs] {
content := read_file(path)?
content
} Generics
fn identity[T](x: T) -> T = x
fn max[T: Ord](a: T, b: T) -> T {
if a > b { a } else { b }
}
fn process[T: Eq + Hash](val: T) -> bool = true
// Where clause
fn merge[T](a: [T], b: [T]) -> [T] where T: Ord + Clone {
// ...
} Structs
struct Point {
x: f64
y: f64
}
p := Point{x: 3.0, y: 4.0}
impl Point {
fn new(x: f64, y: f64) -> Point = Point{x: x, y: y}
fn distance(self, other: Point) -> f64 {
dx := self.x - other.x
dy := self.y - other.y
dx * dx + dy * dy
}
}
// Derives
struct Color {
r: i64
g: i64
b: i64
} derives [Eq, Clone, Debug] Sum Types
type Shape =
| Circle(f64)
| Rectangle(f64, f64)
| Triangle(f64, f64, f64)
| Point
s := Circle(5.0)
r := Ok(42)
o := Some(10) Pattern Matching
// Exhaustive (compiler enforces all cases)
result := match shape {
Circle(r) => 3.14 * r * r
Rectangle(w, h) => w * h
Triangle(a, b, c) => 0.0
Point => 0.0
}
// Guards
match value {
x if x > 100 => "large"
x if x > 0 => "positive"
0 => "zero"
_ => "negative"
}
// Or-patterns
match color {
Red | Orange | Yellow => "warm"
Blue | Green | Purple => "cool"
_ => "neutral"
}
// Named patterns
match shape {
s @ Circle(r) => use_shape(s, r)
_ => default()
}
// Array patterns
match arr {
[first, ..rest] => first
[] => 0
}
// Refutable binding
Ok(value) := try_parse(input) else {
return default_value
} Error Handling
// ? propagates errors
fn load_config() -> Config ! IoError {
content := read_file("config.json")?
parse_json(content)?
}
// catch for recovery
config := read_file("config.json") catch |e| {
"{}" // fallback
}
// ! for assert-unwrap (panics on Err)
value := parse_int("42")! Optionals
fn find_user(id: i64) -> User? {
if id == 42 { return Some(user) }
None
}
// ?? null coalesce
name := find_user(42)?.name ?? "anonymous"
// ?. optional chaining
email := find_user(42)?.email Traits
trait Display {
fn display(self) -> str
}
// Supertrait
trait Loggable: Display {
fn log_level(self) -> i64
}
impl Display for Point {
fn display(self) -> str = "({self.x}, {self.y})"
}
// dyn Trait (dynamic dispatch)
fn process(shape: dyn Area) {
println("Area: {shape.area()}")
} Collections
// Arrays
nums := [1, 2, 3, 4, 5]
nums.len()
nums[0]
nums.append(6)
// Maps
m := Map()
m.set("key", "value")
val := m.get("key")
m.has("key")
// Pipeline operator
result := data
|> transform
|> filter_valid
|> summarize Concurrency
// Spawn a task
task := spawn compute_heavy(data)
result := task.await()
// Channels
ch := _ariaChanNew(10)
ch.send(42)
val := ch.recv()
ch.close() Modules
mod myapp.server
use std.{fs, json}
use myapp.models.{User, Order}
use myapp.db as database
pub fn start_server(port: i64) {
// public function
}
fn internal_helper() {
// private to this module
} Testing
test "addition works" {
assert add(2, 3) == 5
assert add(-1, 1) == 0
} Translation Cheat Sheet
If your AI knows Rust, Go, or TypeScript, these translations help it map to Aria quickly:
From Rust
| Rust | Aria |
|---|---|
let x = 5; | x := 5 |
let mut x = 5; | mut x := 5 |
fn foo(x: i32) -> i32 { x + 1 } | fn foo(x: i64) -> i64 = x + 1 |
Result<T, E> | T ! E |
Option<T> | T? |
enum Foo { A(i32), B } | type Foo = | A(i64) | B |
x.unwrap() | x! |
println!("{}", x) | println("{x}") |
vec![1, 2, 3] | [1, 2, 3] |
From Go
| Go | Aria |
|---|---|
x := 5 | x := 5 (same) |
var x int = 5 | x: i64 = 5 |
func foo(x int) int { return x + 1 } | fn foo(x: i64) -> i64 = x + 1 |
if err != nil { return err } | value := expr? |
go func() { ... }() | spawn fn() -> i64 { ... } |
struct Foo { X int } | struct Foo { x: i64 } |
interface Foo { Bar() int } | trait Foo { fn bar(self) -> i64 } |
From TypeScript
| TypeScript | Aria |
|---|---|
const x = 5 | x := 5 |
let x = 5 | mut x := 5 |
x?.name ?? "default" | x?.name ?? "default" (same!) |
try { ... } catch(e) { ... } | expr catch |e| { ... } |
{ ...obj, key: value } | obj.{key: value} |
type Foo = { x: number } | struct Foo { x: i64 } |
Common Mistakes to Avoid
Tell your AI to watch out for these:
- Don't use semicolons
- Don't use
()around if/while conditions - Don't use
let— use:= - Don't use
var— usemut - Don't return null — use
NoneorErr(...) - Don't use
{}for maps — useMap()with.set()/.get() - Don't forget:
[T]means both array type and generic parameter - Don't use
asfor type casts — it's only for import aliases - String
{and}need escaping as\{and\}in non-interpolation contexts
Common Patterns
Builder Pattern
struct ServerBuilder {
host: str
port: i64
workers: i64
}
impl ServerBuilder {
fn new() -> ServerBuilder =
ServerBuilder{host: "0.0.0.0", port: 8080, workers: 4}
fn with_host(self, h: str) -> ServerBuilder =
ServerBuilder{host: h, port: self.port, workers: self.workers}
fn with_port(self, p: i64) -> ServerBuilder =
ServerBuilder{host: self.host, port: p, workers: self.workers}
fn build(self) -> Server =
Server{host: self.host, port: self.port, workers: self.workers}
}
server := ServerBuilder.new()
.with_host("localhost")
.with_port(9090)
.build() Error Propagation Chain
fn process_request(req: Request) -> Response ! AppError {
user := auth(req) ? |e| AppError.Auth{source: e}
data := fetch_data(user.id) ? |e| AppError.Data{source: e}
rendered := render(data) ? |e| AppError.Render{source: e}
Ok(Response{body: rendered, status: 200})
} Concurrent Fan-Out
fn fetch_all(urls: [str]) -> [Response] {
mut tasks := [0]
for url in urls {
t := spawn fetch(url)
tasks = tasks.append(t)
}
mut results := [Response{}]
for t in tasks {
results = results.append(t.await())
}
results
} IDE-Specific Setup
Cursor
Create a .cursorrules file in your Aria project root with the following content:
Copy: .cursorrules for Aria
You are an expert Aria programming language developer. Aria is a statically typed, compiled language (LLVM backend) with these key rules:
SYNTAX:
- No semicolons — newline terminates statements
- No parens around conditions: `if x > 0 { }` not `if (x > 0) { }`
- `:=` for variable binding, `mut` for mutable: `x := 5`, `mut y := 0`
- `=` for expression-body functions: `fn add(a: i64, b: i64) -> i64 = a + b`
- Last expression is implicit return — no `return` needed for final expression
- String interpolation with {}: `"Hello, {name}!"`
- `\{` and `\}` to escape braces in strings
TYPES:
- Integers: i64 (default), i32, i16, i8, u64, u32, u16, u8
- Floats: f64 (default), f32
- Strings: str (UTF-8)
- Boolean: bool (true/false)
- Arrays: [i64], [str], etc.
- No null — use Option[T] (sugar: T?)
- No exceptions — use Result[T, E] (sugar: T ! E)
ERROR HANDLING:
- `?` propagates errors: `val := fallible_call()?`
- `catch |e| { }` for recovery: `val := expr catch |e| { default }`
- `!` for assert-unwrap: `val := expr!`
FUNCTIONS:
- `fn name(param: Type) -> ReturnType { body }`
- `fn name(param: Type) -> ReturnType = expr` (expression body)
- Generics: `fn identity[T](x: T) -> T = x`
- Trait bounds: `fn process[T: Eq + Hash](val: T) -> bool`
- Where clauses: `fn merge[T](a: [T], b: [T]) -> [T] where T: Ord`
- Effects: `fn read() -> str ! IoError with [Io, Fs]`
STRUCTS & SUM TYPES:
- `struct Point { x: f64, y: f64 }`
- `type Shape = | Circle(f64) | Rectangle(f64, f64) | Point`
- Derives: `struct Foo { ... } derives [Eq, Clone, Debug]`
- Methods: `impl Point { fn distance(self) -> f64 { ... } }`
TRAITS:
- `trait Display { fn display(self) -> str }`
- `impl Display for Point { fn display(self) -> str = "..." }`
- Supertraits: `trait Loggable: Display { }`
- dyn Trait for dynamic dispatch
PATTERN MATCHING (exhaustive):
- `match val { Pattern => expr, ... }`
- Variant destructuring: `Circle(r) => ...`
- Guards: `x if x > 0 => ...`
- Or-patterns: `Red | Blue => ...`
- Named: `s @ Circle(r) => ...`
- Wildcard: `_ => ...`
CONCURRENCY:
- `spawn expr` or `spawn { block }`
- Channels: `ch.send(val)`, `ch.recv()`, `ch.close()`
MEMORY:
- Drop trait for cleanup, `with` blocks for scoped resources
MODULES:
- `mod myapp.server` (first line)
- `use std.{fs, json}`
- `pub fn` for public, no prefix for private
TESTING:
- `test "name" { assert expr == expected }`
COMMON MISTAKES TO AVOID:
- Don't use semicolons
- Don't use `()` around if/while conditions
- Don't use `let` — use `:=`
- Don't use `var` — use `mut`
- Don't return null — use `None` or `Err(...)`
- Don't use `{}` for maps — use `Map()` with `.set()/.get()`
- Don't use `as` for type casts — it's only for import aliases GitHub Copilot
Create .github/copilot-instructions.md in your Aria project root:
Copy: copilot-instructions.md for Aria
# Aria Language — GitHub Copilot Instructions
When generating Aria code (`.aria` files), follow these rules:
## Syntax
- No semicolons. Newlines terminate statements.
- No parentheses around `if`/`while` conditions
- Variable binding: `x := 42` (immutable), `mut x := 0` (mutable)
- Expression-body functions: `fn add(a: i64, b: i64) -> i64 = a + b`
- Last expression is the implicit return value.
- String interpolation: `"Hello, {name}!"`
- Entry point: `entry { ... }` (not `fn main`)
## Types
- Default integer: `i64`. Default float: `f64`.
- Strings: `str`. Booleans: `bool`.
- Arrays: `[i64]`, `[str]`.
- No null. Use `Option[T]` or `T?`. Values: `Some(x)`, `None`.
- No exceptions. Use `Result[T, E]` or `T ! E`. Values: `Ok(x)`, `Err(e)`.
- Sum types: `type Shape = | Circle(f64) | Rect(f64, f64) | Point`
- Structs: `struct Point { x: f64, y: f64 }`
## Error Handling
- `?` propagates errors: `val := try_parse(input)?`
- `catch |e| { recovery }` for inline recovery
- `!` assert-unwrap: `val := parse("42")!`
## Functions & Generics
- `fn name[T: Bound](param: T) -> T`
- Where clauses: `fn f[T](x: T) where T: Eq + Hash`
- Effects: `fn read() -> str with [Io, Fs]`
## Pattern Matching
- `match val { Pattern => expr, ... }` — must be exhaustive
- Destructuring: `Circle(r) => ...`, `Some(x) => ...`
- Guards: `x if x > 0 => ...`
- Or-patterns: `Red | Blue => ...`
## Traits
- `trait Display { fn display(self) -> str }`
- `impl Display for Point { ... }`
- `derives [Eq, Clone, Debug]` on structs
## Concurrency
- `spawn expr` — spawn a task
- Channels: `ch.send(val)`, `ch.recv()`
## Modules
- First line: `mod myapp`
- Imports: `use std.{fs, json}`
- Public: `pub fn`, `pub struct`
## Do NOT
- Use semicolons
- Use parentheses around conditions
- Use `let`, `var`, `const` for bindings (use `:=` and `mut`)
- Return null (use `None` or `Err`)
- Use `class` or inheritance (use `struct` + `trait`)
- Use `try/catch` blocks (use `?`, `catch`) Claude (CLAUDE.md)
Create a CLAUDE.md file in your Aria project root. Claude Code and other Claude-based tools will automatically read this file. Use the same content as the Cursor rules above, or the full AI guide for maximum context.
Other AI Tools
For any other AI tool that supports system prompts or project-level instructions:
- Copy the Universal AI Guide above
- Paste it into your tool's system prompt, project instructions, or context window
- Start asking it to write Aria code
Compiler Commands
Include these in your AI's context so it knows how to build and test:
aria check file.aria # Type-check without compiling
aria build file.aria # Compile to native executable
aria run file.aria # Compile and run
aria test file.aria # Run test blocks