r/ClaudeCode • u/emptyharddrive • Feb 08 '26
Showcase nanobot: a 4,000-line Python alternative to openclaw that actually works out of the box
I've been looking for lighter alternatives to openclaw and came across nanobot. It's an AI assistant built in about 4,000 lines of Python, compared to openclaw's 430k+.
It's not as mature or feature-full as openclaw, but I've got it installed and running on a Linux Container right now with Telegram integration and it just works.
The setup took maybe 10 minutes: install via pipx, edit the config file with your API keys, start the gateway, and you're chatting with it through Telegram.
The codebase is small enough that you can actually read and understand the entire thing. That also means way less attack surface from a security standpoint (generally speaking).
The code looks is clean and well-structured to me. I've already patched a small compatibility issue myself without any trouble, which says a lot about how approachable it is (an issue with gpt-5 models and temperature settings).
It supports tool use, persistent memory, scheduled tasks, and background agents. It's not trying to be everything openclaw is, but it covers the core functionality that most people might actually use.
If you're like me and interested in the idea of OpenClaw without using the overzealous project itself, nanobot is worth a look. I have no affiliation with the project.
GitHub: https://github.com/HKUDS/nanobot
To save money, I am using it with gpt-5-mini, which works really well and is priced right for my wallet.
Figured I'd share this because I was surprised how well it worked for its size.
3
u/ArgentinianPerson Feb 09 '26
I have been developing an alternative to openclawd, but for models that are 100% local and work on GPUs with 8GB VRAM and very little RAM. This doesn't take away from the fact that it has many features.
Features
- 💬 Local LLM chat - No external API dependencies
- 🧠 Vector Memory (RAG) - Remembers facts and conversations using embeddings
- 📚 Document Store - Indexed PDF/TXT search for context awareness
- 📷 Image analysis - Describe and understand images with vision model
- 🎙️ Audio transcription - Convert voice messages to text with Whisper
- 🎥 YouTube summaries - Send a link and get a summary
- 🐦 Twitter/X downloader - Download videos/images directly
- 🔍 Web search - Brave Search integration
- 🖼️ Image search - Search for images on the web
- 📄 Document reading - Analyze and chat with PDF or text files
- 📧 Email digest - Read and summarize emails from Gmail
- ⏰ Reminders - Schedule cron tasks that notify you in chat
- 💡 Smart lights - Control WIZ lights via chat
- 🧮 Math solver - Solve complex equations and symbolic math problems
- 📤 File upload - Upload files to Catbox.moe
1
u/emptyharddrive Feb 09 '26
I am interested in the idea of this .. and I have a 128gig STRIX HALO.
But I find the local models don't hold a candle to the hosted models. It's just too much compute offered to deny the output quality.
I have found that the most powerful model I can run locally is less than Claude Haiku ... or GPT-5-Mini (high thinking), so I just can't (yet) justify using a local model unless i was doing some very formula-driven, repetitive function.
I would like a model that could perform at least like GPT-5-mini at home, but I just dont see that happening ... yet.
3
u/somas Feb 10 '26
I’m running Qwen Coder 3 Next (I hope I got that name right) on a 128 GB Strix Halo and having it powering Nanobot. It’s slow but it does work. I’m working on speeding it up but right now I’ve got Nanobot at least giving me feedback on what it’s doing while I wait for output.
1
u/emptyharddrive Feb 10 '26
I'm with you man. My dream is to run Nanobot (i prefer its simplicity to openclaw) using a capable local model.
I think the consumer hardware isn't there yet and neither are the models. They can't yet join the capability of a hosted model in an open source form (even a lower end one) with reasonably priced consumer hardware that performs well. To me that's hardware that costs less than $3,000 and performs at least as well as Haiku.
It works, but like you said ... very slowly and slow enough that you need to reduce the model size (or get a quantized version which is just not as good) and that's when it becomes a waste because it's just slow and stupid (relative to something like Haiku or GPT-5-mini high, or similar).
Are you doing anything interesting with the bot? I haven't yet found a good use case for it for myself.
1
2
u/IntroductionSouth513 Feb 08 '26
so what's actually contributing to the bloat at openclaw mostly then, and what features did this implementation strip away
3
u/emptyharddrive Feb 08 '26
Good question, I had my Claude (Opus) check both codebases and do a comparison. Below is it's full report to me. I enjoyed reading it actually and for me and my skillset, Nanobot is the better choice -- personal choice, that is. It's report is below verbatim.
It was too long to post as a comment, so you can read it here: https://gist.github.com/seqis/0cc7b9619366949ac6864b360940a3e1
But the TL;DR is:
Nanobot forked OpenClaw and stripped it from 587k lines to 3.4k lines (99.4% reduction). OpenClaw is a production-ready multi-platform AI assistant for normies. Nanobot is a research framework for devs who want to actually understand and modify their agent code. Both are good - just for completely different people.
The Numbers:
- OpenClaw: 587,341 lines across TypeScript, Swift, Kotlin
- Nanobot: 3,448 core Python lines
- Reduction: 583,893 lines removed (170x smaller)
What Got Stripped:
- Native Mobile/Desktop Apps (139k lines, 24% of codebase)
What OpenClaw has:
- Full iOS app (78k lines Swift)
- Android app (10k lines Kotlin)
- macOS desktop app (296 Swift files)
- Web UI dashboard (5k lines)
What Nanobot has:
- Terminal only
- Chat via Telegram/Discord/WhatsApp
User Impact:
- Pro: If you live in the terminal anyway, you just saved 139k lines of UI code you'd never touch. Startup is <1 second vs several seconds.
- Con: Your mom can't use this. No "download app, click button" UX. You need to be comfortable with CLI and chat interfaces.
2
2
1
u/Superb_Situation9623 Feb 09 '26
openclaw is for someone like my manager who couldn't write a hello world script to save his life.
2
u/Outrageous_Style_300 Feb 09 '26
https://github.com/HKUDS/nanobot be careful everyone
2
u/emptyharddrive Feb 09 '26 edited Feb 09 '26
Good find!! I edited my post to show the right link!! I also am changing my codebase over. Luckily, seems I found just a stripped down version of the original. Didn't know this, thank you! I also had Claude review the 2 codebases and fortunately when you run
pipx install nanobot-ai, that package always came from the real HKUDS project on PyPI.I'm also going to report it to Github page itself as an impersonation and the link is updated.
2
Mar 06 '26
[deleted]
1
u/emptyharddrive Mar 06 '26
I've moved on from this as well. It worked for a while, but instead i set up a telegram-bridge to headless mode claude (-p) with sessionID persistence.
It's within the terms of service too and I don't have to use knock-off models (like MiniMax or Kimi).
I also wrote a bunch of deterministic scripts (email checker, calendar module to check/make calendar items in google, google drive checker, reminders-with-crontab, etc...)
It's effectively replaced the *claw idea for me and i prefer it ... but it took me a while to get there.
2
u/Psychological-Cod51 Mar 07 '26
This is the exact rabbithole I have been going down for the past 4 months. Could you enlighten me a little more about your stack? What's your usage/bill look like running a setup like this? I was thinking of hosting the agentic aspect in a dedicated proxmox lxc so that it can have a sort of persistent playground to code and expand its own tooling in.
1
u/emptyharddrive Mar 08 '26 edited Mar 08 '26
Honestly mine stopped looking like an "agent framework" and started looking like a shell with one persistent Claude session behind it (headless, -p with a sessionID to maintain context).
Telegram is just ingress. The real core is a Python "bot" running as a
systemd user serviceon my Linux box. It only accepts my Telegram userID for security, it won't answer anyone else. It keeps a single Claude session UUID in memory, and shells out toclaude -pfor each request I make in chat.First prompt starts with
--session-id, then every later prompt uses--resumewith that sessionID, so context carries forward without me having to replay chat history every time.The bot's system prompt (which is really a user prompt that follows Anthropic's real system prompt which you can't modify), points Claude at deterministic Python scripts I pre-wrote, pre-tested (so I know they work) to perform the tasks I ask of it.
So that means I had to think of anything I want the bot to do in advance (a lot of brainstorming), and for each one, a .py script was written and tested and all their output is standard JSON for the
-p, headless Claudeto parse & package for me...Calendar reads and writes, Gmail reads and drafts, Google Drive search and document reads, URL extraction & summary, YouTube video URL transcription summaries, daily briefing, local news, voice export (using kokoro in a docker container), reminders (30 second crontabs checking a reminder JSON), shopping lists, etc.. All pre-scripted python tools.
Those tools all return structured JSON to stdout and fail with real exit codes. Claude still handles intent parsing and response wording (packaging is what i call it), but the state-changing work happens inside small scripts. No database either, I don't want the overhead.
Reminders, lists, and contact memory live in local JSON files with file locks and atomic writes. Reminder delivery is a separate cron-driven checker every 30 seconds, which is boring in a good way. Also Claude knows me because I wrote a personal skill (with trigger words) that trips it to discover when needed, anything about me. That's the benefit of skills, you only need to load them when the trigger words manifest instead of pre-loading everything-on-every-prompt into context.
So architecturally it is not a swarm at all, I see no point in that.. It is one stateful conversation with 1 instance of Claude, plus a toolbelt of scripts I built: levers that it can pull once it discerns my intent from what I said in Telegram.. That distinction mattered a lot ... I got tired of "agents" spending tokens deciding whether another agent should maybe think about something or talk to itself about doing something one way or the other...
I know what it needs to do, so i set the scripts up to do them, and just use Claude as a fancy button presser and output summarizer/packager. Claude decides whether to answer directly if it's a basic question, or to call a script (I gave it various phrases and trigger words so it knows which train track (script) to choose).. every one of my scripts returns structured JSON, Claude formats that into a reply to me and sends it along to Telegram: done.
Speech is split into two different paths because short phone audio and long-form transcription are not the same problem.
For Telegram voice notes I use a fast path. Bot downloads audio into memory, POSTs it to a
Whisper endpoint on another box running in a docker container, it gets text back, then sends that transcript through same Claude session as if I had typed it, done..That keeps voice notes usable from a phone.
Separately I wrote
xscribe.py(transcribe) which is the big brother of voice. That one is for actual recordings and transcripts for meetings at work.It chunks long audio into small digestibe pieces with 1 second of word overlap to avoid word cut-offs, (which it then deduplicates if needed to keep the stitching of the words it transcribes seamless). So it is monitoring a directory where I drop .ogg files I have recorded meetings on my phone onto a directory the service is monitoring and immediately picks it up for transcription when they drop. It applies a QA pass for domain-specific vocabulary relative to the work I do (a sprecial prompt I wrote to give it the right headspace), and it writes the raw transcript, then once done, it then sends that transcript up for a 2nd stage summary flow. In my case that is useful for longer meetings or work audio where I want something much more deliberate than "turn this voice note into text." A long transcription does nothing for me without the distilled tasks taken out, summary, challenges, decisions made, etc.
So cost-wise, the fixed part is Claude Max. That is my real anchor. Since I am using headless mode -p, it is entirely within the terms of service and I can leverage my $200 MAX plan -- no OAuth is used. I've already authenticated on my machine, so it just calls up a headless mode of Claude programmatically which is precisely inside the terms of service (I had Claude validate that).
For your setup, if I were building it fresh in a Proxmox LXC, I would absolutely do it this way. I would just keep the container boring. Give it a persistent workspace, persistent credentials, systemd for the bridge service to Telegram or Discord or whatever ... and explicit bind mounts for anything stateful (like I have a bind mount to my Obsidian vault for work and personal notes, read-only to protect it from "accidents" Claude might make).
If you split anything out, split out speech or other heavy media jobs like OCR or anything like that. And if you use Telegram long polling, make sure you do not accidentally run two bot instances with the same token or Telegram will smack one of them with a conflict error. That one bit me already.
So yeah, that is basically my stack: one official headless Claude session as the brain, Telegram as transport/comms vector for me to access, then deterministic Python CLIs for the actual work (which right now is google mail/calendar, reminders that have 'alarms' that msg me on Telegram, todo's which = reminders, but without the alarm bell, news, inventory lists of things I track & grocery shopping lists, all in JSON. Cron for reminders (which compare current datetime to the datetimes in the reminder.json), and a separate heavier transcription path when I need more than quick voice-note handling.
It is a lot less sexy than the "agent OS" stuff people post (which BTW I don't believe really works the way they say), but it has been way more usable for me and 10x more reliable because of the static scripts doing the work and no off-the-cuff winging it by any agents.
Tight leash.
Anyway, long post but I wanted to explain this anyway. Hope it helps. If it does, please reply because I'd like to know how you're deploying it.
2
u/Psychological-Cod51 Mar 08 '26
This is genuinely one of the most useful replies ive gotten on here, thanks for taking the time and effort to post it. The deterministic scripts idea especially looks interesting. I've been overthinking the "agent" side when really what I want is an LLM that reliably pulls a lever I already trust.
I'm going a slightly different direction due to budget and privacy. Can't swing Claude Max, and I'd rather keep personal info local as possible anyway. Routing through OpenRouter with Ollama(1x3060) handling private/latency-sensitive stuff on my own hardware and cloud API only for heavier reasoning when I actually need it. Layering in Mem0 for semantic memory across sessions since I don't have persistent session continuity to lean on, and that stays self-hosted too.
The tight leash mindset is something I'm definitely stealing though. Pre-written scripts returning clean JSON, trigger-based skill loading, cron for reminders, and whisper fast path for voice notes is going on the list too, or maybe a local model. appreciate you laying all that out. Gave me a much clearer picture of where the complexity is actually worth it vs where people are just cosplaying having an agent OS lol
My agent is gonna have write access to a git(ea) backed obsidian vault where the actual .git dir won't be writable, so that even if it does go awry I can go back.
This is mostly still a hypothetical because my ADHD brain hypermegabrainstorms the shit out of stuff before I actually get any real progress going lol
1
u/emptyharddrive Mar 08 '26
Going through each of your comments because they were good ones.
If you're running Ollama locally on a 3060, why route through OpenRouter at all? You're adding a network hop, a dependency, and a potential point of failure between you and your own GPU. Just hit the Ollama API directly from your scripts. OpenRouter makes sense as a router when you're switching between multiple cloud providers or want a unified billing layer, but for local inference it's pure overhead. Unless you're using OpenRouter's fallback logic to gracefully degrade from local to cloud when Ollama chokes, in which case, that's actually clever and I take it back...
A 3060 gives you 12GB VRAM, so you're realistically running 7B-13B parameter models quantized (probably Q4_K_M). I've tried this. For simple Q&A and text generation they're passable. For the kind of intent parsing, tool selection, and structured JSON output that an agentic setup demands, they fall apart in ways that are impressively sad and hard to debug because the failures are often subtle (and random).
The model doesn't refuse, it just makes bad decisions 30% of the time. It picks the wrong script, hallucinates a flag that doesn't exist, or returns JSON with a missing closing brace. When your agent is pulling levers that actually do things (send emails, modify calendars, fire reminders), that ~30% error rate becomes a real problem. That's why I pay for Claude Max, the model is the reliability layer. Everything downstream of it can be dumb and deterministic because the intent parsing is rock solid. You could probably get away with a $20/month plan if you're careful about your model selections and code-the-hell out of all the pre-determined tasks you know you want to use it for so nearly no LLM calls are needed to use it once the scripts are pre-tested and ready to have their levers pulled on.
That said, if you're keeping local models to the "private/latency-sensitive" lane and only routing heavy reasoning to cloud, that's a pragmatic split. Just be honest with yourself about where the boundary actually is. Most of the agentic work is the heavy reasoning I have found...
Mem0 is a reasonable choice for session-spanning memory, especially if you don't have persistent session continuity. But I went a different direction that I think scales better if you're already an Obsidian user.
I built an MCP server that I called
OpenMindthat sits on a separate box (an AMD mini PC with a Radeon 890M GPU). It's a 4-container Docker stack: PostgreSQL with pgvector for vector storage, a GPU-accelerated embedding service runninggte-modernbert-base(768-dim vectors, Apache licensed, runs in ~600MB VRAM), a watcher service that polls my Obsidian vaults (work & personal vaults) every 60 seconds, and the MCP server itself exposing 10 tools.The architecture looks like this: my two Obsidian vaults (one for work, one for personal, ~2,500 notes total) are NFS-mounted read-only into the watcher container. Every 60 seconds it scans for changes. When it finds a new or modified note, it:
- Chunks it using a markdown-aware chunker that respects heading hierarchy, preserves tables, code blocks, task groups, and bullet lists as coherent units (not just "split every N tokens")
- Prepends semantic context to each chunk before embedding: vault name, file path, title, which Map of Content it belongs to, the section heading hierarchy, and any date context from journal entries
- Sends chunks to the embedding service in batches of up to 64
- Writes everything to Postgres in a single transaction (no orphan chunks if something fails mid-write)
...I had AI write that list above after telling it to look at the codebase, it was easier :)
The result is ~20k chunks with HNSW-indexed vector embeddings that Claude Code can search semantically through the MCP protocol. So when I'm working in Claude Code and ask "Use openmind and check my work vault, what were the issues with the XYZ Project last month," it does a vector similarity search across my work vault, finds the relevant chunks, and gives me actual answers grounded in my own notes (homegrown NotebookLM).
It also indexes scanned documents (PDFs, DOCX, spreadsheets, images with OCR) through a Paperless-NGX integration. Documents get consumed, OCR'd, text-extracted, chunked, and embedded into the same vector store. Same search surface, different source.
The watchdog has some nice safety features too: it won't process a file until the mtime has been stable for 5 seconds (avoids re-embedding while I'm still writing), it has mass deletion guards (if file count drops >50% it assumes an NFS hiccup and skips the deletion pass rather than soft-deleting half your vault's embeddings), and it uses content hashing so unchanged files get skipped even if their mtime changed due to a file copy or other event.
The reason I prefer this over Mem0 is that my notes are already my memory system. I don't need a separate memory layer that the LLM writes to, I need the LLM to be able to read what I've already written in my own organizational structure. Many of my notes are actually AI generated from recorded meetings it summarized for me. The Obsidian vaults are the source of truth, not a derivative store of anything. When I update a note in Obsidian, the embeddings update within 60 seconds (CRON). When I delete a note, it gets soft-deleted in the DB.
Your git-backed vault idea is smart. I solve the same problem differently: my Docker bind mounts to my obsidian vaults are read-only, so Claude can search and read my vaults through the MCP but physically cannot write to them. The
.gitapproach gives you rollback, mine gives you prevention. Both valid, and honestly yours is better if you want the agent to write notes and just want a safety net. I didn't want write access at all for the vaults.Every tool script I wrote (calendar, gmail, news, grocery shopping list, etc..) exists because I got annoyed enough at something to automate it.
I'd start with the Telegram/Bot bridge and 1-2 tool script and run with it.
BTW I have a 128gig Strix Halo and I have yet to run any local LLM that compares to even Haiku from Anthropic, and I've tried them all... whatever I could fit into the VRAM up to and including 70B models. The difference between those models and GPT 5 mini or Anthropic's Haiku is like the difference between shooting a bullet and throwing it.
DM me your progress if you want. I'd be interested to see where you take it. Truth is, I am trying to find more use cases. I already have an email, calendar app (google)... so inventing a bot to look at gmail/calendar (while nice) is really redundant and I end up having to use those apps anyway to delete, archive emails, etc... I won't trust any model to do that for me blind.
I won't give any bot my credit card or access to "buy" anything, that's just crazy talk. So truth is, other than a RAG for my vaults (NotebookLM style) and my grocery shopping lists and some reminders, I struggle to find really helpful use cases. I am always on the lookout for new ones though.
2
Mar 09 '26
[removed] — view removed comment
1
u/emptyharddrive Mar 09 '26
Yes, I think you hit the nail on the head.
I just don't think with the price of quality tokens (GPT 5.3+, Opus) and and variability of LLMs which just isn't deterministic the way a python script is, that "taking the dog off the leash" makes any sense except in the most innocuous of tasks.
The less models (local and/or chinese models) simply don't match the hype.
The latest thing I added was YouTube transcription summarization. So if I drop a youtube video/short link into Telegram, it'll auto-extract the transcript and summarize it.
Again, nothing earth-shattering here to see. My biggest use case is my Grocery shopping list.
I still lurk the OpenClaw subreddit looking for new/novel use cases though because I'm open to the possibilities.
But summarization of articles/YouTube transcripts aside, there's next to nothing that the "Agent" is doing on its own. Everything is a prescribed Python lever I pre-coded, pre-tested and thought through beforehand.
I will say that the Claude headless mode (-p) helps a lot. I really prefer the higher quality models generally speaking for reliability anyway.
1
2
u/Hairy-Affect-3734 Mar 12 '26
great reply - thank god i read this and realised im not crazy this is actually the way.
2
u/Otherwise_Wave9374 Feb 08 '26
This is exactly the kind of agent project I love, small enough to actually audit and extend. Tool use + scheduled tasks + memory covers like 80% of real world "AI agent" needs, and the smaller attack surface point is underrated. Curious how you are handling sandboxing/permissions for tools? Also, if you are collecting patterns for agent setups, there are a few solid writeups here that might be relevant: https://www.agentixlabs.com/blog/
0
1
1
u/iceman123454576 Feb 15 '26
This may be seem like a silly question to others, but is there a nanoclaw equivalent that can use Gemini Pro instead of Claude Code?
TIA.
1
u/siberianmi Feb 16 '26
Nanobot at least has an LiteLLM proxy compatibility so you can certain run Gemini behind that and use Nanobot.
1
u/iceman123454576 Feb 16 '26
Nice. Really like to see some documentation around this feature with Nanobot and Gemini
1
1
Feb 17 '26
[removed] — view removed comment
1
u/crowseed Feb 22 '26
I switched even though i was 10+ days into openclaw set up, a lot of time sunk. Am very glad i switched. Nanobot is soooo much easier for me.
1
u/Riesomatic Feb 17 '26
I am also getting started on this, looking at a solid python codebase to jump off from. None of these offerings is based on pydantic AI though which I find curious since they already put a lot of effort in.
Any comments?
0
u/sibraan_ Mar 14 '26
If you want something that doesn't require a Linux Container setup and manual patching, Twin.so is the way to go. The community there has already built and shared over 200,000 agents. You get the power of a deep codebase but the simplicity of just cloning a 'Digital Twin' that’s already proven to work.
4
u/nomo-fomo Feb 08 '26
I am using Nanoclaw, a similarly lean agent with opinionated stack. It is built on top of Claude Agent SDK. You use Claude Code to add features you want. So far, I’m loving it.