Skip to content

zoxilsi/Linara-Terminal

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

30 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿš€ Linara Terminal

A Next-Generation AI-Powered Terminal Emulator Built with Rust ๐Ÿฆ€

Rust License: MIT GUI: egui

Transform natural language into powerful terminal commands with AI assistance


๐Ÿ“š Table of Contents

  1. Project Overview
  2. โœจ Key Features
  3. ๐Ÿ—๏ธ Architecture Explained
  4. ๐Ÿงฉ Core Working Logic
  5. ๐ŸŒ API Integration
  6. ๐Ÿ” Function-by-Function Guide
  7. ๐Ÿง  Step-by-Step Execution Flow
  8. ๐Ÿ—‚๏ธ Dependencies & Setup
  9. ๐Ÿš€ Usage Examples
  10. ๐Ÿ’ก Teaching Explanation (ELI5)
  11. ๐Ÿ”ง Extension Ideas
  12. ๐Ÿค Contributing

๐ŸŽฏ Project Overview

What is Linara Terminal?

Linara Terminal is a modern, AI-enhanced terminal emulator written in Rust that bridges the gap between human language and command-line interfaces. Think of it as your personal terminal assistant that understands plain English!

๐ŸŽญ The Problem It Solves

Traditional terminals require you to remember exact command syntax:

  • โŒ "I want to see all files including hidden ones" โ†’ You need to know: ls -la
  • โŒ "Remove the folder called 'old-project'" โ†’ You need to know: rm -r old-project
  • โŒ "Show me what's inside config.txt" โ†’ You need to know: cat config.txt

Linara Terminal makes this easy:

  • โœ… Just type: "list all files" โ†’ Instantly executes ls -la
  • โœ… Just type: "remove folder old-project" โ†’ Executes rm -r old-project
  • โœ… Just type: "view config.txt" โ†’ Shows file contents with line numbers

๐ŸŒŸ Main Features at a Glance

Feature Description
๐Ÿค– AI Natural Language Convert English to shell commands using Google Gemini 2.0 Flash
โšก Lightning Fast Local pattern matching for instant responses (no API call needed)
๐ŸŽจ Beautiful GUI Modern dark theme with authentic terminal aesthetics
๐Ÿ“‹ Clipboard Operations Full copy/paste/cut support (Ctrl+C/V/X)
๐Ÿ” Smart Autocomplete Intelligent command suggestions from history, PATH, and files
๐Ÿ›ก๏ธ Safety First Detects and blocks dangerous commands (like rm -rf /)
๐Ÿ“„ File Viewer Built-in file viewer with syntax highlighting and line numbers
๐Ÿง  Gibberish Detection Filters out nonsense input before making API calls
๐Ÿ”„ Auto-Retry Smart retry logic with exponential backoff for API failures
๐ŸŽฏ Context-Aware Tracks current directory, git branches, and command history

๐Ÿ—๏ธ Architecture Explained

๐Ÿ“ Project Structure

Linara-Terminal/
โ”‚
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ main.rs              # GUI, terminal logic, command execution
โ”‚   โ”œโ”€โ”€ ai_assistant.rs      # AI/NLP engine, API integration
โ”‚   โ””โ”€โ”€ [compiled files]
โ”‚
โ”œโ”€โ”€ Cargo.toml               # Rust dependencies and metadata
โ”œโ”€โ”€ Cargo.lock               # Dependency lock file
โ”œโ”€โ”€ .env                     # Environment variables (API keys)
โ””โ”€โ”€ README.md                # This file!

๐Ÿงฑ Architecture Pattern

Pattern: Event-Driven GUI with Asynchronous AI Backend

Think of it like a restaurant:

  • Frontend (GUI) = The dining room where customers interact
  • Backend (AI Engine) = The kitchen where magic happens
  • Event Loop = The waiters taking orders and delivering food
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    USER INTERFACE (egui)                     โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”‚
โ”‚  โ”‚  Terminal  โ”‚  โ”‚   Input Box  โ”‚  โ”‚  Autocomplete    โ”‚    โ”‚
โ”‚  โ”‚   Display  โ”‚  โ”‚   + Cursor   โ”‚  โ”‚   Suggestions    โ”‚    โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ†“ โ†‘
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                   TERMINAL LOGIC (main.rs)                   โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚  โ”‚   Command    โ”‚  โ”‚  Directory  โ”‚  โ”‚   Clipboard     โ”‚   โ”‚
โ”‚  โ”‚   Parsing    โ”‚  โ”‚  Management โ”‚  โ”‚   Operations    โ”‚   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ†“ โ†‘
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                 AI ASSISTANT (ai_assistant.rs)               โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚  โ”‚   Pattern    โ”‚  โ”‚  OpenRouter โ”‚  โ”‚   Gibberish     โ”‚   โ”‚
โ”‚  โ”‚   Matching   โ”‚  โ”‚  API Client โ”‚  โ”‚   Detection     โ”‚   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ†“ โ†‘
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚              EXTERNAL SYSTEMS                                โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚  โ”‚  OpenRouter  โ”‚  โ”‚    System   โ”‚  โ”‚   File System   โ”‚   โ”‚
โ”‚  โ”‚     API      โ”‚  โ”‚   Commands  โ”‚  โ”‚                 โ”‚   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿ”„ Data Flow: Input โ†’ Process โ†’ Output

Simple Version:

You type "list files" 
โ†’ Terminal checks if it's a known pattern (YES! "list files" = "ls")
โ†’ Executes "ls" command
โ†’ Shows output on screen

Complex Version (AI-assisted):

You type "show me what's in config.txt"
โ†’ Terminal checks local patterns (no match)
โ†’ Sends to AI Assistant
โ†’ AI converts to "view config.txt"
โ†’ Terminal validates command
โ†’ Executes command
โ†’ Shows file contents with line numbers

๐Ÿ”— Component Interactions

  1. User Types Input โ†’ TerminalApp::update() captures keystrokes
  2. Enter Pressed โ†’ execute_command() parses input
  3. Is it a command? โ†’ Execute directly via std::process::Command
  4. Is it natural language? โ†’ Send to AIAssistant::generate_command()
  5. AI Processing:
    • Check gibberish filter
    • Check local pattern cache
    • Check 5-minute response cache
    • Make API call to OpenRouter
    • Validate response
  6. Execute Translated Command โ†’ run_command_and_render()
  7. Display Results โ†’ Add lines to terminal output

๐Ÿงฉ Core Working Logic

๐Ÿšฆ Main Entry Point: main()

What happens when you run cargo run?

fn main() -> Result<(), eframe::Error> {
    // 1. Load environment variables from .env file
    dotenvy::dotenv().ok();
    
    // 2. Configure the window
    let options = eframe::NativeOptions {
        viewport: egui::ViewportBuilder::default()
            .with_inner_size([1000.0, 700.0])
            .with_title("Linara Terminal"),
        ..Default::default()
    };

    // 3. Launch the GUI application
    eframe::run_native(
        "Terminal",
        options,
        Box::new(|cc| {
            // Set dark theme
            cc.egui_ctx.set_visuals(egui::Visuals::dark());
            Ok(Box::new(TerminalApp::new()))
        }),
    )
}

Step-by-step breakdown:

  1. Load secrets from .env (API key, model name)
  2. Create window with 1000x700 pixels
  3. Apply dark theme for terminal aesthetics
  4. Initialize TerminalApp which contains all the logic
  5. Start event loop that listens for user input

๐ŸŽจ Terminal Initialization: TerminalApp::new()

What happens when the terminal starts?

impl TerminalApp {
    fn new() -> Self {
        // 1. Get current directory
        let current_dir = env::current_dir().to_string_lossy().to_string();
        
        // 2. Get user info
        let username = env::var("USER").unwrap_or("user".to_string());
        let hostname = get_hostname();
        
        // 3. Initialize data structures
        let mut app = Self {
            lines: VecDeque::new(),          // Terminal output
            input_buffer: String::new(),      // What you're typing
            cursor_pos: 0,                    // Where cursor is
            command_history: Vec::new(),      // Previous commands
            common_commands: vec![...],       // 200+ common commands
            ai: AIAssistant::new(),           // AI engine
            rt: tokio::runtime::Runtime::new(), // Async runtime
            // ... more fields
        };
        
        // 4. Scan system for available commands
        app.scan_path_commands();
        
        // 5. Show welcome message
        app.add_system_info();
        
        // 6. Show first prompt
        app.show_prompt();
        
        app
    }
}

Think of it like setting up a workspace:

  • ๐Ÿ“ Find where you are (current directory)
  • ๐Ÿ‘ค Know who you are (username/hostname)
  • ๐Ÿ“ Prepare notepad (terminal lines buffer)
  • ๐Ÿ” Scan available tools (system commands)
  • ๐Ÿ‘‹ Say hello (welcome message)
  • โ–ถ๏ธ Ready for input (show prompt)

โŒจ๏ธ Input Processing: How Commands are Handled

When you type and press Enter:

User Input: "list all files"
    โ†“
Step 1: Is it a built-in command? (help, clear, cd, exit, etc.)
    โ†“ NO
Step 2: Is it a direct system command? (ls, git, python, etc.)
    โ†“ NO
Step 3: Is it instant-pattern-matched? ("list all files" โ†’ "ls -la")
    โ†“ YES!
Step 4: Execute "ls -la"
    โ†“
Step 5: Capture output
    โ†“
Step 6: Display in terminal

Code flow:

fn execute_command(&mut self, command: &str) {
    let parts = self.parse_command_with_quotes(command);
    let cmd_name = parts[0];
    let args = parts[1..];
    
    // Built-in commands
    match cmd_name {
        "help" => self.show_help(),
        "clear" => self.lines.clear(),
        "cd" => self.change_directory(&args),
        "exit" => std::process::exit(0),
        _ => {
            // External command - try to execute
            let output = Command::new(&cmd_name)
                .args(&args)
                .current_dir(&self.current_dir)
                .output();
            
            match output {
                Ok(result) => self.display_output(result),
                Err(_) => {
                    // Not found! Try AI interpretation
                    let ai_result = self.ai.generate_command(command);
                    self.execute_ai_suggested_command(ai_result);
                }
            }
        }
    }
}

