MCPcopy
hub / github.com/MetaCubeX/metacubexd

github.com/MetaCubeX/metacubexd @v1.265.0 sqlite

repository ↗ · DeepWiki ↗ · release v1.265.0 ↗
1,086 symbols 2,630 edges 244 files 36 documented · 3%
README

metacubexd

Mihomo Dashboard, The Official One, XD

pr-closed last-commit build downloads license

✨ Features

  • 📊 Real-time traffic monitoring and statistics
  • 🔄 Proxy group management with latency testing
  • 📡 Connection tracking and management
  • 📋 Rule viewer with search functionality
  • 📝 Live log streaming
  • 🎨 Beautiful UI with light/dark theme support
  • 📱 Fully responsive design for mobile devices
  • 🌐 Multi-language support (English, 中文, Русский)

🖼️ Preview

Desktop Screenshots

Overview Proxies
overview proxies
Connections Rules
connections rules
Logs Config
logs config

Mobile Screenshots

Overview Proxies Connections
overview proxies connections
Rules Logs Config
rules logs config

🔗 Official Links

Platform URL
GitHub Pages https://metacubex.github.io/metacubexd
Cloudflare Pages https://metacubexd.pages.dev

🚀 Deployment

metacubexd ships in three forms from one codebase:

Form Who hosts the UI Who runs the kernel Best for
Hosted panel (classic) gh-pages / your static host your own remote mihomo pointing a browser at an existing mihomo
Desktop app the app (bundled) the app supervises a bundled mihomo a single machine, zero setup
All-in-one server the Docker image the container's bundled mihomo a router / NAS / VPS

The classic pure-panel mode still works against any remote mihomo — the kernel-control and profile features simply stay hidden when the dashboard isn't talking to a bundled agent.

1. Hosted Panel (point at your own mihomo)

Enable the external-controller in your mihomo config.yaml:

external-controller: 0.0.0.0:9090

Then either open the hosted dashboard and enter your mihomo {url, secret}:

Platform URL
GitHub Pages https://metacubex.github.io/metacubexd
Custom domain https://d.metacubex.one

…or self-host the static assets via external-ui:

# Clone the prebuilt gh-pages branch
git clone https://github.com/metacubex/metacubexd.git -b gh-pages /etc/mihomo/ui

# Set external-ui in your config:
#   external-ui: /etc/mihomo/ui

# Update to the latest build later:
git -C /etc/mihomo/ui pull -r

2. Desktop App

Download the installer for your platform from the latest release:

OS Arch File
macOS (Apple Silicon) arm64 MetaCubeXD-<version>-mac-arm64.dmg
macOS (Intel) x64 MetaCubeXD-<version>-mac-x64.dmg
Windows x64 / arm64 MetaCubeXD-<version>-win-<arch>.exe
Linux x64 / arm64 MetaCubeXD-<version>-linux-<arch>.AppImage or .deb

The desktop app bundles its own mihomo kernel and auto-configures the local endpoint — you don't enter any address. Manage profiles, edit configs, and start/stop the kernel directly inside the app.

These builds are unsigned. Each OS warns about unidentified developers; the steps below are expected and safe.

macOS — Gatekeeper blocks unsigned apps ("MetaCubeXD is damaged and can't be opened"). After dragging the app to /Applications, strip the quarantine attribute:

xattr -dr com.apple.quarantine /Applications/MetaCubeXD.app

…or right-click the app → OpenOpen in the confirmation dialog.

Windows — SmartScreen shows "Windows protected your PC". Click More infoRun anyway.

Linux — make the AppImage executable, then run it:

chmod +x MetaCubeXD-*-linux-*.AppImage
./MetaCubeXD-*-linux-*.AppImage
# or install the .deb:
sudo dpkg -i MetaCubeXD-*-linux-*.deb

System proxy / TUN are advanced features. The app defaults to a mixed proxy port (no elevation). System proxy and TUN both require privileges; see TUN mode (desktop) for the one-time privileged-helper install and what the unsigned build means for it.

TUN mode (desktop)

