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
36 changes: 25 additions & 11 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,31 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.10.0] - 2025-09-13

### Added
- Tiled View (MVP): view two sessions side‑by‑side with independent terminals and sockets.
- Resizable splitter between panes with persistent split position.
- Per‑pane session picker and close controls; layout and assignments persist in localStorage.
Comment on lines +11 to +13
Copy link

Copilot AI Sep 13, 2025

Choose a reason for hiding this comment

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

Using en-dash (‑) instead of hyphen (-) in 'side‑by‑side' and 'Per‑pane'. Should use regular hyphens: 'side-by-side' and 'Per-pane'.

Copilot uses AI. Check for mistakes.

### Changed
- Settings font size now applies to all visible panes in tiled view.

### Notes
- Client‑side only; no server/CLI changes required. Default remains single‑pane; toggle via new tile button in the top bar.

## [2.9.0] - 2025-09-13

### Added
- Theme toggle in Settings with persistence (Dark/Light).
- Early theme application to avoid flash of incorrect theme on load.

### Changed
- Default theme set to Dark; Light can be selected in Settings.

### Notes
- UI-only change; no server/CLI APIs modified.

## [2.8.0] - 2025-09-13

### Added
Expand Down Expand Up @@ -133,14 +158,3 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Startup logs show configured aliases.
- README updated with alias usage examples.
## [2.9.0] - 2025-09-13

### Added
- Theme toggle in Settings with persistence (Dark/Light).
- Early theme application to avoid flash of incorrect theme on load.

### Changed
- Default theme set to Dark; Light can be selected in Settings.

