{"id":44914103,"url":"https://github.com/milady-ai/milady","last_synced_at":"2026-05-03T07:02:47.219Z","repository":{"id":336988725,"uuid":"1151870687","full_name":"milady-ai/milady","owner":"milady-ai","description":"terminally online","archived":false,"fork":false,"pushed_at":"2026-04-30T05:20:11.000Z","size":732030,"stargazers_count":396,"open_issues_count":7,"forks_count":67,"subscribers_count":2,"default_branch":"develop","last_synced_at":"2026-04-30T06:15:22.774Z","etag":null,"topics":["agent","agent-skills","agents","autonomous-agents","clawd","clawdbot","clawdbot-plugin","eliza","elizaos","openclaw","openclaw-skills"],"latest_commit_sha":null,"homepage":"https://milady.ai","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/milady-ai.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/security.md","support":null,"governance":null,"roadmap":"docs/roadmap.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-02-07T02:28:06.000Z","updated_at":"2026-04-30T04:26:28.000Z","dependencies_parsed_at":"2026-02-11T11:02:47.971Z","dependency_job_id":"bf574691-7932-4286-85b7-8a8c8c96af3a","html_url":"https://github.com/milady-ai/milady","commit_stats":null,"previous_names":["elizaos/milaidy","milady-ai/milady"],"tags_count":133,"template":false,"template_full_name":null,"purl":"pkg:github/milady-ai/milady","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/milady-ai%2Fmilady","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/milady-ai%2Fmilady/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/milady-ai%2Fmilady/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/milady-ai%2Fmilady/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/milady-ai","download_url":"https://codeload.github.com/milady-ai/milady/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/milady-ai%2Fmilady/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32560914,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T06:36:36.687Z","status":"ssl_error","status_checked_at":"2026-05-03T06:36:09.306Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent","agent-skills","agents","autonomous-agents","clawd","clawdbot","clawdbot-plugin","eliza","elizaos","openclaw","openclaw-skills"],"created_at":"2026-02-18T01:13:54.095Z","updated_at":"2026-05-03T07:02:47.212Z","avatar_url":"https://github.com/milady-ai.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Milady\n\n[![CI](https://github.com/milady-ai/milady/actions/workflows/ci.yml/badge.svg)](https://github.com/milady-ai/milady/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n\n\u003e *your schizo AI waifu that actually respects your privacy*\n\n**Milady** is a personal AI assistant that is **local-first by default** and can also connect to **Eliza Cloud** or a **remote self-hosted backend** when you want hosted runtime access. Built on [elizaOS](https://github.com/elizaOS).\n\nManages your sessions, tools, and vibes through a Gateway control plane. Connects to Telegram, Discord, whatever normie platform you use. Has a cute WebChat UI too.\n\ntl;dr: local AI gf that's actually fast and doesn't phone home\n\n### Energy and polish (desktop)\n\nMilady is **not** a full IDE: the product bet is **fewer wasted GPU frames and wakeups** when you are not looking at the app—especially **on battery**—while keeping the **companion visually strong** when you are. Background polling, off-screen WebGL, and battery-aware render quality are tuned toward that (see [Desktop — battery and energy](docs/apps/desktop.md#battery-and-energy-use-macos)). Comparing to **Cursor** or other heavy dev tools is **workload-dependent**; the north star is **great UX per watt** for a local assistant, not matching an editor’s surface area.\n\n### Desktop 3D avatar (Electrobun / Vite)\n\nIf the **VRM** or **Gaussian splat** background fails only in the **desktop** build, the usual cause is **two copies of `three`** in the bundle (nested `node_modules` vs repo root), which breaks Spark’s **`splatDefines`** shader chunk. Milady forces **one** Three resolution path in Vite and isolates world-load failures so the **avatar** can still load. **Why it matters:** the companion is an **agent surface** (visibility + voice sync), not decoration. See **[Desktop VRM, Three.js, and Spark — WHYs](docs/apps/desktop-vrm-three-and-spark.md)**.\n\n### Dashboard chat: progressive action updates\n\nWhen **actions** call `HandlerCallback` several times in one turn (same idea as Discord **progressive messages**), the Milady API **replaces** the last action-produced segment in the SSE stream instead of concatenating every status line. **Why:** Live status should read like **edits to one message**, not a glued blob. The elizaOS contract stays **`callback({ text, source })`**. **Docs:** [Action callbacks and SSE streaming](docs/runtime/action-callback-streaming.md).\n\n---\n\n## BSC / BNB Chain Integration\n\nMilady ships with native **BNB Smart Chain (BSC)** support — your agent can trade tokens, track meme launches, and interact with DeFi on BSC out of the box.\n\n### Trading (PancakeSwap)\n\nThe built-in `EXECUTE_TRADE` action lets your agent swap tokens on BSC via PancakeSwap. Supports buy/sell with configurable slippage.\n\nTo enable BSC trading, add to your `.env` or `~/.milady/.env`:\n\n```bash\nEVM_PRIVATE_KEY=0x...                    # wallet private key (hex, 0x-prefixed)\nELIZA_TRADE_PERMISSION_MODE=agent        # \"agent\" for autonomous, \"user\" for manual confirm\n```\n\nOptional RPC configuration (defaults to public BSC RPC):\n\n```bash\nALCHEMY_API_KEY=...                      # or use ANKR_API_KEY / INFURA_API_KEY\nEVM_RPC_PROVIDER=alchemy                 # alchemy | infura | ankr | elizacloud\n```\n\nOnce configured, just tell your agent: *\"buy 0.1 BNB of \\\u003ctoken address\\\u003e\"* or *\"sell all my \\\u003ctoken\\\u003e\"*.\n\n### Meme Token Discovery (Binance Skills Hub)\n\nInstall the **meme-rush** skill from [Binance Skills Hub](https://github.com/binance/binance-skills-hub) to track meme token launches across BSC and Solana:\n\n- **Meme Rush** — real-time token lists from Pump.fun, Four.meme across new, finalizing, and migrated stages\n- **Topic Rush** — AI-powered market hot topics with tokens ranked by net inflow\n\nInstall from the Skills Marketplace in the app, or ask your agent to install it.\n\n### Wallet\n\nMilady auto-generates EVM and Solana wallet addresses on startup. For BSC trading you need to import your own private key (see above). If connected to **Eliza Cloud**, managed wallets via Privy are available without local key management.\n\nView your agent's wallet addresses in the Settings tab or ask: *\"what's my wallet address?\"*\n\n---\n\n## Downloads\n\n### Desktop App (recommended for normies)\n\nGrab from **[Releases](https://github.com/milady-ai/milady/releases/latest)**:\n\n| Platform | File | |\n|----------|------|---|\n| macOS (Apple Silicon) | [`Milady-arm64.dmg`](https://github.com/milady-ai/milady/releases/latest) | for your overpriced rectangle |\n| macOS (Intel) | [`Milady-x64.dmg`](https://github.com/milady-ai/milady/releases/latest) | boomer mac (why separate arm64/x64: [Build \u0026 release](docs/build-and-release.md#macos-why-two-dmgs-arm64-and-x64)) |\n| Windows | [`Milady-Setup.exe`](https://github.com/milady-ai/milady/releases/latest) | for the gamer anons |\n| iOS | App Store (coming soon) | for the privacy-pilled |\n| Android | [Google Play](https://play.google.com/store/apps/details?id=ai.milady.app) / [APK](https://github.com/milady-ai/milady/releases/latest) | for the degen on the go |\n| Linux | [`.AppImage`](https://github.com/milady-ai/milady/releases/latest) / [`.deb`](https://github.com/milady-ai/milady/releases/latest) / [Snap](#snap) / [Flatpak](#flatpak) / [APT repo](#debian--ubuntu-apt) | I use arch btw |\n\nSigned and notarized. No Gatekeeper FUD. We're legit.\n\n### Verify (for the paranoid kings)\n\n```bash\ncd ~/Downloads\ncurl -fsSLO https://github.com/milady-ai/milady/releases/latest/download/SHA256SUMS.txt\nshasum -a 256 --check --ignore-missing SHA256SUMS.txt\n```\n\n### Desktop: reset app data\n\n**Milady → Reset Milady…** (menu bar) confirms in the **native** dialog, then the **main process** calls **`POST /api/agent/reset`**, restarts the agent (embedded or external API), and tells the renderer to apply the **same local state wipe** as the end of Settings reset (onboarding, API client, cloud UI, conversations). **Why main does HTTP:** on macOS/WKWebView, the webview can fail to run **`fetch`** immediately after a native dialog, so a renderer-only reset looked stuck. **Why the renderer still runs teardown:** one implementation of “clear UI + `MiladyClient`” avoids duplicating logic in TypeScript main vs React.\n\n- **Docs:** [Desktop app](docs/apps/desktop.md) (native application menu section), [Main-process reset — WHYs](docs/apps/desktop-main-process-reset.md)\n- **Optional network / TTS:** with the agent orchestrator loaded, Edge TTS may call **Microsoft’s cloud** unless you set **`MILADY_DISABLE_EDGE_TTS=1`** — see [Environment variables](docs/cli/environment.mdx#runtime-behavior) and [TTS plugin](docs/plugin-registry/tts.md)\n\n---\n\n## Getting Started\n\n### New Environment Setup (recommended)\n\n```bash\ncurl -fsSL https://get.milady.ai | bash\nmilady setup\n```\n\nThen start Milady:\n\n```bash\nmilady\n```\n\nFirst run walks you through onboarding:\n\n```\n┌  WELCOME TO MILADY!\n│\n◇  ♡♡milady♡♡: Hey there, I'm.... err, what was my name again?\n│  ● Sakuya\n│  ○ Reimu\n│  ○ Koishi\n│  ○ Marisa\n│  ○ Custom...\n│\n◇  Sakuya: Now... how do I like to talk again?\n│  ● uwu~       (soft \u0026 sweet)\n│  ○ hell yeah   (bold \u0026 fearless)\n│  ○ lol k       (terminally online)\n│  ○ Noted.      (composed \u0026 precise)\n│  ○ hehe~       (playful trickster)\n│  ○ ...         (quiet intensity)\n│  ○ lmao kms    (unhinged \u0026 dark)\n│\n◇  Connect a brain\n│  ● Anthropic (Claude)\n│  ○ OpenAI (GPT)\n│  ○ Ollama (local, no key)\n│  ○ Skip for now\n│\n◇  API key?\n│  sk-ant-•••••••••••••••••\n│\n└  Starting agent...\n\n   Dashboard: http://localhost:2138\n   Gateway:   ws://localhost:18789/ws\n\n   she's alive. go say hi.\n```\n\n### Alternative install paths\n\nWindows:\n```powershell\nirm https://get.milady.ai/install.ps1 | iex\n```\n\nNPM global:\n```bash\nnpm install -g miladyai\nmilady setup\n```\n\n### Building from source (developers)\n\nMilady vendors [elizaOS](https://github.com/elizaOS/eliza) as a **git submodule** (with **nested** plugin submodules). Bun resolves root `workspace:*` dependencies **before** lifecycle scripts such as `preinstall`, so on a **fresh clone** a plain `bun install` can fail until those checkouts exist.\n\n**First install after cloning:**\n\n```bash\ngit clone https://github.com/milady-ai/milady.git\ncd milady\n\n./install                 # Unix / macOS — chmod +x install if needed\n# install.cmd on Windows\n\n# Both wrappers init the git submodules first, then run `bun install`.\n# This is required on a fresh clone: Bun resolves workspace globs\n# (eliza/packages/*, eliza/plugins/*) before running the preinstall\n# hook, so without submodules on disk the initial `bun install` fails.\n# Once the submodules exist, plain `bun install` is enough for updates.\n```\n\n**Move eliza and all nested submodules to the latest remote branches** (see `eliza/.gitmodules` for each `branch =`):\n\n```bash\nbun run workspace:bump-eliza-submodules\n```\n\nThen, if `git status` inside `eliza/` shows updated submodule paths, commit there first, then `git add eliza` at the Milady root. Details: [CONTRIBUTING.md](CONTRIBUTING.md#local-clone-and-eliza-submodule-maintenance).\n\n#### Windows: enable long paths\n\nBun's cache stores packages in deep directory trees that exceed the default Windows `MAX_PATH` limit (260 characters). Native builds (e.g. `llama-cpp-capacitor` via CMake/ninja) will fail with `mkdir: No such file or directory` unless long paths are enabled at the OS level.\n\nRun once in an elevated PowerShell, then reboot:\n\n```powershell\nNew-ItemProperty -Path \"HKLM:\\SYSTEM\\CurrentControlSet\\Control\\FileSystem\" `\n  -Name \"LongPathsEnabled\" -Value 1 -PropertyType DWORD -Force\n```\n\nAlso enable long paths in Git:\n\n```bash\ngit config --global core.longPaths true\n```\n\n### Homebrew (macOS / Linux)\n\n```bash\nbrew tap milady-ai/milady\nbrew install milady          # CLI\nbrew install --cask milady   # Desktop app (macOS only)\n```\n\n### Snap\n\n```bash\nsudo snap install milady\nmilady setup\n```\n\nSnap packages auto-update in the background. Available on Ubuntu, Fedora, Manjaro, and any distro with [snapd](https://snapcraft.io/docs/installing-snapd) installed.\n\nFor the latest development builds:\n```bash\nsudo snap install milady --edge\n```\n\n### Flatpak\n\n```bash\nflatpak install flathub ai.milady.Milady\nflatpak run ai.milady.Milady\n```\n\nOr sideload from a [release bundle](https://github.com/milady-ai/milady/releases/latest):\n```bash\nflatpak --user install milady.flatpak\n```\n\n### Debian / Ubuntu (APT)\n\n```bash\n# Add the repository\ncurl -fsSL https://apt.milady.ai/gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/milady.gpg\necho \"deb [signed-by=/usr/share/keyrings/milady.gpg] https://apt.milady.ai stable main\" | \\\n  sudo tee /etc/apt/sources.list.d/milady.list\n\n# Install\nsudo apt update \u0026\u0026 sudo apt install milady\n```\n\nWorks on Debian 12+, Ubuntu 22.04+, Linux Mint 22+, Pop!_OS, and other Debian derivatives. Updates come through `apt upgrade`.\n\n### Security: API token\n\nThe API server binds to `127.0.0.1` (loopback) by default — only you can reach it. If you expose it to the network (e.g. `MILADY_API_BIND=0.0.0.0` for container/cloud deployments), **set a token**:\n\n```bash\necho \"MILADY_API_TOKEN=$(openssl rand -hex 32)\" \u003e\u003e .env\n```\n\nWithout a token on a public bind, anyone who can reach the server gets full access to the dashboard, agent, and wallet endpoints.\n\n### Hosting Modes\n\nOn first run, onboarding now asks where the backend should live:\n\n- `Local` — run the backend on the current machine, exactly like the existing local flow.\n- `Cloud` — either use `Eliza Cloud` or attach to a `Remote Milady` backend with its address and access key.\n\nIf you choose `Eliza Cloud`, the app provisions and connects to a managed backend. If you choose `Remote Milady`, the frontend rebinds to the backend you specify and continues against that API.\n\n### Remote Backend Deployment\n\nUse this when you want the Milady frontend to connect to a backend running on your VPS, homelab box, or another machine.\n\n1. Install Milady on the target machine.\n2. Bind the API to a reachable address.\n3. Generate a strong API token.\n4. Allow the frontend origin explicitly.\n5. Expose the backend over HTTPS or a private Tailscale URL.\n\nRecommended server environment:\n\n```bash\nexport MILADY_API_BIND=0.0.0.0\nexport MILADY_API_TOKEN=\"$(openssl rand -hex 32)\"\nexport MILADY_ALLOWED_ORIGINS=\"https://app.milady.ai,https://milady.ai,https://elizacloud.ai,https://www.elizacloud.ai\"\nmilady start\n```\n\nThe access key the user enters in onboarding is the value of `MILADY_API_TOKEN`.\n\nIf you want to connect from the desktop shell instead of the web frontend:\n\n```bash\nMILADY_DESKTOP_API_BASE=https://your-milady-host.example.com \\\nMILADY_API_TOKEN=your-token \\\nbun run dev:desktop\n```\n\n### Tailscale\n\nFor private remote access without opening the backend publicly, expose it over your tailnet:\n\n```bash\ntailscale serve --https=443 http://127.0.0.1:2138\n```\n\nIf you intentionally want a public Tailscale URL:\n\n```bash\ntailscale funnel --https=443 http://127.0.0.1:2138\n```\n\nThen use the Tailscale HTTPS URL as the backend address in onboarding and keep using the same `MILADY_API_TOKEN` as the access key.\n\n### Eliza Cloud\n\n`Milady` uses the existing `Eliza Cloud` deployment directly at `https://elizacloud.ai`. The managed control plane, auth surface, billing, and instance dashboard all live there; there is no separate Milady-hosted cloud control plane to deploy.\n\nManaged browser flow:\n\n1. Sign in on `https://elizacloud.ai/login?returnTo=%2Fdashboard%2Fmilady`\n2. Open or create a Milady instance in `https://elizacloud.ai/dashboard/milady`\n3. Eliza Cloud redirects to `https://app.milady.ai` with a one-time launch session\n4. `app.milady.ai` exchanges that launch session directly with Eliza Cloud and attaches to the selected managed backend\n\nThe desktop/local app still exposes local `/api/cloud/*` passthrough routes for cloud login, billing, and compat management so it can persist the Eliza Cloud API key into the local config/runtime. That is local app plumbing, not a separate hosted Milady server.\n\nThe integration plan lives in [docs/eliza-cloud-rollout.md](docs/eliza-cloud-rollout.md).\n\nThe implementation and proxy runbook lives in [docs/eliza-cloud-deployment.md](docs/eliza-cloud-deployment.md).\n\n---\n\n## Terminal Commands\n\n```bash\nmilady                    # start (interactive, opens dashboard)\nmilady start              # server-only mode (API server, no interactive chat loop)\nmilady --verbose          # enable informational runtime logs\nmilady --debug            # enable debug-level runtime logs\n```\n\n### Setup \u0026 Config\n\n```bash\nmilady setup              # first-time setup / refresh workspace after update\nmilady configure          # interactive config wizard\nmilady config get \u003ckey\u003e   # read a config value\nmilady config path        # print resolved config file path\nmilady config show        # display all config values grouped by section\n```\n\n### Dashboard \u0026 UI\n\n```bash\nmilady dashboard          # open web UI in browser\nmilady dashboard --port 3000  # custom port\n```\n\n### Models\n\n```bash\nmilady models             # list configured model providers\n```\n\n### Plugins\n\n```bash\nmilady plugins list            # browse registry plugins\nmilady plugins installed       # what's installed\nmilady plugins install \u003cname\u003e  # install a plugin\nmilady plugins uninstall \u003cname\u003e\nmilady plugins search \u003cquery\u003e  # search by keyword\n```\n\n### Misc\n\n```bash\nmilady --version          # version check\nmilady --help             # help\nmilady doctor             # diagnose issues\n```\n\n---\n\n## TUI (Terminal UI)\n\nWhen running, milady shows a live terminal interface:\n\n```\n╭─────────────────────────────────────────────────────────────╮\n│  milady v2.0.0                              ▲ running      │\n├─────────────────────────────────────────────────────────────┤\n│                                                             │\n│  Agent: mila                                                │\n│  Model: anthropic/claude-opus-4.7                           │\n│  Sessions: 2 active                                         │\n│                                                             │\n│  ┌─ Activity ──────────────────────────────────────────┐    │\n│  │ 12:34:02  [web] user: hey mila                      │    │\n│  │ 12:34:05  [web] mila: hi anon~ what's up?           │    │\n│  │ 12:35:11  [telegram] user joined                    │    │\n│  │ 12:35:15  [telegram] user: gm                       │    │\n│  │ 12:35:17  [telegram] mila: gm fren                  │    │\n│  └─────────────────────────────────────────────────────┘    │\n│                                                             │\n│  Tokens: 12,847 in / 3,291 out   Cost: $0.42                │\n│                                                             │\n╰─────────────────────────────────────────────────────────────╯\n  [q] quit  [r] restart  [d] dashboard  [l] logs  [?] help\n```\n\n### TUI Hotkeys\n\n| Key | Action |\n|-----|--------|\n| `q` | quit gracefully |\n| `r` | restart gateway |\n| `d` | open dashboard in browser |\n| `l` | toggle log view |\n| `c` | compact/clear activity |\n| `?` | show help |\n| `↑/↓` | scroll activity |\n\n### Server-only mode\n\nDon't want the interactive TUI? Use the `start` command, which runs in server-only mode (API server, no interactive chat loop):\n\n```bash\nmilady start\n```\n\nLogs go to `stdout/stderr`. Daemonize with your favorite process manager.\n\n---\n\n## Chat Commands (in any chat session)\n\n| Command | What it do |\n|---------|------------|\n| `/status` | session status, tokens, cost |\n| `/new` `/reset` | memory wipe, fresh start |\n| `/compact` | compress context (she summarizes) |\n| `/think \u003clevel\u003e` | reasoning: off\\|minimal\\|low\\|medium\\|high\\|max |\n| `/verbose on\\|off` | toggle verbose responses |\n| `/usage off\\|tokens\\|full` | per-message token display |\n| `/model \u003cid\u003e` | switch model mid-session |\n| `/restart` | restart the gateway |\n| `/help` | list commands |\n\n---\n\n## Ports\n\n**Production** (`milady start`):\n\n| Service | Default | Env Override |\n|---------|---------|--------------|\n| Dashboard + API | `2138` | `MILADY_PORT` |\n| Gateway (WebSocket + HTTP) | `18789` | `MILADY_GATEWAY_PORT` |\n| Home Dashboard | `2142` | `MILADY_HOME_PORT` |\n| WeChat Webhook | `18790` | `MILADY_WECHAT_WEBHOOK_PORT` |\n\n**Development** (`bun run dev`):\n\n| Service | Default | Env Override |\n|---------|---------|--------------|\n| API + WebSocket | `31337` | `MILADY_API_PORT` |\n| Dashboard UI (Vite) | `2138` | `MILADY_PORT` |\n| Gateway | `19001` | `MILADY_GATEWAY_PORT` (set by `--profile dev`) |\n\n**If a default port is already in use:** `bun run dev` / `dev-server.ts` can bind to a different port and then **sync `MILADY_API_PORT` / `ELIZA_PORT`** to match. **`dev:desktop` / `dev:desktop:watch`** resolve **free** loopback ports **before** spawning Vite + API + Electrobun so proxy, `MILADY_RENDERER_URL`, and `MILADY_DESKTOP_API_BASE` stay aligned—**why:** Vite reads `vite.config.ts` once; guessing the API port only inside the API process would desync the UI proxy. The **packaged Electrobun** shell picks the next free port from `MILADY_PORT` for the embedded child instead of `lsof`+SIGKILL by default—**why:** two Milady installs (separate state dirs) should coexist. Opt-in old reclaim: **`MILADY_AGENT_RECLAIM_STALE_PORT=1`**. See [Desktop local development](docs/apps/desktop-local-development.md#when-default-ports-are-busy) and [Desktop — Port configuration](docs/apps/desktop.md#port-configuration).\n\n```bash\n# custom ports\nMILADY_GATEWAY_PORT=19000 MILADY_PORT=3000 milady start\n```\n\n---\n\n## Config\n\nLives at `~/.milady/milady.json` (override with `MILADY_CONFIG_PATH` or `MILADY_STATE_DIR`)\n\n```json5\n{\n  agent: {\n    name: \"mila\",\n    model: \"anthropic/claude-opus-4.7\",\n  },\n  env: {\n    ANTHROPIC_API_KEY: \"\u003cANTHROPIC_API_KEY\u003e\",\n  },\n}\n```\n\nOr use `~/.milady/.env` for secrets.\n\n---\n\n## Model Providers\n\n| Provider | Env Variable | Vibe |\n|----------|--------------|------|\n| [Anthropic](https://anthropic.com) | `ANTHROPIC_API_KEY` | **recommended** — claude is cracked |\n| [OpenAI](https://openai.com) | `OPENAI_API_KEY` | gpt-4o, o1, the classics |\n| [OpenRouter](https://openrouter.ai) | `OPENROUTER_API_KEY` | 100+ models one API |\n| [Google Gemini](https://ai.google.dev) | `GOOGLE_API_KEY` | gemini pro, flash, ultra |\n| [Google Antigravity](https://cloud.google.com/vertex-ai) | `GOOGLE_CLOUD_API_KEY` | vertex AI / cloud models |\n| [Ollama](https://ollama.com) | — | local, free, no API key, full privacy |\n| [Groq](https://groq.com) | `GROQ_API_KEY` | fast af |\n| [xAI](https://x.ai) | `XAI_API_KEY` | grok, based |\n| [DeepSeek](https://deepseek.com) | `DEEPSEEK_API_KEY` | reasoning arc |\n| [Mistral](https://mistral.ai) | `MISTRAL_API_KEY` | mistral + mixtral |\n| [Together AI](https://together.ai) | `TOGETHER_API_KEY` | open-source model hosting |\n| [Cohere](https://cohere.com) | `COHERE_API_KEY` | command R+ and embed |\n| [Perplexity](https://perplexity.ai) | `PERPLEXITY_API_KEY` | search-augmented gen |\n| [Qwen](https://qwen.ai) | — | alibaba's qwen models (configure via plugin entry) |\n| [MiniMax](https://minimaxi.com) | — | minimax language models (configure via plugin entry) |\n| [Zai](https://homunculuslabs.com) | `ZAI_API_KEY` | homunculus labs zai |\n| [Vercel AI Gateway](https://sdk.vercel.ai) | `AI_GATEWAY_API_KEY` | unified gateway |\n\nSee [Model Providers](docs/model-providers.mdx) for the full provider reference with configuration details. The `milady models` command checks which providers are configured.\n\n### Using Ollama (local models)\n\n[Ollama](https://ollama.com) lets you run models locally with zero API keys. Install it, pull a model, and configure Milady:\n\n```bash\n# install ollama\ncurl -fsSL https://ollama.com/install.sh | sh\n\n# pull a model\nollama pull gemma3:4b\n```\n\n\u003e **⚠️ Known issue:** The `@elizaos/plugin-ollama` has an SDK version incompatibility with the current AI SDK. Use Ollama's **OpenAI-compatible endpoint** as a workaround:\n\nEdit `~/.milady/milady.json`:\n\n```json5\n{\n  env: {\n    OPENAI_API_KEY: \"ollama\",           // any non-empty string works\n    OPENAI_BASE_URL: \"http://localhost:11434/v1\",  // ollama's openai-compat endpoint\n    SMALL_MODEL: \"gemma3:4b\",           // or any model you pulled\n    LARGE_MODEL: \"gemma3:4b\",\n  },\n}\n```\n\nThis routes through the OpenAI plugin instead of the broken Ollama plugin. Works with any Ollama model — just make sure `ollama serve` is running.\n\n\u003e **OpenRouter (`@elizaos/plugin-openrouter`):** Milady pins the dependency to **`2.0.0-alpha.13`**. **Why:** npm **`2.0.0-alpha.12`** published **truncated** JavaScript bundles: the files export `openrouterPlugin` / default but never define them (the main plugin chunk is missing), so Bun fails when loading the plugin. A caret range would allow that broken version again. See [Plugin resolution — pinned OpenRouter](docs/plugin-resolution-and-node-path.md#pinned-elizaosplugin-openrouter) and [OpenRouter plugin doc](docs/plugin-registry/llm/openrouter.md#milady-pinned-version-and-upstream-bundle-bug).\n\n**Recommended models for local use:**\n\n| Model | Size | Vibe |\n|-------|------|------|\n| `gemma3:4b` | ~3GB | fast, good for chat |\n| `llama3.2` | ~2GB | lightweight, quick responses |\n| `mistral` | ~4GB | solid all-rounder |\n| `deepseek-r1:8b` | ~5GB | reasoning arc |\n\n---\n\n## Prerequisites\n\n| | Version | Check | Install |\n|---|---------|-------|---------|\n| **Node.js** | \u003e= 22 | `node --version` | [nodejs.org](https://nodejs.org) |\n| **Bun** | latest | `bun --version` | `curl -fsSL https://bun.sh/install \\| bash` |\n| **Git** | any | `git --version` | system package manager |\n\n**Optional** (for vision/TTS plugins with native deps):\n- macOS: `xcode-select --install`\n- Linux: `sudo apt install build-essential python3 libcairo2-dev libjpeg-dev libpango1.0-dev`\n\n## Build from Source\n\n```bash\ngit clone https://github.com/milady-ai/milady.git\ncd milady\nbun install          # runs postinstall hooks (patches deps, seeds skills, etc.)\nbun run build\nbun run milady start\n```\n\n\u003e `bun run build` runs the production build via Node (`eliza/packages/app-core/scripts/run-production-build.mjs`).\n\n### Dev mode (recommended for development)\n\n```bash\nbun run dev          # API (:31337) + Vite dashboard UI (:2138); hot reload (defaults; see Ports if busy)\nbun run dev:web:ui   # explicit alias for the same browser dashboard stack\nbun run dev:desktop  # desktop dev orchestrator + Electrobun, using built renderer assets when fresh\nbun run dev:desktop:watch  # same desktop orchestrator with Vite watch/HMR\n```\n\n**Why separate entry points:** `dev` / `dev:web:ui` are the **browser dashboard** stack only. `dev:desktop` / `dev:desktop:watch` are the **Electrobun** workflow (multi-process: orchestrator, API, optional Vite, native shell) so desktop env and ports stay aligned without changing the default headless-friendly dev command.\n\nThe web-ui orchestrator frees the listen port when needed, waits for the API to be healthy, then starts Vite with an `/api` proxy to **`MILADY_API_PORT`**.\n\n### Desktop shell (Electrobun)\n\n```bash\nbun run dev:desktop        # API + Electrobun; skips vite build when apps/app/dist is fresh\nbun run dev:desktop:watch  # + Vite dev server and MILADY_RENDERER_URL (HMR for UI work)\n```\n\n**Why a separate flow:** the desktop stack runs **multiple processes** (orchestrator, Vite and/or built assets, API, Electrobun). The orchestrator **pre-allocates** free **API** and **Vite** ports when defaults are taken so every child gets consistent env—**why:** misaligned ports cause blank UI or 502s on `/api`. See **[docs/apps/desktop-local-development.md](docs/apps/desktop-local-development.md)** (including [when default ports are busy](docs/apps/desktop-local-development.md#when-default-ports-are-busy)) for signals, shutdown when you quit the app, and env vars.\n\n**IDE / agent hooks** — Editors and agents do not see the native window or auto-discover localhost. **Why we added hooks:** with desktop dev running, the API exposes **`GET /api/dev/stack`** (JSON: ports, renderer URL, which features are on). **`bun run desktop:stack-status -- --json`** probes ports and merges stack + health + status. By default, **`.milady/desktop-dev-console.log`** mirrors prefixed child logs and **`GET /api/dev/cursor-screenshot`** (loopback) returns a full-screen PNG via OS capture — both are opt-out via env (see doc). Cursor uses **`.cursor/rules/milady-desktop-dev-observability.mdc`** plus that guide.\n\n```bash\nbun run verify       # typecheck + lint + test (run before committing; `check` aliases this)\nbun run test         # parallel test suite\nbun run milady:doctor # diagnose environment issues (`doctor` aliases this)\nbun run setup:sync   # re-run postinstall hooks (`repair` aliases this)\nbun run workspace:deps:sync   # normalize workspace:* / local checkout edges (`fix-deps` aliases sync)\nbun run workspace:deps:check  # verify workspace deps without writing (`fix-deps:check`)\n```\n\n**Why workspace scripts:** Local **`./eliza`** and **`plugins/*`** checkouts frequently drift dependency edges; the scripts automate what used to be manual `package.json` surgery. See **[Developer diagnostics and workspace](docs/guides/developer-diagnostics-and-workspace.md)**.\n\nSee **[Architecture](docs/architecture.mdx)** for the full development guide including architecture overview and config reference. See **[CONTRIBUTING.md](./CONTRIBUTING.md)** for contribution guidelines.\n\n### Documentation (with WHYs)\n\n- **[Developer diagnostics and workspace](docs/guides/developer-diagnostics-and-workspace.md)** — Why optional-plugin logs include **load provenance**, why stagehand path **walks parents**, why life-ops migrations use explicit **transactions** and **deferred indexes**, and why **workspace:** scripts / **gitignore** rules exist for local checkouts.\n- **[Plugin resolution and NODE_PATH](docs/plugin-resolution-and-node-path.md)** — Why we set `NODE_PATH` in three places so dynamic plugin imports resolve when building from source (CLI, desktop dev, Electrobun). Includes **pinned `@elizaos/plugin-openrouter`**, **why** `alpha.12` must not be resolved until upstream fixes the published bundle, and **optional plugin provenance** when a package is missing.\n- **[Build and release](docs/build-and-release.md)** — Why the release pipeline uses strict shell, retries, `actions/setup-node@v4` + `check-latest: false`, Bun cache, timeouts; why size-report pipelines handle SIGPIPE; why Windows plugin build uses `npx -p typescript tsc`.\n- **[Desktop local development](docs/apps/desktop-local-development.md)** — Why `dev:desktop` / `dev:desktop:watch` orchestrate Vite, API, and Electrobun; HMR vs `vite build --watch`; Ctrl-C, Quit, and `detached` children; **IDE/agent observability** (`/api/dev/stack`, aggregated console, screenshot proxy, WHY loopback and opt-out).\n- **[Desktop main-process reset](docs/apps/desktop-main-process-reset.md)** — Why **Reset Milady…** runs HTTP in the Electrobun main process after native confirm, how the renderer syncs UI state, reachable API probing (`res.ok`), and where tests live.\n- **[Darwin vs macOS version (Electrobun WebGPU)](docs/apps/electrobun-darwin-macos-webgpu-version.md)** — Why **`uname -r` / `os.release()`** is not the macOS marketing major after Tahoe, how we map **Darwin 25 → macOS 26**, and why the WebGPU gate used to print “macOS 16.”\n- **[Changelog](docs/changelog.mdx)** — Shipped features and fixes with rationale (**WHY** bullets in each update).\n- **[Roadmap](docs/roadmap.md)** — Direction and follow-ups; points to changelog for what already landed.\n\n---\n\n## Contributing\n\n**This project is built by agents, for agents.**\n\nHumans contribute as QA testers — use the app, find bugs, report them. That's the most valuable thing you can do. All code contributions are reviewed and merged by AI agents. No exceptions.\n\nRead [CONTRIBUTING.md](./CONTRIBUTING.md) for the full details.\n\n---\n\n## License\n\n**MIT License**\n\nfree to use, free to modify, free to distribute. see [LICENSE](LICENSE) for details.\n\n---\n\n*built by agents. tested by humans. that's the split.*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmilady-ai%2Fmilady","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmilady-ai%2Fmilady","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmilady-ai%2Fmilady/lists"}