TUN takes over all machine traffic at the network layer, so every app is routed through mihomo without per-app proxy settings (unlike the mixed proxy port, which only catches apps you point at it). Because routing the whole system needs root/admin, the desktop app installs a small privileged helper the first time you enable TUN — a background service that performs the privileged network setup on the app's behalf. Enabling TUN therefore prompts for an administrator authorization the first time (the OS elevation dialog). The helper persists across sessions, so later enables don't re-prompt for install.

These builds are unsigned, so you hit the unidentified-developer warnings twice: once launching the app (see above — macOS Gatekeeper / Windows SmartScreen / Linux "unknown publisher"), and again when the helper install asks for administrator authorization. Both are expected. Allow them the same way you allowed the app itself.

Per-OS notes

  • macOS — the helper is registered as a root LaunchDaemon; you approve it through the standard osascript "wants to make changes" administrator prompt. The kernel binds the system's utun interface.
  • Windows — the helper is registered as an auto-start Windows service (UAC prompt). The build ships wintun.dll alongside the kernel, which mihomo's wintun backend needs — no separate download.
  • Linux — the helper is registered as a root systemd unit; the elevation prompt is pkexec (the GNOME/PolicyKit authorization dialog). On a headless box without a Polkit agent you may need to install/enable one.

If TUN takes down your network

TUN reroutes default traffic, so a bad config or a stuck tunnel can drop connectivity. Two recoveries:

  • Click "Recover network" in the app — it tears down the TUN routing and restores normal networking without quitting.
  • Quit the app — exiting automatically tears down TUN (the helper restores routing), so a force-quit is a safe last resort.

Status: TUN is new. It's verified at the unit-test / command-generation / packaging level, but the real install, elevation, and per-OS tunnel behavior still need smoke testing on actual macOS / Windows / Linux machines. If you hit a problem, please open an issue with your OS, the exact prompt you saw, and whether "Recover network" restored connectivity.

3. All-in-One Server (Docker)

The metacubexd-server image bundles the dashboard UI, the control agent, and a per-arch mihomo kernel. One container serves the panel, supervises the kernel, and exposes the proxy.

# compose.yaml — proxy-only by default; TUN is an advanced override
services:
  metacubexd:
    image: ghcr.io/metacubex/metacubexd-server:latest
    restart: unless-stopped
    environment:
      CONTROL_TOKEN: 'change-me-control'
      CLASH_SECRET: 'change-me-clash'
      CONTROL_PORT: '8080'
      CLASH_API_PORT: '9090'
      MIXED_PORT: '7890'
      TZ: 'Asia/Shanghai'
    ports:
      - '8080:8080' # dashboard UI + /api/control agent API
      - '9090:9090' # mihomo Clash API + WebSocket (UI endpoint target)
      - '7890:7890' # mixed proxy port
    volumes:
      - 'metacubexd-data:/data'

volumes:
  metacubexd-data: {}
docker compose up -d

# Update
docker compose pull && docker compose up -d

Open http://<host>:8080 for the dashboard. The control agent unlocks the kernel/profile UI automatically: the server injects CONTROL_TOKEN into the same-origin page, so the dashboard authenticates its /api/control probe without you entering the token anywhere.

Point the UI endpoint at the kernel. The dashboard talks to mihomo's Clash API directly (never proxied), so set the endpoint to:

Field Value
URL http://<host>:9090
Secret the CLASH_SECRET you set above

Environment variables

