When I started building Jarvis, I thought the hard part was the voice. Wake-word detection, text-to-speech, session management, getting it to actually sound right when it answered. That whole surface area felt like the technical mountain.
Turns out the mountain was something else.
Jarvis runs on top of Mission Control, my local Claude Code setup. Say “Hey Jarvis” from anywhere in the house, it spins up a session and gets to work. I wired it into Home Assistant so it can toggle lights, locks, and switches. Gave it shell access so it can actually do things. Web tools for anything it needs to look up. I built it intentionally capable. That capability is what I then had to contain.
The obvious first move was blocking Jarvis from editing its own source. A live Jarvis session should not be able to rewrite the scripts that govern it. So I blocked the Edit and Write tools from anything inside Mission Control’s directory. Done. Secure. Good.
Then I thought about shell redirection.
echo "something" > scripts/jarvis.sh doesn’t go through the Edit tool. It goes through Bash. And I’d happily handed Jarvis Bash access. So the block did nothing. I’d closed one door and left the window wide open.
The fix was a Bash hook. Before any shell command runs in a live Jarvis session, it now checks whether the command writes to Mission Control’s source directory. If it does, blocked. Not elegant, not airtight, but it closes the path I should have thought of the first time.
Here’s what surprised me about this exercise. Building Jarvis wasn’t that hard. The wake-word stuff, the Home Assistant wiring, the voice synthesis, the session scaffolding, all of it came together over maybe three evenings. What took actual thinking was containment. Figuring out what “contained” even means for an AI that has shell access.
It’s not a firewall question. It’s a trust question. What should this thing be able to do to itself?
The answer is nothing. Which sounds obvious in retrospect. But when you’re in the middle of building something, capability is what feels like progress. Each feature Jarvis got was a good day. The session where I spent three hours writing a hook to stop Jarvis from writing hooks did not feel like a good day. It felt like maintenance. Necessary maintenance, but still.
This is the part of home AI nobody really writes about. Not because it’s a secret. Just because “I added a guard to prevent X” doesn’t make a great demo. But it’s the thing that lets you actually trust what you built. The capable version of Jarvis is the one I trust enough to leave running. Trust requires containment.
Jarvis can now turn off my lights, check whether my 3D printers are still running at midnight, answer questions about my calendar. That part is fun. But without the boring evening on the hooks, I’d be nervous every time it had shell access to a live session. The cage isn’t the feature. The cage is what makes the features safe to run.
If I could tell myself anything from three months ago: build the cage first. Not as cleanup. Not as an afterthought. The moment you give your AI real tools, containment stops being theoretical. Make it the second task, not the last one.