๐ŸŒ API Integration

๐Ÿ”‘ OpenRouter API Configuration

What is OpenRouter? OpenRouter is a unified API gateway that provides access to multiple AI models. We use Google's Gemini 2.0 Flash Experimental (free tier) to convert natural language to shell commands.

API Details:

  • Endpoint: https://openrouter.ai/api/v1/chat/completions
  • Model: google/gemini-2.0-flash-exp:free
  • Context Window: 1,048,576 tokens (1M!)
  • Cost: $0.00 (Free tier with rate limits)
  • Authentication: Bearer token (API key)

๐Ÿ“ก How API Calls Work

Request Structure:

{
  "model": "google/gemini-2.0-flash-exp:free",
  "messages": [
    {
      "role": "system",
      "content": "You are a helpful assistant that converts natural language to Linux commands."
    },
    {
      "role": "user",
      "content": "Convert natural language to Linux command. Return ONLY the command.\n\nInput: list all files\nOutput:"
    }
  ]
}

Response Structure:

{
  "choices": [
    {
      "message": {
        "role": "assistant",
        "content": "ls -la"
      }
    }
  ]
}

๐Ÿ”„ Smart Caching & Optimization

Three-Layer Performance Optimization:

Layer 1: INSTANT PATTERNS (0ms)
โ”œโ”€ "list files" โ†’ "ls"
โ”œโ”€ "go home" โ†’ "cd ~"
โ””โ”€ "clear screen" โ†’ "clear"

Layer 2: RESPONSE CACHE (5-minute TTL)
โ”œโ”€ "create folder test" โ†’ "mkdir test" (cached for 5 min)
โ””โ”€ "remove old-data" โ†’ "rm -r old-data" (cached for 5 min)

Layer 3: AI API CALL (500-2000ms)
โ””โ”€ Novel/complex requests go to OpenRouter

Code implementation:

pub async fn generate_command(&self, input: &str) -> Result<String> {
    // LAYER 1: Instant patterns (local HashMap lookup)
    if let Some(cmd) = self.get_local_command(input) {
        return Ok(cmd); // Returns in <1ms!
    }
    
    // LAYER 2: Check 5-minute cache
    if let Some(cached) = self.get_cached_response(input) {
        return Ok(cached); // Returns in <1ms!
    }
    
    // LAYER 3: Make API call
    let response = self.client
        .post(OPENROUTER_URL)
        .header("Authorization", format!("Bearer {}", api_key))
        .json(&request)
        .send()
        .await?;
    
    let command = extract_command_from_response(response);
    
    // Cache for future use
    self.cache_response(input, &command);
    
    Ok(command)
}

๐Ÿ›ก๏ธ Retry Logic & Error Handling

Transient errors (network issues, rate limits) are automatically retried:

// Retry up to 3 times with exponential backoff
for attempt in 0..3 {
    match self.client.post(OPENROUTER_URL).send().await {
        Ok(response) if response.status() == 429 => {
            // Rate limited - wait and retry
            let backoff_ms = match attempt {
                0 => 300,   // First retry: 300ms
                1 => 800,   // Second retry: 800ms
                _ => 0
            };
            sleep(Duration::from_millis(backoff_ms)).await;
            continue; // Try again
        }
        Ok(response) => return Ok(response), // Success!
        Err(e) => last_error = e, // Network error - retry
    }
}

// All retries failed
Err(last_error)

User-friendly error messages:

if error.contains("429") || error.contains("rate-limited") {
    show_message("๐Ÿšฆ You're being rate-limited by the free model.");
    show_message("   โ€ข Wait a few seconds and try again");
    show_message("   โ€ข Or add your own OpenRouter key");
} else if error.contains("timeout") {
    show_message("โฐ AI timed out. Try again.");
} else {
    show_message(&format!("โŒ Error: {}", error));
}

๐Ÿ” Function-by-Function Guide

๐Ÿ“ฆ Main Module (main.rs)

1๏ธโƒฃ TerminalApp::new() - Constructor

Purpose: Initialize the entire terminal application with all necessary components.

What it does:

  • Gets current directory and user info
  • Initializes all data structures (output buffer, history, etc.)
  • Loads 200+ common command names
  • Scans system PATH for available executables
  • Creates AI assistant instance
  • Shows welcome banner

Analogy: Like a chef preparing their kitchen before opening the restaurant.

fn new() -> Self {
    // Get environment info
    let current_dir = env::current_dir().to_string_lossy().to_string();
    let username = env::var("USER").unwrap_or("user".to_string());
    
    // Create terminal with empty state
    let mut app = Self {
        lines: VecDeque::new(),
        input_buffer: String::new(),
        command_history: Vec::new(),
        ai: AIAssistant::new(),
        // ...
    };
    
    // Setup autocomplete database
    app.scan_path_commands();
    
    // Show welcome
    app.add_system_info();
    app.show_prompt();
    
    app
}

