SINGLE FILE. CONFIG-DRIVEN. SQLITE MEMORY.
UnoClaw is a lightweight, self-contained, single file AI agent that runs locally. It answers you on Telegram or via an interactive CLI. It connects to any OpenAI-compatible LLM (local or remote), manages a permanent SQLite memory, triggers its own background tasks, and exposes a set of sandboxed tools the model can call autonomously — all in under 500 lines of Python (with ~60 of those being just comments and extra whitespace for readability)
Inspired by OpenClaw and the minimalist philosophy of NanoBot, we put a strong emphasis on simplicity and readability. Because the entire core logic lives in a single file, you can easily read it from top to bottom, hack it to your exact needs, or use it as a learning resource to understand how AI agents and tool-calling work under the hood.
Check it out if you want to play around with AI driven assistant that is highly hackable, requires zero external databases and lives in a single file.
GitHub Repository · Installation · Quick Start · Configuration · Extending & Tools · Security
Runtime: Python ≥ 3.10.
uv is the fastest way to install and manage unoclaw.
As a global tool with Telegram:
uv tool install unoclaw --with "unoclaw[telegram]"As a global tool CLI only (no Telegram):
uv tool install unoclawpip install "unoclaw[telegram]"pip install unoclawIf you want to modify the code or contribute, we recommend using uv for a seamless experience:
git clone [https://github.com/2coderok/unoclaw.git](https://github.com/2coderok/unoclaw.git)
cd unoclaw
# Create environment and install all dependencies (including dev tools)
uv sync --all-extrasAlternatively, using standard pip:
git clone [https://github.com/2coderok/unoclaw.git](https://github.com/2coderok/unoclaw.git)
cd unoclaw
# Create a virtual environment
python -m venv .venv
source .venv/bin/activate # (Windows: .venv\Scripts\activate)
# Install in editable mode with Telegram and Dev support
pip install -e ".[telegram,dev]"-
Configure: Copy the example config and add your llm endpoint/telegram settings.
cp config.example.json config.json
-
Run: Start the agent in your terminal using the conifg.
unoclaw --config path/to/your/config.json
UnoClaw will look for
config.jsonin current working directory if --config was not provided.
If you provided a telegram.token, it will start polling immediately. If omitted, it will drop you into the interactive CLI mode.
- Agentic Scheduler — Background loop triggers the LLM to autonomously perform scheduled prompts.
- SQLite Memory — Seamless, permanent conversation and task storage without messy text files.
- Tool-calling — The LLM can execute shell commands, read/write files, and fetch web pages.
- Telegram + CLI — Runs as a Telegram bot; falls back to CLI when no token is configured.
- Workspace sandboxing — Optionally restricts all file and command access to a single directory.
- Async tool dispatch — Tool functions run in threads via
asyncio.to_thread().
- Context trimming: Chat history is automatically trimmed by message count and token heuristics (
max_context_tokens,max_context_messages). - Config validation: Pydantic models validate
config.jsonat startup with clear error messages. - Agent Loop: Handles native tool-calling natively through the official OpenAI SDK structure.
- Automatic Storage: Every time the LLM replies to the user, the exchange is automatically saved to the
memorySQLite table. - On-Demand Recall: When the user sends a new message, UnoClaw scans it for keywords, queries the database, and invisibly injects relevant historical memories directly into the LLM's system prompt.
- Native Tools:
execute_command,read_file,write_file,read_web. - Task Management:
add_task,list_tasks,remove_task. - Agentic Cron: Unlike traditional schedulers, UnoClaw saves natural language prompts to the DB. When the timer hits zero, the background thread wakes up and messages the LLM:
[SYSTEM: AUTOMATED BACKGROUND TASK TRIGGERED]: <prompt>. The agent autonomously executes tools and sends you a message with the result.
Telegram / CLI User config.json & .md docs
│ │
▼ ▼
┌──────────────────────────────────────────────────────────────────┐
│ UnoClaw (main.py) │
│ │
│ ┌────────────────────┐ trigger ┌────────────────────────┐ │
│ │ Scheduler Loop ├─────────────►│ The Agent Loop │ │
│ │ (Background Tasks) │ │ (Context & Reasoning) │ │
│ └──────────┬─────────┘ └──────┬─────────┬───────┘ │
└─────────────┼───────────────────────────────┼─────────┼──────────┘
│ check tasks │ │
│ │ │ execute
▼ read/write │ ▼
┌────────────┐◄───────────────────────┤ ┌──────────────┐
│ SQLite DB │ │ │ Native Tools │
│(unoclaw.db)│ │ │(Shell, File, │
└────────────┘ │ │ Web Reader) │
│ └──────────────┘
prompt & │
tool_calls ▼
┌─────────────────────────┐
│ OpenAI-Compatible LLM │
│ (Ollama, Groq, etc.) │
└─────────────────────────┘
Because UnoClaw uses the standard OpenAI SDK with a configurable base_url, it supports virtually any Large Language Model that exposes an OpenAI-compatible API endpoint.
This means you are not locked into a single provider. You can seamlessly switch between local open-source models and powerful cloud APIs just by changing two lines in your config.json.
If you have the hardware, you can run models entirely locally. Just point UnoClaw's base_url to your local server:
- Ollama:
http://localhost:11434/v1(Supports Llama 3, Qwen, Mistral, Phi, etc.) - LM Studio:
http://localhost:1234/v1 - vLLM:
http://localhost:8000/v1 - Llama.cpp (Server):
http://localhost:8080/v1 - Text-Generation-WebUI (Oobabooga):
http://localhost:5000/v1
If you want to use hosted models, just paste your API key and their base URL into the config:
- OpenAI: GPT-4o, GPT-4-turbo, GPT-3.5
- Groq: Ultra-fast inference for open-source models (Llama 3, Mixtral)
- OpenRouter: Access to hundreds of models including Claude, Gemini, and DeepSeek through a single unified API.
- Together AI: Hosted open-source models.
- DeepSeek: Direct API access to DeepSeek models.
- Mistral API: Direct access to Mistral Large, Nemo, etc.
To fully utilize UnoClaw's features, the model you choose must support Tool Calling (Function Calling).
- Recommended Open-Source: Qwen 2.5 (Instruct), Llama 3.1 (Instruct), or Mistral Nemo.
- Recommended Cloud: GPT-4o, Claude 3.5 Sonnet (via OpenRouter), or Groq-hosted Llama 3.1.
Settings live in config.json. Missing required fields (like llm) will produce a clear validation error on startup.
{
"telegram": {
"token": "YOUR_BOT_TOKEN",
"allowed_usernames": ["your_handle"]
},
"llm": {
"base_url": "http://localhost:8088/v1",
"model": "qwen2.5-7b-instruct",
"api_key": "not-needed"
},
"workspace": {
"path": ".",
"restrict": true
},
"max_context_tokens": 8000,
"max_context_messages": 40
}To prevent runaway API costs and context-window crashes, UnoClaw manages conversation history using a soft token budget:
max_context_tokens: UnoClaw estimates the token count of your active conversation. If it exceeds this limit, it automatically prunes the oldest messages (while always preserving your system prompts).max_context_messages: The absolute maximum number of back-and-forth messages kept in the active LLM context before older messages are trimmed.
Note: For the full schema, check config.example.json.
UnoClaw builds its system prompt dynamically on startup by reading two markdown files from the docs/ directory. You can (and should) edit these to completely customize your assistant.
This file defines who the agent is, its core rules, and its constraints. Use this file to set the agent's behavior:
- Personality: e.g., "You are a sarcastic but highly skilled DevOps engineer."
- Formatting Rules: e.g., "Always provide code snippets without markdown blocks."
- Environment Context: Tell the LLM what OS it is running on! Add a line like
You are running on Windows 11 using PowerShell.orYou are running on Ubuntu Linux 22.04.to ensure it uses the correct syntax (dirvsls) when executing autonomous shell commands.
This file defines what the agent can do. It is appended directly below the AGENT.md text and contains the documentation for your Native Tools and the step-by-step logic for your Composite Skills (detailed in the next section).
UnoClaw is designed to be highly hackable. You can give it new superpowers in two ways: by writing plain English workflows (Composite Skills) or by writing native Python functions (Native Tools).
Because UnoClaw connects to powerful LLMs, you do not need to write a new Python script for every minor feature. You can simply teach the agent a "workflow" by editing the SKILLS.md file and instructing it to use its existing tools (like read_web or read_file).
To add a new skill, just append a clear, step-by-step instruction block to SKILLS.md.
Example: Adding a Bitcoin Price Tracker
Paste the following into your SKILLS.md file. UnoClaw will read this and instantly know how to pull real-time crypto prices without any new Python code:
### get_bitcoin_price_usd
* **Trigger:** When the user asks for the current Bitcoin or BTC price.
* **Execution Workflow:** 1. Call the `read_web` tool with the URL: `https://min-api.cryptocompare.com/data/generateAvg?fsym=BTC&tsym=USD&e=coinbase`
2. Analyze the returned JSON text.
3. Locate the `RAW` object, and extract the numeric value associated with the `PRICE` field.
4. Respond to the user using exactly this format: `BTC price is <PRICE> USD`.If you need UnoClaw to interact with a specific local database, control hardware, or execute complex logic, you can easily add a native tool directly inside unoclaw.py.
Step 1: Define your Python function
Write your function inside unoclaw.py. Crucially, you must include type hints and a clear docstring. UnoClaw parses this to automatically generate the tool schema for the LLM.
def get_system_uptime() -> str:
"""
Returns the current uptime of the host machine.
Call this when the user asks how long the server has been running.
"""
import uptime
return f"System has been running for {uptime.uptime()} seconds."Step 2: Register the tool
Find the available_tools dictionary in unoclaw.py and map your new function:
available_tools = {
"execute_command": execute_command,
"read_file": read_file,
"write_file": write_file,
"read_web": read_web,
"get_system_uptime": get_system_uptime, # <-- Your new tool registered here
}Step 3: Document the tool for the LLM
Finally, open your AGENT.md or SKILLS.md file and add an entry so the LLM knows the tool exists, what it does, and what parameters it requires.
Add this to SKILLS.md under the Native Tools section:
### get_system_uptime
* **Description:** Returns the current uptime of the host machine in seconds. Use this when asked about server status or uptime.
* **Parameters:** None.UnoClaw connects to your host environment. Treat tool access with care!
- Workspace restriction: When
workspace.restrictistrue, the agent cannot access files outsideworkspace.path, runcdcommands with absolute paths, or make network requests. - Allowed usernames: In Telegram mode, only users listed in
telegram.allowed_usernamescan interact with the bot. Any other user is silently ignored. - Shell access: The
execute_commandtool runs arbitrary shell commands. Use workspace restriction and allowed-user lists to limit exposure. - No credential storage: Never commit
config.jsonto version control.
unoclaw/
├── LICENSE # License file
├── README.md # This file
├── pyproject.toml # Build configuration
├── .gitignore
├── assets/
│ └── unoclaw_text_logo.png # UnoClaw logo
├── tests/
│ └── test_unoclaw.py # Test suite (pytest)
└── unoclaw/
├── __init__.py
├── main.py # The entire agent — single file
├── config.example.json # Template configuration
└── docs/
├── AGENT.md # Auto-loaded agent instructions
└── SKILLS.md # Auto-loaded agent skills
