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
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 before 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-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-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.

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
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.

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 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 Quit
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 {pipe-delimited} pick list in the echo area, with the currently selected entry shown in bold.
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
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-h 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-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-^.
not-modified
Clear the modified flag without saving.
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.
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-|.
toggle-read-only
Toggle read-only mode on the current buffer. Equivalent to C-x C-q.
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-_.

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 (horizontal split) or C-x 3 (vertical split). 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. Up to 8 windows may be open simultaneously.

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.

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).
May 26, 2026 Debian