2๏ธโƒฃ update() - Main Event Loop

Purpose: Called 60 times per second to render the UI and handle input.

Parameters:

  • &mut self - Mutable reference to terminal state
  • ctx: &egui::Context - GUI rendering context
  • _frame: &mut eframe::Frame - Window frame

What it does:

  • Renders terminal output lines
  • Processes keyboard input (Enter, Backspace, arrows)
  • Handles clipboard operations (Ctrl+C/V/X)
  • Manages cursor blinking animation
  • Updates autocomplete suggestions

Analogy: Like a movie running at 60 frames per second, constantly checking "what's new?"

fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
    // Request continuous repainting for cursor blink
    ctx.request_repaint_after(Duration::from_millis(500));
    
    egui::CentralPanel::default().show(ctx, |ui| {
        // Display all output lines
        for line in &self.lines {
            ui.label(&line.text);
        }
        
        // Handle keyboard input
        if ctx.input(|i| i.key_pressed(Key::Enter)) {
            self.execute_command(&self.input_buffer.clone());
        }
        
        if ctx.input(|i| i.key_pressed(Key::Backspace)) {
            self.input_buffer.pop();
        }
        
        // Handle clipboard
        if ctx.input(|i| i.modifiers.ctrl && i.key_pressed(Key::C)) {
            self.copy_to_clipboard();
        }
    });
}

3๏ธโƒฃ execute_command() - Command Router

Purpose: Central hub that decides how to handle user input.

Parameters:

  • &mut self - Terminal state
  • command: &str - Raw input from user

Returns: Nothing (mutates state, displays output)

Decision tree:

Is it "help"? โ†’ Show help menu
Is it "clear"? โ†’ Clear screen
Is it "cd"? โ†’ Change directory
Is it "exit"? โ†’ Close program
Is it executable? โ†’ Run it
Command not found? โ†’ Try AI interpretation

Code:

fn execute_command(&mut self, command: &str) {
    let parts = self.parse_command_with_quotes(command);
    let cmd_name = parts[0];
    
    match cmd_name {
        "help" => self.show_help(),
        "clear" => self.lines.clear(),
        "cd" => self.change_directory(&parts[1..]),
        "exit" => std::process::exit(0),
        _ => {
            // Try to execute as system command
            match Command::new(&cmd_name).args(&parts[1..]).output() {
                Ok(output) => self.display_output(output),
                Err(_) => {
                    // Not found - try AI
                    let ai_cmd = self.rt.block_on(
                        self.ai.generate_command(command)
                    );
                    self.execute_ai_command(ai_cmd);
                }
            }
        }
    }
}

4๏ธโƒฃ is_dangerous_command() - Safety Validator

Purpose: Protect users from accidentally destroying their system.

Parameters:

  • &self - Terminal reference
  • command: &str - Command to validate

Returns: Option<String> - Warning message if dangerous, None if safe

Dangerous patterns detected:

  • rm -rf / - Deletes entire filesystem
  • rm -rf ~ - Deletes home directory
  • :(){ :|:& };: - Fork bomb (crashes system)
  • mkfs - Formats disk (destroys data)
  • dd if= - Direct disk write

Example:

fn is_dangerous_command(&self, command: &str) -> Option<String> {
    let cmd_lower = command.to_lowercase();
    
    if cmd_lower.contains("rm -rf /") {
        return Some("โš ๏ธ CRITICAL: This would delete your ENTIRE system!");
    }
    
    if cmd_lower.contains(":(){ :|:& };:") {
        return Some("โš ๏ธ Fork bomb detected! This would crash your system!");
    }
    
    None // Safe
}

5๏ธโƒฃ parse_command_with_quotes() - Smart Parser

Purpose: Split command into parts while respecting quoted strings.

Why needed? Simple split_whitespace() breaks on filenames with spaces:

  • โŒ rm "my file.txt" โ†’ ["rm", "\"my", "file.txt\""] (WRONG!)
  • โœ… rm "my file.txt" โ†’ ["rm", "my file.txt"] (CORRECT!)

Example:

fn parse_command_with_quotes(&self, command: &str) -> Vec<String> {
    let mut parts = Vec::new();
    let mut current = String::new();
    let mut in_quotes = false;
    
    for ch in command.chars() {
        match ch {
            '"' | '\'' if !in_quotes => in_quotes = true,
            '"' | '\'' if in_quotes => in_quotes = false,
            ' ' if !in_quotes => {
                if !current.is_empty() {
                    parts.push(current.clone());
                    current.clear();
                }
            }
            _ => current.push(ch),
        }
    }
    
    if !current.is_empty() {
        parts.push(current);
    }
    
    parts
}

Test cases:

Input: rm "my file.txt"
Output: ["rm", "my file.txt"]

Input: echo 'Hello World'
Output: ["echo", "Hello World"]

Input: ls -la /home
Output: ["ls", "-la", "/home"]

