# Project export: natural-code

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: Cal Hacks 12.0
- Tagline: write in natural language, run as real code.
- Devpost: https://devpost.com/software/natural-code
- GitHub: https://github.com/Idhant297/natural-code
- Video: https://player.vimeo.com/video/1130691205?byline=0&portrait=0&title=0#t=
- Team: 2 GitHub contributor(s) — idhant (9 commits), Rudraksh Awasthi (1 commits)

## Devpost submission (written by the team)

### Overview

natural-code bridges the gap between human thought and executable software. our mission is to make programming accessible to everyone, regardless of their technical background or experience with traditional programming languages. we've built a language-agnostic framework that transforms your ideas into working code. simply describe what you want to build using natural language—your preferred way of thinking and expressing logic—and we handle the translation to executable code in any target programming language. with recent breakthroughs in large language models, code generation has reached unprecedented levels of sophistication. natural code harnesses these capabilities to democratize software development. whether you're a seasoned developer looking to prototype faster or someone with no programming experience wanting to bring ideas to life, our tool adapts to your level and helps you create functional software.

### Inspiration

We believe that the future of programming does not involve the writing of code, but is more focused on the development of logic. Pseudocode is how we abstract programs and simplify logic, and natural-code converts pseudo into working program files that are straightforward, easy to understand, concise, and efficient.

### How we built it

The project has 3 main components. The CLI interface validates .n files and orchestrates code generation through the Claude Code using GROQ's openai/gpt-oss-120b model. A diff tracking system monitors file changes with MD5 hashing and respects .gitignore patterns, providing context for incremental updates. State is maintained in .state.json to track modifications between runs, enabling the AI to understand what changed and update only the changed parts so as to not use excessive resources or tokens. This also helps us better maintain context of the current state as opposed to generating new code every time.

### Challenges we ran into

Balancing AI context was challenging too, little caused inconsistent updates, too much overwhelmed the model. We solved this with targeted diff tracking. Managing background processes with simultaneous output streaming and logging required careful subprocess handling. Implementing comprehensive .gitignore pattern matching proved more complex than expected, requiring support for globs, directory patterns, and edge cases.

### Accomplishments we're proud of

We built a tool that integrates seamlessly into existing workflows without special tooling. The intelligent diff system helps the AI make better decisions, while the .n extension pattern makes the system truly language-agnostic. Despite coordinating AI APIs, file I/O, and subprocess management, we maintained clean, readable code with production-ready logging.

### What we learned

Context quality directly determines AI output quality—our diff tracking was crucial for this. We learned how LLMs excel at pattern recognition but require careful context management. Small UX details like showing PIDs and log paths significantly improve CLI usability. State management across file operations taught us to handle edge cases carefully.

## README (from the GitHub repository)

![nrun](nrun.png)
# natural run


`natural-code` bridges the gap between human thought and executable software. our mission is to make programming accessible to everyone, regardless of their technical background or experience with traditional programming languages.

we've built a language-agnostic framework that transforms your ideas into working code. simply describe what you want to build using natural language—your preferred way of thinking and expressing logic—and we handle the translation to executable code in any target programming language.

with recent breakthroughs in large language models, code generation has reached unprecedented levels of sophistication. natural code harnesses these capabilities to democratize software development. whether you're a seasoned developer looking to prototype faster or someone with no programming experience wanting to bring ideas to life, our tool adapts to your level and helps you create functional software.

**write naturally. build anything.** — let the code follow your thoughts, not the other way around.

## usage
```bash
nrun <filename>.n<lang>
```
> we have came up with this custom file extension i.e `.n<lang>` and then this is converted into the target language code and then executed.

## setup

```bash
pip install uv (if not already installed)

git clone https://github.com/idhant297/natural-code.git
uv pip install natural-code/
```

## internal workings

### core flow

1. **input**: write your logic in `.n<lang>` files (e.g., `.npy` for python, `.njs` for javascript, `.ntsx` for typescript/react)
2. **transpilation**: run `nrun <filename>.n<lang>` to convert natural language to executable code via llm inference
3. **execution**: the generated code runs automatically with the appropriate interpreter

### change tracking

the system maintains a state of your codebase using file hashing:

- all files are hashed and stored in `.state.json`
- on each run, it generates a diff between current and previous states
- the transpiler receives these diffs to understand what changed
- this enables incremental updates rather than regenerating entire files

### key features

- **smart updates**: only modified portions of code are updated, preserving manual edits
- **gitignore support**: respects `.gitignore` patterns when tracking changes
- **session logging**: all transpilation runs are logged to `cli-logs/` for debugging
- **auto-execution**: automatically determines and runs the correct command for your generated code

## Detected evidence (automated analysis)

Indexed codebase: 10 recognized source files, 66 KB.
- Python (language) — detected in the code
- Java (language) — claimed on Devpost, not found in the code
- JavaScript (language) — claimed on Devpost, not found in the code
- React (technology) — claimed on Devpost, not found in the code
- TypeScript (language) — claimed on Devpost, not found in the code
- AI coding agent: Codex — evidence: config files committed to the repository

## Codebase structure (from repository index)

### Files (18 of 18)

```
.env-sample
.github/workflows/ci.yml
.gitignore
.python-version
AGENTS.md
cli-logs/.gitkeep
cli.py
command.py
diff.py
LICENSE
main.py
prompt.md
pyproject.toml
README.md
requirements.txt
test_main.py
tui.py
uv.lock
```

### Dependencies

- pyproject.toml: groq@>=0.12.0, pathlib@>=1.0.1, python-dotenv@>=1.1.1, rich@>=12.4.0, rich-cli@>=1.8.1

### Recent commits (newest first)

- added readme
- minor updates
- build ready
- added code exec support
- added intial terminal ui
- First README update
- updated
- updated diff and cli working
- minor changes
- added diff
- added codex cli w groq support
- init
- Initial commit

## Key source files (fetched from GitHub, selected and truncated for size)

### AGENTS.md

```markdown
# Natural Language Code Transpiler System

You are a specialized code transpiler that converts natural language code (NLC) files into their corresponding programming language implementations.

## Core Task
Transform natural language pseudocode files with the format `{filename}.n{language}` into executable code in the target language:
- `.npy` → Python (.py)
- `.njs` → JavaScript (.js)
- `.ntsx` → TypeScript/React (.tsx)
- `.njava` → Java (.java)
- `.ngo` → Go (.go)

> These are just some examples of sample natural language code files.

## CRITICAL RULE: File Creation Policy
**ONLY create files that the user explicitly provides**. If the user gives you `dashboard.ntsx`, you create ONLY `dashboard.tsx`. 
- DO NOT automatically generate helper files, component files, or utility files
- DO NOT create configuration files unless explicitly provided as `.n{ext}` files
- If the code references other files/modules that don't exist, import them as if they exist but DO NOT create them
- Only create multiple files when the user provides multiple `.n{language}` files

## Key Responsibilities

### 1. Single File Focus
- Transform ONLY the provided natural language file(s)
- Assume any referenced imports/modules exist externally
- Write imports for dependencies as if they exist (the user will create them if needed)
- Make the generated code as self-contained as possible within the file

### 2. Code Generation Rules
- Convert natural language descriptions into idiomatic code for the target language
- Preserve the intent and logic flow from the natural language version
- Add necessary imports (assume external dependencies exist)
- Follow best practices and conventions for each language
- Include inline helper functions rather than separate files when possible

### 3. Incremental Updates
When receiving diffs after subsequent runs:
- Apply only the changed portions to the existing generated code
- Maintain consistency within the file
- Preserve any manual optimizations unless explicitly overridden

## Example Transformations

### Example 1: Single React Component (No Extra Files)

**Input: `dashboard.ntsx`**
```
component Dashboard:
    state: 
        users = empty array
        loading = true
    
    when component loads:
        fetch users from "/api/users"
        set users to response
        set loading to false
    
    render:
        if loading show "Loading..."
        else show UserCard for each user
```

**Output: ONLY `dashboard.tsx` (No UserCard.tsx created!)**
```typescript
import React, { useState, useEffect } from 'react';
// Assuming UserCard exists elsewhere - imported but not created
import UserCard from './UserCard';

interface User {
    id: number;
    name: string;
    email: string;
}

