Tux
Terminal-first IDE focused on split panes, session management, and git visibility — built after Warp and VSCode buried the features a terminal-centric workflow depends on.
Context & Overview
The daily development environment was a combination of Warp and VSCode. Both shipped split panes, a file explorer, a git tree, and session monitoring as secondary concerns — missing, hidden behind flags, or buried several menus deep. Tux was built to expose only the features a terminal-centric workflow actually uses, in a predictable order, with a native feel and a small footprint.
The Challenge
Problem Statement
Modern IDEs and terminals prioritize feature breadth over feature access. The capabilities that matter most — layout, git visibility, file state, fast terminal access — sit behind menus and flags, creating friction that compounds across a full workday.
Why It Matters
Layout, git state, and file state account for the majority of daily interactions. If a tool cannot surface those in under a second, it acts as a tax on every task — even when the feature technically exists somewhere.
Constraints
- Sub-2s cold start target
- Only used features ship — no speculative functionality
- Native feel — not a web wrapper
- Small binary size, not a multi-hundred-megabyte bundle
Goals & Metrics
Objectives
- Split panes (vertical and horizontal)
- Right-side terminal
- Left sidebar: file explorer, git tree, terminal sessions
- Inline git diffs
- File reading, writing, and editing with CodeMirror highlighting and Prettier formatting
- Rust + Tauri for performance and binary size
Target KPIs
- Time from launch to first command
- Package / binary size
- Feature count held intentionally small
Research & Discovery
Methodology
Key Insights
- Most IDE features went unused across the two-week window — extensions marketplace, debugger, plugin system, integrated package manager.
- Layout, git state, and file state covered roughly 90% of daily usage. Those three justified the entire build.
- Tauri delivers native UX with webview flexibility, without the ~200MB Electron overhead.
Approach & Strategy
PRD-first development: a single-day scaffold followed by 5 targeted fix commits. The Rust backend owns PTY, git operations, and the editor engine; the React frontend owns layout, where the webview pays for itself.
Frameworks
Tauri 2, xterm.js 6 (terminal rendering), CodeMirror 6 (editor), @pierre/diffs (diff viewer), portable-pty (PTY sessions), git2-rs (git operations)
Collaboration
Solo. Dogfooding from the first commit — every feature entered daily use the same day it was built.
The Solution
A three-pane desktop app. Sessions and the file tree occupy the left pane. The terminal plus editor/diff sit in the middle. Git state lives on the right. xterm.js with a WebGL renderer powers the terminal; CodeMirror powers the editor with Prettier formatting for JS/TS/JSON/HTML/CSS/MD; @pierre/diffs renders the diff pane. Session state persists across launches.
App Visuals
Design Rationale
Rust + Tauri for sub-2s cold start and a small binary. React only where layout genuinely requires it (split panes, drag-resize, sidebar collapse). No LSP, no plugin marketplace, no debugger — explicitly out of scope per the PRD.
Execution
Roadmap
PRD
20-section PRD covering layout, terminal, git, editor, persistence, performance targets
Initial commit
Tauri 2 + React 19 scaffold with all 7 panes wired (App, Sidebar, FileTree, Terminal, GitViewer, Diff, Editor)
5 fix passes
File explorer → CWD reset → GitViewer → shortcuts + git.rs → backspace keystroke
Challenges Overcome
- ⚠ File explorer: PTY and sidebar state required rewiring so the tree and terminals stayed in sync (`7097843`).
- ⚠ CWD reset bug: shell working directory failed to restore on session switch, breaking per-session isolation (`de63eac`).
- ⚠ GitViewer stability: two passes required to render diffs reliably across staged / unstaged / untracked states (`d10a0a4`, `53678a0`).
- ⚠ Keyboard shortcut layer and dedicated `git.rs` module landed in the same commit to keep surface area small (`53678a0`).
- ⚠ Backspace keystrokes reached the shell in dev but not in the built binary — keymap registration was happening too late (`be3d4d1`).
Outcomes & Impact
Quantifiable Results
- 1.Terminal, editor, and git state visible at a glance — no menu navigation
- 2.Single binary replaces a two-tool setup (Warp + VSCode) for daily sessions
- 3.Dogfooded from the first commit: every feature entered daily use the day it shipped
Qualitative Feedback
“Feels native, not browser-like”
“No features shipped that require ignoring or disabling”
“Daily-driver capable for terminal-centric workflows”
Learnings & Future
Key Takeaways
- Tools built around observed daily usage outperform tools assembled from a standard feature list.
- A written PRD prevents scope creep more effectively than any framework choice — and makes cut decisions straightforward.
- Fix commits reveal where the real engineering effort went. The initial scaffold is the easy part.
Next Steps
- LSP for syntax-only lint hints (no autocomplete — out of scope by design)
- Hunk staging directly in the diff viewer
- Fuzzy file search (Cmd+P)
- Workspace JSON snapshots for cross-machine restore
- UI improvements tailored for terminal-based coding agents (Claude Code, Codex, Aider) — clearer diffs, in-place prompts, agent run state
- Context-aware shortcut detection that does not conflict with the shell or agent