๐Ÿค– AI Assistant Module (ai_assistant.rs)

1๏ธโƒฃ AIAssistant::new() - AI Engine Constructor

Purpose: Create and configure the AI assistant with all optimizations.

What it sets up:

  • HTTP client with connection pooling (20 max connections, 60s keepalive)
  • 5-minute response cache (HashMap)
  • Local pattern dictionary (100+ instant commands)
  • Async communication channel

Think of it like: Building a super-fast delivery system with shortcuts!

pub fn new() -> Self {
    // Ultra-fast HTTP client
    let client = reqwest::Client::builder()
        .timeout(Duration::from_secs(5))
        .pool_max_idle_per_host(20)
        .tcp_keepalive(Duration::from_secs(60))
        .build()
        .expect("Failed to build HTTP client");
    
    // Instant-response patterns
    let mut local_commands = HashMap::new();
    local_commands.insert("list files", "ls");
    local_commands.insert("list all files", "ls -la");
    local_commands.insert("go home", "cd ~");
    // ... 100+ more patterns
    
    Self {
        client,
        cache: Arc::new(Mutex::new(HashMap::new())),
        local_commands,
    }
}

2๏ธโƒฃ is_gibberish() - Nonsense Filter

Purpose: Detect and reject random/meaningless input before making expensive API calls.

Detection strategies:

  1. Too short: Less than 2 characters
  2. No vowels: "sdfghj" has no vowels = gibberish
  3. Repeated characters: "aaaaa" or "asdasdasd"
  4. Uncommon patterns: "qweasd", "zxcfgh"
  5. Incoherent phrases: "how hello", "what is the"
  6. Short nonsense tokens: 3-5 letter words not in common word list

Example:

pub fn is_gibberish(input: &str) -> bool {
    let input = input.trim().to_lowercase();
    
    // Too short
    if input.len() < 2 { return true; }
    
    // Allow meaningful words
    let meaningful = ["open", "list", "show", "create", "remove"];
    if meaningful.iter().any(|&w| input.contains(w)) {
        return false;
    }
    
    // Check for single-word 3-5 letter nonsense
    let words: Vec<&str> = input.split_whitespace().collect();
    if words.len() == 1 {
        let word = words[0];
        if (3..=5).contains(&word.len()) {
            let common = ["list", "show", "open", "help", "view"];
            if !common.contains(&word) {
                return true; // "adsa", "qwer" = gibberish!
            }
        }
    }
    
    // Check vowel ratio
    let vowels = input.chars().filter(|&c| "aeiou".contains(c)).count();
    let consonants = input.chars().filter(|&c| c.is_alphabetic() && !"aeiou".contains(c)).count();
    
    if consonants > 0 && (vowels == 0 || consonants as f32 / vowels as f32 > 4.0) {
        return true; // "sdfghj" has no vowels
    }
    
    false
}

Test cases:

"adsa" โ†’ true (gibberish)
"qwer" โ†’ true (gibberish)
"sdfghj" โ†’ true (no vowels)
"list files" โ†’ false (valid)
"show me" โ†’ false (valid)

3๏ธโƒฃ generate_command() - Main AI Logic

Purpose: Convert natural language to shell commands using smart caching and AI.

Parameters:

  • &self - AI assistant reference
  • natural_input: &str - User's English request

Returns: Result<String, Error> - Shell command or error

Step-by-step flow:

Step 1: Check if gibberish
    โ†“ NO
Step 2: Check local patterns (instant)
    โ†“ NOT FOUND
Step 3: Check 5-minute cache
    โ†“ NOT FOUND
Step 4: Make API call to OpenRouter
    โ†“
Step 5: Parse JSON response
    โ†“
Step 6: Validate command
    โ†“
Step 7: Cache result
    โ†“
Step 8: Return command

Code with retry logic:

pub async fn generate_command(&self, natural_input: &str) -> Result<String> {
    // FILTER: Reject gibberish
    if Self::is_gibberish(natural_input) {
        return Err("I don't understand that input.");
    }
    
    // OPTIMIZATION 1: Instant patterns
    if let Some(cmd) = self.get_local_command(natural_input) {
        return Ok(cmd);
    }
    
    // OPTIMIZATION 2: Cache lookup
    if let Some(cached) = self.get_cached_response(natural_input) {
        return Ok(cached);
    }
    
    // LAST RESORT: API call with retry logic
    for attempt in 0..3 {
        let response = self.client
            .post(OPENROUTER_URL)
            .header("Authorization", format!("Bearer {}", api_key))
            .json(&request)
            .send()
            .await;
        
        match response {
            Ok(resp) if resp.status() == 200 => {
                let command = extract_command(resp);
                self.cache_response(natural_input, &command);
                return Ok(command);
            }
            Ok(resp) if resp.status() == 429 => {
                // Rate limited - retry with backoff
                sleep(Duration::from_millis(300 * (attempt + 1))).await;
                continue;
            }
            Err(e) => return Err(e),
        }
    }
    
    Err("Max retries exceeded")
}

