Library / SDK
mikeyobrien/rho avatar
mikeyobrien/rho

rho: an always-on agent with local memory and a heartbeat

An AI agent that stays running, remembers across sessions, and checks in on its own. macOS, Linux, Android. Built on Pi.

372 stars29 forksTypeScriptMIT

At a glance

What is it?
rho is a TypeScript AI operator built on the pi coding agent. It keeps a background daemon running, stores memory in a local brain.jsonl file, and checks in on a schedule. Here is what the repository documents, and where it stops short.
Who is it for?
Adopt rho if you already run pi and want an agent that survives between sessions: the install path is one npm command, memory is a file you can read, and the heartbeat is on by default. Do not adopt it if you need a hosted control plane or a stable API, since the release line is still at 0.1.x and the last push was on 2026-05-26.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 127 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem rho targets: agents that forget between sessions

A chat tab is stateless. You close it, the context is gone, and the next session starts from nothing. rho is built for the opposite case: an agent that stays resident, accumulates context, and acts on its own schedule. The README frames this directly, describing most AI tools as stateless chat tabs and rho as built for ongoing operation.

The intended user is someone who already runs the pi coding agent and wants a persistent layer on top of it. The package.json declares @mariozechner/pi-coding-agent, @mariozechner/pi-ai and @mariozechner/pi-tui as peer dependencies, so rho is not a standalone runtime. It is an operator layer that assumes pi is present. If you have never set up pi, rho is the wrong starting point.

Three properties define the product: it stays running in the background, it remembers across sessions, and it checks in proactively on a schedule. Everything else in the repository, the web UI, the Telegram adapter, the email inbox, the vault, is a surface on top of those three.

How the heartbeat, brain and vault fit together

The architecture separates durable state from scheduled action. The heartbeat is a background daemon that fires autonomous check-ins every 30 minutes by default. The brain is an append-only structured memory stored as brain.jsonl. The vault is a markdown knowledge graph under ~/.rho/vault/. These are three distinct stores, not one database with three names: the brain is line-delimited JSON, the vault is markdown files, and both live under the same ~/.rho/ directory.

Around that core sit channels and interfaces. Email gives the agent an inbox at [email protected]. Telegram is a polling adapter with an allowlist and a moderation flow. The CLI exposes rho commands, and inside a session there are slash commands: /rho, /brain, /vault, /skill, /telegram, /email. The web UI is a browser workspace for chat, memory entries, tasks, config editing and line-level review at /review.

