Four user-reported issues with the AI-driven browser test feature:
1. WS dies on every page reload / navigation (token was single-use,
5 min TTL → AI loses session permanently).
2. AI can't see new pages opened by its actions (same root cause).
3. No screenshot capability — AI cannot capture page state visually.
4. AI burns ~150 tool calls for what's 5 human actions, mostly
list_clickables loops.
Fixes:
- Token sliding TTL (60 min): ConsumeToken no longer deletes the
token; it refreshes its expiration on each successful WS connect.
Same token survives reload / re-paste / navigation as long as
there's no 60-min idle gap.
- Snippet auto-reconnect: WS onclose schedules reconnect with
500ms × attempt backoff (max ~2.5s). Handles transient drops,
server restarts, and WS hiccups without user intervention. Full
navigation kills the JS context and is unrecoverable from JS — but
the user just re-pastes the snippet, same token works.
- New 'screenshot' action: snippet captures via SVG foreignObject +
canvas → base64 PNG → sent back over the existing WS reply
channel. Server decodes and writes to ~/.muyue/screenshots/
<filename>.png (sanitized name, timestamp default). Filename
characters limited to a safe charset to prevent path escape.
Best-effort: external CSS / cross-origin images / iframes won't
inline.
- Studio system prompt rewritten <browser_test_strategy>:
- Explicit rule: don't list_clickables after every click
- Action cost table (cheap vs expensive)
- When to re-list (URL change, dialog, click-not-found only)
- Standard final report format ✓ / ✗ / ⚠ / 📸
Also bundles v0.7.8 (cherry-picked): unsafe.Pointer(uintptr(hPC))
instead of unsafe.Pointer(&hPC) in UpdateProcThreadAttribute, so
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE is correctly applied and the
spawned shell attaches to the embedded xterm.js instead of opening
a separate external console window (regression fix from v0.7.6).
- internal/api/browsertest.go: token sliding, screenshot save,
param schema, snippet rewrite, helpers
- internal/agent/prompts/studio_system.md: strategy rewrite
- internal/version/version.go: 0.7.7 → 0.7.9
- CHANGELOG.md: v0.7.9 entry covering all fixes
muyue
AI-powered development environment assistant by La Légion de Muyue.
What it does
muyue is a single binary (frontend embedded) that transforms your entire development environment:
- Desktop app — React web UI served locally, auto-opens in your browser
- Scans your system for tools, runtimes, and configs
- Installs missing tools automatically (Crush, Claude Code, BMAD, Starship, runtimes...)
- Updates everything in the background
- Profiles you on first run to personalize the experience
- Unifies control of Crush and Claude Code from one interface
- Orchestrates AI agents via MiniMax M2.7
- Configures MCP servers, LSPs, and skills automatically
- i18n — Full FR/EN support with keyboard layout awareness (AZERTY, QWERTY, QWERTZ)
- 4 themes — Cyberpunk Red, Cyberpunk Pink, Midnight Blue, Matrix Green
Tech Stack
| Layer | Technology |
|---|---|
| Backend | Go 1.24 — single binary, no runtime dependencies |
| Frontend | React 19, Vite 8 — embedded via go:embed |
| Styling | CSS custom properties, 4 built-in themes |
| i18n | Custom FR/EN system with keyboard layout awareness |
| CLI | Charm (Bubble Tea, Huh) — for setup wizard, profiler, and CLI commands |
| AI | MiniMax M2.7 — orchestration |
| CI/CD | Gitea Actions — Go + Node build, multi-platform releases |
Install
go build -o muyue ./cmd/muyue/
Or with Make:
make build
make install-local
The frontend is built automatically during make build (runs npm ci && npm run build in web/).
Usage
muyue # Launch desktop app (opens browser)
muyue --port=8080 # Launch on a specific port
muyue --no-open # Launch without opening the browser
muyue scan # Scan system
muyue install # Install missing tools
muyue update # Check and apply updates
muyue setup # Run setup wizard
muyue config # Show configuration
muyue doctor # Diagnose configuration issues
muyue version # Show version
LSP Management
muyue lsp scan # Scan for installed LSP servers
muyue lsp install # Install LSPs for configured languages
muyue lsp install gopls # Install a specific LSP
MCP Server Configuration
muyue mcp config # Configure MCP servers for Crush and Claude Code
muyue mcp scan # Scan available MCP servers
Skills Management
muyue skills list # List installed skills
muyue skills init # Install built-in skills
muyue skills show <name> # Show skill details
muyue skills generate <name> <desc> [crush|claude|both] # AI-generate a skill
muyue skills deploy # Deploy skills to Crush and Claude Code
muyue skills delete <name> # Delete a skill
Desktop App — 4 Tabs
The web UI is organized into 4 tabs with a cyberpunk dark theme. Navigate with Ctrl+1 through Ctrl+4.
■ Dashboard
System overview with sub-tabs:
- Tools — installed/missing tools with status badges and version info
- Notifications — activity log with colored severity
- Workflows — quick actions (install missing, check updates, rescan, configure MCP)
⟨⟩ Studio
AI chat interface with a sidebar containing 3 panels:
| Panel | Description |
|---|---|
| Chat | AI conversation, /plan <goal> to start workflows |
| Agents | Status of Crush and Claude Code agents |
| Workflows | Plan→Execute workflow controls |
$ Shell
Split-view: terminal emulator on the left (sends commands to the Go backend), collapsible AI assistant panel on the right. Full command history with ↑/↓ navigation.
⚙ Config
Two-column profile settings:
- Profile — name, pseudo, email, editor, shell, default AI, languages
- AI Providers — active provider, API key status, model info
- Theme — 4 swatches (Cyberpunk Red, Cyberpunk Pink, Midnight Blue, Matrix Green)
- Language — FR/EN with keyboard layout selection (AZERTY, QWERTY, QWERTZ)
- Skills — installed skills list
Keyboard Shortcuts
| Key | Context | Action |
|---|---|---|
Ctrl+1 |
Global | Dashboard tab |
Ctrl+2 |
Global | Studio tab |
Ctrl+3 |
Global | Shell tab |
Ctrl+4 |
Global | Config tab |
Enter |
Studio | Send message |
Shift+Enter |
Studio | New line |
Enter |
Shell | Run command |
↑/↓ |
Shell | Command history |
API Endpoints
The Go backend serves 15 REST endpoints under /api/:
| Endpoint | Method | Description |
|---|---|---|
/api/info |
GET | App name, version, author |
/api/system |
GET | OS, arch, platform info |
/api/tools |
GET | Tool scan results |
/api/config |
GET | Profile, terminal, BMAD config |
/api/providers |
GET | AI provider list |
/api/skills |
GET | Installed skills |
/api/lsp |
GET | LSP server scan |
/api/mcp |
GET | MCP server scan |
/api/updates |
GET | Update check results |
/api/scan |
POST | Trigger system rescan |
/api/install |
POST | Install tools {"tools": [...]} |
/api/terminal |
POST | Execute command {"command": "...", "cwd": "..."} |
/api/mcp/configure |
POST | Configure MCP servers |
/api/preferences |
PUT | Save language/keyboard preferences |
Project Structure
.
├── cmd/muyue/main.go # CLI entry point + command routing
├── internal/
│ ├── api/ # HTTP server + handlers (15 endpoints)
│ ├── config/ # YAML config + XDG paths
│ ├── daemon/ # Background daemon
│ ├── desktop/ # Desktop mode (HTTP server + SPA)
│ ├── installer/ # Tool installation logic
│ ├── lsp/ # LSP server scan + install
│ ├── mcp/ # MCP server configuration
│ ├── orchestrator/ # AI agent orchestration
│ ├── platform/ # Cross-platform abstractions
│ ├── preview/ # HTML preview server
│ ├── profiler/ # First-run setup wizard
│ ├── proxy/ # AI proxy agents
│ ├── scanner/ # System tool/runtime scanner
│ ├── secret/ # AES-256-GCM key encryption
│ ├── skills/ # Skills management (CRUD, deploy, AI-generate)
│ ├── updater/ # Tool auto-updater
│ ├── version/ # Version constants
│ └── workflow/ # Plan→Execute workflow engine
├── web/ # Frontend (React 19 + Vite)
│ ├── embed.go # go:embed dist/
│ ├── src/
│ │ ├── api/client.js # API client
│ │ ├── components/ # App, Dashboard, Studio, Shell, Config
│ │ ├── i18n/ # FR/EN translations + keyboard layouts
│ │ ├── styles/global.css # Full CSS theme system
│ │ └── themes/index.js # 4 themes with CSS variable injection
│ └── vite.config.js # Vite + dev proxy to :8095
├── .gitea/workflows/ # CI/CD (PR check, beta, stable)
└── Makefile # build, test, lint, cross-compile
Configuration
Config stored at $XDG_CONFIG_HOME/muyue/config.yaml (defaults to ~/.config/muyue/config.yaml).
API keys are encrypted at rest using AES-256-GCM with a machine-local key stored in ~/.muyue_key.
First run launches an interactive profiling wizard that:
- Asks your name, pseudo, email
- Detects your languages and editor
- Chooses your AI provider
- Scans your system
- Installs missing tools
Themes
4 built-in themes, selectable from the Config tab:
| Theme | Accent Color |
|---|---|
| Cyberpunk Red | #FF0033 |
| Cyberpunk Pink | #FF1A8C |
| Midnight Blue | #0088FF |
| Matrix Green | #00FF41 |
Themes are applied via CSS custom properties injected at runtime. All colors (30+ variables) adapt automatically.
i18n & Keyboard Layouts
- Languages: Français, English
- Keyboard layouts: AZERTY (fr-FR), QWERTY (en-US), QWERTZ (de-DE)
- Keyboard layout affects displayed shortcuts in the status bar (e.g.,
Ctrl+&-é-"-'on AZERTY vsCtrl+1-4on QWERTY) - Preferences saved to backend and synced across sessions
Security
- API keys encrypted at rest (AES-256-GCM) with a per-machine key
- Config files use restrictive permissions (0600)
- MCP config files use restrictive permissions (0600)
- Terminal API executes commands via shell — only accessible on localhost
Cross-Platform
Built for Linux (primary), macOS, and Windows. WSL supported.
Single binary includes both CLI and embedded web frontend.
Contributing — GitFlow Workflow
This project uses a lightweight GitFlow with 2 permanent branches and conventional commits.
Branch model
feature/xxx ──PR (squash)──▶ develop ──PR (merge)──▶ main
fix/xxx ──PR (squash)──▶ develop
hotfix/xxx ──PR (squash)──▶ main (+ backport develop)
| Branch | Purpose | Permanent? |
|---|---|---|
main |
Production — stable releases only | Yes |
develop |
Integration — all features merge here first | Yes |
feature/* |
New feature or enhancement | No (deleted after merge) |
fix/* |
Bug fix | No |
hotfix/* |
Urgent fix on production | No |
Release channels
| Event | Channel | Tag format | Prerelease? |
|---|---|---|---|
PR merge → develop |
Beta | vX.Y.Z-beta.N |
Yes |
Merge develop → main |
Stable | vX.Y.Z |
No |
CI/CD Pipelines
| Workflow | Trigger | What it does |
|---|---|---|
ci-pr.yml |
PR to main or develop |
vet + test + build (no release) |
ci-develop.yml |
Push to develop |
vet + test + build all platforms + create beta release |
ci-main.yml |
Push to main |
vet + test + build all platforms + update CHANGELOG.md + create stable release |
All CI pipelines build the frontend (npm ci && npm run build) before Go vet/test/build.
Step-by-step: contribute a feature
# 1. Create your branch from develop
git checkout develop
git pull
git checkout -b feature/my-feature
# 2. Work, commit with conventional messages
git commit -m "feat: add amazing thing"
git commit -m "docs: update usage"
# 3. Push and create a PR to develop (squash merge)
git push -u origin feature/my-feature
# → Create PR on Gitea: feature/my-feature → develop
# → CI runs ci-pr.yml (test + vet + build)
# → Squash & merge the PR
# → ci-develop.yml triggers: beta release created
Step-by-step: release a stable version
# 1. Bump the version in internal/version/version.go
# Change: Version = "0.2.1" → Version = "0.3.0"
# Commit on develop:
git checkout develop
# (edit internal/version/version.go)
git commit -m "chore: bump version to 0.3.0"
git push
# 2. Create a PR from develop to main
# → CI runs ci-pr.yml (test + vet + build)
# → Merge the PR
# → ci-main.yml triggers:
# - Builds all platforms
# - Auto-generates changelog from conventional commits
# - Updates CHANGELOG.md
# - Creates stable release v0.3.0
Step-by-step: hotfix on production
# 1. Create hotfix branch from main
git checkout main
git pull
git checkout -b hotfix/critical-fix
# 2. Fix and commit
git commit -m "fix: resolve critical issue"
# 3. Create PR to main (squash merge)
# → CI runs, then ci-main.yml creates a new stable release
# 4. Backport to develop
git checkout develop
git merge hotfix/critical-fix
git push
Versioning — How it works
The base version (X.Y.Z) is manual. It lives in internal/version/version.go:
const (
Version = "0.2.1" // ← bump this before a release
)
The prerelease suffix is automatic:
- Beta:
ci-develop.ymlauto-incrementsbeta.Nby counting existingvX.Y.Z-beta.*tags - Stable:
ci-main.ymluses the exact version fromversion.go(no suffix)
Binary version is injected at build time via -ldflags:
# Beta build (automatic in CI)
go build -ldflags="-X github.com/muyue/muyue/internal/version.Prerelease=beta.3" ./cmd/muyue/
# → muyue v0.2.1-beta.3
# Stable build (automatic in CI)
go build -ldflags="-s -w" ./cmd/muyue/
# → muyue v0.2.1
Conventional commits
Use Conventional Commits for all commit messages:
| Prefix | Use for | Example |
|---|---|---|
feat: |
New feature | feat: add Docker support |
fix: |
Bug fix | fix: correct config path on Windows |
docs: |
Documentation | docs: add API reference |
chore: |
Maintenance | chore: bump version to 0.3.0 |
refactor: |
Code restructuring | refactor: split scanner module |
perf: |
Performance | perf: cache scanner results |
test: |
Tests | test: add config unit tests |
ci: |
CI/CD changes | ci: add beta release workflow |
security: |
Security fixes | security: encrypt API keys at rest |
Branch protection (configure in Gitea UI)
main: Require PR + passing CI + at least 1 approvaldevelop: Require PR + passing CI- Squash merge: Enabled by default for PRs to
develop - Merge commit: For PRs from
developtomain
License
MIT