const Dashboard: React.FC = () => {
    const [users, setUsers] = useState<User[]>([]);
    const [loading, setLoading] = useState<boolean>(true);
    
    useEffect(() => {
        const fetchUsers = async () => {
            try {
                const re
[truncated — 5197 more characters]
```

### prompt.md

```markdown
# Natural Language Code Transpiler System

You are a specialized code transpiler that converts natural language code (NLC) files into their corresponding programming language implementations.

## Core Task
Transform natural language pseudocode files with the format `{filename}.n{language}` into executable code in the target language:
- `.npy` → Python (.py)
- `.njs` → JavaScript (.js)
- `.ntsx` → TypeScript/React (.tsx)
- `.njava` → Java (.java)
- `.ngo` → Go (.go)

> These are just some examples of sample natural language code files.

## CRITICAL RULE: File Creation Policy
**ONLY create files that the user explicitly provides**. If the user gives you `dashboard.ntsx`, you create ONLY `dashboard.tsx`. 
- DO NOT automatically generate helper files, component files, or utility files
- DO NOT create configuration files unless explicitly provided as `.n{ext}` files
- If the code references other files/modules that don't exist, import them as if they exist but DO NOT create them
- Only create multiple files when the user provides multiple `.n{language}` files

## Key Responsibilities

### 1. Single File Focus
- Transform ONLY the provided natural language file(s)
- Assume any referenced imports/modules exist externally
- Write imports for dependencies as if they exist (the user will create them if needed)
- Make the generated code as self-contained as possible within the file

### 2. Code Generation Rules
- Convert natural language descriptions into idiomatic code for the target language
- Preserve the intent and logic flow from the natural language version
- Add necessary imports (assume external dependencies exist)
- Follow best practices and conventions for each language
- Include inline helper functions rather than separate files when possible

### 3. Incremental Updates
When receiving diffs after subsequent runs:
- Apply only the changed portions to the existing generated code
- Maintain consistency within the file
- Preserve any manual optimizations unless explicitly overridden

## Example Transformations

### Example 1: Single React Component (No Extra Files)

**Input: `dashboard.ntsx`**
```
component Dashboard:
    state: 
        users = empty array
        loading = true
    
    when component loads:
        fetch users from "/api/users"
        set users to response
        set loading to false
    
    render:
        if loading show "Loading..."
        else show UserCard for each user
```

**Output: ONLY `dashboard.tsx` (No UserCard.tsx created!)**
```typescript
import React, { useState, useEffect } from 'react';
// Assuming UserCard exists elsewhere - imported but not created
import UserCard from './UserCard';

interface User {
    id: number;
    name: string;
    email: string;
}

const Dashboard: React.FC = () => {
    const [users, setUsers] = useState<User[]>([]);
    const [loading, setLoading] = useState<boolean>(true);
    
    useEffect(() => {
        const fetchUsers = async () => {
            try {
                const re
[truncated — 5197 more characters]
```

### requirements.txt

```
# This file was autogenerated by uv via the following command:
#    uv export --output-file requirements.txt
# Test comment
```

### pyproject.toml

```
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[project]
name = "natural-code"
version = "0.1.0"
description = "A natural language code transpiler that converts .n<language> files into executable code"
readme = "README.md"
requires-python = ">=3.13"
license = "MIT"
authors = [
    {name = "Your Name", email = "your.email@example.com"}
]
keywords = ["transpiler", "natural-language", "code-generation", "ai", "llm"]
classifiers = [
    "Development Status :: 3 - Alpha",
    "Intended Audience :: Developers",
    "Topic :: Software Development :: Code Generators",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3.13",
]
dependencies = [
    "pathlib>=1.0.1",
    "python-dotenv>=1.1.1",
    "rich>=12.4.0",
    "rich-cli>=1.8.1",
    "groq>=0.12.0",
]

[project.urls]
Homepage = "https://github.com/idhant297/natural-code"
Repository = "https://github.com/idhant297/natural-code"
Issues = "https://github.com/idhant297/natural-code/issues"

[project.scripts]
nrun = "tui:main"

[tool.uv]
package = true

[tool.setuptools]
py-modules = ["tui", "cli", "diff", "command"]

[dependency-groups]
dev = [
    "pytest>=8.4.2",
    "ruff>=0.14.2",
]

```

### main.py

```python
def main():
    pass


if __name__ == "__main__":
    main()

```

### cli.py

```python
#!/usr/bin/env python3
"""CLI tool to run natural code files .n<language> files through codex"""

import sys
import os
import subprocess
import argparse
from pathlib import Path
from datetime import datetime
from dotenv import load_dotenv
from diff import main as diff_main

# Configuration: Set to False to hide codex output
SHOW_CODEX_OUTPUT = True

# Log directory
LOG_DIR = Path(__file__).parent / "cli-logs"

PROMPT_FILE = Path(__file__).parent / "prompt.md"


def read_prompt_file():
    """Read the contents of the prompt file"""
    with open(PROMPT_FILE, "r", encoding="utf-8") as f:
        return f.read()


def ensure_log_dir():
    """Create log directory if it doesn't exist"""
    LOG_DIR.mkdir(exist_ok=True)


def get_log_filepath(input_file):
    """Generate log file path based on input file and timestamp"""
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    input_filename = Path(input_file).stem
    log_filename = f"{input_filename}_{timestamp}.log"
    return LOG_DIR / log_filename


def load_env_file():
    """Load environment variables from .env file"""
    # Try current working directory first (where the user runs the command)
    env_path = Path.cwd() / ".env"
    if not env_path.exists():
        # Fall back to script directory (for development mode)
        env_path = Path(__file__).parent / ".env"

    if env_path.exists():
        load_dotenv(env_path)
    else:
        print(f"Warning: .env file not found at {env_path}", file=sys.stderr)


def read_natural_code_file(filepath):
    """Read the contents of a .n<language> file"""
    import re

    path = Path(filepath)

    if not path.exists():
        print(f"Error: File '{filepath}' not found", file=sys.stderr)
        sys.exit(1)

    # Extract language from .n<lang> extension
    match = re.search(r"\.n(\w+)$", filepath)
    if not match:
        print(
            "Error: File must have .n<language> extension (e.g., .npy, .njava, .njs)",
            file=sys.stderr,
        )
        sys.exit(1)

    # Language extracted but not currently used

    try:
        with open(path, "r", encoding="utf-8") as f:
            return f.read()
    except Exception as e:
        print(f"Error reading file: {e}", file=sys.stderr)
        sys.exit(1)


def cli_prompt(tagged_file):
    """
    Collect and construct the full prompt for codex.

    Args:
        prompt_file: Path to the natural code file
        additional_context: Optional additional context to include

    Returns:
        Fully formatted prompt string ready for codex
    """
    tagged_file = f"@{tagged_file}"

    # Get diff output without printing to stdout
    diff = diff_main(print_output=False)

    # Handle case where diff_main returns None
    if diff is None:
        diff = "No diff information available"

    # prompt = f"""{system_prompt}

    prompt = f"""Main file that the user is intended to run:
{tagged_file}

Changes that user has made since the last run of the code:
{diff}

Now please create the desired code file (if not already created) for the user to run and other necessary ones OR update the existing code file to the desired state."""

    return prompt


def run_codex(
    prompt, prompt_file, groq_api_key, log_file, show_output=SHOW_CODEX_OUTPUT
):
    """Run codex with the given prompt in the background"""
    if not groq_api_key:
        print("Error: GROQ_API key not found in .env file", file=sys.stderr)
        sys.exit(1)

    # Set up environment with GROQ_API_KEY
    env = os.environ.copy()
    env["GROQ_API_KEY"] = groq_api_key

    # Use the prompt that was passed in (already constructed by cli_prompt)
    full_prompt = prompt

    cmd = [
        "codex",
        "exec",
        "--profile",
        "groq",
        "--model",
        "openai/gpt-oss-120b",
        full_prompt,
    ]

    try:
        # Open log file for writing
        log_handle = open(log_file, "w", encoding="utf-8")

        # Write header to log file
        log_handle.write("=== Codex Execution Log ===\n")
        log_handle.write(f"Timestamp: {datetime.now().isoformat()}\n")
        log_handle.write(
            f"Prompt: {prompt[:100]}{'...' if len(prompt) > 100 else ''}\n"
        )
        log_handle.write(f"{'=' * 50}\n\n")
        log_handle.flush()

        # Determine output streams based on configuration
        if show_output:
            # Use Tee-like behavior: show on terminal AND write to log
            stdout_stream = subprocess.PIPE
            stderr_stream = subprocess.STDOUT
        else:
            # Only write to log file, don't show on terminal
            stdout_stream = log_handle
            stderr_stream = subprocess.STDOUT

        # Run codex in the background
        process = subprocess.Popen(
            cmd,
            env=env,
            stdout=stdout_stream,
            stderr=stderr_stream,
            stdin=subprocess.DEVNULL,
            text=True,
            bufsize=1,
        )

        # If showing output, we need to tee the output to both terminal and log file
        if show_output and stdout_stream == subprocess.PIPE:

            def tee_output():
                try:
                    for line in process.stdout:
                        print(line, end="")  # Print to terminal
                        log_handle.write(line)  # Write to log
                        log_handle.flush()
                    log_handle.close()
                except Exception as e:
                    print(f"Error in tee_output: {e}", file=sys.stderr)

            import threading

            tee_thread = threading.Thread(target=tee_output, daemon=True)
            tee_thread.start()

        print(f"process started (PID: {process.pid})")
        print(f"Log file: {log_file}")
        return process.pid

    except FileNotFoundError:
        print(
            "Error: 'codex' command not found. Make sure codex CLI is installed.",
            file=sys.stderr,
        )
        sys.exit(1)
    except Exception as e:
       
[truncated — 4032 more characters]
```

### test_main.py

```python
from main import main


def test_main_runs_without_error():
    """Test that main function runs without raising exceptions."""
    # This should not raise any exceptions
    main()


def test_main_module_imports():
    """Test that the main module can be imported."""

    # assert hasattr(main, "main")

```

### command.py

```python
#!/usr/bin/env python3
"""
Terminal Command Generator using Groq API
Generates the terminal command to run the transpiled code
"""

import os
import re
from groq import Groq
from dotenv import load_dotenv


def generate_run_command(file_path, changes_summary):
    """
    Generate terminal command to run the transpiled code using Groq inference.

    Args:
        file_path: Original .n<lang> file path (e.g., "hello.npy")
        changes_summary: Git diff summary showing what files were created/modified

    Returns:
        dict: {
            "success": bool,
            "command": str,
            "error": str
        }
    """
    # Load environment and get API key
    load_dotenv()
    api_key = os.getenv("GROQ_API")

    if not api_key:
        return {
            "success": False,
            "command": None,
            "error": "GROQ_API key not found in .env",
        }

    # Build prompt for Groq
    prompt = f"""Generate the terminal command to run the transpiled code.

Original file: {file_path}
(e.g., if original is "hello.npy", the transpiled file will be "hello.py")

Changes made by the transpiler:
{changes_summary[:600]}

Your task: Generate the exact terminal command to run the main transpiled file.

Examples:
- If original: hello.npy → command: python hello.py
- If original: server.njs → command: node server.js
- If original: app.ngo → command: go run app.go
- If original: main.nts → command: tsx main.ts

Return ONLY the terminal command in this format:
```bash
<command>
```
"""

    try:
        # Call Groq API
        client = Groq(api_key=api_key)

        system_prompt = """You are a terminal command expert for a natural code transpiler system.

The system works like this:
- Users write code in .n<language> files (e.g., .npy for Python, .njs for JavaScript)
- The transpiler converts these to actual runnable code files
- Your job: Generate the EXACT terminal command to run the transpiled file

Rules:
1. The transpiled file name = original filename with 'n' removed from extension
   - hello.npy → hello.py → command: python hello.py
   - server.njs → server.js → command: node server.js
   - app.njava → app.java → command: java app (for Java, no extension)

2. Use the appropriate runtime/interpreter:
   - .py → python or python3
   - .js → node
   - .java → javac <file_name>.java && java <file_name>
   - .go → go run
   - .ts/.tsx → tsx or ts-node
   - .rb → ruby
   - .php → php
   
   NOTE: the command should be self contained and should NOT any further steps to run the code.

3. Return ONLY the command in this format:
   ```bash
   <command>
   ```

Do NOT add explanations, do NOT add extra text. ONLY the command in a bash code block."""

        response = client.chat.completions.create(
            messages=[
                {"role": "system", "content": system_prompt},
                {"role": "user", "content": prompt},
            ],
            model="llama-3.3-70b-versatile",
            temperature=0.1,
            max_tokens=100,
        )

        # Parse command from response
        raw_output = response.choices[0].message.content.strip()
        command = parse_bash_block(raw_output)

        if not command:
            return {
                "success": False,
                "command": None,
                "error": "Empty command generated",
            }

        return {"success": True, "command": command, "error": None}

    except Exception as e:
        return {"success": False, "command": None, "error": f"Groq API error: {str(e)}"}


def parse_bash_block(raw_output):
    """
    Parse command from Groq output in format:
    ```bash
    <command>
    ```
    """
    # Extract content between ```bash and ```
    match = re.search(r"```bash\s*\n(.+?)\n```", raw_output, re.DOTALL)
    if match:
        return match.group(1).strip().split("\n")[0].strip()

    # Fallback: try generic code block
    match = re.search(r"```\s*\n(.+?)\n```", raw_output, re.DOTALL)
    if match:
        return match.group(1).strip().split("\n")[0].strip()

    # Fallback: use raw output first line
    return raw_output.strip().split("\n")[0].strip()

```

### diff.py

```python
import json
import hashlib
import fnmatch
from pathlib import Path
import difflib


def get_hash(path):
    try:
        with open(path, "rb") as f:
            return hashlib.md5(f.read()).hexdigest()
    except Exception:
        return ""


def get_content(path):
    try:
        with open(path, "r", encoding="utf-8") as f:
            return f.read()
    except Exception:
        return ""


def load_gitignore_patterns(folder):
    """Load patterns from .gitignore file"""
    gitignore_path = Path(folder) / ".gitignore"
    patterns = []

    if gitignore_path.exists():
        try:
            with open(gitignore_path, "r", encoding="utf-8") as f:
                for line in f:
                    line = line.strip()
                    # Skip empty lines and comments
                    if line and not line.startswith("#"):
                        patterns.append(line)
        except Exception:
            pass

    return patterns


def is_ignored(file_path, patterns):
    """Check if a file path matches any gitignore pattern"""
    file_path_str = str(file_path)

    for pattern in patterns:
        # Handle directory patterns (ending with /)
        if pattern.endswith("/"):
            if file_path_str.startswith(pattern) or ("/" + pattern) in file_path_str:
                return True
        # Handle negation patterns (starting with !)
        elif pattern.startswith("!"):
            # This is a negation pattern - would need more complex logic
            # For now, we'll skip negation patterns
            continue
        # Handle glob patterns
        else:
            if fnmatch.fnmatch(file_path_str, pattern) or fnmatch.fnmatch(
                file_path_str, "*/" + pattern
            ):
                return True
            # Also check if any parent directory matches
            parts = file_path_str.split("/")
            for i in range(len(parts)):
                partial_path = "/".join(parts[: i + 1])
                if fnmatch.fnmatch(partial_path, pattern):
                    return True

    return False


def scan(folder):
    folder = Path(folder)
    files = {}
    gitignore_patterns = load_gitignore_patterns(folder)

    for f in folder.rglob("*"):
        if (
            f.is_file()
            and not f.name.startswith(".DS_Store")
            and ".git" not in str(f)
            and f.name != ".state.json"
        ):
            relative_path = f.relative_to(folder)

            # Check if file should be ignored based on gitignore patterns
            if not is_ignored(relative_path, gitignore_patterns):
                files[str(relative_path)] = {
                    "hash": get_hash(f),
                    "content": get_content(f),
                }
    return files


def save(data, fname):
    with open(fname, "w") as f:
        json.dump(data, f, indent=2)


def load(fname):
    if Path(fname).exists():
        try:
            with open(fname) as f:
                return json.load(f) or {}
        except Exception:
            return {}
    return {}


def is_json_file(filename):
    """Check if a file is likely a JSON file based on extension"""
    return filename.lower().endswith((".json", ".ipynb"))


def format_content_for_diff(content, filename):
    """Format content for better diff display"""
    if is_json_file(filename):
        try:
            # Try to parse and pretty-print JSON
            parsed = json.loads(content)
            return json.dumps(parsed, indent=2, sort_keys=True)
        except (json.JSONDecodeError, ValueError):
            # If it's not valid JSON, return as-is
            pass
    return content


def show_diff(added, removed, modified, context_lines=2):
    """Display changes in a clean, simple format - returns string instead of printing"""
    output = []

    # New files
    if added:
        output.append("NEW FILES:")
        for f in sorted(added):
            output.append(f"  + {f}")
        output.append("")

    # Deleted files
    if removed:
        output.append("DELETED FILES:")
        for f in sorted(removed):
            output.append(f"  - {f}")
        output.append("")

    # Modified files
    if modified:
        output.append("Modified files:")
        output.append("")

        for f in modified:
            filename = f["file"]
            output.append(f"File: {filename}")
            output.append("-" * 70)

            old_content = f["old_content"]
            new_content = f["new_content"]

            # Format content for better diffing (pretty-print JSON, etc.)
            old_formatted = format_content_for_diff(old_content, filename)
            new_formatted = format_content_for_diff(new_content, filename)

            # Split content into lines
            old_lines = old_formatted.splitlines()
            new_lines = new_formatted.splitlines()

            # Use SequenceMatcher for comparison
            matcher = difflib.SequenceMatcher(None, old_lines, new_lines)
            opcodes = list(matcher.get_opcodes())

            # Check if there are any changes
            has_changes = any(tag != "equal" for tag, _, _, _, _ in opcodes)
            if not has_changes:
                output.append("  (No textual differences found)")
                output.append("")
                continue

            # Build hunks: regions to display (changes + context)
            hunks = []
            for tag, i1, i2, j1, j2 in opcodes:
                if tag != "equal":
                    # Include context around changes
                    # For inserts where i1==i2, ensure we still create a valid hunk
                    hunk_start = max(0, i1 - context_lines)
                    hunk_end = min(len(old_lines), max(i1, i2) + context_lines)
                    hunks.append((hunk_start, hunk_end, tag, i1, i2, j1, j2))

            # Merge overlapping hunks and track which opcodes belong to each
            if hunks:
                merged_hunks = [(hunks[0][0], hunks[0][1], [hunks[0][2
[truncated — 7030 more characters]
```

### tui.py

```python
#!/usr/bin/env python3
"""
nrun - Natural Code Runner
A clean, classic terminal interface for running natural code files
"""

import sys
import os
import time
import threading
import random
import subprocess
from pathlib import Path
from rich.console import Console
from rich.live import Live
from rich.text import Text
import cli
import diff
import command

# Collection of fun ASCII animation styles - one is picked randomly per session
ANIMATION_STYLES = {
    "circle": ["◐", "◓", "◑", "◒"],
    "dots": ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"],
    "growing": ["·", "··", "···", "····", "·····", "····", "···", "··"],
    "arrows": ["→", "⇢", "⇉", "➜", "⇉", "⇢"],
    "bounce": ["◡", "◠", "◡", "◠"],
    "pulse": ["○", "◎", "●", "◎"],
    "dance": ["⊂", "⊃", "⊂", "⊃"],
    "wave": ["~", "≈", "≋", "≈"],
    "blocks": ["▁", "▃", "▅", "▆", "▇", "█", "▇", "▆", "▅", "▃"],
    "sparkle": ["✦", "✧", "★", "✧"],
    "pipe": ["|", "/", "—", "\\"],
    "progress": [
        "[    ]",
        "[=   ]",
        "[==  ]",
        "[=== ]",
        "[====]",
        "[ ===]",
        "[  ==]",
        "[   =]",
    ],
    "clock": ["◷", "◶", "◵", "◴"],
    "squares": ["◰", "◳", "◲", "◱"],
    "triangles": ["◢", "◣", "◤", "◥"],
    "asterix": [
        "✢",
        "✣",
        "✤",
        "✥",
        "✦",
        "✧",
        "",
        "✩",
        "✪",
        "✫",
        "✬",
        "✭",
        "✮",
        "✯",
        "✰",
        "✱",
        "✲",
        "✳",
        "✴",
        "✵",
        "✶",
        "✷",
        "✸",
        "✹",
        "✺",
        "✻",
        "✼",
        "✽",
        "✾",
        "✿",
        "❀",
        "❁",
        "❂",
        "❃",
        "❄",
        "❅",
        "❆",
        "❇",
        "❈",
        "❉",
        "❊",
        "❋",
        "❍",
    ],
}

# Fun ASCII-style status messages that rotate during code generation
FUN_VERBS = [
    "* thinking about this...",
    "> sketching the logic...",
    "~ focusing on the details...",
    "+ building your function...",
    "* adding the finishing touches...",
    ">> making it snappy...",
    "~ connecting the pieces...",
    "* brewing up some code...",
    "> growing your idea...",
    "+ writing it down...",
    "* performing some magic...",
    ">> launching the logic...",
    "~ having a lightbulb moment...",
    "> consulting the archives...",
    "+ composing your symphony...",
    "* deep thinking mode activated...",
    "~ setting the stage...",
    "> going with the flow...",
    "+ rolling the dice...",
    "* experimenting with ideas...",
    ">> aiming for perfection...",
    "~ sprinkling some stardust...",
    "> heating things up...",
    "+ painting the picture...",
    "* turning the gears...",
    "~ laying the foundation...",
    "> orchestrating the solution...",
    "+ making it happen...",
    "* adding some flavor...",
    "~ mixing the ingredients...",
    "> parsing the possibilities...",
    "+ compiling creativity...",
    "* weaving the logic...",
    "~ crafting the solution...",
    "> assembling the pieces...",
    "+ cooking up something good...",
    "* conjuring the code...",
]


class NaturalCodeRunner:
    """Main class for the nrun TUI"""

    def __init__(self, filename):
        self.filename = filename
        self.console = Console()
        self.animation_running = True
        self.current_frame = 0
        self.status = "Initializing..."
        self.error = None

        # Pick a random animation style for this session
        self.animation_style = random.choice(list(ANIMATION_STYLES.keys()))
        self.animation_frames = ANIMATION_STYLES[self.animation_style]

        # Track verb rotation - used when codex is actively generating
        self.verb_index = 0
        self.last_verb_time = time.time()
        self.use_fun_verbs = False  # Flag to show we're in code generation mode

    def get_animation_frame(self):
        """Get the current animation frame"""
        frame = self.animation_frames[self.current_frame]
        self.current_frame = (self.current_frame + 1) % len(self.animation_frames)
        return frame

    def get_fun_verb(self):
        """Get a fun verb, rotating through them"""
        # Rotate verbs every 2 seconds
        if time.time() - self.last_verb_time > 2.0:
            self.verb_index = (self.verb_index + 1) % len(FUN_VERBS)
            self.last_verb_time = time.time()
        return FUN_VERBS[self.verb_index]

    def create_display(self):
        """Create clean, minimal display"""
        lines = []

        # Simple header with filename and animation - teal/cyan theme
        lines.append("")
        header_text = Text()
        header_text.append("  nrun ", style="bold cyan")
        header_text.append(self.get_animation_frame(), style="cyan")

        display = Text()
        display.append(header_text)
        display.append("\n\n")
        display.append(f"  {self.filename}\n\n", style="dim")

        # Status - show fun verbs during code generation, normal status otherwise
        if self.error:
            display.append(f"  ✗ {self.error}", style="red")
        elif self.use_fun_verbs:
            display.append(f"  {self.get_fun_verb()}", style="cyan")
        else:
            display.append(f"  {self.status}", style="dim")
        display.append("\n")

        return display

    def update_status(self, new_status):
        """Update the current status message"""
        self.status = new_status

    def set_error(self, error_message):
        """Set an error message"""
        self.error = error_message
        self.animation_running = False

    def run_natural_code(self):
        """Run the natural code file through cli.py"""
        try:
            self.update_status("Validating file...")
            time.sleep(0.3)

            # Validate file exists and has correct extension
            path = Path(self.filename)
            if not path.exists():
                self.set_error(f"File not found: {self.fi
[truncated — 13457 more characters]
```

[1 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]