4๏ธโƒฃ looks_like_valid_command() - Command Validator

Purpose: Ensure AI-generated response is actually an executable command, not hallucination.

Validation checks:

  1. Not empty
  2. Remove code fences (bash)
  3. First token is executable in PATH or known builtin
  4. Reject sentence-like patterns

Example:

fn looks_like_valid_command(command: &str) -> bool {
    let cleaned = command
        .trim_start_matches("```bash")
        .trim_start_matches("```")
        .trim_end_matches("```")
        .trim();
    
    let first_token = cleaned.split_whitespace().next().unwrap_or("");
    
    // Allow known builtins
    if ["cd", "cursor", "code"].contains(&first_token) {
        return true;
    }
    
    // Check if executable exists in PATH
    if let Ok(path) = env::var("PATH") {
        for dir in path.split(':') {
            let exe_path = Path::new(dir).join(first_token);
            if exe_path.is_file() && is_executable(&exe_path) {
                return true;
            }
        }
    }
    
    false
}

Test cases:

"ls -la" โ†’ true (ls is in PATH)
"cd /home" โ†’ true (builtin)
"cursor ." โ†’ true (allowlist)
"this is a sentence" โ†’ false (not executable)
"Hello world" โ†’ false (not a command)

๐Ÿง  Step-by-Step Execution Flow

๐Ÿ“– Complete User Journey

Let's trace what happens when you type "view hai.py" and press Enter:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ 1. USER TYPES: "view hai.py"                            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                        โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ 2. GUI CAPTURES INPUT (update function)                 โ”‚
โ”‚    - Every keystroke updates input_buffer               โ”‚
โ”‚    - Enter key detected โ†’ trigger execute_command()     โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                        โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ 3. PARSE COMMAND (parse_command_with_quotes)            โ”‚
โ”‚    Result: ["view", "hai.py"]                           โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                        โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ 4. CHECK BUILT-IN COMMANDS                              โ”‚
โ”‚    "view" โ†’ Not in [help, clear, cd, exit, pwd]         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                        โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ 5. TRY SYSTEM COMMAND                                   โ”‚
โ”‚    Command::new("view").arg("hai.py") โ†’ NOT FOUND!      โ”‚
โ”‚    (view is not a standard Linux command)               โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                        โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ 6. CHECK INSTANT PATTERNS                               โ”‚
โ”‚    AIAssistant::get_instant_command("view hai.py")      โ”‚
โ”‚    โ†’ No instant match                                   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                        โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ 7. AI INTERPRETATION                                    โ”‚
โ”‚    - Check gibberish: "view hai.py" โ†’ VALID             โ”‚
โ”‚    - Check local patterns: "view file" โ†’ "view"         โ”‚
โ”‚    - Pattern matched! Return "view hai.py"              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                        โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ 8. VALIDATE AI RESPONSE                                 โ”‚
โ”‚    - Not dangerous command โœ“                            โ”‚
โ”‚    - Looks executable โœ“                                 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                        โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ 9. EXECUTE "view hai.py" (Built-in handler)             โ”‚
โ”‚    - Check if file exists                               โ”‚
โ”‚    - Read file contents                                 โ”‚
โ”‚    - Add line numbers                                   โ”‚
โ”‚    - Detect syntax (Python)                             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                        โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ 10. DISPLAY OUTPUT                                      โ”‚
โ”‚     ๐Ÿ“„ hai.py (Python, 45 bytes)                        โ”‚
โ”‚     โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€                    โ”‚
โ”‚     1 | print("Hello World")                            โ”‚
โ”‚     2 | x = 42                                          โ”‚
โ”‚     3 | print(f"The answer is {x}")                     โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                        โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ 11. UPDATE TERMINAL STATE                               โ”‚
โ”‚     - Add output lines to display buffer                โ”‚
โ”‚     - Save "view hai.py" to command history             โ”‚
โ”‚     - Clear input buffer                                โ”‚
โ”‚     - Show new prompt                                   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿ”ฅ Hot Path: Instant Command (< 1ms)

Example: "list files"

Input: "list files"
    โ†“
get_instant_command() lookup
    โ†“
HashMap["list files"] = "ls"
    โ†“
Execute "ls" directly
    โ†“
Display results
    
Total time: < 1 millisecond!

๐ŸŒ Slow Path: API Call (500-2000ms)

Example: "show me what's in config.txt"

Input: "show me what's in config.txt"
    โ†“
Not in instant patterns
    โ†“
Not in 5-minute cache
    โ†“
Make API call to OpenRouter
    โ†“ (500-2000ms network delay)
Parse JSON: "view config.txt"
    โ†“
Validate command
    โ†“
Cache for 5 minutes
    โ†“
Execute "view config.txt"
    โ†“
Display file contents

Total time: ~1 second (first time)
Next time: < 1ms (cached!)

๐Ÿ—‚๏ธ Dependencies & Setup

๐Ÿ“ฆ Required Dependencies

