troglobit/man
KG(1) General Commands Manual KG(1)

kg
a small text editor with Emacs keybindings

kg [
-RVh
] [
file ...
]

Open all files given on the command line in read-only mode.
Print version and exit.
Print a short usage message and exit.

kg is a minimal terminal text editor with Emacs-style keybindings. It supports syntax highlighting for many programming languages, multiple buffers, split windows, incremental search, a kill ring, and undo/redo.
kg does not depend on curses; it uses VT100 escape sequences directly.
If no files are given, kg opens a scratch buffer. Multiple files each open in their own buffer.

Key Action
C-f / → Move forward one character
C-b / ← Move backward one character
C-n / ↓ Move to next line
C-p / ↑ Move to previous line
C-a / Home Move to beginning of line
C-e / End Move to end of line
C-v / PgDn Scroll down one page
M-v / PgUp Scroll up one page
M-f / C-→ Move forward one word
M-b / C-← Move backward one word
M-e Move forward one sentence
M-a Move backward one sentence
C-↑ / M-{ Move to previous paragraph
C-↓ / M-} Move to next paragraph
C-Home / M-< Move to beginning of buffer
C-End / M-> Move to end of buffer
C-PgUp / C-PgDn Move to beginning / end of buffer
M-m Back to indentation on current line
M-r Cycle cursor through top/middle/bottom of window
M-g Go to line (prompts for line or line:col)
C-u Numeric prefix for the next command (see below)
C-u captures a count that the next command runs that many times. Type C-u alone for 4, repeat C-u to multiply by 4 each time (‘C-u C-u ⇒ 16, ‘C-u C-u C-u ⇒ 64’’), or follow C-u with digits to set an explicit count (‘C-u 8 ⇒ 8, ‘C-u 1 0 0 ⇒ 100’’). C-g cancels an in-progress prefix. The accumulated count is shown in the echo area while it is being built.
Cursor motion, character and word deletion, word-case commands, opening lines, inserting newlines and inserting plain characters all honour the count; ‘C-u 80 -’ inserts eighty dashes, handy for header rules. Commands without a meaningful repeat semantics ignore the count silently.
M-a and M-e use a deliberately simple sentence-boundary heuristic: a sentence ends at ‘.’, ‘?’, or ‘!’ immediately followed by whitespace. Mid-text periods such as “Mr. Smith” or “e.g.” will be mis-detected as sentence ends.

Key Action
Enter Insert newline with auto-indent
Tab Insert tab (with bracket autocomplete)
Backspace Delete character before point
Delete Delete character at point
C-d Delete character at point
C-k Kill from point to end of line
C-o Open line (insert newline, keep cursor)
C-q Quoted-insert: insert the next byte literally
M-^ Join current line with the previous one
M-q Reflow paragraph to the fill column
C-x f Set the fill column (per-buffer)
M-u Upcase word forward from point
M-l Downcase word forward from point
M-c Capitalize word forward from point
M-; Toggle line comment
C-t Transpose the two characters around point
M-h Mark the paragraph around point
M-z Zap: kill up to and including a typed character
M-\ Delete all whitespace around point
M-SPC Collapse whitespace around point to one space
C-k at end of line joins it with the next line (Emacs behavior). Killed text is appended to the kill ring when C-k commands are consecutive.
C-q reads the next byte from the terminal verbatim and inserts it, bypassing auto-indent and bracket completion. Used to embed a literal Tab, Escape, or other control byte — handy when editing terminfo, sendmail.cf or similar files that need a specific byte the regular key bindings would otherwise consume.
M-; toggles a line comment on the current line using the comment prefix defined by the current syntax (e.g. ‘//’ for C, ‘#’ for Python and Shell). If the mark is set, every line between the mark and the cursor is toggled. When adding a comment the prefix is inserted at column 0 followed by a space; when removing one, the prefix and the optional following space are deleted.
M-q reflows the paragraph around point to the fill column, re-applying the indentation of the first line to every wrapped line. Paragraph boundaries are blank lines, and the whole reflow is a single undo step.
C-x f sets the fill column that M-q wraps to. It prompts in the echo area, seeded with the current value; empty input leaves the setting unchanged. The fill column is per-buffer and defaults to 72. M-q never wraps wider than the window, so a larger value is clamped to the window width when reflowing.

Key Action
C-Space Set mark at point
C-w Kill region (cut to kill ring)
M-w Copy region (copy to kill ring)
C-y Yank from kill ring (paste)
Set the mark with C-Space; the region between point and mark renders in reverse video and tracks the cursor as it moves. Cut it with C-w, copy with M-w, or paste from the kill ring anywhere with C-y. The highlight is per-buffer; it survives a C-x b switch and reappears when you come back, and it follows Emacs' transient-mark convention: the region deactivates on C-g, on the first edit, and after a region command (C-w, M-w) has consumed it. The mark itself stays set for the next C-x C-x. The kill ring is shared across all buffers.

Key Action
S-← / S-→ Extend region one character
S-↑ / S-↓ Extend region one line
S-Home / S-End Extend region to line bounds
S-PgUp / S-PgDn Extend region one page
C-S-← / C-S-→ Extend region one word
C-S-↑ / C-S-↓ Extend region one paragraph
C-S-Home / C-S-End Extend region to buffer beginning / end
Shift-Delete Cut region
Shift-Insert Paste from kill ring
Ctrl-Insert Copy region
Delete Delete active region (or character if none)
Shift+motion drops the mark at point and extends the region as the cursor moves, so anyone coming from a modern GUI editor no longer has to remember C-Space first. The region is transient: a non-shifted key tears it down after the command runs, while region-consuming commands (C-w, M-w, C-x C-x) still see the mark intact during their dispatch. Mixing styles works: an explicit C-Space mark stays sticky when extended with shift+motion.
The CUA clipboard trio maps to the same kill ring as C-w / M-w / C-y. Note that some terminals (Terminator, gnome-terminal, ...) intercept Shift-Insert and Ctrl-Insert for their own clipboard handling; unbind them in the terminal preferences if you want kg to see them.
The same applies to several of the modifier-arrow bindings: Terminator grabs Ctrl+Shift and the arrow keys to resize its panes and Alt and the arrow keys to move between them, kitty reserves Ctrl+Shift for its own shortcuts (tab switching on left/right), and gnome-terminal takes Ctrl+PgUp/PgDn for tab switching. Free the keys in the terminal preferences, or fall back on the plain Emacs bindings, which cover the same ground: C-Space with M-b, M-f, M-{, M-}, window motion with C-x o, and M-< / M-> for the buffer ends.
The rxvt family (rxvt, urxvt) is a harder case: by a legacy encoding it cannot distinguish Ctrl+Shift with an arrow key from a plain Shift+arrow – both send the same bytes – so those combinations cannot be told apart there, whatever the configuration. (The keypad keys, such as Ctrl+Shift+Home, do have distinct encodings and work.) Remapping the cursor keys to their xterm sequences with a ~/.Xresources keysym resource is the only cure. Note also that urxvt(1) opens an ISO 14755 Unicode-entry prompt on Ctrl+Shift by default, which shadows these keys until it is turned off.

Key Action
C-x Space Rectangle mark mode
C-x r k Kill rectangle (cut)
C-x r y Yank rectangle (paste at point)
C-x r d Delete rectangle (no save)
C-x r c Clear rectangle (spaces)
C-x Space sets a rectangle mark at point and turns the highlight rectangular: every row in the row range gets reverse-video on the same visual column span, lined up across tabs and UTF-8 content. The same transient-mark tear-down rules apply: C-g, an edit, or a region command ends the mode.
C-x r y pastes the last killed rectangle at point, padding short target rows with spaces and appending new rows when the buffer is too short. C-x r c overwrites every char in the rectangle with a space, padding short rows out to the right edge so the rectangle “exists” everywhere it should. Each rectangle command is one undo step; C-_ restores the entire affected range, including any padding or row appends.

Key Action
C-s Incremental search forward
C-r Incremental search backward
M-% Query replace
While searching: type to extend the query; C-s or or finds the next match; C-r or or finds the previous match; Enter accepts the match; Esc cancels and returns to the original position; Backspace removes the last character from the query.
M-% prompts for a search string and a replacement string, then steps through every match from the current position to the end of the buffer. At each match: y or Enter replaces the match and moves to the next; n skips the match; ! replaces the current match and all remaining matches without prompting; q, Esc, or C-g stops the search. Each replacement is independently reversible with C-_.

Key Action
C-_ / C-/ Undo last change
Undo history is per-buffer. Each buffer keeps up to 1000 operations. The buffer is marked unmodified when undo returns to the last-saved state.

Key Action
C-x C-s / F2 Save current buffer
C-x s Save all modified buffers
C-x C-x Exchange point and mark
C-x C-w Write buffer to a different file (save as)
C-x i Insert file contents at point
C-x C-f Open file in new buffer
C-x C-r Open file read-only in new buffer
C-x C-q Toggle read-only mode on current buffer
C-x b Switch to buffer (interactive)
C-x k Kill (close) current buffer
C-x C-b Open buffer list
C-x C-c / F10 Quit
Quitting with C-x C-c offers to save each modified buffer in turn, then asks for confirmation only if any are left unsaved, like GNU Emacs.
The filename prompts for C-x C-f, C-x C-r, C-x C-w and C-x i open an ido-style picker. Matching directory entries render as a pick list in the echo area, with the currently selected entry shown in reverse video.
What you type narrows the list by substring, the way Emacs' ido-mode does it: typing ‘buf’ matches both ‘bufmgr.c’ and ‘editor_buffer.c’. Prefix matches still rank above mid-name ones, so a leading letter prioritises the obvious candidate. Files already open in a buffer get pushed to the back of the list, matched by basename the way Emacs does it, so the default selection lands on something not yet open. Handy when walking a directory to open several files in turn.
Left/Right arrows cycle the selection; Enter on a directory descends into it; Enter on a file completes the typed path and submits. Backspace at a trailing ‘/’ walks you up one level in a single keystroke. Tab extends the typed text to the longest common prefix of the prefix- matched group, or appends a ‘/’ when the sole match is a directory.
C-x b opens the same picker shape against the active buffers (everything except the current one). What you type narrows the list by basename; Left/Right cycles; Enter switches to the selected buffer.

Key Action
C-x 2 Split window horizontally
C-x 3 Split window vertically
C-x o Switch to next window
M-← / M-→ / M-↑ / M-↓ Select window in that direction
M-S-← / → / ↑ / ↓ Resize window, divider travels with the arrow
C-x ^ Enlarge window
C-x } Enlarge window horizontally
C-x { Shrink window horizontally
C-x + Balance windows
C-x 0 Delete current window
C-x 1 Delete all other windows

Key Action
C-x (/ F3 Start recording a keyboard macro
C-x) / F4 Stop recording
C-x e / F4 Execute (replay) last macro
While recording, C-x) or F4 stops the macro. When not recording, F4 (or C-x e) replays it. Every keystroke during recording is captured, including characters typed into prompts (search strings, goto-line numbers, etc.), so the macro replays the full interaction faithfully. The macro buffer holds up to 1024 keystrokes.

Key Action
C-g Cancel current operation
C-l Recenter: cycle current line to center, top, then bottom of window
C-z Suspend to the shell (resume with fg)
C-h / F1 Open *help* buffer (q closes)
M-x Execute named command
M-! Run shell command, insert output at point
M-| Pipe region through shell command, replace it with the output
M-! prompts for a shell command line, runs it with ‘/bin/sh -c’, and inserts the command's standard output at the cursor position. The command's standard error is discarded so it cannot disturb the editor.
M-| extracts the active region, prompts for a shell command, runs it with the region piped to standard input, and replaces the region with the command's standard output. The original region text is left in the kill ring so C-y recovers it if the result was not what was wanted.
Both commands are intended for non-interactive filters such as sort(1), fmt(1), column(1), jq(1) or sed(1); interactive programs that require a terminal will not work.
C-h opens a special *help* buffer with the full key-binding table. It is a regular buffer. Scroll with the usual motion keys, then press q to dismiss it (or C-x k, or C-x b back to wherever you were).
M-x prompts for a command name and executes it. The completion prompt is the same ido-style picker as C-x C-f: substring matching, Left/Right to cycle, Tab to extend to the longest common prefix. Available commands:
auto-revert-mode
Toggle automatic re-reading of the current buffer's file when it changes on disk. A buffer is only auto-reverted while it is unmodified; a buffer with unsaved edits is never silently overwritten.
capitalize-word
Capitalize the word forward from point (first letter upper, rest lower). Equivalent to M-c.
delete-horizontal-space
Delete all spaces and tabs around point. Equivalent to M-\.
delete-trailing-space
Remove trailing whitespace from the current line only. Reversible with C-_.
downcase-word
Convert the word forward from point to lower case. Equivalent to M-l.
global-auto-revert-mode
Toggle automatic re-reading for every buffer at once. Equivalent to enabling auto-revert-mode in every buffer.
goto-line
Go to a specific line (prompts for line or line:col). Equivalent to M-g.
join-line
Join the current line with the previous one, stripping leading whitespace from the current line and inserting a space at the join point. Equivalent to M-^.
just-one-space
Collapse the spaces and tabs around point to a single space. Equivalent to M-SPC.
make-backup-files
Toggle whether the first save of a visit keeps the previous version of the file as a file~ backup. On by default.
mark-paragraph
Set the mark at the paragraph's start and put point at its end. Equivalent to M-h.
not-modified
Clear the modified flag without saving.
read-only-mode
Toggle read-only mode on the current buffer, like C-x C-q. While a buffer is read-only, editing keys and buffer-modifying M-x commands are refused. The mode line shows read-only as ‘%%’, or ‘%*’ when the buffer has unsaved changes. A file the user lacks permission to write opens read-only automatically.
require-final-newline
Toggle whether saving ensures the file ends with a newline. When on, a buffer whose last line has text gains a trailing empty line (visible, as in GNU Emacs) so the saved file ends with a newline. Off by default, so a file without a final newline is preserved as-is.
revert-buffer
Re-read the current file from disk, discarding all unsaved changes. If the buffer is modified a confirmation prompt is shown.
save-buffer
Save the current buffer to its file. Equivalent to C-x C-s.
set-fill-column
Set the current buffer's fill column, the width M-q reflows to. Equivalent to C-x f.
shell-command
Run a shell command and insert its standard output at point. Equivalent to M-!.
shell-command-on-region
Pipe the region through a shell command and replace it with the command's standard output. Equivalent to M-|.
sort-lines
Sort the lines the region spans into byte order (case-sensitive, not numeric), as a single undo step. Needs an active mark.
toggle-read-only
Toggle read-only mode on the current buffer. Equivalent to C-x C-q.
transpose-chars
Transpose the two characters around point. Equivalent to C-t.
upcase-word
Convert the word forward from point to upper case. Equivalent to M-u.
version
Print the editor version string in the status bar.
what-cursor-position
Show current line, column, and percentage through the buffer.
whitespace-cleanup
Remove trailing whitespace from every line in the buffer. Each modified line is independently reversible with C-_.
zap-to-char
Kill from point up to and including the next occurrence of a prompted character. Equivalent to M-z.

