⚠️ Archived — This project is no longer actively maintained.
BasedClaw was an experimental project to explore building an agentic LLM client in Rust. I saw the multitude of OpenClaw-style clients popping up, wanted to see if I could build one myself, and it turns out, they're not as complicated as they look. The project successfully achieved its goals as a simple, functional agentic client. The code remains here for reference and as a portfolio piece.
An experimental agentic LLM client written entirely in Rust. BasedClaw provides a unified interface across multiple cloud LLM providers (OpenAI, Anthropic, and OpenAI-compatible APIs like Ollama/vLLM) with full tool/function calling support, streaming responses, session management, and multiple frontends, which include an interactive terminal UI and a Telegram bot.
BasedClaw turns a language model into an agent that can autonomously execute tools including reading/writing files, running shell commands, and more! It's essentially an OpenClaw-style coding assistant, but built from scratch in Rust.
| Category | Details |
|---|---|
| Multi-Provider | OpenAI, Anthropic, and any OpenAI-compatible API (Ollama, vLLM, etc.) |
| Agentic Tool Calling | Support for LLMs with tool support to call tools, observe results, and continue reasoning |
| Streaming | Real-time token streaming with proper buffering and partial tool call accumulation |
| Interactive TUI | Full terminal chat interface with ratatui, syntax highlighting (syntect), markdown rendering, streaming indicators |
| Telegram Bot | Long-running bot with per-user persistent sessions, tool execution, and DSML parsing |
| Session Management | Persist, resume, search, and export chat sessions as JSON/Markdown/YAML |
| Built-in Tools | file_read, file_write, file_list, shell — with path sandboxing and configurable security |
| Configuration | YAML/JSON config, multiple profiles, env var expansion, and an interactive setup wizard |
| Middleware | Extensible middleware system with logging and exponential backoff retry logic |
src/
├── lib.rs # Public API and re-exports
├── main.rs # CLI entry point (dispatches to all subcommands)
├── types.rs # Unified data model (Message, Tool, ChatRequest, etc.)
├── error.rs # Error types and conversions
├── client.rs # BasedClawClient with builder pattern, retry, middleware
├── conversation.rs # Conversation + StreamingConversation managers
├── providers/
│ ├── mod.rs # LlmProvider trait + ProviderFactory
│ ├── openai.rs # Full OpenAI API provider
│ ├── anthropic.rs # Full Anthropic API provider
│ └── compatible.rs # OpenAI-compatible wrapper (Ollama, vLLM, etc.)
├── tools/
│ ├── mod.rs # ToolHandler trait, ToolRegistry, define_tool! macro
│ └── executor.rs # Tool call execution and validation
├── streaming/
│ └── mod.rs # SSE parser and stream utilities
├── middleware/
│ └── mod.rs # Middleware trait + LoggingMiddleware + RetryMiddleware
├── cli/
│ └── mod.rs # Full clap CLI definition with subcommands
├── config/
│ └── mod.rs # ConfigManager, profiles, setup wizard (env var expansion)
├── session/
│ └── mod.rs # SessionManager with JSON file storage, search, export
├── bin_tools/
│ └── builtin.rs # File read/write/list, shell execution with sandboxing
├── ui/
│ ├── mod.rs # TUI chat interface (ratatui + crossterm, ~980 LOC)
│ └── features.rs # Code highlighting, markdown rendering, streaming indicator
└── telegram/
├── mod.rs # Telegram bot setup (teloxide)
├── handler.rs # Message/command handlers with tool support
└── session.rs # Per-user Telegram session wrapper
# Set your API key
export OPENAI_API_KEY="sk-..."
# First run — triggers the setup wizard
basedclaw
# Interactive TUI chat
basedclaw agent
# Send a single message
basedclaw agent -m "Write a Rust function to reverse a string"
# One-shot query (no session)
basedclaw ask "What's the difference between Box and Rc in Rust?"
# Resume your last session
basedclaw agent --resume last
# List and search chat history
basedclaw history list
basedclaw history search "refactor"
# Export a session as markdown
basedclaw history export abc123 --format markdown
# Run the Telegram bot
basedclaw telegram startuse basedclaw::{BasedClawClientBuilder, ProviderFactory, Message, ChatRequest};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let provider = ProviderFactory::openai(std::env::var("OPENAI_API_KEY")?);
let client = BasedClawClientBuilder::new(provider)
.with_timeout(std::time::Duration::from_secs(60))
.with_retry(3)
.build();
let request = ChatRequest::new("gpt-4o")
.with_message(Message::system("You are a helpful assistant."))
.with_message(Message::user("What is Rust?"));
let response = client.chat(request).await?;
if let basedclaw::ChatResponse::Complete(completion) = response {
println!("{}", completion.content);
}
Ok(())
}use basedclaw::{ChatRequest, Message, ToolRegistry, tool};
use futures::StreamExt;
let mut registry = ToolRegistry::new();
tool!(registry, Calculator, "calculator", "Perform calculations", {
"expression": String
} => {
// evaluate expression...
Ok(format!("Result: ..."))
});
let request = ChatRequest::new("gpt-4o")
.with_message(Message::user("What is 15 * 37?"))
.with_streaming()
.with_tools(registry.definitions());
let response = client.chat(request).await?;# ~/.config/basedclaw/config.yaml
version: "1.0"
default_profile: openai
profiles:
openai:
provider: openai
model: gpt-4o
api_key: "${OPENAI_API_KEY}"
parameters:
temperature: 0.7
max_tokens: 4096
system_prompt: "You are BasedClaw, a coding assistant."
ollama:
provider: openai_compatible
model: codellama:13b
base_url: "http://localhost:11434/v1"
api_key: ""
settings:
behavior:
max_tool_iterations: 10
stream: true
security:
sandbox: true
allowed_paths:
- "~/projects"
logging:
level: info
workspace:
name: "default"This was an experimental project to experiment with Rust's async runtime and see what it takes to build an agentic client from scratch. The goal was to create something comparable to OpenClaw or PicoClaw but entirely in Rust.
It succeeded. The core loop works: chat with an LLM, let it call tools, observe the results, and continue the conversation. Multiple frontends (TUI, CLI, Telegram) share the same underlying engine.
Key takeaways from the build:
- Rust's type system is excellent for modeling LLM interactions (typed messages, tool schemas, provider dispatch)
- Ratatui is amazing
- Things that seemingly appeared as magic black boxes — i.e., other claw-family clients — are actually quite simple once you get to know how they work
| Layer | Technology |
|---|---|
| Language | Rust 2021 edition |
| Async Runtime | Tokio |
| HTTP | reqwest + rustls |
| Serialization | serde (JSON, YAML) |
| CLI | clap + dialoguer + indicatif |
| TUI | ratatui + crossterm |
| Telegram | teloxide |
MIT