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
4 changes: 4 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Parallel agentic development with Electron + React" />
<meta name="theme-color" content="#1e1e1e" />
<link rel="manifest" href="/manifest.json" />
<link rel="apple-touch-icon" href="/icon-192.png" />
<title>cmux - coder multiplexer</title>
<style>
body {
Expand Down
Binary file added public/icon-192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/icon-512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 35 additions & 0 deletions public/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "cmux - coder multiplexer",
"short_name": "cmux",
"description": "Parallel agentic development with Electron + React",
"start_url": "/",
"display": "standalone",
"background_color": "#1e1e1e",
"theme_color": "#1e1e1e",
"orientation": "any",
"icons": [
{
"src": "/icon-192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "/icon-512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any maskable"
}
],
"categories": ["development", "productivity", "utilities"],
"shortcuts": [
{
"name": "New Workspace",
"short_name": "New",
"description": "Create a new workspace",
"url": "/?action=new",
"icons": []
}
]
}

53 changes: 53 additions & 0 deletions public/service-worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// cmux Service Worker for PWA support
const CACHE_NAME = 'cmux-v1';
const urlsToCache = [
'/',
'/index.html',
];

// Install event - cache core assets
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME)
.then((cache) => cache.addAll(urlsToCache))
.then(() => self.skipWaiting())
);
});

// Activate event - clean up old caches
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys()
.then((cacheNames) => {
return Promise.all(
cacheNames.map((cacheName) => {
if (cacheName !== CACHE_NAME) {
return caches.delete(cacheName);
}
})
);
})
.then(() => self.clients.claim())
);
});

// Fetch event - network first, fallback to cache
self.addEventListener('fetch', (event) => {
event.respondWith(
fetch(event.request)
.then((response) => {
// Clone the response before caching
const responseToCache = response.clone();
caches.open(CACHE_NAME)
.then((cache) => {
cache.put(event.request, responseToCache);
});
Comment on lines +35 to +44

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Skip caching streaming/API requests in service worker

The fetch handler caches every request (including POST or long‑lived fetch streams) by cloning the response and writing it to the default cache. This means SSE/chat streams from the backend will be duplicated and buffered until completion so they can be cached, which in practice never happens and causes the service worker to keep consuming the stream indefinitely, increasing memory usage and potentially stalling updates. Limit caching to static GET asset requests (e.g. by checking event.request.method === "GET" and filtering by pathname) instead of intercepting every network call.

Useful? React with 👍 / 👎.

return response;
})
.catch(() => {
// If network fails, try cache
return caches.match(event.request);
})
);
});

12 changes: 12 additions & 0 deletions src/components/Messages/MarkdownComponents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ interface SummaryProps {
children?: ReactNode;
}

interface AnchorProps {
href?: string;
children?: ReactNode;
}

interface CodeBlockProps {
code: string;
language: string;
Expand Down Expand Up @@ -89,6 +94,13 @@ export const markdownComponents = {
// Pass through pre element - let code component handle the wrapping
pre: ({ children }: PreProps) => <>{children}</>,

// Custom anchor to open links externally
a: ({ href, children }: AnchorProps) => (
<a href={href} target="_blank" rel="noopener noreferrer">
{children}
</a>
),

// Custom details/summary for collapsible sections
details: ({ children, open }: DetailsProps) => (
<details
Expand Down
14 changes: 14 additions & 0 deletions src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,17 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
<App />
</React.StrictMode>
);

// Register service worker for PWA support
if ("serviceWorker" in navigator) {
window.addEventListener("load", () => {
navigator.serviceWorker
.register("/service-worker.js")
.then((registration) => {
console.log("Service Worker registered:", registration);
})
.catch((error) => {
console.log("Service Worker registration failed:", error);
});
});
}