Conversation
Implement iTerm2-style split views for terminal panes within tabs: Architecture: - SplitNode: Sealed class hierarchy (Pane, VerticalSplit, HorizontalSplit) - SplitViewState: Manages tree structure, focus tracking, spatial navigation - SplitContainer: Recursive composable rendering split tree - SplitDivider: 1dp visible line + 16dp invisible drag overlay Features: - Split panes vertically (Cmd+D) or horizontally (Cmd+Shift+H) - Navigate between panes with Cmd+Option+arrows or Cmd+]/[ - Resize splits by dragging dividers (10%-90% ratio constraints) - Focus indication with blue border on active pane - Auto-close panes when shell exits - Working directory inheritance for new splits - Context menu integration for split actions - Shell menu with split options Keyboard shortcuts: - Cmd+D: Split vertically (left/right) - Cmd+Shift+H: Split horizontally (top/bottom) - Cmd+Option+arrows: Navigate between panes directionally - Cmd+]: Navigate to next pane - Cmd+[: Navigate to previous pane New files: - splits/SplitNode.kt: Tree node sealed class - splits/SplitOrientation.kt: HORIZONTAL/VERTICAL enum - splits/NavigationDirection.kt: UP/DOWN/LEFT/RIGHT enum - splits/SplitViewState.kt: State management - splits/SplitContainer.kt: UI rendering - splits/SplitDivider.kt: Draggable divider components 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Code Review: Split Pane SupportThis is a solid implementation of iTerm2-style split panes! The architecture is well-designed with a clean tree-based approach. ✅ StrengthsArchitecture & Design
Implementation Quality
🐛 Critical Issues1. Session ID Closure Capture Bug (HIGH PRIORITY)Location: Problem: The Solution: Use reference equality instead of ID lookup: val newSession = tabController.createSessionForSplit(
workingDir = workingDir,
onProcessExit = {
splitState.getAllPanes()
.find { it.session === newSession } // Reference equality
?.let { pane -> splitState.closePane(pane.id) }
}
)Occurrences: This pattern appears 3 times and all need fixing. 2. Memory Leak Verification Needed (HIGH PRIORITY)Location: When a pane is closed manually, 3. Unsafe Type Casting (MEDIUM PRIORITY)Location: Multiple (e.g., TabbedTerminal.kt:133) Add validation: val newSession = tabController.createSessionForSplit(...)
require(newSession is TerminalTab) { "Session must be TerminalTab" }
|
- Add onMoveToNewTab callback throughout split component hierarchy - Add extractFocusedPaneSession() to SplitViewState for non-destructive pane extraction - Add createTabFromExistingSession() to TabController for session reuse - Wire up context menu option in TabbedTerminal (only shown when splits exist) The feature allows moving a split pane to a new tab while preserving the running shell session and terminal history. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Code Review: Split Pane SupportThis is a substantial feature addition with excellent architectural design. ✅ Strengths1. Excellent Architecture
2. Comprehensive Keyboard Shortcuts
3. Spatial Navigation
4. Resource Management
5. Visual Feedback
|
| Priority | Issue | Action |
|---|---|---|
| HIGH | Mutable sessionId closure | Refactor to immutable capture |
| MEDIUM | Code duplication | Extract to shared lambda |
| MEDIUM | Missing null safety | Add defensive checks |
| LOW | SplitDragHandle recomposition | Use plain var |
| LOW | Unsafe cast | Change return type |
| LOW | Missing unit tests | Add tree operation tests |
✅ Overall Assessment
Status: Approve with Minor Changes
Well-architected feature with excellent design patterns. The identified issues are mostly minor and can be addressed in follow-up commits. Core functionality is sound.
Recommended merge strategy:
- Fix HIGH priority mutable closure issue
- Address MEDIUM priority items (DRY violations, null safety)
- Merge to dev branch
- Address LOW priority items in follow-up PRs
Great work! The split pane architecture follows best practices from iTerm2/tmux, and the implementation is production-ready with minor polish.
Review generated by Claude Code
Reviewed commit: a85e2f4
- Add Cmd+Shift+M (macOS) / Ctrl+Shift+M (Windows/Linux) shortcut - Only registered when splits exist (same as context menu behavior) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Code Review: Split Pane ImplementationThis is an excellent addition that brings iTerm2-style split panes to BossTerm! The implementation is well-structured with a clean tree-based architecture. Here's my detailed feedback: ✅ Strengths
🔍 Issues & ConcernsCritical
High Priority
Medium Priority
Low Priority
🎨 Code Quality Notes
🏁 RecommendationsBefore Merge:
Nice to Have: ✨ Overall AssessmentThis is a high-quality implementation with a solid foundation. The architecture is clean, the feature set is comprehensive, and the code is well-organized. The main concerns are around memory management and some minor performance optimizations. Rating: 8/10 (would be 9.5/10 after addressing the critical issues) Great work! This brings BossTerm much closer to feature parity with iTerm2 and tmux. 🚀 |
New settings in ~/.bossterm/settings.json: - splitDefaultRatio: Initial ratio for new splits (default 0.5) - splitMinimumSize: Minimum pane size when resizing (default 0.1 = 10%) - splitFocusBorderEnabled: Show border on focused pane (default true) - splitFocusBorderColor: Color of focus indicator (default #4A90E2) - splitInheritWorkingDirectory: New splits inherit CWD (default true) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Code Review: Split Pane SupportThis is an impressive feature implementation that adds iTerm2-style split panes to BossTerm! The code is well-architected with a clean tree-based approach. Here's my detailed feedback: ✅ Strengths
🐛 Potential Bugs1. Session ID Capture Race Condition (TabbedTerminal.kt:122-158)var sessionId: String? = null
val newSession = tabController.createSessionForSplit(
workingDir = workingDir,
onProcessExit = {
sessionId?.let { id -> // ⚠️ sessionId may still be null here
splitState.getAllPanes()
.find { (it.session as? TerminalTab)?.id == id }
?.let { pane -> splitState.closePane(pane.id) }
}
}
)
sessionId = (newSession as? TerminalTab)?.idProblem: If the process exits immediately before Fix: Capture the session directly instead of relying on ID: val newSession = tabController.createSessionForSplit(
workingDir = workingDir,
onProcessExit = {
splitState.getAllPanes()
.find { it.session === newSession } // Direct reference comparison
?.let { pane -> splitState.closePane(pane.id) }
}
)This pattern repeats in 3 places in TabbedTerminal.kt (lines 122-158, 206-242, and 249-266). 2. Missing Validation in SplitNode Init Blocks (SplitNode.kt:35, 49)init {
require(ratio in 0.1f..0.9f) { "Split ratio must be between 0.1 and 0.9" }
}Problem: This hardcodes the min/max ratio (0.1-0.9) but the settings allow user-configurable Fix: Make ratio validation use the configurable setting or remove the hardcoded validation since clamping happens in 3. Redundant LaunchedEffect Re-triggering (TabbedTerminal.kt:122)LaunchedEffect(menuActions, tabController.activeTabIndex, tabController.tabs.size) {
// ... sets onSplitVertical, onSplitHorizontal, onClosePane ...
}Problem: This re-runs whenever Fix: Remove LaunchedEffect(menuActions, tabController.activeTabIndex) {
// ... (tabs.size is redundant - activeTabIndex already triggers update)
}
|
| Category | Count |
|---|---|
| Critical Bugs | 1 (race condition) |
| Medium Issues | 2 (validation, unbounded splits) |
| Minor Issues | 2 (error handling, magic numbers) |
| Enhancements | 2 (persistence, zoom) |
Recommendation:
- ✅ Approve with minor changes - The core architecture is excellent
- 🔧 Fix the session ID race condition before merge (critical)
- 📝 Consider adding max pane limit for safety
🎉 Overall Assessment
This is high-quality work! The tree-based split architecture is elegant and extensible. The spatial navigation algorithm is particularly impressive. Great job following Kotlin idioms (sealed classes, data classes, immutability).
The main concern is the session lifecycle race condition - please address that before merging. Everything else is polish for future iterations.
Testing Notes:
- Verify the race condition: Test rapid exit in new panes
- Test with 10+ splits and streaming output
- Verify working directory inheritance with nested splits
🤖 Generated with Claude Code
- Add SPLITS category to SettingsCategory enum - Create SplitsSettingsSection.kt with: - Default Split Ratio slider (30%-70%) - Minimum Pane Size slider (5%-40%) - Inherit Working Directory toggle - Show Focus Border toggle - Focus Border Color picker (enabled when border is on) - Wire up SPLITS case in SettingsPanel 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Code Review: Split Pane SupportThis is an excellent implementation of iTerm2-style split panes! The architecture is well-designed with clean separation of concerns. StrengthsArchitecture & Design
Features
Potential Issues1. Race Condition in Session Lifecycle (High Priority)Location: TabbedTerminal.kt lines 227-257, 130-164 The sessionId capture pattern has a race condition. If the process exits immediately after creation, sessionId is still null when onProcessExit fires. Fix: Capture the pane ID directly and update SplitViewState.splitFocusedPane() to accept optional newPaneId parameter. 2. Duplicate Session Cleanup (Medium Priority)Location: SplitViewState.kt lines 141-169 When a process exits, onProcessExit calls closePane() which calls session.dispose(), but the session might already be disposed. Fix: Add try-catch guard in closePane() for IllegalStateException. 3. Inconsistent Working Directory Inheritance (Medium Priority)Location: TabbedTerminal.kt lines 127-164 vs lines 227-257 Menu-triggered splits always inherit working directory, but keyboard shortcuts respect settings.splitInheritWorkingDirectory. Fix: Apply the setting consistently in menu actions. 4. Missing Null Safety in Navigation (Low Priority)Location: SplitViewState.kt lines 233-252 If focusedPaneId becomes invalid, indexOfFirst returns -1 which is not handled. Fix: Add fallback for currentIndex == -1. Code QualityGood Practices:
Minor Improvements:
Test Coverage Suggestions
Performance
Final VerdictRecommend: Merge after addressing race condition (issue 1) This is production-quality code with only one high-priority fix needed. The architecture is solid and follows best practices. Priority fixes before merge:
Post-merge improvements: Great work! This maintains the codebase high quality standards. Review generated by Claude Code following BossTerm development guidelines |
- Add materialIconsExtended dependency for better icon selection - Change Splits icon from Add to Splitscreen (shows split screen layout) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Code Review: Split Pane SupportThis is an impressive and well-architected feature! The split pane implementation follows solid design principles and integrates cleanly with the existing codebase. Here's my detailed review: 🎯 Overall AssessmentGrade: A- (Excellent work with minor improvement opportunities) The implementation demonstrates:
🌟 Strengths1. Architecture & Design
2. Resource Management
3. Navigation Logic
4. Session Lifecycle
5. Settings Integration
🔧 Areas for Improvement1. Session ID Lifecycle Race Condition
|
| Metric | Score | Notes |
|---|---|---|
| Architecture | 9/10 | Clean tree-based design |
| Resource Management | 8/10 | Good disposal, minor race condition |
| Error Handling | 7/10 | Missing debug logging |
| Documentation | 9/10 | Excellent KDoc comments |
| Test Coverage | 5/10 | No unit tests included (expected for PR) |
✅ Recommendation
APPROVE with minor changes
The code is production-ready with the session lifecycle race condition fix (#1). Other improvements are optional enhancements that can be addressed in follow-up PRs.
Required Before Merge:
- Fix session ID race condition (Issue feat: Terminal rendering improvements + 4 high-priority features (#2, #3, #4, #5) #1)
Optional Follow-ups:
- Remove unused helper function (Issue 🔍 Implement text search/find functionality (Ctrl+F) #2)
- Optimize menu actions LaunchedEffect (Issue 🔗 Implement hyperlink detection and click handling #3)
- Add debug logging to tree operations (Issue ⚙️ Implement user settings and configuration system #4)
- Document Cmd+D conflict (Issue 🌏 Implement IME (Input Method Editor) support for CJK languages #5)
- Add spatial navigation unit tests (Issue 📝 Add context menu / right-click menu #6)
Great work on this feature! The architecture is solid and the implementation is thorough. 🚀
Bug fixes: - Remove hardcoded ratio validation (0.1-0.9) from SplitNode init blocks - Parameterize updateRatio() with minRatio to respect user settings - splitMinimumSize setting now properly enforced during resize Code cleanup: - Use direct reference comparison in session lookup callbacks - Remove redundant tabs.size from LaunchedEffect dependencies 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Code Review: Split Pane SupportThis is a well-structured implementation of iTerm2-style split views! The architecture is clean, the code quality is high, and the feature set is comprehensive. Here's my detailed review: ✅ StrengthsArchitecture & Design
Code Quality
User Experience
|
Code Review: Split Pane FeatureThis is a comprehensive and well-implemented feature that adds iTerm2-style split views to BossTerm. The implementation demonstrates strong architectural design and attention to detail. ✅ StrengthsArchitecture & Design
Feature Completeness
Code Quality
|
feat: Add horizontal and vertical split pane support
Summary
Features
Split Operations
Navigation
Visual Feedback
Resize
New Files
splits/SplitNode.ktsplits/SplitOrientation.ktsplits/NavigationDirection.ktsplits/SplitViewState.ktsplits/SplitContainer.ktsplits/SplitDivider.ktTest Plan
exit)🤖 Generated with Claude Code