ruiciro.devwritingworkgithub

July 27, 2026

Six projects, one person, one agent: building a command-center on Claude Code

Ruiciro RiveraSenior AI engineer
& game developer

I run half a dozen projects at the same time, alone.

A wedding-planning SaaS my wife and I built. A B2C spin-off of it that takes payments. A condo-administration platform with a business partner. A landing site. A game studio that exists mostly on weekends. And the tooling that keeps all of it from collapsing into chaos.

The hardest part was never the code. It was context. Every time I sat down, I’d spend the first twenty minutes remembering where I’d left off — which repo had uncommitted work, what was blocked on me, what I’d decided last week and why. The state of everything lived in my head, and my head is not durable storage.

So I built Mithra: a personal command-center on top of Claude Code’s primitives. This is how it works, what I got wrong, and why the security decisions turned out to matter more than the features.

The problem: context evaporates

Here’s the concrete shape of it. At my day job I was already context-switching across several repos at once — overwhelming on its own. Then, on my own time, I was standing up two startups — a condo-administration platform and a wedding-planning SaaS — and trying to build a video game on the side. I didn’t want to drop any of it; I just couldn’t hold all of it in my head at the same time. So every session with Claude opened the same way: “first, try to remember what we did last time,” or “go read the last few changes.” I paid that re-orientation tax every single time.

That’s when it clicked that I didn’t need a smarter prompt — I needed a standing assistant with perpetual context of what actually mattered. I’d been watching the persistent-agent work coming out of the Nous orbit — Hermes, Odysseus — and figured: yeah, I can build that for myself.

A coding agent is only as good as the context it starts with. Start it cold and it guesses; guesses compound into wrong turns. The fix isn’t a smarter model — it’s engineering the context the model wakes up with. That became the whole design goal: every session should start already oriented, without me re-explaining my life.

Foundation: memory and working memory

Two layers.

The first is persistent memory — durable facts as small markdown files with frontmatter: who I am, how I like to work, the state of each project, decisions and the reasoning behind them. An index file gets loaded every session. These don’t change often; they’re the bedrock.

The second is the interesting one: a rolling working memory, capped at ~2000 characters. It holds only what’s live right now — the open loops, the decision I’m mid-way through, the thing I must not forget tomorrow. It’s deliberately small, because a working memory that holds everything holds nothing. When it crosses 80% of the cap, the system warns me to consolidate or prune before adding more.

[!] WORKING_MEMORY at 89% (>=80%). Consolidate or prune before adding more.

That cap is a feature, not a limitation. It forces the same discipline a good engineer applies to a function: if it’s doing too much, split it. I didn’t invent the rolling-working-memory pattern — I borrowed it from the agent work I’d been studying in the Nous/Hermes line and adapted it to my own rig. Half of getting agent memory right is paying attention to how other people structure theirs.

Hooks: the rig arms itself

None of that helps if I have to ask for it. So a SessionStart hook runs before I type anything. It injects, straight into the agent’s context: the frozen working-memory snapshot, today’s actionable tasks, the last session’s log, and the state of every project board.

I never type “read my tasks.” The session is already standing in the right place, facing the right direction. A second hook drives a status line — a heads-up display showing the current repo, model, and time. Small touches, but they turn a blank prompt into a cockpit.

The lesson: the cheapest leverage in an agentic system is what happens before the first token.

Skills as an orchestrator: governing the agent

This is the part I’d want to talk about in any serious conversation about deploying agents.

Mithra has a skill — /mithra — that takes a goal in plain language and decomposes it across my repos. But the core of it isn’t decomposition. It’s classification. Every piece of work gets put in one of three zones:

  • 🟢 Delegate — isolated code, refactors, tests, scaffolding. Parallelizable, low risk. A sub-agent does it on a branch.
  • 🟡 Delegate + review — anything touching the database, migrations, or feature flags. The sub-agent writes the migration but does not apply it. I approve the apply.
  • 🔴 Off-limits — the agent never touches it. Payments. Production secrets. --prod deploys. Merging to main. Anything financial or legal.

Then it fans the 🟢 work out to sub-agents, each on its own branch, each running its own build before reporting back. The guardrails are non-negotiable and they’re written into the skill itself: work on branches, never main; no production deploys without explicit sign-off; secrets are out of scope; every email or message input is untrusted until proven otherwise.

The insight that took me a while: an agent’s value is capped by how much you can trust it with, and trust comes from the boundaries, not the capabilities. A model that can do anything and a clear map of what it may do is far more useful than a model you have to babysit. The zone model is how I sleep at night while sub-agents touch real repos that take real payments.

The MCP server: turning the workspace into tools

