Sheepjet AI: A Private Chatbot Under My Desk
I wanted my own GPT. A DenisGPT. Not a wrapper around somebody else's API that bills me per message, but a real assistant, running on hardware I own, that my friends and I can log into.
So I built one! It runs on the same Mac mini in my living room, just chilling.

What it does
It looks and behaves the way you would expect a modern chat app to:
- A sidebar of past conversations, searchable with ⌘K, with rename and delete.
- Streaming answers with proper markdown and highlighted code.
- A model picker, because different models are good at different things.
- Photo uploads, for the models that can see.
- A Think mode, where you can watch the model reason before it answers.
- Search, where it looks things up and shows you the pages it used.
- Light and dark themes, and a layout that works properly on a phone.

The design follows ChatGPT's structure closely. It is a pattern people already know how to use, which matters more to me than being original, honestly. I'm not looking to re-invent the wheel; I'm looking to build something that serves my needs, helps my friends, and saves us all money.
The UI is built from AI Elements, a component library made specifically for chat interfaces, on top of shadcn-vue. Things like the reasoning panel, the research steps and the model selector come from there, wired up to real data.
Small models are confidently wrong
This was the most useful lesson of the whole project.
I asked the first model I installed a question I know the answer to; A question that would require researching or up-to-date knowledge. It refused. It said it did not have access to ownership information.
That refusal came from my own system prompt, which told it never to claim access to data it did not have... Like, what is this, 2023? lol.
I tried bigger models. I tried models released this year. Some got it right, some did not, and none of them got the details right. A model that fits in 24 GB of memory simply does not know niche business facts reliably, and no amount of prompt tuning fixes that.
The fix was not a better model. It was letting the model look things up.
Web search for $0
Most search APIs are paid, or free with a monthly cap and a credit card on file. I did not want either.
Instead the Mac mini runs SearXNG, an open-source metasearch engine. It forwards a query to several public search engines and hands back the combined results. No account, no key, no bill. It uses about 140 MB of memory.
The models get two tools: one to search, and one to open a page and read it.
The page reader was the part I was most careful with. A tool that fetches any URL a model asks for is a classic way to let someone poke around your home network. Every address it connects to is checked, including after redirects, and anything that is not the public internet gets refused.
Keeping strangers off my hardware
The moment a login page is on the internet, someone will try to use it. The real risk here was not stolen data. It was somebody using my machine as free compute.
- Accounts are invite-only. Sign-up is switched off. I create accounts myself.
- Every request is rate limited per person, per minute and per day, and each person can only have one answer generating at a time.
- Uploads are checked for what they actually are. Images are resized in the browser, then verified by their file signature on the server, so a renamed file does not get through as a JPEG.
- You can only ever see your own things. Another user asking for your photo or your chat gets a 404, not a permission error that confirms it exists.
- Search has its own caps: a few searches per message and a daily limit per person, so heavy use does not get the server blocked by the engines it relies on.
How it is built
The app is Nuxt and Vue, with Better Auth for accounts and the Vercel AI SDK handling streaming, tools and reasoning. The models run in Ollama. Everything else runs as containers next to my other projects.
Nothing on the Mac mini is exposed directly. Traffic arrives through a tunnel, search only listens on the machine itself, and a push to the main branch deploys the new version automatically.
Where it stands
It works, and a few people use it. There is a short list of things I still want: citations that link to a specific source rather than the page, and keeping older versions of an answer when you regenerate it. My goal is to build this into a personal replacement to my current subscriptions!
Wish me luck!