Metadata-Version: 2.4
Name: r-cli-ai
Version: 0.3.2
Summary: R CLI - Local AI Agent Runtime. Tool orchestrator connecting local LLMs to 74 system tools via function calling.
Project-URL: Homepage, https://github.com/raym33/r
Project-URL: Repository, https://github.com/raym33/r
Project-URL: Documentation, https://github.com/raym33/r#readme
Project-URL: Issues, https://github.com/raym33/r/issues
Author-email: Ramón Guillamón <learntouseai@gmail.com>
License: MIT
License-File: LICENSE
Keywords: agent,ai,cli,code-generation,llm,lm-studio,local,offline,ollama,pdf,private,productivity,rag,sql,voice,whisper
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: End Users/Desktop
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Utilities
Requires-Python: >=3.10
Requires-Dist: click>=8.0.0
Requires-Dist: duckdb>=0.9.0
Requires-Dist: fastapi>=0.109.0
Requires-Dist: fpdf2>=2.7.0
Requires-Dist: httpx>=0.25.0
Requires-Dist: jinja2>=3.0.0
Requires-Dist: openai>=1.0.0
Requires-Dist: pandas>=2.0.0
Requires-Dist: passlib[bcrypt]>=1.7.0
Requires-Dist: pillow>=10.0.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: pypdf>=3.0.0
Requires-Dist: python-docx>=1.0.0
Requires-Dist: python-jose[cryptography]>=3.3.0
Requires-Dist: pyyaml>=6.0.0
Requires-Dist: requests>=2.31.0
Requires-Dist: rich>=13.0.0
Requires-Dist: tiktoken>=0.5.0
Requires-Dist: uvicorn[standard]>=0.27.0
Provides-Extra: all
Requires-Dist: accelerate>=0.25.0; extra == 'all'
Requires-Dist: beautifulsoup4>=4.12.0; extra == 'all'
Requires-Dist: chromadb>=0.4.0; extra == 'all'
Requires-Dist: deep-translator>=1.11.0; extra == 'all'
Requires-Dist: diffusers>=0.25.0; extra == 'all'
Requires-Dist: faster-whisper>=0.10.0; extra == 'all'
Requires-Dist: jmespath>=1.0.0; extra == 'all'
Requires-Dist: jsonschema>=4.0.0; extra == 'all'
Requires-Dist: langdetect>=1.0.9; extra == 'all'
Requires-Dist: lxml>=4.9.0; extra == 'all'
Requires-Dist: numpy>=1.24.0; extra == 'all'
Requires-Dist: piper-tts>=1.0.0; extra == 'all'
Requires-Dist: psycopg2-binary>=2.9.0; extra == 'all'
Requires-Dist: pytesseract>=0.3.10; extra == 'all'
Requires-Dist: sentence-transformers>=2.2.0; extra == 'all'
Requires-Dist: textual>=0.47.0; extra == 'all'
Requires-Dist: torch>=2.0.0; extra == 'all'
Provides-Extra: all-mac
Requires-Dist: accelerate>=0.25.0; extra == 'all-mac'
Requires-Dist: beautifulsoup4>=4.12.0; extra == 'all-mac'
Requires-Dist: chromadb>=0.4.0; extra == 'all-mac'
Requires-Dist: deep-translator>=1.11.0; extra == 'all-mac'
Requires-Dist: diffusers>=0.25.0; extra == 'all-mac'
Requires-Dist: faster-whisper>=0.10.0; extra == 'all-mac'
Requires-Dist: huggingface-hub>=0.20.0; extra == 'all-mac'
Requires-Dist: jmespath>=1.0.0; extra == 'all-mac'
Requires-Dist: jsonschema>=4.0.0; extra == 'all-mac'
Requires-Dist: langdetect>=1.0.9; extra == 'all-mac'
Requires-Dist: lxml>=4.9.0; extra == 'all-mac'
Requires-Dist: mlx-lm>=0.10.0; extra == 'all-mac'
Requires-Dist: numpy>=1.24.0; extra == 'all-mac'
Requires-Dist: piper-tts>=1.0.0; extra == 'all-mac'
Requires-Dist: psycopg2-binary>=2.9.0; extra == 'all-mac'
Requires-Dist: pytesseract>=0.3.10; extra == 'all-mac'
Requires-Dist: sentence-transformers>=2.2.0; extra == 'all-mac'
Requires-Dist: textual>=0.47.0; extra == 'all-mac'
Requires-Dist: torch>=2.0.0; extra == 'all-mac'
Provides-Extra: all-rpi
Requires-Dist: accelerate>=0.25.0; extra == 'all-rpi'
Requires-Dist: beautifulsoup4>=4.12.0; extra == 'all-rpi'
Requires-Dist: chromadb>=0.4.0; extra == 'all-rpi'
Requires-Dist: deep-translator>=1.11.0; extra == 'all-rpi'
Requires-Dist: diffusers>=0.25.0; extra == 'all-rpi'
Requires-Dist: faster-whisper>=0.10.0; extra == 'all-rpi'
Requires-Dist: gpiozero>=2.0.0; extra == 'all-rpi'
Requires-Dist: jmespath>=1.0.0; extra == 'all-rpi'
Requires-Dist: jsonschema>=4.0.0; extra == 'all-rpi'
Requires-Dist: langdetect>=1.0.9; extra == 'all-rpi'
Requires-Dist: lxml>=4.9.0; extra == 'all-rpi'
Requires-Dist: numpy>=1.24.0; extra == 'all-rpi'
Requires-Dist: piper-tts>=1.0.0; extra == 'all-rpi'
Requires-Dist: psycopg2-binary>=2.9.0; extra == 'all-rpi'
Requires-Dist: pytesseract>=0.3.10; extra == 'all-rpi'
Requires-Dist: rpi-gpio>=0.7.0; extra == 'all-rpi'
Requires-Dist: sentence-transformers>=2.2.0; extra == 'all-rpi'
Requires-Dist: textual>=0.47.0; extra == 'all-rpi'
Requires-Dist: torch>=2.0.0; extra == 'all-rpi'
Provides-Extra: audio
Requires-Dist: faster-whisper>=0.10.0; extra == 'audio'
Requires-Dist: piper-tts>=1.0.0; extra == 'audio'
Provides-Extra: design
Requires-Dist: accelerate>=0.25.0; extra == 'design'
Requires-Dist: diffusers>=0.25.0; extra == 'design'
Requires-Dist: torch>=2.0.0; extra == 'design'
Provides-Extra: dev
Requires-Dist: build>=1.0.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
Requires-Dist: pytest>=7.0.0; extra == 'dev'
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Requires-Dist: twine>=4.0.0; extra == 'dev'
Provides-Extra: json-tools
Requires-Dist: jmespath>=1.0.0; extra == 'json-tools'
Requires-Dist: jsonschema>=4.0.0; extra == 'json-tools'
Provides-Extra: mlx
Requires-Dist: huggingface-hub>=0.20.0; extra == 'mlx'
Requires-Dist: mlx-lm>=0.10.0; extra == 'mlx'
Provides-Extra: ocr
Requires-Dist: pytesseract>=0.3.10; extra == 'ocr'
Provides-Extra: postgres
Requires-Dist: psycopg2-binary>=2.9.0; extra == 'postgres'
Provides-Extra: rag
Requires-Dist: chromadb>=0.4.0; extra == 'rag'
Requires-Dist: numpy>=1.24.0; extra == 'rag'
Requires-Dist: sentence-transformers>=2.2.0; extra == 'rag'
Provides-Extra: rpi
Requires-Dist: gpiozero>=2.0.0; extra == 'rpi'
Requires-Dist: rpi-gpio>=0.7.0; extra == 'rpi'
Provides-Extra: simulator
Requires-Dist: textual>=0.47.0; extra == 'simulator'
Provides-Extra: translate
Requires-Dist: deep-translator>=1.11.0; extra == 'translate'
Requires-Dist: langdetect>=1.0.9; extra == 'translate'
Provides-Extra: web
Requires-Dist: beautifulsoup4>=4.12.0; extra == 'web'
Requires-Dist: lxml>=4.9.0; extra == 'web'
Description-Content-Type: text/markdown

