DECUDK — Define User-Defined Keys (DCS Pc;Pl|Ky/St;... ST)
Remap the DEC user-defined function keys (F6–F20) at runtime — legacy DEC VT, still decoded by xterm and its forks.
Byte forms
Every common string-literal form so you can paste-and-search either direction.
\x1bPPc;Pl|Ky/St;Ky/St;...\x1b\\\033PPc;Pl|Ky/St;...\033\\\ePPc;Pl|Ky/St;...\e\\ESC P Pc ; Pl | Ky / St ; ... ESC \1b 50 ... 1b 5cDescription
DECUDK — Define User-Defined Keys. The DCS frame whose body starts with two numeric parameters separated by ;, then a | literal, then one-or-more Ky/St pairs separated by ;. Pc = clear-policy: 0 clear all keys first, 1 clear only the keys being defined. Pl = lock-state: 0 lock the definitions (further DECUDK ignored until DECSTR), 1 keep unlocked. Ky = the key code (17 = F6, 18 = F7, ..., 34 = F20; F1–F5 are reserved as terminal-local). St = the replacement bytes, hex-encoded (two ASCII hex chars per byte). On a DEC VT520 the user could thus map F6 to send vim<CR> by emitting \x1bP1;1|17/76696D0D\x1b\\. xterm honours DECUDK by routing the hex payload into its translation table for the named PF key. Modern emulators that draw their own UI for shortcut binding (kitty, wezterm) ignore DECUDK in favour of their config file, but xterm + mintty + some industrial terminals still implement it. Practical value today: legacy DEC software, terminal-test-suites (vttest includes a DECUDK page), and emulator development.
Spec citation: DEC STD 070 (DECUDK) / xterm-ctlseqs
Examples
# Map F6 to literally type 'vim\\n' when pressed (key code 17, hex 76 69 6d 0d):\nprintf '\033P1;1|17/76696D0D\033\\'import sys; sys.stdout.write('\x1bP1;1|17/76696D0D\x1b\\\\')fmt.Print("\x1bP1;1|17/76696D0D\x1b\\\\")process.stdout.write('\x1bP1;1|17/76696D0D\x1b\\\\')printf("\x1bP1;1|17/76696D0D\x1b\\\\");Used in
Real-world tools that emit this sequence — anchors the bytes to commands you've already used.
- xterm programmable function keys (UDK)xterm implements DECUDK as `\x1bP1;1|17/61626364\x1b\\` where `17` is the F6 key and `61626364` is the hex-encoded `abcd` string the key will produce on next press. Disabled by default in modern xterm (X resource `*allowUserDefinedKeys: false`) to prevent untrusted output from rebinding F-keys
- GNU screen `bindkey` (parallel mechanism)GNU screen doesn't transit DECUDK to the outer terminal, but its own `bindkey -k F6 "some text"` config achieves the same outcome — rebinding F-keys to literal strings within a screen session, locally to the multiplexer
- DEC VT220 / VT320 firmware demosDEC's own VT220 and VT320 firmware demonstration apps (shipped as VAX/VMS executables in the early 1990s) used DECUDK to rebind F11–F20 for the demo's macro flow — historically the canonical use case the spec was written around. Vt100.net's emulator preserves the behaviour for the demo programs
- rxvt-unicode `keysym` perl extensionrxvt-unicode's `perl-ext-common` extensions historically included a `keysym` extension that emitted DECUDK-style sequences to rebind function keys at runtime — superseded by the modern `URxvt.keysym.<key>: <string>` X resource convention, but the DCS bytes still appear in old screencast captures
- PuTTY saved-session key remappingPuTTY's `Connection > Data > Terminal-type string` plus the Function Keys panel emit DECUDK sequences during session init when a saved profile rebinds F1–F20 — gives mainframe-style accessor key behaviour for users connecting to AS/400 or OpenVMS systems
Frequently asked
Short answers to the questions developers actually search for this sequence.
- Which F-keys can DECUDK actually remap?
- F6 through F20, key codes 17–34. F1–F5 are reserved as terminal-local on the DEC hardware (they invoked terminal setup menus) and DECUDK definitions for them are silently ignored. The full code table: F6=17, F7=18, F8=19, F9=20, F10=21, F11=23, F12=24, F13=25, F14=26, F15(Help)=28, F16(Do)=29, F17–F20=31–34 — note the gaps at 22, 27, 30, which are unassigned. Modern keyboards without F13–F20 still accept the definitions, but the keys are obviously unreachable from the user side; the only practical use beyond F6–F12 is automated test rigs replaying recorded DEC VT520 transcripts. For modern shortcut binding, use the emulator's config (kitty.conf, wezterm.lua, etc.) rather than DECUDK.
- How do I encode the replacement bytes for a DECUDK definition?
- Each byte becomes two ASCII hex characters (upper or lower case both accepted by xterm). To bind F6 to type the literal string
vim\n, the four payload bytes are 0x76 0x69 0x6D 0x0D and the Ky/St pair is17/76696D0D. Wrap it in a full DECUDK frame:\x1bP1;1|17/76696D0D\x1b\\— Pc=1 (clear only this key), Pl=1 (keep unlocked so a later DECUDK can replace it),|separator, key code17(F6),/, hex-encoded payload, ST terminator\x1b\\. Multiple keys in one frame: separate Ky/St pairs with;— e.g.17/76696D0D;18/6C73defines F6 →vim<CR>and F7 →ls. Avoid embedding\x1bdirectly in the payload bytes (it would interfere with the parser even though hex-encoded) — most legitimate uses keep payloads short and printable.
Terminal support
- xterm
- yes
- Linux console (fbcon)
- no
- macOS Terminal.app
- no
- iTerm2
- no
- Windows Terminal
- no
- cmd.exe / ConPTY
- no
- kitty
- no
- alacritty
- no
- WezTerm
- no
- Ghostty
- no
- GNOME Terminal
- no
- Konsole
- no
- tmux
- yes
- GNU screen
- yes
| xterm | Linux console (fbcon) | macOS Terminal.app | iTerm2 | Windows Terminal | cmd.exe / ConPTY | kitty | alacritty | WezTerm | Ghostty | GNOME Terminal | Konsole | tmux | GNU screen |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| yes | no | no | no | no | no | no | no | no | no | no | no | yes | yes |
Related sequences
In the family cookbook
DCS cookbook · 4. VT remap surfaces — DECUDK (user-defined keys) and DECDLD (downloaded glyphs)