Overview

AetherShell provides multiple interfaces for programmatic usage:

Rust Library API

Adding Dependency

[dependencies]
aethershell = { path = "../AetherShell" }
# or when published:
# aethershell = "1.0.0"

Basic Usage

use aethershell::{parser, eval, env::Env};

fn main() -> anyhow::Result<()> {
    // Parse AetherShell code
    let program = parser::parse_program(r#"
        [1, 2, 3, 4, 5]
        | map(fn(x) => x * 2)
        | reduce(fn(a,b) => a + b, 0)
    "#)?;
    
    // Create environment
    let mut env = Env::new();
    
    // Evaluate
    let result = eval::eval_program(&program, &mut env)?;
    
    println!("Result: {:?}", result);
    Ok(())
}

Core Modules

Module Description Key Types
parser Parse AetherShell code to AST parse_program(), parse_expr()
ast Abstract Syntax Tree definitions Expr, Stmt, BinOp
eval AST evaluation engine eval_program(), eval_expr()
value Runtime value system Value, Lambda
env Variable environment Env
builtins Built-in functions eval_builtin()
syntax_kb Syntax Knowledge Base SyntaxKB, AgenticBinary

Value System

Value Enum

pub enum Value {
    Null,
    Int(i64),
    Float(f64),
    Str(String),
    Bool(bool),
    Array(Vec<Value>),
    Record(BTreeMap<String, Value>),
    Lambda(Lambda),
}

Creating Values

use aethershell::value::Value;
use std::collections::BTreeMap;

// Primitive values
let num = Value::Int(42);
let text = Value::Str("hello".to_string());
let flag = Value::Bool(true);

// Collections
let arr = Value::Array(vec![
    Value::Int(1),
    Value::Int(2),
    Value::Int(3),
]);

let mut map = BTreeMap::new();
map.insert("name".to_string(), Value::Str("Alice".to_string()));
map.insert("age".to_string(), Value::Int(30));
let record = Value::Record(map);

Value Operations

use aethershell::value::Value;

// Pattern matching
match value {
    Value::Int(n) => println!("Integer: {}", n),
    Value::Str(s) => println!("String: {}", s),
    Value::Array(arr) => println!("Array with {} elements", arr.len()),
    Value::Record(map) => println!("Record with {} fields", map.len()),
    _ => println!("Other type"),
}

Parser API

Parsing Programs

use aethershell::parser;

// Parse full program
let program = parser::parse_program(r#"
    x = 10
    y = 20
    x + y
"#)?;

// Parse single expression
let expr = parser::parse_expr("1 + 2 * 3")?;

AST Types

use aethershell::ast::{Expr, Stmt, BinOp};

pub enum Expr {
    Literal(Value),
    Ident(String),
    BinOp(Box<Expr>, BinOp, Box<Expr>),
    Pipeline(Box<Expr>, Box<Expr>),
    Lambda(Vec<String>, Vec<Stmt>, Box<Expr>),
    Call(Box<Expr>, Vec<Expr>),
    FieldAccess(Box<Expr>, String),
    IndexAccess(Box<Expr>, Box<Expr>),
    // ... more variants
}

pub enum Stmt {
    VarDecl(String, Mutability, Expr),
    Expression(Expr),
}

Evaluator API

Evaluating Code

use aethershell::{parser, eval, env::Env};

fn evaluate_code(code: &str) -> anyhow::Result<Value> {
    let program = parser::parse_program(code)?;
    let mut env = Env::new();
    eval::eval_program(&program, &mut env)
}

// Usage
let result = evaluate_code("[1,2,3] | len")?;
assert_eq!(result, Value::Int(3));

Environment Management

use aethershell::env::Env;

// Create environment
let mut env = Env::new();

// Set variables
env.set("x", Value::Int(10));
env.set_mutable("counter", Value::Int(0));

// Get variables
if let Some(value) = env.get("x") {
    println!("x = {:?}", value);
}

// Child scope
{
    let mut child_env = env.child();
    child_env.set("y", Value::Int(20));
    // y only visible in child scope
}

Syntax Knowledge Base API

Accessing Syntax KB

use aethershell::syntax_kb::{get_kb, SyntaxEntry};

fn get_protocol() -> anyhow::Result<()> {
    let kb = get_kb()?;
    
    // Get entry
    if let Some(entry) = kb.get("ab") {
        println!("Protocol: {}", entry.name);
        println!("Category: {}", entry.category);
    }
    
    // Search
    let results = kb.search("binary");
    println!("Found {} results", results.len());
    
    // List by category
    let protocols = kb.list_by_category("protocol");
    
    Ok(())
}

Adding Entries

use aethershell::syntax_kb::{get_kb, SyntaxEntry};

fn add_custom_syntax() -> anyhow::Result<()> {
    let kb = get_kb()?;
    
    let entry = SyntaxEntry {
        id: "myproto".to_string(),
        name: "My Protocol".to_string(),
        category: "protocol".to_string(),
        specification: "Custom protocol specification...".to_string(),
        examples: vec!["example1".to_string(), "example2".to_string()],
    };
    
    kb.add(entry)?;
    Ok(())
}

AgenticBinary Encoding/Decoding

use aethershell::syntax_kb::AgenticBinary;

fn encode_decode() -> anyhow::Result<()> {
    // Encode message
    let bytes = AgenticBinary::encode("command", "ping", "hello")?;
    
    // Decode message
    let msg = AgenticBinary::decode(&bytes)?;
    
    println!("Type: {}", msg.msg_type);
    println!("Opcode: {}", msg.opcode);
    println!("Payload: {}", msg.payload);
    
    Ok(())
}

Command-Line Interface

Basic Usage

# Run script file
ae script.ae

# Run with arguments
ae script.ae arg1 arg2

# REPL mode
ae

# TUI mode
ae tui

# Execute inline code
ae -c "print([1,2,3] | len)"

Environment Variables

Variable Purpose Example
AETHER_AI Default AI provider openai, ollama
OPENAI_API_KEY OpenAI API key sk-...
AGENT_ALLOW_CMDS Whitelisted agent commands ls,find,grep,cat

Exit Codes

Code Meaning
0 Success
1 General error
2 Parse error
3 Runtime error
4 File not found

REPL API

Interactive Session

# Start REPL
ae

# Execute commands
> x = 10
> y = 20
> x + y
30

# Multi-line input
> [1, 2, 3, 4, 5]
| map(fn(x) => x * 2)
| print

# Load file
> load("script.ae")

# Exit
> exit(0)

REPL Commands

Command Description
help() Show help
clear() Clear screen
exit(code) Exit REPL
env("VAR") Get environment variable

Type Checking API

Type Inference

use aethershell::typecheck;

fn check_types() -> anyhow::Result<()> {
    let program = parser::parse_program(r#"
        x = 10
        y = 20
        x + y
    "#)?;
    
    // Infer types
    let type_env = typecheck::infer_program(&program)?;
    
    // Get type of variable
    if let Some(ty) = type_env.get("x") {
        println!("x has type: {:?}", ty);
    }
    
    Ok(())
}

Type Representation

pub enum Type {
    Int,
    Float,
    Str,
    Bool,
    Null,
    Array(Box<Type>),
    Record(BTreeMap<String, Type>),
    Lambda(Vec<Type>, Box<Type>),
    Var(String),  // Type variable for polymorphism
}

Error Handling

Error Types

use anyhow::{Result, Context};

fn safe_evaluation(code: &str) -> Result<Value> {
    let program = parser::parse_program(code)
        .context("Failed to parse code")?;
    
    let mut env = Env::new();
    
    let result = eval::eval_program(&program, &mut env)
        .context("Failed to evaluate program")?;
    
    Ok(result)
}

// Usage with error handling
match safe_evaluation("[1,2,3] | len") {
    Ok(value) => println!("Result: {:?}", value),
    Err(e) => eprintln!("Error: {}", e),
}

Building & Compilation

Build Commands

# Build debug binary
cargo build

# Build release binary
cargo build --release

# Build all binaries (ae + aimodel)
cargo build --bins --release

# Run tests
cargo test

# Run with features
cargo build --features "ai,mcp"

Binary Outputs

Binary Purpose Location
ae Main AetherShell executable target/release/ae.exe
aimodel AI model management tool target/release/aimodel.exe

Extension Points

Adding Custom Builtins

// In builtins.rs

// 1. Add to lookup
map.insert("my_function", 72);

// 2. Add to dispatch table
|args, input, _| bi_my_function(args, input),

// 3. Implement function
fn bi_my_function(args: Vec<Value>, input: Option<Value>) -> Result<Value> {
    // Get argument or piped input
    let value = if let Some(inp) = input {
        inp
    } else {
        args.get(0).context("Expected argument")?.clone()
    };
    
    // Process and return
    Ok(value)
}

Adding to Syntax KB

// In syntax_kb.rs - add_builtin_syntaxes()

kb.add(SyntaxEntry {
    id: "my_protocol".to_string(),
    name: "My Custom Protocol".to_string(),
    category: "protocol".to_string(),
    specification: "Protocol specification...".to_string(),
    examples: vec!["example1".to_string()],
})?;

Performance Considerations

Optimization Tips

Memory Usage

// Values are reference-counted internally
let arr = Value::Array(vec![...]);  // No deep copies
let shared = arr.clone();  // Cheap clone (Rc)

Testing

Unit Tests

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_pipeline() -> Result<()> {
        let program = parser::parse_program(
            "[1,2,3] | map(fn(x) => x * 2)"
        )?;
        
        let mut env = Env::new();
        let result = eval::eval_program(&program, &mut env)?;
        
        assert_eq!(
            result,
            Value::Array(vec![
                Value::Int(2),
                Value::Int(4),
                Value::Int(6)
            ])
        );
        
        Ok(())
    }
}

Running Tests

# All tests
cargo test

# Specific test
cargo test test_pipeline

# With output
cargo test -- --nocapture

# Integration tests only
cargo test --test '*'

Documentation

Generate Rust Docs

# Generate documentation
cargo doc --open

# With dependencies
cargo doc --open --document-private-items

API Documentation Location

target/doc/aethershell/index.html
Complete! You now have the full AetherShell API reference. For more details, see the GitHub repository.