Tiling multi-terminal manager for WSL
Find a file
megaproxy 4fd613438c Remove accidentally-committed dev-session screenshots/scripts
The previous commit (96a9180) pulled in 38 debugging screenshots,
the PowerShell automation driver, and the dev.log file alongside
the actual fix. Remove them from the working tree and ignore them
going forward via /-prefixed patterns in .gitignore (so the
legitimate src-tauri/icons/*.png stay tracked).

Files remain in git history; the binary diff is small so this isn't
worth a force-push to scrub.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 14:37:00 +01:00
scripts M5 ship infrastructure: icon, version, release script, README 2026-05-22 13:38:29 +01:00
src Fix active-pane click via document-capture pointerdown 2026-05-22 14:35:59 +01:00
src-tauri Pick up Cargo.lock version bump from pnpm tauri build 2026-05-22 13:46:27 +01:00
.gitignore Remove accidentally-committed dev-session screenshots/scripts 2026-05-22 14:37:00 +01:00
CLAUDE.md Initial scaffold from M1 spike (tiletopia) 2026-05-22 12:31:29 +01:00
index.html Initial scaffold from M1 spike (tiletopia) 2026-05-22 12:31:29 +01:00
memory.md M5 ship infrastructure: icon, version, release script, README 2026-05-22 13:38:29 +01:00
package.json M5 ship infrastructure: icon, version, release script, README 2026-05-22 13:38:29 +01:00
pnpm-lock.yaml Add vitest + 43 unit tests for tree.ts 2026-05-22 13:28:02 +01:00
pnpm-workspace.yaml Initial scaffold from M1 spike (tiletopia) 2026-05-22 12:31:29 +01:00
README.md Slim README for public visibility 2026-05-22 13:50:02 +01:00
svelte.config.js Initial scaffold from M1 spike (tiletopia) 2026-05-22 12:31:29 +01:00
tsconfig.json Initial scaffold from M1 spike (tiletopia) 2026-05-22 12:31:29 +01:00
tsconfig.node.json Initial scaffold from M1 spike (tiletopia) 2026-05-22 12:31:29 +01:00
vite.config.ts Add vitest + 43 unit tests for tree.ts 2026-05-22 13:28:02 +01:00

tiletopia

A Windows desktop app for running and arranging many WSL terminals at once. Built primarily for managing multiple claude sessions across projects in parallel; works for any multi-shell workflow.

  • Tiling layout — recursive splits, draggable dividers, preset layouts (single / 2-col / 3-col / 2-row / 2×2)
  • Per-pane distro + cwd + label, persisted across restarts
  • Broadcast input to a group of panes
  • Idle-detection toasts when a pane goes quiet
  • Ctrl+K palette to fuzzy-jump between panes

Install

  1. Download the latest tiletopia_<version>_x64-setup.exe from the releases page.
  2. Run it. Windows SmartScreen will warn "unrecognized publisher" — it's not code-signed. More info → Run anyway.
  3. Launch tiletopia from the Start menu. A window opens with one terminal pane bound to your default WSL distro.

Requirements

  • Windows 10/11 with WebView2 Runtime (preinstalled on Win11).
  • At least one WSL distro registered (wsl -l -v).

Using it

  • Split panes in the pane toolbar splits right, splits down. The new pane inherits the parent's distro + cwd.
  • Close pane×. The sibling expands to fill.
  • Rename pane — click the label in the toolbar, type, Enter (Esc to cancel).
  • Change distro — click the small Ubuntu ▾ chip; pick a distro from the popover. The pane respawns (old shell is killed).
  • Broadcast — toggle 📡 on two or more panes (orange border). Typing in any of them mirrors to all.
  • Preset layouts — titlebar buttons: 1 / 2H / 3H / 2V / 2×2. Confirms before replacing a multi-pane layout.
  • Active pane — click any pane → blue border + keyboard focus.
  • Jump to paneCtrl+K opens a fuzzy picker over label / distro / cwd. ↑/↓ to navigate, Enter to focus, Esc to close.
  • Idle toasts — top-right notification when a pane goes quiet for 5 s. Useful for "I started a long task; tell me when it's done."

Layout + per-pane settings auto-save to %APPDATA%\com.megaproxy.tiletopia\workspace.json (debounced 500 ms).

Stack

  • Tauri 2 (Rust backend, WebView2 frontend) — small bundle, native NSIS installer.
  • Svelte 5 + TypeScript + Vite + pnpm.
  • xterm.js + @xterm/addon-fit for terminal rendering.
  • portable-pty (Rust) spawning wsl.exe -d <distro> PTYs.

Build from source

This targets Windows; the Rust toolchain runs on the Windows host. Prereqs per Tauri docs: MSVC ("C++ build tools" workload), Rust, Node 20+, pnpm (corepack use pnpm@latest), at least one WSL distro.

git clone https://git.rdx4.com/megaproxy/tiletopia.git
cd tiletopia
pnpm install
pnpm tauri dev          # iterate
pnpm tauri build        # NSIS installer at src-tauri\target\release\bundle\nsis\

Keep the source on a Windows-native drive (e.g. C:\ or D:\). Running pnpm against a \\wsl.localhost\... UNC path crashes pnpm 11.x inside isDriveExFat (with a misleading error from the crashing hint formatter).

Run the tests

pnpm test          # vitest, 43 cases on the layout tree
pnpm test:watch
pnpm check         # svelte-check

The test suite covers the pure helpers in src/lib/layout/tree.ts. UI behavior, broadcast routing, and Tauri integration are manually tested.

Architecture

  • Backend (src-tauri/src/pty.rs): PtyManager holding Mutex<HashMap<PaneId, PaneHandle>> of portable-pty children. Each spawned pane gets a background reader thread that emits pane://{id}/data events (base64 byte chunks). Counterparts: write_to_pane / resize_pane / kill_pane. Workspace persistence via save_workspace / load_workspace writes to app.path().app_config_dir() with atomic tmp + rename.
  • Layout (src/lib/layout/tree.ts): binary tree of splits. HSplit | VSplit internal nodes with a ratio, Leaf at the bottom — same model as i3 / tmux / Zellij. Adaptive resize falls out of mutating one parent ratio. Pure helpers (splitLeaf, closeLeaf, changeDistro, etc.) live in tree.ts; the rendering chain (Pane.svelteSplitNode.svelte / LeafPane.svelte) is thin.
  • Orchestration — broadcast routing, idle detection, palette, active-pane focus all live in App.svelte and reach the panes via a PaneOps bundle (src/lib/layout/ops.ts) drilled through the Pane chain.

License

No formal license yet. Public for inspection and personal use; if you want to redistribute, open an issue and ask.