4.8 KiB
4.8 KiB
cmux
A macOS terminal app with vertical tabs, using libghostty (GhosttyKit.xcframework) for terminal emulation.
User Preferences
- Always use Release builds when building and launching for testing
- Build libghostty with
-Doptimize=ReleaseFastfor performance
Development
Build and launch (Release)
cd /Users/lawrencechen/fun/cmux-terminal/GhosttyTabs
pkill -9 cmux 2>/dev/null
xcodebuild -scheme cmux -configuration Release build
open ~/Library/Developer/Xcode/DerivedData/GhosttyTabs-cbjivvtpirygxbbgqlpdpiiyjnwh/Build/Products/Release/cmux.app
Rebuild libghostty (optimized)
cd /tmp/ghostty
zig build -Demit-xcframework=true -Dxcframework-target=native -Doptimize=ReleaseFast
cp -R /tmp/ghostty/macos/GhosttyKit.xcframework /Users/lawrencechen/fun/cmux-terminal/GhosttyTabs/
Project structure
Sources/- Swift source filescmuxApp.swift- App entry point with keyboard shortcutsContentView.swift- Main UI with vertical tabs sidebarTabManager.swift- Tab state managementGhosttyTerminalView.swift- libghostty terminal integrationGhosttyConfig.swift- Ghostty config parserTerminalController.swift- Unix socket server for programmatic control
tests/- Test files and utilitiescmux.py- Python client library for socket APItest_ctrl_socket.py- Main automated test suite
GhosttyKit.xcframework/- libghostty static library (gitignored, rebuild from /tmp/ghostty)ghostty.h- Ghostty C API headercmux-Bridging-Header.h- Swift bridging header
Keyboard Shortcuts
Cmd+T/Cmd+N/ `Ctrl+Shift+`` - New tabCmd+W- Close tabCmd+Shift+]/Ctrl+Tab- Next tabCmd+Shift+[/Ctrl+Shift+Tab- Previous tabCmd+1-9- Jump to tab by number
Config
Reads user's Ghostty config from:
~/Library/Application Support/com.mitchellh.ghostty/config
Testing
Unix Socket Control API
cmux exposes a Unix socket at /tmp/cmux.sock for programmatic control and automated testing. The socket is created when the app launches.
Socket Commands
Text-based protocol with newline-delimited commands:
| Command | Description | Response |
|---|---|---|
ping |
Check if server is running | PONG |
list_tabs |
List all tabs | * 0: <UUID> <title> (per line) |
new_tab |
Create a new tab | OK <UUID> |
close_tab <id> |
Close tab by UUID | OK or ERROR: ... |
select_tab <id|index> |
Select tab by UUID or index | OK or ERROR: ... |
current_tab |
Get current tab UUID | <UUID> |
send <text> |
Send text to terminal | OK |
send_key <key> |
Send special key | OK |
help |
Show available commands | Help text |
Special Keys for send_key
ctrl-c,ctrl-d,ctrl-z,ctrl-\- Control signalsenter,tab,escape,backspace- Common keysctrl-<letter>- Any control+letter combination
Text Escaping for send
Use \n for Enter (carriage return), \t for tab, \r for raw CR.
Python Client Library
Located at tests/cmux.py:
from cmux import cmux
with cmux() as client:
# Send text with Enter
client.send("echo hello\n")
# Send special keys
client.send_ctrl_c() # Interrupt
client.send_ctrl_d() # EOF
client.send_key("enter")
# Tab management
tabs = client.list_tabs()
client.new_tab()
client.select_tab(0)
Running Tests
# Build and launch the app first
pkill -9 cmux 2>/dev/null
xcodebuild -scheme cmux -configuration Release build
open ~/Library/Developer/Xcode/DerivedData/GhosttyTabs-cbjivvtpirygxbbgqlpdpiiyjnwh/Build/Products/Release/cmux.app
sleep 3
# Run the main test suite (tests Ctrl+C, Ctrl+D)
python3 tests/test_ctrl_socket.py
# Interactive CLI for manual testing
python3 tests/cmux.py
Writing New Tests
-
Use marker files for verification - Create temp files to verify commands executed:
marker = Path(tempfile.gettempdir()) / f"test_marker_{os.getpid()}" client.send(f"touch {marker}\n") time.sleep(0.5) assert marker.exists() -
Allow settling time - Terminal commands need time to execute:
client.send("sleep 5\n") time.sleep(0.3) # Wait for command to start client.send_ctrl_c() time.sleep(0.3) # Wait for interrupt -
Clean up marker files - Always remove test artifacts:
try: # test code finally: marker.unlink(missing_ok=True)
Test Files
tests/cmux.py- Python client library for socket APItests/test_ctrl_socket.py- Automated Ctrl+C/D test suite (main tests)tests/test_signals_auto.py- PTY-based signal tests (standalone)tests/test_ctrl_interactive.py- Interactive manual teststests/test_ctrl_signals.sh- Simple bash signal testtests/test_app_keystrokes.sh- AppleScript keystroke tests (deprecated)