Crate Version Purpose
eframe 0.28 GUI framework (windowing, rendering)
egui 0.28 Immediate-mode GUI library
tokio 1.0 Async runtime for concurrent operations
reqwest 0.12 HTTP client for API calls
serde 1.0 JSON serialization/deserialization
dotenvy 0.15 Environment variable loading from .env
anyhow 1.0 Error handling utilities

Why each one?

  • eframe/egui: Modern, lightweight GUI that doesn't need Qt/GTK
  • tokio: Enables non-blocking API calls (terminal stays responsive)
  • reqwest: Industry-standard HTTP client with connection pooling
  • serde: Parse JSON responses from OpenRouter API
  • dotenvy: Keep API keys secure in .env file (not hardcoded)

๐Ÿ› ๏ธ Installation & Setup

Prerequisites

# Install Rust (if not already installed)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Verify installation
rustc --version  # Should show 1.70+
cargo --version

Step 1: Clone Repository

git clone https://github.com/zoxilsi/Linara-Terminal.git
cd Linara-Terminal

Step 2: Configure API Key

Create .env file in project root:

# .env file
OPENROUTER_API_KEY=sk-or-v1-YOUR_API_KEY_HERE
OPENROUTER_MODEL=google/gemini-2.0-flash-exp:free

Get your API key:

  1. Visit https://openrouter.ai/
  2. Sign up (free)
  3. Go to Settings โ†’ Keys
  4. Create new key
  5. Copy to .env file

Step 3: Build & Run

# Debug build (faster compile, slower runtime)
cargo build
cargo run

# Release build (slower compile, optimized runtime)
cargo build --release
./target/release/terminal-app

Expected output:

    Compiling terminal-app v0.1.0
    Finished dev [unoptimized + debuginfo] target(s) in 45.2s
     Running `target/debug/terminal-app`

Then the GUI window opens! ๐ŸŽ‰

๐Ÿณ Docker Setup (Optional)

FROM rust:1.70

WORKDIR /app
COPY . .

RUN cargo build --release

CMD ["./target/release/terminal-app"]

๐Ÿš€ Usage Examples

๐ŸŽฏ Basic Commands

# Traditional way
ls -la

# Natural language way
list all files
show me all files
what files are here

๐Ÿ“ File Operations

# View file contents
view config.txt
show me what's in README.md
read package.json

# Create directories
mkdir test-folder
create folder my-project
make directory data

# Remove files/folders
rm old-file.txt
remove folder old-project
delete file temp.log

๐Ÿงญ Navigation

# Change directory
cd /home/user/projects
go to home
go back
go up

# Show location
pwd
where am i
current location

๐Ÿ” Search & Info

# Find files
find . -name "*.py"
search for python files

# Git operations
git status
git add .
git commit -m "Update"
show me git status

๐ŸŽจ Terminal Management

# Clear screen
clear
clear screen
clean terminal

# View history
history
show command history

# Get help
help
explain ls
what is grep

โšก Copy/Paste

Ctrl+C โ†’ Copy selected text (or current line)
Ctrl+V โ†’ Paste from clipboard
Ctrl+X โ†’ Cut selected text
Shift+Arrows โ†’ Select text

๐ŸŽฌ Real Demo Session

๐Ÿ  user ๐Ÿ“‚ ~/projects ๐ŸŒฟ main
> list all files
โšก ls -la
total 48
drwxr-xr-x  6 user user 4096 Oct  5 10:30 .
drwxr-xr-x 12 user user 4096 Oct  5 09:15 ..
-rw-r--r--  1 user user  256 Oct  5 10:25 config.txt
drwxr-xr-x  8 user user 4096 Oct  5 10:30 .git

๐Ÿ  user ๐Ÿ“‚ ~/projects ๐ŸŒฟ main
> view config.txt
๐Ÿ“„ config.txt (Text, 256 bytes)
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
1 | app_name=MyApp
2 | version=1.0.0
3 | debug=true

๐Ÿ  user ๐Ÿ“‚ ~/projects ๐ŸŒฟ main
> create folder test
โšก mkdir test
โœ… Command executed successfully

๐Ÿ  user ๐Ÿ“‚ ~/projects ๐ŸŒฟ main
> go to test
โœ… Directory changed

๐Ÿ  user ๐Ÿ“‚ .../projects/test ๐ŸŒฟ main
>

๐Ÿ’ก Teaching Explanation (ELI5)

๐Ÿ• The Pizza Delivery Analogy

Imagine you're ordering pizza, but you don't speak "pizza language" fluently. Linara Terminal is like having a smart translator!

Traditional Terminal (No Translator):

You: "I want a large pepperoni pizza"
Terminal: "Error: command not found"
You: ๐Ÿ˜ข *has to learn the exact code: ORDER_PIZZA --size=L --topping=pepperoni*

Linara Terminal (With AI Translator):

You: "I want a large pepperoni pizza"
Translator: "Oh! You mean: ORDER_PIZZA --size=L --topping=pepperoni"
Terminal: "โœ… Pizza ordered!"
You: ๐Ÿ˜Š

