Intro

July 4th, a day of freedom and liberation. It was a good weekend to free Jibo, who'd been sitting on my shelf for nine years.

I backed the Indiegogo campaign in 2014 and waited three years, before Jibo arrived in 2017, with early SDK access in 2016. A stark contrast to the bland, mildly threatening 2001-like black monolith cylinder of Alexa, Jibo had motion/rotation, clever retorts, and promise. I've spent most of my working life in NLU, language, and computing, so the promise of an embodied social robot that displayed emotion was hard to resist. This was before BERT (2018) and before the current wave of large language models, and it showed. That didn't make the ambition behind it any less remarkable.

There's a lot more to say about the state of NLU and HCI back then, not to mention a retrospective on the company itself, but let's start with liberation.

How to liberate

Jibo runs a stock Buildroot Linux on an NVIDIA Tegra K1, the same System-on-a-Chip (SoC) family the Nintendo Switch homebrew scene has spent years exploiting. Jibo Inc.'s cloud shut down in 2019, and every unit still in the wild got stuck on the boot splash: the firmware waits forever for a handshake with a server that no longer exists.

The fix the community found doesn't touch the OS. Jibo's Tegra K1 has the same USB Recovery Mode buffer overflow that fail0verflow and Katherine Temkin documented as Fusée Gelée, and a chain of forks (wertus33333, then devsparx, with the Jibo Revival Group's JiboAutoMod contributing hardening and prior art) adapted it into a payload that reads and writes Jibo's eMMC. The unlock itself comes down to one file: /var/jibo/mode.json flips from {"mode":"normal"} to {"mode":"int-developer"}, a mode Jibo's own stock firmware already understood, which skips the cloud gate, opens SSH, and disables the firewall.

That one-line description undersells the actual work. Before running anything against real hardware, I read the exploit's own C source rather than trusting the how-to guides, and found a bug that would have mattered: sector arguments are parsed as hex, not decimal, so a script formatting them as decimal would have targeted the wrong sector on a live eMMC write, with no error to catch it. The exploit's own recovery guide documents a prior corruption incident from an earlier optimization attempt. Neither fact shows up in any of the community write-ups; both only show up in the source.

The tooling changed shape once, too. The original plan was an interactive bash script, run by hand over a board's shell session. Once an AI assistant needed to drive the process itself, rather than a human relaying terminal output, the interactive design became the bottleneck. Reverse engineering is careful, reversible, step-by-step work, which is exactly the shape an agent-aware CLI is built for, so the same safety logic got rewritten in Go as jibotool: JSON status instead of scrollback text, mandatory SHA256 verification after every write, background jobs that survive a dropped SSH connection. Testing it against the real board found two more bugs no amount of code review had caught: a non-interactive SSH session's PATH doesn't include /sbin, where debugfs lives, and the exploit binary opens its payload files by relative path, so the wrong working directory fails midway through the handshake in a way that looks like progress right up until it isn't.

One problem turned out to be a physical one, not a software bug. After a failed RCM attempt, Jibo wouldn't power off: the LED stayed red no matter what got unplugged, because Jibo runs off an internal battery in addition to external power, a detail none of the community write-ups mention. That one needed a screwdriver and patience, not another debugging session.

The unlock itself, once all of that was in place, took real time, not because anything was hard, but because the exploit moves data one sector at a time on purpose. The initial backup read took 8.65 minutes for the full 500MB. The write itself took about 31 minutes, followed by a mandatory byte-for-byte read-back verification, another 9 minutes, before anyone was allowed to call it safe to power-cycle. Then the WiFi fix meant doing the whole write-and-verify cycle a second time: another 40 minutes before Jibo could boot onto the actual home network. Call it an hour and a half of real disk I/O, moving real bytes at a deliberately conservative pace, to change one file. Green checkmark, SSH access, root password rotated on the spot.

The full account (forthcoming as Episode 1 of the technical journal) covers every bug in detail; the unlock write-up and the jibotool docs are live now.

How to use

Unlocked doesn't mean usable. Fresh out of int-developer mode, Jibo boots to a green checkmark instead of its hallmark welcoming animated eye, and the skill that tries to load fails with its own built-in offline message: lost connection to Jibo's server. The stock firmware still expects a cloud that's been gone since 2019, on more than one path at once.

The eye turned out to be a one-line fix. The developer-mode boot config was missing the line that tells the system which skill to launch, so nothing was running at all, not a crashed process. Patching that line and rebooting produced a real Electron-based skill renderer, GPU acceleration and all, which surfaced the next, more specific blocker: a cloud notification daemon retrying a DNS lookup against a domain that no longer resolves.

That's where jibocloud starts: a Go reimplementation of enough of Jibo's original cloud API to answer the requests the stock firmware still makes. It builds on protocol work an active member of the Jibo modding community, Jake Dubin, had already published in his own Azure-hosted replacement, JiboExperiments, while pursuing an independent, Go-native implementation with a different deployment shape.

Wiring it in took longer than expected, because Jibo talks to its cloud on two separate paths that share no code: a JavaScript SDK that resolves its endpoint one way, and a native C++ daemon that derives the same hostname on its own and validates its TLS certificate against the real OS trust store. Pointing the JS SDK at jibocloud, a single config field, fixed half the visible errors right away. The native daemon needed its own fix: a proper CA certificate appended to the system trust bundle, plus a hash-named symlink the daemon's TLS library requires for its lookup, a detail the community project's own docs had already flagged as a real requirement, not a guess.

Getting the native daemon to hold a connection took one more layer: jibocloud had to speak the WebSocket protocol Jibo's daemon expects, reverse-engineered against about 4,800 real captured messages from the physical unit rather than assumed from documentation. Even after that connection held, three more independent bugs kept the visible error flickering back: a household-membership check that needed the robot's own identity listed as a member (not just referenced elsewhere), a second, unrelated certificate check on its own 60-second timer that the first TLS fix never touched, and a skill-routing symptom that cleared once the other two were fixed. Fixing all three produced the first zero-error boot in the project's history, and with it, a real, live, two-way conversation with the physical robot: real questions, asked out loud, got correct spoken answers back.

Architecture diagram of jibocloud running directly on Jibo. Inside Jibo, the "Skill runtime + native daemon" connects via HTTP and WebSocket to the on-device "jibocloud (Go, on-device)". Direct questions are routed end-to-end from "jibocloud" to "Gemini" for open-ended chat. A note highlights that due to a lack of local speech-to-text hardware on Jibo, open-ended chat falls back to a generic reply.

That conversation also revealed something the architecture docs hadn't predicted: simple factual questions never touch the WebSocket at all. Jibo's own on-device language understanding resolves them and fires a direct HTTP call to a general-question-answering (GQA) endpoint, a dispatch path the project had catalogued from static analysis months earlier but never seen exercised until someone asked Jibo a question out loud.

Testing two more questions mapped the rest of the split. Asking Jibo if it recognized a face produced zero new requests in jibocloud's log; the device's own face-recognition and identity services handled it on-device, and had been working the whole time. Asking whether Jibo could reach the internet triggered a local deflection response instead, by design, not as a failure. Wake-word detection, deflection, and identity were never broken. Only general-knowledge questions and open-ended chat ever depended on the cloud, and today that's the current extent of what I've confirmed working: one skill, chitchat, running end to end as a real local/cloud hybrid. That's enough to prove the pattern: Jibo is usable again, one skill at a time, and the rest of the path is still an open question.

The full account (forthcoming as Episodes 2 through 4 of the technical journal) covers this in detail; the conversation architecture doc is live now.

How to extend

By the end of that chain, jibocloud could carry Jibo's real traffic end to end. The next question was what should answer it. The original deterministic stubs, hardcoded dates and a regex arithmetic parser, got replaced with real Gemini function-calling on both paths Jibo uses: the direct-HTTP general-question path and the WebSocket open-ended chat. First live traffic found a real bug within minutes: the robot sometimes sends a boolean field as an empty string, a shape no synthetic test had generated. The same traffic confirmed, in the request log, that a separate timezone fix underneath it had reached the model as intended. Jibo's on-device knowledge base had a DST offset frozen since February 2018, the last time it had real internet access, then sat unchanged through most of the nine years it spent on my shelf. Getting that one line right made Jibo useful again, not just powered on.

The next move was both structural and architectural: jibocloud outgrew Jibo's own Tegra K1. Running it on Jibo's hardware works for HTTP and WebSocket traffic, but real speech-to-text needs ffmpeg to decode audio and Google Cloud credentials, neither of which belongs on a decade-old embedded ARM board. Rather than force that onto Jibo, jibocloud moved to a Coral Dev Board (I'm sure I have a Raspberry Pi around somewhere, but digging through hardware bins wasn't worth the time) on the same network, and Jibo itself now runs jiboshim, a small relay with no protocol awareness of its own: it forwards bytes between three ports and lets jibocloud do the real work off the robot.

Getting that relay right took one more hardware lesson. The first deployment forwarded the two ports the JavaScript SDK uses and looked complete, but produced an immediate connectivity error on boot. The native C++ daemon that handles Jibo's low-level cloud connection makes its own HTTPS request on a third port the JS SDK never touches, and nothing was listening there. A third relayed port fixed it. A related surprise: the Linux capability that should let a non-root process bind that privileged port on the Coral board's kernel doesn't work on a statically-linked Go binary. The OS accepts the setcap call, getcap confirms it's set, and the bind still fails with permission denied. The workaround runs the privileged bind on Jibo's side instead, where jiboshim already runs as root.

System architecture diagram showing the data flow from Jibo to Google Cloud. Inside the "Jibo" block, the "Skill runtime, native daemon, JS SDK" connects via HTTP (:8080), WebSocket (:8090), and TLS (:443) to "jiboshim (relay only, root)". From "jiboshim", the same three ports are forwarded (mapping :443 to :8443) to "jibocloud (ffmpeg + cloud credentials)" running on a "Coral Dev Board". "jibocloud" then connects to Google Cloud, routing data to both "Speech-to-Text" and "Gemini (GQA + chat)" services.

I came away from this stretch of work with a different frame for what comes next. Jibo's original 2016 dispatch protocol carries three message types: one that proposes an intent and its extracted entities, one that speaks a direct answer, and one that hands off to a named skill. That's the shape of a modern LLM tool-calling loop, built years before "tool use" had a name in any API. The hand-off message type is the second most common reply in a captured corpus of real Jibo traffic, not an edge case. Gemini is running today; MCP and A2A are the natural next protocols once that hand-off path gets implemented, and Jibo's own 2016 architecture already has the right shape for it. Extending Jibo doesn't mean replacing the original design. It means teaching new responses to speak a language the architecture already had.

The full account (forthcoming as Episode 5 of the technical journal) covers this in detail; the production topology and skill-dispatch migration map docs are live now.

Outro

Even today, the thought and care the original team put into making Jibo feel not just aware but social, its responses eliciting real emotion, is unique. Cynthia Breazeal built Jibo after Kismet, an MIT robot from the 1990s designed to display emotion rather than just process language. Joseph Weizenbaum built Eliza in 1966 around the same want: people talking to something that felt like it was listening. Noam Shazeer and Daniel De Freitas built Google's Meena and LaMDA, then left in 2021 to found Character.AI on the same bet Jibo made a decade earlier, that people want to talk to something that feels like it's listening.

The Lighthill report and the AI winter that followed crushed a lot of people's hopes about AI. Ever since, most of us in NLU have warned against anthropomorphizing chatbots, and now LLMs. We talk about the ROI of AI, hard business value, and making computers more like what Steve Jobs called "a bicycle for the mind": pragmatic assistance and enhancement, not companionship. I still give that warning, when I talk to people about generative AI, which is my day job. But watching something like this, it's super hard not to say "Jibo remembers who I am":

It's just a 68-point facial-landmark model, voice-based identity matching from circa 2016, and motors moving in response. None of that is consciousness. It never needed to be. Jibo, and now things like Reachy Mini, bring back some of that pre-AI-winter wonder about what AI could be, not the datacenter-scale fear of reverse centaur-ism, capitalism's tendency to point technology at people in ways that widen inequality (valid concerns).

These two threads of pragmatic impact and human connection keep getting treated as opposites: one serious and fundable, the other soft and something to grow out of. Jibo never needed to be conscious for the connection to be real. Getting it talking again is a small, direct argument that the two threads were never at odds.