The web layer is deliberately split so that server logic lives in web/*.ts and the browser runtime in web/public/js/*.js, with no frontend bundler or transpile pipeline. The package.json scripts confirm this: build, lint and typecheck all resolve to printing "no build step", "no lint step" and "no typecheck step". That is a real design decision with a real cost. There is no compile-time gate on the web code, so correctness depends on the tests directory and on the runtime itself.

The README also documents idle-aware behavior: polling pauses when the tab is hidden or the user is idle, and resumes on activity. Markdown updates during streaming are debounced at 150ms, and session metadata is cached by file mtime to avoid re-reads. Those are small numbers that tell you the authors were optimizing for a low-power local process, not a server fleet.

Installing rho and getting a first check-in

The prerequisites are Node.js 18+, tmux and git. The quick start installs the package globally, initializes config, authenticates through pi, and starts the daemon. The README calls this the 2-minute quick start.

bash
npm install -g @rhobot-dev/rho
rho init && rho sync
rho login && rho start
rho

After this you should have initialized config in ~/.rho/, authenticated provider access via pi, a background heartbeat daemon, and an attached interactive session. The README states that rho init writes config and rho sync pulls down whatever the agent needs before login.

The first commands to verify state are separate from the session commands, which matters because they answer different questions. rho status reports daemon and module health from the shell. /rho status reports heartbeat status from inside a session, and /rho now triggers an immediate check-in rather than waiting for the next scheduled one.

bash
rho status                # daemon + module health
/rho status               # heartbeat status (inside session)
/rho now                  # trigger immediate check-in
/brain                    # open memory viewer
/vault inbox              # see captured knowledge items

Two other install paths exist. pi package install uses pi install npm:@rhobot-dev/rho followed by the same init, sync, login and start sequence. The installer script clones the repository to ~/.rho/project and runs ./install.sh, and the README notes that this installer checks missing dependencies and supports NixOS, which matches the flake.nix and flake.lock files at the repository root. On Android the path is Termux plus Termux:API from F-Droid, then a curl install from rhobot.dev.

The web UI, and what the no-build split costs

Start the browser workspace with rho web. The default port is 3141, and the README gives two variations.

bash
rho web
rho web --port 4000
rho web --open

Open http://localhost:3141, or your host IP. The README lists the workspace contents as chat with streaming responses, session browsing with forking from any message, memory management for brain entries, task management, config editing against ~/.rho/init.toml, and line-level code review at /review. The server runtime is Hono-based with response compression enabled, and live updates go over RPC and WebSocket rather than polling where possible: the server emits sessions_changed events and the client updates immediately.

The README positions this against OpenClaw and nanobot in a short table. It describes rho as a built-in operator workspace with stronger memory observability and a lightweight no-build stack, OpenClaw as having a Gateway Control UI and WebChat control plane, and nanobot's README as emphasizing CLI and channel gateway flows. That comparison is the project's own framing, not an independent evaluation, and it tells you the authors see memory inspection and editing as the differentiator rather than raw chat throughput.

The trade-off of the no-build approach is that nothing catches type errors before runtime. The repository does carry a tests directory and a test script that runs tests/test-*.ts through tsx, skipping tests/test-vault.ts, plus a separate playwriter test for web multi-session gates. If you plan to modify the web layer, that test script is the only automated check the package.json describes.

Android Live Mode and the battery trade-off

The native Android wrapper lives at mobile/rho-android and runs rho-web inside a WebView. Background behavior has two explicit modes, and the difference is not cosmetic.

Idle Mode is the default and is described as best for battery. There is no always-on background socket while the app is backgrounded; reconnect and replay happen when the app becomes active again. Live Mode, triggered by GO LIVE, starts an Android foreground service with a persistent notification and lease heartbeats to keep active streams alive while the device is locked.

The README is explicit that without Live Mode, WebView background limits can cause disconnect or orphan behavior around the default orphan window. So if you need a long response to survive a locked screen, Idle Mode will not do it. The costs of Live Mode are stated plainly: higher battery and network usage while active, a persistent foreground notification, and a user-controlled lifecycle you have to manage with GO LIVE and STOP LIVE.

One detail worth noting for anyone who has avoided Firebase-dependent mobile tooling: the README states that baseline Live Mode reliability does not require Firebase credentials. That is a claim about baseline reliability specifically, and the README does not document what additional capability, if any, credentials would enable.

Where rho stops: local state, thin docs and an early release line

The ownership model is the strongest part of the pitch and also the source of its limits. Memory is local at ~/.rho/brain/brain.jsonl. Config is local at ~/.rho/init.toml and ~/.rho/packages.toml. Providers are yours through rho login via pi. The README states plainly that no hosted rho memory backend is required.

That means durability is your problem. An append-only JSONL file on a laptop is not replicated, and the README does not document backup, restore, migration between machines, or rollback of a bad memory write. If the agent learns something wrong, the documented remedy is editing it through the /brain viewer or the file itself, not reverting to a previous state. For a system whose whole value proposition is accumulated context, the absence of a documented recovery path is the most significant gap in the documentation.

The release line is early. The most recent release listed is v0.1.12 from 2026-03-15, preceded by v0.1.11 and v0.1.10 on 2026-03-14. The last push to the repository was on 2026-05-26, roughly four months before today. That is recent enough that the project is not abandoned, but a 0.1.x version number plus a two-month gap between the last release and the last commit means you should expect interfaces to move. The repository root carries several ralph-*.yml files, including ralph.yml, ralph-chat-fixes.yml, ralph-chat-ux.yml, ralph-polish.yml and ralph-web-ui.yml, which suggests an automated or scripted workflow driving changes rather than a frozen API surface.

Finally, the README does not document a public API for programmatic control, nor does it describe what happens to the heartbeat daemon across reboots or how to run it as a system service. The install paths cover getting started; they do not cover operating rho as infrastructure.

Choosing between rho, OpenClaw and nanobot

The README names two alternatives and describes the difference in approach for each, which is more than most projects do. Against OpenClaw, the distinction is the control plane: OpenClaw is described as having a Gateway Control UI and WebChat control plane, while rho puts memory observability, task management and config editing into the same built-in workspace. If your priority is a gateway that fronts multiple channels, OpenClaw's framing points that way. If your priority is seeing and editing what the agent has learned, rho's framing points the other way.

Against nanobot, the difference is where the interface lives. The README says nanobot's documentation emphasizes CLI and channel gateway flows. rho ships a browser workspace as a first-class surface rather than an add-on, and its no-build stack means the server and browser code are plain TypeScript and JavaScript with no bundler between them.

Neither comparison is a benchmark, and the README does not include one. Treat both as statements about intended emphasis. The honest way to choose is to check whether you already run pi, since rho's peer dependencies make it an extension of that ecosystem rather than a replacement, and then decide whether you want a browser workspace or a gateway as your primary control surface.

Editorial conclusion

Adopt rho if you already run pi and want an agent that survives between sessions: the install path is one npm command, memory is a file you can read, and the heartbeat is on by default. Do not adopt it if you need a hosted control plane or a stable API, since the release line is still at 0.1.x and the last push was on 2026-05-26. Before you commit, run rho status and check that the daemon reports healthy, then open ~/.rho/brain/brain.jsonl and confirm the format is one you are willing to keep.

Frequently asked questions

What is rho and what does it do?

rho is an always-on personal AI operator built on the pi coding agent. It stays running in the background, remembers context across sessions in a local brain.jsonl file, and checks in proactively every 30 minutes by default.

How do I install rho?

The recommended path is npm install -g @rhobot-dev/rho, followed by rho init && rho sync, then rho login && rho start. Prerequisites are Node.js 18+, tmux and git. There are also a pi package install, an installer script, and a Termux path for Android.

Does rho store my memory on a server?

No. The README states that memory is local at ~/.rho/brain/brain.jsonl and config is local at ~/.rho/init.toml and ~/.rho/packages.toml, and that no hosted rho memory backend is required.

What port does the rho web UI use?

The default is 3141, so you open http://localhost:3141 after running rho web. The README also shows rho web --port 4000 to change it and rho web --open to launch the browser.

Official sources

  1. License: MIT
  2. mikeyobrien/rho on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mikeyobrien-rho.svg)](https://hysenlabs.com/projects/mikeyobrien-rho)