Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

All notable changes to Claude Matrix are documented here.

## [2.3.1] - 2026-03-02

### Fixed
- **Dashboard port conflict crashes plugin** - `Bun.serve()` threw a fatal error when the configured port was in use, taking down the entire MCP server. Now falls back to an OS-assigned random port.
- **Dashboard server lingers after Claude Code exits** - Added `stdin` end/close listeners to trigger clean shutdown when the parent process disconnects.

---

## [2.3.0] - 2026-03-02

### Added
Expand Down
39 changes: 26 additions & 13 deletions src/http/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,33 @@ export function startDashboard(): ReturnType<typeof Bun.serve> | null {
const config = getConfig();
if (!config.dashboard?.enabled) return null;

const { port, host } = config.dashboard;

const server = Bun.serve({
port,
hostname: host,
fetch: handleRequest,
error(err: Error) {
console.error('[Dashboard] HTTP error:', err.message);
return new Response('Internal Server Error', { status: 500 });
},
});
const host = config.dashboard.host;
const preferredPort = config.dashboard.port;

// Try preferred port first, then fall back to OS-assigned port
for (const tryPort of [preferredPort, 0]) {
try {
const server = Bun.serve({
port: tryPort,
hostname: host,
fetch: handleRequest,
error(err: Error) {
console.error('[Dashboard] HTTP error:', err.message);
return new Response('Internal Server Error', { status: 500 });
},
});

console.error(`[Matrix] Dashboard → http://${host}:${server.port}`);
return server;
} catch {
if (tryPort !== 0) {
console.error(`[Matrix] Port ${tryPort} in use, trying random port…`);
}
}
}

console.error(`[Matrix] Dashboard → http://${host}:${port}`);
return server;
console.error('[Matrix] Dashboard failed to start — no available port');
return null;
}

// ── Request dispatcher ──────────────────────────────────────────────────
Expand Down
4 changes: 4 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,10 @@ async function main(): Promise<void> {

process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);

// When Claude Code exits, stdin closes — shut down cleanly instead of lingering
process.stdin.on('end', shutdown);
process.stdin.on('close', shutdown);
}

main().catch((error) => {
Expand Down