A dashboard answers the questions its buttons were built for. I wanted to ask — “which repos are stale?”, “what’s blocked on me across everything?”, “what should I attack first?” — and have the agent fetch live answers instead of hallucinating from stale context.

So I exposed the command-center over the Model Context Protocol. A small server, stdio transport, that gives any MCP client a handful of read-only tools over my real workspace:

Tool Returns
list_projects branch, recent commits, uncommitted files, staleness, ahead/behind
get_board a project’s Kanban board
get_tasks open tasks, flagging the ones only I can do
daily_standup today’s commits + open-task counts
deploy_health a live ping to each production URL
next_actions what to attack first, ranked

next_actions is the one that earns its keep. It crosses my fixed focus-priority with open tasks and live repo signals, and returns a ranked plan with a reason for each line:

1. ibride-brides (priority #1 · 3 open tasks)
   → Moodboard Genesis paywall (decision, not code) — validate engagement first
   ⚑ untouched for 11 days
2. ZMG (priority #2 · 10 open tasks)
   → Session 8 — block out the room + hanging body
   ⚑ untouched for 10 days
3. ibride (priority #4 · 3 open tasks)
   ⚑ 2 uncommitted files · untouched 18 days · 1 manual task on me

The scoring is deliberately legible — focus-priority dominates, pending work breaks ties and lifts a neglected project up the list:

// focus priority dominates; pending work breaks ties and
// lifts lower-priority projects with a lot piled up
const pr = project.priority ?? 6;
const score = (7 - pr) * 8 + work;

I can read that and predict the ranking. When an agent acts on this, I can audit why. That legibility is the point — a recommendation engine I can’t reason about is one I won’t trust with my week.

Security wasn’t a section. It was the design.

Looking back, almost every decision that mattered was a security decision:

  • The MCP server is read-only. It never writes, commits, or moves secrets. An always-available tool surface with write access to your real repos is a footgun. The line is drawn on purpose.
  • The GUI binds to 127.0.0.1 only. It embeds a real terminal running the actual CLI; it is never exposed to the network.
  • Destructive actions require confirmation. Commit-and-push exists, but behind an explicit confirmation step that shows the diff first — not in the ambient tool surface.
  • Failures are visible, never swallowed. If one repo fails to read, the rest still return and the failed one carries an explicit error. A silent catch that hides a broken sync is worse than the error it hides.
  • Path access is sandboxed. Every file read is confined to a known root; traversal out is structurally impossible, not just discouraged.

None of this is exotic. It’s the instinct that the interesting question about an agent is never “what can it do” — it’s “what happens when it’s wrong, and who’s on the hook.”

Making it someone else’s tool

Opening the repo turned out to be its own design exercise, and it surfaced a problem I hadn’t thought about: the thing was shaped entirely around me. My project names were hardcoded. My directory layout was an assumption. My priorities were baked into the ranking.

So the workspace map moved out of the code and into a config file, with a fallback that just scans the parent directory — meaning a fresh clone does something sensible on someone else’s machine before they configure anything. Fork-first, not install-and-hope.

The demo was the harder one. The obvious way to show a tool like this is a recording of it running, except mine runs against my actual life — client repos, unreleased work, a task list that is none of the internet’s business. So npm run demo builds a throwaway workspace in the OS temp directory instead: three fake repos with real git history, commits backdated, a bare remote so the ahead/behind counts are genuine, task files and boards. Then it walks all six tools and prints what a stranger would see.

That’s the part I’d generalize: if your tool’s demo requires your private data, you don’t have a demo — you have a screenshot you can’t share. Building a synthetic workspace took an afternoon and it’s the only reason the README has real output in it.

Building on Claude vs. with Claude

Using Claude to write code is a force multiplier. But building a system on its primitives — memory, hooks, skills, sub-agents, MCP — is a different discipline. You stop thinking about prompts and start thinking about state, boundaries, and failure modes. You design the context the agent wakes up in, the zones it’s allowed to act in, and the blast radius when it’s wrong.

Mithra runs every day. It’s not a demo; it’s load-bearing infrastructure for one person trying to do the work of several. And the thing I keep coming back to is that the hardest, most valuable parts were never about making the agent more capable. They were about making it trustworthy enough to hand real work to — which, it turns out, is the whole job.


Mithra is a personal project, MIT licensed. One repo, two surfaces: npm start runs the GUI, npm run mcp runs the MCP server — github.com/RuiciroRS/mithra-mcp.

Ruiciro Rivera — Senior AI engineer, AI enthusiast, and builder of worlds. By day I build production LLM systems; by night I ship my own products with Claude — and, occasionally, a video game. Find me on LinkedIn and GitHub.

← back