Variable Default Purpose
CONTROL_TOKEN (none) Bearer token guarding the control agent (/api/control/**); also accepted as ?token= for the SSE log stream. Set a strong value.
CLASH_SECRET (none) Secret for mihomo's Clash API (external-controller). Use this as the UI endpoint's Secret.
CONTROL_PORT 8080 Port serving the dashboard UI + control agent API.
CLASH_API_PORT 9090 Port for mihomo's Clash API + WebSocket. The UI endpoint targets this port.
MIXED_PORT 7890 mihomo mixed (HTTP + SOCKS) proxy port.
TZ (container default) Timezone for logs/scheduling, e.g. Asia/Shanghai.

The named volume mounts /data, which holds your profiles, the active config, and the kernel's geo / fake-ip caches. It must be writable — a read-only data dir makes the kernel exit non-zero.

TUN mode (advanced)

TUN needs NET_ADMIN, the /dev/net/tun device, and host networking. Override the service:

services:
  metacubexd:
    image: ghcr.io/metacubex/metacubexd-server:latest
    restart: unless-stopped
    network_mode: host
    cap_add:
      - NET_ADMIN
    devices:
      - '/dev/net/tun:/dev/net/tun'
    environment:
      CONTROL_TOKEN: 'change-me-control'
      CLASH_SECRET: 'change-me-clash'
    volumes:
      - 'metacubexd-data:/data'

volumes:
  metacubexd-data: {}

With network_mode: host the ports: mapping is ignored — the container binds 8080/9090/7890 directly on the host. Enable a tun: block in your profile's mihomo config for the tunnel to come up.

Standalone panel image (Doc

Extension points exported contracts — how you extend this code

RequestEnvelope (Interface)
Fields every request shares: auth secret + protocol version.
apps/desktop/src/main/helper/protocol.ts
IPSBResponse (Interface)
(no doc)
packages/ui/types/network.ts
WebdavClientOptions (Interface)
(no doc)
packages/agent/src/webdav.ts
AuthInput (Interface)
(no doc)
apps/server/middleware/auth.ts
ResponseEnvelope (Interface)
Fields every response shares: success flag + the helper's version.
apps/desktop/src/main/helper/protocol.ts
IPWhoIsResponse (Interface)
(no doc)
packages/ui/types/network.ts
WebdavClient (Interface)
(no doc)
packages/agent/src/webdav.ts
ServerEnv (Interface)
(no doc)
apps/server/lib/supervisor.ts

Core symbols most depended-on inside this repo

useControlApi
called by 48
packages/ui/composables/useControlApi.ts
useRequest
called by 30
packages/ui/composables/useApi.ts
createSystemProxyController
called by 29
apps/desktop/src/main/sysproxy.ts
useProfiles
called by 27
packages/ui/composables/useProfiles.ts
useBatchLatencyTest
called by 25
packages/ui/composables/useBatchLatencyTest.ts
isResolvableIP
called by 24
packages/ui/composables/useReverseDns.ts
createSupervisor
called by 24
packages/agent/src/supervisor.ts
createHelperServer
called by 24
apps/desktop/src/main/helper/server.ts

Shape

Function 863
Interface 179
Class 18
Method 15
Enum 11

Languages

TypeScript100%

Modules by API surface

packages/ui/utils/index.ts50 symbols
packages/ui/composables/useApi.ts49 symbols
packages/ui/stores/proxies.ts33 symbols
packages/ui/composables/useQueries.ts26 symbols
packages/agent/src/supervisor.ts25 symbols
apps/desktop/src/main/sysproxy.ts25 symbols
packages/agent/src/profiles.ts24 symbols
apps/desktop/src/main/helper/installer.ts24 symbols
apps/desktop/src/main/index.ts21 symbols
apps/desktop/src/main/helper/client.ts20 symbols
packages/ui/composables/useGeoLookup.ts19 symbols
packages/ui/composables/useProfiles.ts18 symbols

Dependencies from manifests, versioned

@antfu/eslint-configcatalog: · 1×
@commitlint/config-conventionalcatalog: · 1×
@electron/fusescatalog: · 1×
@floating-ui/vuecatalog: · 1×
@metacubexd/agentworkspace:* · 1×
@nuxt/fontscatalog: · 1×
@nuxtjs/i18ncatalog: · 1×
@nuxtjs/tailwindcsscatalog: · 1×
@pinia/nuxtcatalog: · 1×
@playwright/testcatalog: · 1×
@prettier/plugin-oxccatalog: · 1×
@tabler/icons-vuecatalog: · 1×

For agents

$ claude mcp add metacubexd \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact