https://github.com/roramirez/mmterm
https://github.com/roramirez/mmterm
Last synced: 6 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/roramirez/mmterm
- Owner: roramirez
- License: gpl-2.0
- Created: 2026-05-02T00:48:57.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-05-20T21:36:59.000Z (14 days ago)
- Last Synced: 2026-05-24T00:24:12.109Z (11 days ago)
- Language: Rust
- Size: 4.07 MB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
- Agents: AGENTS.md
Awesome Lists containing this project
README
# mmterm

A cross-platform, GPU-free terminal emulator written in Rust with vim-style modal input, split panes, and multi-tab sessions.

Renders entirely via a CPU pixel buffer — no GPU, no OpenGL, no Vulkan.
## Features
- **Modal input** — Insert, Normal, Visual, and Search modes (vim-style)
- **Split panes** — binary-tree layout, horizontal and vertical splits; drag separators or use `Ctrl+Shift+Arrow` to resize
- **Multi-tab** — independent pane trees and font metrics per tab
- **Scrollback search** — live match highlighting across 10 000-line buffer
- **Themes** — 9 built-in themes; custom themes via `~/.config/mmterm/themes/`
- **OSC 8 hyperlinks** — clickable URLs rendered in the terminal
- **OSC 52 clipboard sync** — copy/paste over SSH without extra tools
- **Focus reporting** — `?1004h/l` sends `\e[I`/`\e[O` on window, tab, and pane focus changes; neovim `autoread` and tmux work correctly
- **DEC line drawing** — box-drawing characters for ncurses TUI apps (`dialog`, `nmtui`, `mutt`)
- **Pane zoom** — full-window focus for the active pane
- **Session logging** — capture PTY output per-pane to `~/.mmterm/` with `Ctrl+Shift+L`
- **Color emoji** — rendered via FreeType CBDT/CBLC
- **Session persistence** — tabs, splits, and per-pane CWDs are saved on quit and restored on next launch; a centered dialog asks `[s] Save and quit / [q] Quit / [Esc] Cancel`; toggle with `restore_session` in `[general]`
- **Command palette** — `Ctrl+Shift+P` fuzzy-filter and run any action by name; shows the keyboard shortcut for each entry
- **TUI config editor** — edit settings in-process with `Ctrl+,`
- **Zero-config startup** — bundled JetBrains Mono fallback font (regular, bold, italic)
## Requirements
- Rust 1.85+ (edition 2024)
- Linux (X11 or Wayland) or macOS
- On Linux: a C toolchain and FreeType headers (`libfreetype-dev`)
## Build
```sh
cargo build --release
```
The binary is at `target/release/mmterm`.
## Install
```sh
cargo install --path .
```
## Running
```sh
mmterm
```
Print version:
```sh
mmterm --version # e.g. mmterm 0.3.0+abc1234 (local) or mmterm 0.3.0 (release)
```
Print help:
```sh
mmterm --help
```
Enable logging:
```sh
RUST_LOG=info mmterm
```
Enable debug logging to file:
```sh
mmterm --debug # writes DEBUG-level logs to ~/.mmterm/debug-.log
```
## Configuration
On first run, a config file is created at:
- **Linux/macOS**: `$XDG_CONFIG_HOME/mmterm/config.toml` (defaults to `~/.config/mmterm/config.toml`)
```toml
[font]
family = "Noto Sans Mono"
size = 16.0
[window]
width = 800
height = 600
title = "mmterm"
cursor_blink_ms = 500
[shell]
# program = "/bin/zsh" # defaults to $SHELL
[terminal]
scrollback_lines = 10000 # minimum 100
[logging]
auto_log = false # start logging automatically for every new pane
log_dir = "" # destination directory (empty = ~/.mmterm)
[status_bar]
right = "%pwd %date{%H:%M}" # format string (%pwd = OSC 7 cwd, %date{fmt} = strftime)
[theme]
name = "default" # see ~/.config/mmterm/themes/ for available themes
[colors]
background = "#121212"
foreground = "#a0a0a0"
cursor = "#bbbbbb"
selection = "#3d3d3d"
palette = [ ... ] # 16-color ANSI palette
```
You can also edit settings live with `Ctrl+,`.
## Key Bindings
### Global
| Binding | Action |
|---|---|
| `Ctrl+Q` | Quit — when `restore_session = true` shows save-session dialog; otherwise confirmation overlay when multiple tabs/panes are open |
| `Ctrl+Enter` | Toggle borderless fullscreen |
| `Ctrl+,` | Open config panel |
| `Ctrl+Shift+P` | Open command palette |
| `Ctrl+T` | New tab |
| `Ctrl+PageUp` / `Ctrl+PageDown` | Previous / next tab |
| `Ctrl+Shift+PageUp` / `Ctrl+Shift+PageDown` | Move tab left / right |
| `Ctrl+Shift+W` | Close tab |
| `Ctrl+Shift+R` | Rename tab |
| `Alt+1`..`Alt+9` | Jump to tab by position |
| `Ctrl++` / `Ctrl+=` | Increase font size (current tab) |
| `Ctrl+-` | Decrease font size (current tab) |
| `Ctrl+0` | Reset font size |
| `Ctrl+Shift+K` | Clear scrollback |
| `Ctrl+Shift+L` | Toggle session logging for active pane |
### Modes
| Binding | Action |
|---|---|
| `Ctrl+.` | Cycle Insert → Normal → Visual → Insert |
| `Ctrl+\` | Enter Normal mode |
### Panes (`Ctrl+W` prefix)
| Binding | Action |
|---|---|
| `Ctrl+W v` | Split horizontally |
| `Ctrl+W s` | Split vertically |
| `Ctrl+W a` | Auto-split (along longest dimension) |
| `Ctrl+W h/j/k/l` | Focus left / down / up / right |
| `Ctrl+W w` | Cycle focus |
| `Ctrl+W q` | Close pane |
| `Ctrl+W z` | Toggle pane zoom |
| `Ctrl+Shift+←/→` | Grow/shrink active pane horizontally |
| `Ctrl+Shift+↑/↓` | Grow/shrink active pane vertically |
| drag separator | Drag the 1 px separator line to resize |
### Scrollback
| Binding | Action |
|---|---|
| `Shift+PageUp` / `Shift+PageDown` | Scroll half screen |
| `Ctrl+Shift+Home` / `Ctrl+Shift+End` | Jump to top / bottom |
### Search (enter from Normal mode with `/`)
| Binding | Action |
|---|---|
| `/` | Open search |
| `Enter` | Next match |
| `n` / `N` | Next / previous match (Normal mode) |
| `Escape` | Exit search |
### Normal Mode
| Binding | Action |
|---|---|
| `v` | Enter Visual mode |
| `i` / `Escape` | Return to Insert mode |
| `j` / `k` | Scroll down / up |
| `/` | Open search |
| `n` / `N` | Next / previous search match |
### Visual Mode
Navigate freely to position the cursor, press `v` to set the selection anchor, then move to the end and copy.
| Binding | Action |
|---|---|
| `h/j/k/l` or arrows | Move cursor (scrolls viewport at boundaries) |
| `w` / `b` / `e` | Forward word / backward word / end of word |
| `0` / `$` | Start / end of line |
| `g` / `G` | Top / bottom of viewport |
| `v` | Set selection anchor at cursor (starts highlighting) |
| `o` | Swap anchor and cursor |
| `y` / `Ctrl+C` | Copy selection and exit |
| `Y` | Yank (copy) the entire line at cursor |
| `q` / `Escape` | Exit to Insert mode |
### Clipboard
| Binding | Action |
|---|---|
| `Ctrl+Shift+C` | Copy selection |
| `Ctrl+Shift+V` | Paste |
## Architecture
```
main.rs (App, event loop)
├── input/ — key → Action mapping, modal state
├── pty/ — PTY fork, shell spawn, read/write
├── terminal/ — VT/ANSI parser, cell grid, scrollback
├── ui/ — binary-tree split layout, pane struct
├── renderer/ — CPU pixel rendering, glyph cache
├── config.rs — TOML load/save
└── tui_config/ — in-process config editor
```
See [`doc/SPEC.md`](doc/SPEC.md) for the full architecture and feature specification.
## License
GPL-2.0 — see [LICENSE](LICENSE).