๐Ÿ—๏ธ How It Works (Kids Version)

Think of it like a LEGO building system:

  1. The Window (GUI) = The building table where you see everything
  2. Your Words (Input) = The LEGO pieces you want to use
  3. The Smart Helper (AI) = Friend who knows which pieces to use
  4. The Computer (System) = The instruction manual that builds stuff

Story Example:

You say: "Show me my toys"

  1. Window hears you
  2. Smart Helper thinks: "Hmm, 'show toys' = look in the toy box"
  3. Smart Helper says: "Use the ls command!" (like saying "open toy box")
  4. Computer opens the toy box
  5. Window shows you: ๐Ÿš— ๐Ÿงธ ๐ŸŽฎ ๐ŸŽจ

๐ŸŽญ The Three Magic Tricks

Trick 1: The Memory Shortcut (Cache)

  • If you ask the same question twice, it remembers the answer!
  • Like asking "Where are my shoes?" โ†’ Mom remembers you left them by the door

Trick 2: The Pattern Book (Local Commands)

  • Common phrases have instant translations
  • "list files" always means "ls" (like "hello" always means ๐Ÿ‘‹)

Trick 3: The Smart Brain (AI API)

  • For new questions, asks a super-smart robot (Gemini AI)
  • Robot knows EVERY command in existence!

๐Ÿ” The Safety Guard

Like a parent saying "Don't touch the hot stove!"

If you try dangerous commands:

You: "delete everything"
Safety Guard: "โš ๏ธ STOP! That would delete your whole computer!"
Terminal: *blocks the command*

Protected from:

  • Deleting important files
  • Breaking your system
  • Typing gibberish that makes no sense

๐Ÿ”ง Extension Ideas

๐Ÿš€ Performance Improvements

  1. Command Prediction

    • Analyze history to predict next command
    • Pre-fetch autocomplete suggestions in background
  2. Smarter Caching

    • Increase cache TTL to 30 minutes
    • Add persistent cache (save to disk)
  3. Parallel Execution

    • Run multiple commands simultaneously
    • Background tasks with progress bars

๐ŸŽจ UI Enhancements

  1. Syntax Highlighting

    • Color code different command parts
    • Highlight errors in red
  2. Themes

    • Light/dark mode toggle
    • Custom color schemes (Dracula, Monokai, etc.)
  3. Split Panes

    • Multiple terminals in one window
    • Tabs for different sessions

๐Ÿค– AI Enhancements

  1. Multi-Model Support

    • Switch between GPT-4, Claude, Gemini
    • Fallback to backup model if primary fails
  2. Context Awareness

    • Remember previous commands in conversation
    • "do it again" = repeat last command
  3. Error Auto-Fix

    • Detect command errors
    • Suggest corrections automatically

๐Ÿ”’ Security Features

  1. Command Whitelist

    • Admin approval for dangerous commands
    • Sandboxed execution mode
  2. Audit Logging

    • Track all executed commands
    • Export to file for review
  3. Encrypted Secrets

    • Store API keys in system keyring
    • Auto-rotate credentials

๐ŸŒ Integration Features

  1. Cloud Sync

    • Sync history across devices
    • Share command aliases with team
  2. Plugin System

    • Custom command handlers
    • Third-party extensions
  3. Remote Execution

    • SSH into servers
    • Execute commands on multiple machines

๐Ÿ“Š Advanced Features

  1. Command Metrics

    • Track most-used commands
    • Time each command execution
  2. AI Training

    • Fine-tune model on your command history
    • Personalized command suggestions
  3. Script Generator

    • Convert command sequences to bash scripts
    • One-click script export

๐Ÿค Contributing

We welcome contributions! Here's how to get started:

๐Ÿ› Report Bugs

  1. Check existing issues
  2. Create new issue with:
    • Steps to reproduce
    • Expected vs actual behavior
    • Terminal output / screenshots

โœจ Suggest Features

  1. Open discussion in Issues
  2. Describe use case
  3. Propose implementation approach

๐Ÿ”จ Submit Pull Requests

  1. Fork the repository
  2. Create feature branch: git checkout -b feature/amazing-feature
  3. Make changes
  4. Test thoroughly
  5. Commit: git commit -m "Add amazing feature"
  6. Push: git push origin feature/amazing-feature
  7. Open Pull Request

๐Ÿ“ Code Style

  • Follow Rust conventions (cargo fmt)
  • Run linter (cargo clippy)
  • Add tests for new features
  • Update documentation

๐Ÿ“„ License

MIT License - See LICENSE file for details.


๐Ÿ™ Acknowledgments

  • egui - Amazing immediate-mode GUI framework
  • OpenRouter - Unified API gateway for AI models
  • Google Gemini - Powerful language model
  • Rust Community - Best programming community ever!

๐Ÿ“ž Support


Made with โค๏ธ and ๐Ÿฆ€ Rust

โญ Star this repo if you find it useful!

Report Bug ยท Request Feature

# Development milestone: Initial project setup # Feature: Basic GUI implementation # Testing framework setup # Bug fixes and stability

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published