A generative-UI playground for financial research. You bring an agent and your data; µ turns the agent's validated tool calls into a live canvas of typed cards — price charts, comparisons, news, release calendars, key stats, options boards, and your own brokerage portfolio — sitting beside the conversation that produced them.
The agent never writes UI code. It emits a validated spec; µ decides how to render it safely. Agent decides what to see · runtime decides how to render it · you stay in the conversation.
- You ask for something in plain language.
- The agent fetches data through µ's typed verbs (
data_fetch/view/list) and composes the canvas throughcanvas_*verbs — it moves handles, never bulk data. - µ validates every spec against a renderer contract and every payload against a data shape, then streams the full canvas to the browser, which renders it.
Data is normalized into a few canonical shapes; renderers bind to a shape, never a provider, so any source that produces a shape just works. The card is chosen by the question:
| Card | Shape | Answers | Sources |
|---|---|---|---|
| Price chart | ohlcv |
price action + 21 technical indicators | Yahoo |
| Comparison | ohlcv |
indexed relative performance | Yahoo |
| News wire | news |
headlines / catalysts (aggregated, labeled) | Yahoo, CNBC, Finnhub |
| Release calendar | releases |
expected vs actual, by date (bitemporal) | Finnhub earnings, FRED macro |
| Key statistics | key_stats |
what a company is right now | Finnhub |
| Options chain | options_chain |
calls │ strike │ puts ladder · IV smile · term structure | ORATS |
| Portfolio | positions |
your brokerage holdings · balances · equity curve | Alpaca |
| Memo | — | agent-authored prose | — |
A global refresh re-pulls bound data on demand; releases and key-stats are point-in-time, so each refresh accrues a new vintage rather than overwriting.
pnpm install
pnpm build
# server (omit MU_MODEL for API-only mode, no agent)
MU_MODEL=<provider/model> pnpm start # → http://localhost:4000
# web client, in another shell
pnpm dev:web # → http://localhost:5173µ works with no API keys (Yahoo/CNBC RSS for prices + news). Keys unlock more
sources — copy .env.example to .env and fill in what you want
(FINNHUB_API_KEY, FRED_API_KEY, ORATS_API_KEY for options, Alpaca keys for your
portfolio). The agent is enabled by two values: MU_MODEL
(a provider/model) and that provider's key (<PROVIDER>_API_KEY, e.g.
DEEPSEEK_API_KEY); µ supervises a headless opencode
to drive it. Omit MU_MODEL to run API-only (no agent).
A self-contained published image runs the whole thing — web + API + the agent — in one container on one port. You only bring a model key.
Easiest — Docker Compose:
cp .env.example .env # then edit .env: set MU_MODEL + your provider key
docker compose up # → http://localhost:4000Or a one-off docker run:
docker run --rm -p 4000:4000 -v mu-data:/data \
-e MU_MODEL=deepseek/deepseek-v4-pro \
-e DEEPSEEK_API_KEY=sk-... \
docker.io/spicadust/mu:latestOpen http://localhost:4000. Unlike dev (where Vite serves the web on :5173
separately), the image serves the web same-origin from the API server — one port, no CORS.
The /data volume persists the store, sessions, and the agent's own storage across restarts.
See DOCKER.md for the full image reference: every env var, volumes, API-only mode, building the image yourself, and troubleshooting.
A pnpm monorepo, TypeScript throughout. The data plane never imports the agent or the UI — opencode is replaceable at exactly one package, keeping the bring-your-own-agent promise honest.
packages/
protocol pure contracts — shapes, handles, canvas ops, renderer manifests
broker the data store — DuckDB + parquet, per-shape validate/merge
resource-sdk the resource plugin SDK + registry/loader
runtime sessions, the canvas applier, the tool surface
opencode-plugin the agent binding (the one opencode-coupled package)
server HTTP + SSE composition root
web the React/Vite client (its own build)
resources/ first-party data sources (yahoo-finance, rss-news, finnhub, fred, orats, alpaca)
pnpm test # deterministic, keyless suiteLive, network/model-gated suites opt in via env (e.g. MU_LIVE_OPENCODE=1 for the
full real-agent loop).
Design and contracts live in docs/ — start with
overview, then data-architecture,
the shape catalogue, and the HTTP/SSE API.
v0 — implemented and runnable end-to-end. Interfaces may still move.