# R CLI

<div align="center">

```
██████╗        ██████╗██╗     ██╗
██╔══██╗      ██╔════╝██║     ██║
██████╔╝█████╗██║     ██║     ██║
██╔══██╗╚════╝██║     ██║     ██║
██║  ██║      ╚██████╗███████╗██║
╚═╝  ╚═╝       ╚═════╝╚══════╝╚═╝
```

**Local AI Agent Runtime**

[![PyPI version](https://badge.fury.io/py/r-cli-ai.svg)](https://pypi.org/project/r-cli-ai/)
[![Downloads](https://static.pepy.tech/badge/r-cli-ai)](https://pepy.tech/project/r-cli-ai)
[![CI](https://github.com/raym33/r/actions/workflows/ci.yml/badge.svg)](https://github.com/raym33/r/actions/workflows/ci.yml)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

A tool orchestrator that connects local LLMs to 74 system tools via function calling.

[Installation](#installation) · [Quick Start](#quick-start) · [All Skills](#all-74-skills) · [Why Not Just Terminal Access?](#why-structured-tools-instead-of-terminal-access) · [Docs](docs/COMPLETE_GUIDE.md)

</div>

---

## What is R CLI?

R CLI is a **tool orchestrator** for local LLMs. It exposes 74 "skills" (PDF generation, SQL queries, git, docker, etc.) as structured function calls that any OpenAI-compatible model can invoke.

**This is NOT an operating system.** It's a Python CLI that sits between your local LLM (Ollama, LM Studio) and real system tools.

```
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   You       │────▶│   R CLI     │────▶│  Local LLM  │
│  (prompt)   │     │ (orchestrator)│    │  (Ollama)   │
└─────────────┘     └──────┬──────┘     └──────┬──────┘
                          │                    │
                          ▼                    │
                   ┌─────────────┐             │
                   │   Skills    │◀────────────┘
                   │ (74 tools)  │  function call
                   └─────────────┘
```

```bash
$ r chat "Create a PDF report about Python"
# LLM calls pdf.generate_pdf() -> creates python_report.pdf

$ r sql sales.csv "SELECT product, SUM(revenue) FROM data GROUP BY product"
# Runs actual SQL against CSV using DuckDB

$ r rag --add ./docs/ && r rag --query "how does auth work"
# ChromaDB vectors, semantic search across your docs
```

## Why Structured Tools Instead of Terminal Access?

You could just give an LLM shell access. But structured function calling provides:

| Raw Terminal Access | R CLI Structured Tools |
|---------------------|------------------------|
| Model guesses bash syntax | Model sees JSON schema for each tool |
| "Run `zip *.py`" can fail in many ways | `archive.create_zip(files=["*.py"])` with validation |
| Hard to add confirmation gates | Each tool can require user approval |
| No type checking | Pydantic validates all inputs |
| Unpredictable output parsing | Structured return values |

**Example:** When you ask "compress python files", the LLM doesn't generate bash. It calls:

```json
{
  "tool": "archive.create_zip",
  "arguments": {
    "source_path": ".",
    "pattern": "*.py",
    "output": "python_files.zip"
  }
}
```

R CLI validates the arguments, executes the tool, and returns structured results.

---

## Features

| Feature | Description |
|---------|-------------|
| **100% Local** | Your data never leaves your machine |
| **74 Skills** | PDF, SQL, code, git, docker, RAG, voice, and more |
| **REST API** | OpenAI-compatible server for IDE integration |
| **Plugin System** | Add custom skills in Python |
| **Voice Interface** | Whisper STT + Piper TTS (optional) |
| **Hardware Skills** | GPIO, Bluetooth, WiFi for Raspberry Pi |

---

## Installation

```bash
# Basic
pip install r-cli-ai

# With all features
pip install r-cli-ai[all]

# R OS Simulator (Textual TUI)
pip install r-cli-ai[simulator]

# Raspberry Pi (with GPIO)
pip install r-cli-ai[all-rpi]
```

### Requirements

- Python 3.10+
- [Ollama](https://ollama.ai/) or [LM Studio](https://lmstudio.ai/)
- 8GB+ RAM (16GB+ recommended)

---

## Quick Start

### 1. Start your LLM

```bash
# Ollama
ollama pull qwen3:4b && ollama serve

# Or use LM Studio GUI
```

### 2. Run R CLI

```bash
# Interactive chat
r

# Direct command
r chat "Explain quantum computing in simple terms"

# Start API server
r serve --port 8765
```

---

## R OS - Terminal UI (Experimental)

A terminal-based interface that looks like Android. Built with [Textual](https://textual.textualize.io/). This is an experimental feature for Raspberry Pi and edge devices - not an actual OS.

```
┌─────────────────────────────────────────────────────────┐
│ ▁▂▄█ 📶 R OS          12:45          🔋 85%             │
├─────────────────────────────────────────────────────────┤
│                                                         │
│   💬 Messages   📞 Phone     📧 Email     🌐 Browser   │
│                                                         │
│   📷 Camera     🖼️ Gallery   🎵 Music     🎬 Video     │
│                                                         │
│   📁 Files      📅 Calendar  ⏰ Clock     🔢 Calculator │
│                                                         │
│   🤖 R Chat     🎤 Voice     🌍 Translate 📝 Notes     │
│                                                         │
│   ⚙️ Settings   📶 WiFi      🔵 Bluetooth 🔋 Battery   │
│                                                         │
│   💡 GPIO       💻 Terminal  🔌 Network   📊 System    │
│                                                         │
├─────────────────────────────────────────────────────────┤
│           ◀ Back      ● Home      ▢ Recent             │
└─────────────────────────────────────────────────────────┘
```

### Launch

```bash
r-os                    # Material theme
r-os --theme amoled     # AMOLED black
r-os --theme light      # Light theme
```

### Keyboard Shortcuts

| Key | Action |
|-----|--------|
| `t` | Cycle themes |
| `n` | Notifications panel |
| `h` | Home |
| `Esc` | Back |
| `q` | Quit |

### Raspberry Pi Setup

```bash
# One-command installer
curl -sSL https://raw.githubusercontent.com/raym33/r/main/r_os/rpi/install.sh | bash
```

📖 **[Full R OS Documentation](r_os/README.md)**

---

## All 74 Skills

### 📄 Documents
`pdf` · `latex` · `markdown` · `pdftools` · `template` · `resume` · `changelog`

### 💻 Code & Data
`code` · `sql` · `json` · `yaml` · `csv` · `regex` · `schema` · `diff`

### 🤖 AI & Knowledge
`rag` · `multiagent` · `translate` · `faker`

### 🎨 Media
`ocr` · `voice` · `design` · `image` · `video` · `audio` · `screenshot` · `qr` · `barcode`

### 📁 Files
`fs` · `archive` · `clipboard` · `env`

### 📅 Productivity
`calendar` · `email` · `ical` · `vcard`

### 🔧 DevOps
`git` · `docker` · `ssh` · `http` · `web` · `network` · `system` · `metrics`

### 🔍 Dev Tools
`logs` · `benchmark` · `openapi` · `cron` · `jwt`

### 📝 Text
`text` · `html` · `xml` · `url` · `ip` · `encoding`

### 🔢 Data
`datetime` · `color` · `math` · `currency` · `crypto` · `semver` · `mime`

### 🌐 Web
`rss` · `sitemap` · `manifest` · `hublab` · `weather`

### 🔌 Hardware (R OS)
`gpio` · `bluetooth` · `wifi` · `power` · `android`

### 🧩 Extensions
`plugin`

---

## REST API

```bash
# Start server
r serve --port 8765

# Chat (OpenAI-compatible)
curl -X POST http://localhost:8765/v1/chat \
  -H "Content-Type: application/json" \
  -d '{"messages": [{"role": "user", "content": "Hello!"}]}'

# Call skill directly
curl -X POST http://localhost:8765/v1/skills/call \
  -d '{"skill": "pdf", "tool": "generate_pdf", "arguments": {"content": "Hello"}}'
```

**Swagger UI:** http://localhost:8765/docs

---

## Configuration

```yaml
# ~/.r-cli/config.yaml
llm:
  backend: ollama
  model: qwen3:4b
  base_url: http://localhost:11434/v1

ui:
  theme: ps2  # ps2, matrix, minimal, retro

skills:
  disabled: []  # Skills to disable
```

---

## Create Custom Skills

```python
# ~/.r-cli/skills/my_skill.py
from r_cli.core.agent import Skill
from r_cli.core.llm import Tool

class MySkill(Skill):
    name = "my_skill"
    description = "My custom skill"

    def get_tools(self) -> list[Tool]:
        return [
            Tool(
                name="my_function",
                description="Does something useful",
                parameters={"type": "object", "properties": {"input": {"type": "string"}}},
                handler=self.my_function,
            )
        ]

    def my_function(self, input: str) -> str:
        return f"Processed: {input}"
```

---

## Development

```bash
git clone https://github.com/raym33/r.git
cd r
pip install -e ".[dev]"
pytest tests/ -v
ruff check . && ruff format .
```

---

## Links

- [Complete Documentation](docs/COMPLETE_GUIDE.md)
- [Changelog](CHANGELOG.md)
- [Contributing](CONTRIBUTING.md)
- [Report Issues](https://github.com/raym33/r/issues)
- [PyPI Package](https://pypi.org/project/r-cli-ai/)

---

## Honest Limitations

- **Sandboxing is basic** - Skills run with your user permissions. Working on better isolation.
- **Small models (4B) sometimes pick the wrong tool** - Larger models (7B+) work better.
- **It's a tool layer, not magic** - Prompt quality still matters.
- **Some skills need external dependencies** - OCR needs Tesseract, voice needs Whisper, etc.

---

## License

MIT License

---

<div align="center">

**R CLI** - A tool orchestrator for local LLMs.

Created by [Ramón Guillamón](https://x.com/learntouseai)

</div>
