# Agent OS: Bun + Ink + WebSocket shell-native orchestrator

Source: https://www.michaelchurley.com/blog/agent-os-bun-ink-websocket-zsh-orchestrator  
Published: 2026-03-21  
Author: Michael C. Hurley  
Tags: agent-os, hurleyus, bun, ink, websocket, zsh, orchestrator, mission-control, openclaw, anthropic, terminal-ui, michaelmonetized

## Who

I still run multi-agent days where the bottleneck is the shell context, the task queue, and whether each agent can see my real `~/.zshrc` aliases instead of a sandboxed stub.

For operators wiring local agent pools against a Mission Control ship list on their own machine.

## What

I shipped **HurleyUS Agent OS**, public https://github.com/michaelmonetized/agent-os. HEAD `f66fffa`. **2** commits. package **hurleyus-agent-os@1.0.0**.

![Ink UI](/blog/agent-os-bun-ink-websocket-zsh-orchestrator/screenshots/ink-ui.png)

`orchestrator.ts` is an Ink React terminal UI plus a `WebSocketServer` on **ws://localhost:9999**. Agents connect with `?agent=<name>`, pull `task_dispatch`, and stream `task_output` / complete / fail. State lives in `~/.hurleyus/agent-os/state.json`; every session transcript lands in `~/.hurleyus/agent-os/sessions/<sessionId>.log`.

![Zsh agent](/blog/agent-os-bun-ink-websocket-zsh-orchestrator/screenshots/zsh-agent.png)

`agent-client.ts` spawns **interactive zsh** (`zsh -i -c …`), sources `~/.zshrc`, optionally loads `~/.hurleyus/GOALS` and `~/.hurleyus/TASKS`, then evals the task description. If the cwd is a git repo it auto-commits `[agent-name] <taskId>` and pushes `origin HEAD`.

![Mission Control seed](/blog/agent-os-bun-ink-websocket-zsh-orchestrator/screenshots/mc-seed.png)

`mission-control-tasks.ts` seeds **seven Phase 1 tasks** aimed at `hurley-mission-control`: Convex backend, web layout, architecture review, message wiring, polling, Vercel deploy, QA smoke. `cli.ts load-mission-control` / `start.sh` load that list.

![Dual path gaps](/blog/agent-os-bun-ink-websocket-zsh-orchestrator/screenshots/dual-path-gaps.png)

Same tree also has `core.ts`: four personas (Codex Dev, SR Designer, SR Architect, QA Auditor) on `claude-opus-4-6` via Anthropic Messages API, with a dependency-aware priority queue. Honest gaps: `@anthropic-ai/sdk` is imported but **missing** from `package.json`; `.env` with `ANTHROPIC_API_KEY` is **still tracked** after the `.gitignore` commit (gitignore only covers `node_modules/`, `*.log`, `.DS_Store`). OpenClaw relay to `ws://192.168.1.134:18789` is stubbed. `agent-runner.sh` is a file inbox/outbox fallback, not live WS.

Sibling tools in the same shop: orclawstrator's OpenClaw `:3377` gateway, the Go p10k `mission-control` portfolio TUI, the Convex human|agent `hurley-mission-control` web plane, and `shagent`'s MCP/OpenRouter loop. Agent OS is the Ink/WS/zsh control plane with a Mission Control Phase 1 seed.

## Where

Code: [github.com/michaelmonetized/agent-os](https://github.com/michaelmonetized/agent-os), public, no LICENSE file (README: internal HurleyUS).

```bash
git clone https://github.com/michaelmonetized/agent-os.git
cd agent-os
bun install
# Terminal 1
bun cli.ts run-orchestrator
# Terminal 2+
bun cli.ts spawn-agent codex-dev
bun cli.ts spawn-agent sr-designer
# Load Phase 1
bun cli.ts load-mission-control
bun cli.ts status
```

Local only: orchestrator `ws://localhost:9999`. Optional env `OPENCLAW_GATEWAY`. Runtime state under `~/.hurleyus/agent-os/`.

## When

Created on GitHub **2026-03-20**. First commit **11:13 AM ET** same day: full v2 surface (Ink + WS + zsh + CLI + Mission Control seed). Second commit **10:25 PM ET**: `.gitignore` only. GitHub `pushed_at` **2026-03-21T02:25:13Z**. Pack prepared **2026-09-08 ~5:17 PM ET**. Draft + assets only.

## Why

I needed a shell-native control plane that treats agents like terminals with jobs. Ink for the operator view, WebSocket for fan-out, real zsh so aliases and git muscle memory stay intact, and a Mission Control Phase 1 seed so the queue is not empty on day one. The Anthropic `core.ts` path is the API-side twin when you want model output without a shell; the gaps (missing SDK dep, tracked `.env`) are the honest day-one scars.

**Engagement Q:** How would you unify the Ink/WS/zsh path and the Anthropic `core.ts` path: one CLI surface, or keep them as two intentional modes?