### Notes
- UI-only change; no server/CLI APIs modified.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "claude-code-web",
"version": "2.9.0",
"version": "2.10.0",
"description": "Web-based interface for Claude Code CLI accessible via browser",
"main": "src/server.js",
"bin": {
Expand Down
23 changes: 22 additions & 1 deletion src/public/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class ClaudeCodeWebInterface {
this.sessionTimer = null;
this.sessionTimerInterval = null;

this.paneManager = null;
this.init();
}

Expand Down Expand Up @@ -72,6 +73,8 @@ class ClaudeCodeWebInterface {
this.setupTerminal();
this.setupUI();
this.setupPlanDetector();
// Pane manager after UI exists
this.paneManager = new PaneManager(this);
this.loadSettings();
this.applyAliasesToUI();
this.disablePullToRefresh();
Expand Down Expand Up @@ -109,6 +112,7 @@ class ClaudeCodeWebInterface {

window.addEventListener('resize', () => {
this.fitTerminal();
if (this.paneManager?.enabled) this.paneManager.panes.forEach(p => p.fit());
});

window.addEventListener('beforeunload', () => {
Expand Down Expand Up @@ -151,7 +155,7 @@ class ClaudeCodeWebInterface {

// Plan modal title
const planTitle = document.querySelector('#planModal .modal-header h2');
if (planTitle) planTitle.innerHTML = `<span class="icon" aria-hidden="true">${window.icons?.clipboard?.(18) || ''}</span> ${this.getAlias('claude')}'s Plan`;
if (planTitle) planTitle.innerHTML = `<span class=\"icon\" aria-hidden=\"true\">${window.icons?.clipboard?.(18) || ''}</span> ${this.getAlias('claude')}'s Plan`;
Copy link

Copilot AI Sep 13, 2025

Choose a reason for hiding this comment

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

Escaped quotes in template literal are incorrect. Should use single quotes around class names: <span class="icon" aria-hidden="true">.

Suggested change
if (planTitle) planTitle.innerHTML = `<span class=\"icon\" aria-hidden=\"true\">${window.icons?.clipboard?.(18) || ''}</span> ${this.getAlias('claude')}'s Plan`;
if (planTitle) planTitle.innerHTML = `<span class='icon' aria-hidden="true">${window.icons?.clipboard?.(18) || ''}</span> ${this.getAlias('claude')}'s Plan`;

Copilot uses AI. Check for mistakes.
}

detectMobile() {
Expand Down Expand Up @@ -432,6 +436,19 @@ class ClaudeCodeWebInterface {
if (settingsBtn) settingsBtn.addEventListener('click', () => this.showSettings());
if (retryBtn) retryBtn.addEventListener('click', () => this.reconnect());

// Tile view toggle
const tileToggle = document.getElementById('tileViewToggle');
if (tileToggle) {
tileToggle.addEventListener('click', () => {
if (!this.paneManager) return;
if (this.paneManager.enabled) {
this.paneManager.disable();
} else {
this.paneManager.enable();
}
});
}

// Mobile menu event listeners
if (closeMenuBtn) closeMenuBtn.addEventListener('click', () => this.closeMobileMenu());
if (settingsBtnMobile) {
Expand Down Expand Up @@ -947,6 +964,8 @@ class ClaudeCodeWebInterface {
message.plan,
message.limits
);
// Also refresh pane session selectors when sessions list changes
if (this.paneManager) this.paneManager.refreshSessionSelects();
break;

default:
Expand Down Expand Up @@ -1155,6 +1174,7 @@ class ClaudeCodeWebInterface {
}

this.terminal.options.fontSize = settings.fontSize;
if (this.paneManager?.panes) this.paneManager.panes.forEach(p => { if (p.terminal) p.terminal.options.fontSize = settings.fontSize; p.fit();});
Copy link

Copilot AI Sep 13, 2025

Choose a reason for hiding this comment

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

Missing space before closing brace. Should be 'p.fit(); });' for better readability.

Suggested change
if (this.paneManager?.panes) this.paneManager.panes.forEach(p => { if (p.terminal) p.terminal.options.fontSize = settings.fontSize; p.fit();});
if (this.paneManager?.panes) this.paneManager.panes.forEach(p => { if (p.terminal) p.terminal.options.fontSize = settings.fontSize; p.fit(); });

Copilot uses AI. Check for mistakes.

this.fitTerminal();
}
Expand Down Expand Up @@ -2248,5 +2268,6 @@ document.head.appendChild(style);

document.addEventListener('DOMContentLoaded', () => {
const app = new ClaudeCodeWebInterface();
window.app = app;
app.startHeartbeat();
});
42 changes: 39 additions & 3 deletions src/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,21 @@
<!-- Overflow tabs will be listed here -->
</div>
</div>
<button class="tab-settings" id="settingsBtn" title="Settings">
<div class="tab-actions">
<button class="tab-tile" id="tileViewToggle" title="Toggle Tile View">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="3" width="8" height="8"/>
<rect x="13" y="3" width="8" height="8"/>
<rect x="3" y="13" width="18" height="8"/>
</svg>
</button>
<button class="tab-settings" id="settingsBtn" title="Settings">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z"/>
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1Z"/>
</svg>
</button>
</button>
</div>
</div>


Expand All @@ -130,7 +139,7 @@ <h2><span class="icon" aria-hidden="true"><svg width="18" height="18" viewBox="0
</div>

<main class="main">
<div class="terminal-container" id="terminalContainer">
<div class="terminal-container" id="terminalContainer" data-view="single">
<div class="terminal-wrapper">
<div id="terminal"></div>
</div>
Expand Down Expand Up @@ -158,6 +167,32 @@ <h3>Connection Error</h3>
</div>
</div>
</div>
<!-- Tiled Panes Container (hidden by default) -->
<div class="tiles-container" id="tilesContainer" style="display:none;">
<div class="tile-grid" id="tileGrid">
<div class="tile-pane" data-index="0">
<div class="tile-toolbar">
<select class="tile-session-select" data-index="0"></select>
<div class="spacer"></div>
<button class="tile-close" data-index="0" title="Close Pane">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
</button>
</div>
<div class="tile-terminal" id="tileTerminal0"></div>
</div>
<div class="resizer" id="tileResizer" title="Drag to resize"></div>
<div class="tile-pane" data-index="1">
<div class="tile-toolbar">
<select class="tile-session-select" data-index="1"></select>
<div class="spacer"></div>
<button class="tile-close" data-index="1" title="Close Pane">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
</button>
</div>
<div class="tile-terminal" id="tileTerminal1"></div>
</div>
</div>
</div>
</main>

<div class="settings-modal" id="settingsModal">
Expand Down Expand Up @@ -329,6 +364,7 @@ <h2>Sessions</h2>
<script src="auth.js"></script>
<script src="plan-detector.js"></script>
<script src="session-manager.js"></script>
<script src="panes.js"></script>
<script src="icons.js"></script>
<script src="app.js"></script>

Expand Down
Loading