Repo is now public; the previous README leaked author-only context (local ~/claude/projects path, scripts/release.sh + tea workflow, icon-regen steps) that's irrelevant to anyone landing fresh. Now: Install / Using it / Stack / Build from source / Tests / Architecture / License-note. The release + icon-regen flows live in memory.md for the maintainer. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
75 lines
4.5 KiB
Markdown
75 lines
4.5 KiB
Markdown
# 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](https://git.rdx4.com/megaproxy/tiletopia/releases).
|
||
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](https://developer.microsoft.com/microsoft-edge/webview2/) (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 pane** — `Ctrl+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](https://v2.tauri.app/start/prerequisites/#windows): MSVC ("C++ build tools" workload), Rust, Node 20+, pnpm (`corepack use pnpm@latest`), at least one WSL distro.
|
||
|
||
```powershell
|
||
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
|
||
|
||
```sh
|
||
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.svelte` → `SplitNode.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.
|