It feels like a dev environment that happens to have an AI inside, not a chat with code stapled on the side.
Multi-project workspace, live file streaming, integrated terminal (local + SSH), git tooling, and per-project chat sessions — all in one window.
This isn't a wrapper. The editor on the right shows the file being written, character by character, while Claude generates it. Click for the higher-quality MP4.
You point SubLodeX at a folder (local or remote via SSH). Claude shows up as a chat in the middle of the window. When Claude reads or writes a file, the editor on the right opens that file and shows the changes appear character by character. The left sidebar gives you the file tree, the project commands (/init, /cost, /permissions, …), and a full git panel. The terminal at the bottom is a real PTY — local shell or ssh user@host depending on the project. Conversations are persisted, scoped per project, and you can have multiple parallel chat sessions on the same project. Themes are real themes — Monaco, xterm, and the UI all change together.
Pre-built bundles will be on the Releases page for macOS (Intel + Apple Silicon), Linux (
.deb/.AppImage/.rpm), and Windows (.msi/.exe).
After download, on macOS:
-
Drag
SubLodeX.appinto/Applications/. -
The app is unsigned. First launch needs Gatekeeper bypass:
xattr -dr com.apple.quarantine /Applications/SubLodeX.app
Or right-click → Open → confirm.
On Linux: sudo dpkg -i SubLodeX_*.deb (Debian/Ubuntu), or chmod +x SubLodeX_*.AppImage && ./SubLodeX_*.AppImage.
On Windows: run the .msi. SmartScreen will warn (unsigned) — More info → Run anyway.
The bundle ships everything:
- its own Bun runtime (sidecar binary, ~70 MB)
- the bundled
server.ts(single.mjsfile) - the native
claudebinary (~217 MB — yes, that's why the.appis ~293 MB) - a Rust-native PTY (
portable-pty) — no Node, nonode-pty, no extra installs
The only optional runtime dependency:
sshpass— only if you want SSH password authentication for remote projects. Key-based / agent SSH works without it. (brew install sshpass/apt install sshpass).
SubLodeX uses your existing Claude credentials:
-
Subscription (recommended) — log in once with the
claudeCLI:claude # then: /loginSubLodeX picks up the token from:
- macOS Keychain
~/.claude/.credentials.jsonon Linux / Windows
No
claudeCLI installed? The bundle already ships one. Use it directly or symlink it into your$PATH:# macOS (after installing /Applications/SubLodeX.app) sudo ln -s /Applications/SubLodeX.app/Contents/Resources/_up_/resources/claude-bin/claude /usr/local/bin/claude claude /login # Linux (after installing the .deb) sudo ln -s /usr/lib/SubLodeX/resources/claude-bin/claude /usr/local/bin/claude claude /login # Windows: the binary is at # %ProgramFiles%\SubLodeX\resources\claude-bin\claude.exe # add that folder to your PATH or call it directly with full path
On Linux, calling the binary by full path will fail with
Executable not found in $PATH: "claude"because it self-respawns through$PATH. The symlink (or aPATHprepend) fixes it. -
API key — set
ANTHROPIC_API_KEYand start withCLAUDE_WEB_USE_API_KEY=1. By default the API key is ignored when subscription credentials are present, so subscription wins.
Multi-project workspace. Each project has its own path (local or SSH), its own conversations, its own settings. You switch with one click and everything follows: file tree, terminal, chat, git state.
When Claude calls Write or Edit, the editor opens that file and writes it character by character, in real time. Not "here's the code, paste it" — you watch it happen.
There's a speed regulator because at full speed you barely see it:
instant— no animation, full speed (default)fast— ~330 char/snormal— ~100 char/sslow— ~33 char/s, true typewriter
Set it from projects → live file write speed. (see the GIF at the top of this README for a demo)
PTY backed by Rust portable-pty. Bytes streamed to xterm.js via Tauri Channel — no Node helper, no SIGHUP wrangling, no node-pty native modules to ship per platform. SSH sessions reuse a ControlMaster socket with the file-ops connection, so the second pane / file open / git op opens in ~10 ms instead of ~300 ms.
One project can have N parallel chat sessions. Use them for: bug fix vs new feature, daily threads, "spike I might come back to", onboarding vs implementation. Each session has its own Claude session_id so --resume keeps working independently.
The session bar above the chat shows the current session, summary of the first user message, and lets you switch / create / delete.
A full git panel in the sidebar (only appears if the project is a repo).
- current branch + ahead/behind counts
- branch switcher (checkout existing or
-bnew) - dirty files split into staged / changes with
M/A/D/?markers +to stage,−to unstage,⌫to discard (with confirm — for untracked files =git clean -f)- stage all / unstage all buttons in section headers
- commit message + commit
- pull / push (disabled when ahead/behind = 0)
- history of last 30 commits — click any → editor opens
git show <hash>in diff highlighting - stash save / pop / drop
- PR review — paste a GitHub PR url or
#number, the app doesgit fetch origin pull/N/head:pr-Nand opens the diff vs the default branch in the editor - every operation's stdout/stderr appears in a small drawer (
pullshowing changed files,pushshowing rejection reason, etc.)
VS Code-style fuzzy finder. Press ⌘P (or ⌘K, or click the find button in the header), type 2-3 chars, hit ↵. Subsequence matching, basename bonus.
The ⇣ export button (visible only when the chat has messages) saves the conversation as a markdown file. Tool calls are expanded with their input + result. Useful for sharing debug sessions or saving "how I solved X" memos.
7 built-in themes:
- Monokai (default)
- Dracula
- Nord
- Tokyo Night
- One Dark
- Solarized Dark
- GitHub Light
Themes are scoped per area — you can mix. Editor in Monokai, terminal in Dracula, sidebar in Nord. Useful when one area has bad contrast against the other.
Native Claude slash commands (/init, /permissions, /cost, …) wired up in the left rail. Click → sent to Claude. There's also a small set of UI-only commands (settings, etc.).
A read-only viewer for what's hooked into your Claude Code:
- Plugins — installed Claude Code plugins from
~/.claude/plugins/installed_plugins.json, with their manifest, capabilities (commands / agents / skills / hooks / MCP / LSP), version, scope. - Extensions — auto-detected: npm packages installed globally that hook into Claude Code (e.g.
@ccplug/claude-reforge). Inferred from hook command paths. - MCP servers — global (
~/.claude/settings.json) + project (.mcp.json). - Hooks — grouped by event (
PreToolUse,UserPromptSubmit, …), with matcher and command visible. - Marketplaces — registered plugin sources.
Read-only: install / enable / remove via the official claude plugin CLI.
Point a project at a remote and everything runs there:
~/.ssh/confighost names autocompleted when adding a project- password, identity file, or agent forwarding
- connection reuse via
ControlMaster - file tree, file open/save, terminal, claude — all over SSH
Claude runs on the remote (uses the remote's claude CLI). The local app proxies the conversation. No per-character live streaming when editing remote files — this is a Claude CLI limitation, not ours: the CLI's stream-json output doesn't emit partial tool input the way the local SDK does. Tool results still arrive (you see the diff after the tool returns), just no typewriter animation during the write.
(See 02-projects.png above for the SSH form.)
# macOS via Homebrew
brew install bun rustup-init
rustup-init -y# Ubuntu 22.04+
sudo apt-get install -y \
libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf \
build-essential
curl -fsSL https://bun.sh/install | bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh# Windows (PowerShell)
winget install -e --id Rustlang.Rustup
irm bun.sh/install.ps1 | iexgit clone <this repo>
cd claude-web
bun installbun run dev # bun server :3001 + vite :5173Open http://localhost:5173 in any browser. Vite has HMR; for the desktop window use:
bun run tauri:devThe Tauri window in dev still loads from
:3001(the bundled URL). If you change frontend code, runbun run buildto refresh the static bundle the desktop window sees. For pure UI hacking, use the browser at:5173— much faster cycle.
# (one-time per machine) download bun for the current arch
mkdir -p src-tauri/binaries
curl -fsSL https://github.com/oven-sh/bun/releases/latest/download/bun-darwin-x64.zip -o /tmp/bun.zip
unzip -oq /tmp/bun.zip -d /tmp
cp /tmp/bun-darwin-x64/bun src-tauri/binaries/bun-x86_64-apple-darwin
chmod 755 src-tauri/binaries/bun-x86_64-apple-darwin
bun run tauri:buildOutput ends up in src-tauri/target/release/bundle/. On macOS:
cp -R src-tauri/target/release/bundle/macos/SubLodeX.app /Applications/
xattr -dr com.apple.quarantine /Applications/SubLodeX.appFor other targets, swap the bun zip URL:
| Target | bun zip | rust triple |
|---|---|---|
| macOS Apple Silicon | bun-darwin-aarch64.zip |
bun-aarch64-apple-darwin |
| macOS Intel | bun-darwin-x64.zip |
bun-x86_64-apple-darwin |
| Linux x64 | bun-linux-x64.zip |
bun-x86_64-unknown-linux-gnu |
| Windows x64 | bun-windows-x64.zip |
bun-x86_64-pc-windows-msvc.exe |
The bun run tauri:build script will:
vite build→dist/bun build server.ts --target=bun --outfile=src-tauri/resources/server.bundled.mjs- copy
dist/, the nativeclaudebinary, intosrc-tauri/resources/ - compile the Rust shell, bundle as
.app/.dmg/.deb/.msi
CI does the same per-platform — see .github/workflows/release.yml.
┌──────────────────────────────────────────────┐
│ Tauri WebView (React + Vite) │
│ http://127.0.0.1:3001 │
└────┬──────────────────────────────────┬──────┘
│ REST /api/* + WebSocket /ws │ Tauri invoke + Channel
│ │
┌────┴──────────────────────────┐ ┌─────┴────────────────────┐
│ Bun server (sidecar) │ │ Rust commands │
│ • settings, file ops │ │ • portable-pty manager │
│ • git operations │ │ • app data dir resolve │
│ • SSH (sshExec) │ │ • bun sidecar lifecycle │
│ • Claude SDK streaming │ └──────────────────────────┘
└────┬──────────────────────────┘
│ spawn
↓
`claude` native binary (bundled)
or remote `claude` over SSH
Why two communication channels? The Bun side is great at HTTP/WS and has the Claude SDK. The Rust side is great at native PTYs and process management. Splitting along that axis keeps each side doing what it's good at.
The native claude binary is bundled so the .app works on a clean machine (no npm install required for the user). On launch the Tauri Rust setup hook:
- Resolves bundled paths (
server.bundled.mjs,dist/,claudebinary) - Computes the platform-specific app data dir
- Spawns the Bun sidecar with all of these as env vars
- Waits for
:3001to come up before opening the window
Frontend ↔ PTY uses Tauri Channel (typed streaming), not events — events broadcast unreliably to webviews loaded from non-frontend URLs in Tauri 2.
Everything is local. The app data dir is platform-specific:
- macOS —
~/Library/Application Support/com.pinperepette.sublodex/ - Linux —
~/.local/share/com.pinperepette.sublodex/ - Windows —
%APPDATA%\com.pinperepette.sublodex\
settings.json
conversations/<projectId>/<sessionId>.json
- per-project conversations, multiple sessions per project
- session resume supported (Claude
session_idreused) - no external storage, no telemetry, no analytics
When running from source (bun run dev), settings live in <repo>/.data/ instead — dev runs don't touch your home dir.
- no live streaming for remote edits — Claude CLI limitation, not ours
- remote file ops use shell (cat/find/etc.) — no SFTP yet, so they're slower than they could be on big repos
- passwords stored in plain text in
settings.json. Fine for localhost, but use SSH keys when possible - app is unsigned — first launch needs
xattr/ right-click on macOS, SmartScreen confirmation on Windows
- SFTP for remote file ops
- signed builds (macOS notarization, Windows code signing)
- better streaming for remote (claude runs locally + proxied tool ops)
- inline AI suggestions (Copilot-like, ghost text in editor)
- MCP server mode — expose SubLodeX's PTY/file/git as an MCP server for external Claude clients
- auto-updater (Tauri plugin)
Works well. The risky areas are the same areas any tool like this has:
- streaming partial JSON
- PTY lifecycle (Rust + portable-pty handles this much better than the old Node helper, but cross-platform PTYs are still cross-platform PTYs)
- SSH (
sshpass, ControlMaster, key types, agent forwarding — many corners)
If it doesn't explode on first launch, you're probably fine.
SubLodeX — by Amani Andrea aka The Pirate Pinperepette.
If this saves you time, throw a coin to your captain:
MIT — see LICENSE.
Once you get used to watching files write themselves, copy-pasting code from a chat feels broken.












