- Odin 78.5%
- Python 19.8%
- Nix 1.3%
- Shell 0.3%
|
All checks were successful
ci-tron/ci Success
Runs term in an isolated headless sway and delivers real Wayland events: a persistent zwlr_virtual_pointer_v1 client (pywayland, bindings generated from the protocol XML at run time) for wheel and clicks, and wtype for keys. Checks alt scroll, the four mouse encodings and Ctrl+Shift+Z/X prompt jumps by what the program inside receives and by screenshot pixels. Lives in its own dev shell (nix develop .#live-input) and is not part of CI or the build. |
||
|---|---|---|
| dbus | ||
| docs | ||
| font | ||
| fontconfig | ||
| harfbuzz | ||
| issues | ||
| nix | ||
| profile | ||
| pty | ||
| render | ||
| scripts | ||
| testdata | ||
| vt | ||
| wayland | ||
| xkb | ||
| .ci-tron.json | ||
| .gitignore | ||
| AGENTS.md | ||
| buffers.odin | ||
| CLAUDE.md | ||
| cli.odin | ||
| cli_test.odin | ||
| clipboard.odin | ||
| clipboard_test.odin | ||
| config.odin | ||
| e2e_features_test.odin | ||
| e2e_keyboard_test.odin | ||
| e2e_test.odin | ||
| e2e_tmux_test.odin | ||
| events.odin | ||
| flake.lock | ||
| flake.nix | ||
| input.odin | ||
| input_test.odin | ||
| kitty.odin | ||
| kitty_media.odin | ||
| kitty_media_test.odin | ||
| kitty_test.odin | ||
| links.odin | ||
| links_test.odin | ||
| main.odin | ||
| main_test.odin | ||
| modes_test.odin | ||
| open_url.odin | ||
| osc_color.odin | ||
| osc_color_test.odin | ||
| pty_output.odin | ||
| pty_output_test.odin | ||
| ptylog.odin | ||
| ptylog_test.odin | ||
| ptyreplay.odin | ||
| README.md | ||
| ROADMAP.md | ||
| select.odin | ||
| select_test.odin | ||
| terminfo.odin | ||
| terminfo_test.odin | ||
| theme.odin | ||
| theme_test.odin | ||
| working_directory.odin | ||
| working_directory_test.odin | ||
term
A fast, small, hackable terminal emulator for Wayland.
Written in Odin, built with Nix, configured by editing one file.
Why term
- Modern protocols, done properly. Kitty keyboard protocol, the complete kitty graphics protocol (placements, animation, Unicode placeholders), sixel, synchronized output, grapheme clustering, OSC 8 hyperlinks, OSC 52 clipboard.
- Looks right. HarfBuzz shaping with ligatures, fontconfig family lookup and optional per-glyph fallback fonts, wide and CJK characters (give it a fallback font that has them), curly / dotted / dashed / coloured underlines, overline, a redefinable 256-colour palette, built-in box-drawing glyphs, scrollback that reflows when you resize.
- Themes that follow your desktop. Light and dark switching through the desktop portal, and any kitty theme works as-is.
- Plays well with tmux and ssh.
termgenerates its own terminfo entry, ships a tmux policy file and an ssh wrapper, and a test suite compares its behaviour in 12 setups. - Keyboard-first selection. A vim-style select mode copies and opens links without the mouse.
- Small and stateless. The whole project stays under 15 000 lines; configuration is an Odin
value compiled in, in the spirit of
dwmandst, so nothing is parsed, watched or out of sync with what is running.
Install
You need a Wayland compositor and Nix with flakes enabled.
nix run git+https://git.antoinevaure.fr/ant/term.git # try it
From a checkout:
nix build && ./result/bin/term
The package also compiles and installs the term-256color terminfo entry.
Home Manager
{
inputs.term.url = "git+https://git.antoinevaure.fr/ant/term.git";
# ...
imports = [ inputs.term.homeManagerModules.default ];
programs.term = {
enable = true;
fontFamily = "Fira Code"; # fontconfig family, default "monospace"
fontSize = 15; # pixels, default 16
fallbackFontFamilies = [ "Symbols Nerd Font Mono" ];
themeMode = "Auto"; # "Auto" | "Dark" | "Light"
kittyTheme = { # optional: kitty theme names per mode
light = "Github";
dark = "Dracula";
};
};
}
extraKeybinds and extraSelectKeybinds take raw Odin for a complete replacement of the key
tables. If you used scripts/install_terminfo.py before, remove its copy once, so Home Manager
can link the packaged one: rm ~/.terminfo/t/term-256color.
From source
nix develop
odin build . -out:term
scripts/install_terminfo.py # once: installs the terminfo entry into ~/.terminfo
More in docs/development.md.
Using term
Keys
| Keys | Action |
|---|---|
Ctrl+Shift+C / Ctrl+Shift+V |
Copy the selection / paste the clipboard |
Ctrl+Shift+Space |
Enter keyboard select mode |
Ctrl+Shift+? / Ctrl+Shift+. |
Increase / decrease the font size (6–96 px)¹ |
Shift+PageUp / Shift+PageDown |
Scroll back / forward a page |
Ctrl+Shift+Z / Ctrl+Shift+X |
Jump to the previous / next shell prompt (needs shell integration marks, OSC 133 or 633) |
| Mouse wheel | Scroll (3 lines per notch), or forwarded to apps that track the mouse |
| Drag, double-click, triple-click | Select text, a word, a line (also sets the primary selection) |
| Hold after a double or triple click, then drag | Extend the selection by whole words or lines |
Ctrl+drag or Ctrl+Shift+drag |
Select a rectangle |
| Middle-click | Paste the primary selection |
Ctrl+click on a link |
Open it, even inside tmux or vim |
Shift + mouse |
Select even when an app has captured the mouse |
¹ These match the character your layout produces with Shift held, not a physical key, so they
sit on different keys on different layouts; edit the table in config.odin if yours is awkward.
Select mode (Ctrl+Shift+Space) works on the scrollback and on full-screen apps alike.
Other keys are swallowed until you leave.
| Keys | Action |
|---|---|
h j k l |
Move |
w b e / W B E |
Word motions (small / big word) |
0 $ |
Start / end of line |
g G |
Oldest scrollback line / newest line |
Ctrl+U Ctrl+D |
Half page up / down |
v V Ctrl+V |
Select by character / line / block (press again to cancel) |
y |
Copy the selection to the clipboard |
o |
Open the link under the cursor, or the first one in the selection |
Esc |
Clear the selection, then leave select mode |
Links
OSC 8 hyperlinks and plain URLs (http://, https://, mailto:, file://, and a bare www.)
are underlined under the pointer, which turns into a hand; Ctrl+click opens them with
xdg-open. url_detection in config.odin limits detection to Schemes or turns it Off.
A link the application declares (OSC 8) always wins over a detected one. Detected URLs follow
soft and hard line wraps (tmux, pagers), stop at quotes, brackets and borders, and are ignored
when cut short with ….
Command line
term [--class APP_ID] [--working-directory DIR] [--log-pty FILE] [-e COMMAND [ARGS...]]
term --version | --print-terminfo | --replay FILE
| Flag | Meaning |
|---|---|
-e cmd args… |
Run a command instead of $SHELL |
--class APP_ID |
Wayland app id, for window rules (default term) |
--working-directory DIR |
Start in a directory |
--log-pty FILE |
Record what apps send and what term answers (never your keystrokes) |
--replay FILE |
Replay a recording headless and summarise it |
--print-terminfo |
Print the terminfo source term generates |
--version |
Print the commit it was built from |
Configuration
Settings live in config.odin, one Odin value that you edit and rebuild with
nix build or odin build . (with Home Manager, the options above set the common ones for
you). The ones people reach for:
| Field | Default | |
|---|---|---|
font_family |
"monospace" |
Fontconfig family; bold and italic faces are found for you |
fallback_font_families |
none | Consulted per glyph, in order, when the main font lacks it |
font_size |
16 |
Pixels; step and range are font_size_step, font_size_min, font_size_max |
theme_mode |
Auto |
Auto follows the desktop's light/dark setting; or force Dark / Light |
theme_dark_overrides, theme_light_overrides |
none | Replace individual palette entries per mode |
scrollback_capacity |
2000 |
Rows kept on the main screen |
default_cursor_shape |
Block |
Block, Underline, Bar; apps can change it |
block_select_mods |
Ctrl, Ctrl+Shift |
Modifier combinations that make a drag select a rectangle |
url_detection |
Schemes_And_Www |
Schemes, or Off for OSC 8 only |
osc52_read |
true |
Let programs read the clipboard; false answers with an empty reply |
kitty_local_media |
true |
Let graphics clients name files and shared memory; see the issue |
keybinds, select_keybinds |
see above | The key tables themselves |
Colours
The palette can also come from a file, read at startup and again on SIGUSR1:
$XDG_CONFIG_HOME/term/theme (else ~/.config/term/theme). It overrides foreground,
background and color0…color15. Both color1=ff5555 and kitty's color1 #ff5555 lines work,
so a kitty theme can be copied or symlinked there unchanged, and a missing file changes nothing.
Home Manager's kittyTheme.light and kittyTheme.dark select separate Kitty palettes,
stored in term/theme-light and term/theme-dark beside the shared file. themeMode
selects which applies (Auto follows the desktop); each defaults to null, keeping
that mode's built-in palette. These files are also read at startup and on SIGUSR1.
The shared term/theme file overrides either mode's palette; nix/noctalia-theme.tmpl
is a template for generating it from the Noctalia shell's colours. The previous
string-valued kittyTheme = "Name" option is replaced by this light/dark attribute set.
Browse themes live with the picker, inside term:
nix run .#theme-preview # arrows to move, type to filter,
# Enter keeps it for this window, Esc restores
nix run .#theme-preview -- --list --dark
It uses the standard colour sequences any program may send (OSC 4 for entries 0–15, OSC 10 and 11 to set, OSC 104, 110 and 111 to reset). Those change only that window, survive a theme-file reload, and are not cleared by a terminal reset.
tmux, ssh and other hosts
term-256color is an entry only your machine has. For ssh there is a wrapper that installs it
on first login (or falls back to xterm-256color), and tmux needs one source-file line to
pass Shift+Enter and friends through. Everything else, plus how to debug a misbehaving setup, is
in docs/tmux-and-ssh.md.
Every detectable feature, with whether term implements it and how it looks inside tmux and
over ssh, is tabulated in docs/capabilities.md.
Not there yet
No bell or desktop notifications, HiDPI / fractional scaling, input methods (IME), scrollback search, tabs or splits, client-side decorations, overline, working-directory reports (OSC 7) and colour emoji. Software rendering only. The kitty graphics protocol is complete apart from a few caveats listed in issues/. Plans are in ROADMAP.md.
Contributing
docs/development.md covers building and testing, AGENTS.md the code style and the design principles. Found a bug that is not being fixed right now? Add a file to issues/.