Introducing Leo: From OpenClaw to Native Claude Code
Like many, I participated in the AI agent revolution that is OpenClaw early this year. In the beginning, it was magical. It managed my inbox and calendar, kept me up to date on news. I even tried using it for coding.
It wasn’t long before I started to get frustrated. OpenClaw is a genuinely impressive project, but it moves fast and updates would frequently break things. It got to the point where I found myself spending more time making sure things were working than actually getting any benefit out of it. Eventually I found myself reaching for Claude Code more than my OpenClaw agent.
When Anthropic announced that their Claude subscription would no longer cover OpenClaw usage, I knew it was time to cut my losses. Claude on its own actually offers nearly everything I wanted out of OpenClaw. That’s why I built Leo, a thin wrapper around the claude CLI. Leo supervises claude processes, which can connect to channel plugins like Telegram or iMessage, dispatches ephemeral agents for targeted work, and includes a task scheduler. And the best part is that it’s all accessible from anywhere via the leo CLI and tmux.
What Leo is
Three primitives, one Go daemon.
- Processes: long-running Claude sessions, supervised with auto-restart. Each one gets its own workspace, model, permission mode, and channel plugins.
- Templates → Agents: reusable blueprints. Spawn an ephemeral agent from the CLI, the web UI, or a Telegram message. Leo clones the repo into a tmux session and the agent shows up in claude.ai like any other session (if remote control is enabled).
- Tasks: cron-driven non-interactive Claude runs. Prompt file, schedule, optional retry, optional channel-notify on failure.
A web dashboard, an HTTP API, and a built-in MCP server all live in the same binary. The MCP server is what makes the channel integrations feel native — every channel plugin gets /clear, /compact, /stop, /tasks, /agent, and /agents for free. I can type /tasks into Telegram and the supervised process routes the command back to the daemon.
Leo runs the stock claude CLI. It doesn’t fork it, wrap it in Python, or reimplement its runtime. Every supervised process is just claude attached to a tmux session that Leo watches. When Anthropic ships something new I pick it up on the next claude update.
How it fits together
Here’s a trimmed leo.yaml in the shape I use:
processes:
assistant:
model: opus[1m]
permission_mode: auto
channels: [plugin:telegram@claude-plugins-official]
enabled: true
agent: assistant # Uses Claude's agent flag to give my assistant a soul and identity
templates:
coding:
model: opus
permission_mode: auto
workspace: ~/.leo/agents
remote_control: true # Session appears in the Claude app and claude.ai
tasks:
daily-briefing:
schedule: "0 7 * * *"
timezone: America/New_York
prompt_file: prompts/daily-briefing.md
model: sonnet
channels: [plugin:telegram@claude-plugins-official]
enabled: true
inbox-calendar-watch:
schedule: "0 7-22 * * *"
timezone: America/New_York
prompt_file: prompts/inbox-calendar-watch.md
model: sonnet
channels: [plugin:telegram@claude-plugins-official]
enabled: true
assistant is a long-running process I talk to through Telegram. daily-briefing fires at 7 AM and writes me a morning summary. inbox-calendar-watch runs every hour during waking hours and only pings me if something actually needs attention.
To spawn a short-lived coding agent:
leo agent spawn coding --repo blackpaw-studio/leo --worktree feat/cache --name leo-cache
Leo clones the repo, creates a worktree, and starts claude in a named tmux session, reachable from my terminal, the Claude app, or claude.ai. To attach from a terminal:
leo attach leo-cache
This launches a tmux session giving you direct access to the Claude Code instance. This even works from a remote machine over SSH. When the work is done:
leo agent stop leo-cache --prune --delete-branch
The session closes, the worktree is removed, the branch is deleted. Short-lived spawn-and-cleanup is the flow this is best at.
Moving from OpenClaw
Because Leo runs the stock claude CLI, the migration was mostly translating configuration and moving markdown files. While Leo is certainly not a full replacement for OpenClaw, it gives me what I wanted from it and fits into my workflow far better.
Unlike OpenClaw, Leo doesn’t ship with any predefined behavior or knowledge aside from telling Claude how to utilize the available Leo functionality like agent and scheduled task management. Leo leaves you free to use whatever Claude Code plugins you want. For example, I’ve found the claude-mem tool to work significantly better than OpenClaw’s memory system. I just need to install the plugin once, and it’s available across all of my processes, agents, and tasks.
Final Thoughts
The system I was running before leaned heavily on a framework under active development. Now I only run native Claude Code, and Leo handles the supervision and scheduling bits around it.
Leo is still in alpha, so expect rough edges and occasional issues while things stabilize.
Leo is on GitHub and at leo.blackpaw.studio. Docs live at docs.leo.blackpaw.studio. This project is named after my void, Leo. He’s a very good kitty.
If you end up running it, I’d love to hear about it — reach out on Mastodon at @[email protected] or BlueSky at @edc.me.