kg supports up to 20 open buffers. Each buffer has its own undo history, dirty flag, and read-only state. Special system buffers (the buffer list with C-x C-b, the help buffer with C-h) have names enclosed in ‘*’ and can be closed with q when another buffer is available to switch to.
The kill ring is global and shared across all buffers, so text killed in one buffer can be yanked in another.

kg keeps track of each open file's modification time and size as last seen. A background poll catches files that have been rewritten by another process and tags the affected buffer with a ‘(changed)’ marker in the mode line. On C-x C-s against such a buffer the user is prompted to confirm before overwriting.
With auto-revert-mode (or its global counterpart global-auto-revert-mode) turned on, a clean buffer whose file has changed on disk is silently reloaded so the view always matches the file. Modified buffers are never reverted automatically — the ‘(changed)’ marker stays visible until either the user saves (and is prompted) or explicitly runs M-x revert-buffer to discard local edits.

The terminal can be divided into multiple windows with C-x 2 (the current window splits into an upper and a lower half) or C-x 3 (into a left and a right half), like in GNU Emacs: other windows are not disturbed, so stacked and side-by-side layouts mix freely. C-x 0 closes the current window and gives its space to the neighbors. Each window shows one buffer and maintains its own scroll position and cursor. Multiple windows may show the same buffer. Use C-x o to cycle between windows, or Meta and an arrow key to select the window in that direction, like windmove in GNU Emacs. Up to 8 windows may be open simultaneously.
Resize windows with Meta, Shift and an arrow key: the divider on that side of the window travels with the arrow. C-x ^ enlarges the current window, C-x } and C-x { widen and narrow it, and C-x + evens out all window sizes again.

Syntax highlighting is detected automatically from the file extension or type, e.g., Makefile. Hash-bang lines (#!) are used as a fallback when the extension is not recognised.
Language Extensions
C/C++ .c .h .cpp .hpp .cc
Python .py .pyw .pyi .pyx
Shell .sh .bash .zsh .profile .bashrc .zshrc
JavaScript .js .mjs .cjs
TypeScript .ts .tsx .d.ts
Rust .rs .rlib
Java .java
C# .cs .csx
PHP .php .phtml
Ruby .rb .rbw .rake
Swift .swift
SQL .sql .ddl .dml
Dart .dart
HTML .html .htm .xhtml
JSX .jsx
Vue .vue
Angular .component.ts .service.ts .module.ts .directive.ts .pipe.ts
Svelte .svelte
Makefile Makefile .mk .mak
Markdown .md .markdown .mkd

kg automatically inserts matching closing brackets when an opening bracket is typed, provided the cursor is at the end of a line. Recognised pairs are ‘()’, ‘[]’, and ‘{}’. Autocomplete is suppressed when text arrives quickly, such as during a paste operation.

M-g prompts for a line number, optionally followed by a colon and a column number (e.g. 42:10). The cursor is moved to that position and the view is centred vertically.

kg uses the controlling terminal /dev/tty for raw-mode input and output. Terminal size changes (SIGWINCH) are handled gracefully.

/dev/tty
Terminal device used for raw-mode I/O.
file~
Backup of a file's previous contents, written on the first save of each visit unless disabled with M-x make-backup-files.

mg(1), emacs(1), vi(1)

kg is derived from kilo by Salvatore Sanfilippo. The name is a nod to mg(1) (Micro GNU Emacs), suggesting a kilo-gram-weight minimal editor with Emacs keybindings.

The kg editor was created by Joachim Wiberg (troglobit) based on the original kilo by Salvatore Sanfilippo (antirez).
July 6, 2026 Debian

Maintained in troglobit/kg as doc/kg.1. Send corrections there, or read it on the mirror.