I switched to Colemak a couple of years ago. I love it. Never going back. Not really any faster than QWERTY, but so much more comfortable.
One issue though is whenever I jump on someone else's machine or remote into some server. I want to switch the layout but I don't really want to install anything.
Here's a little seventy-line F# app that will intercept all keys on the system on which it's running and remap to Colemak:
open Systemopen System.Diagnosticsopen System.Runtime.InteropServicesopen System.Windows.Forms [<Literal>]let WH_KEYBOARD_LL = 13 [<StructLayout(LayoutKind.Sequential)>]type KBDLLHOOKSTRUCT = val vkCode : uint32 val scanCode : uint32 val flags : uint32 val time : uint32 val dwExtraInfo : nativeinttype LowLevelKeyboardProc = delegate of int * nativeint * KBDLLHOOKSTRUCT -> nativeint [<DllImport("kernel32.dll", SetLastError = true)>]extern nativeint GetModuleHandle(string lpModuleName) [<DllImport("user32.dll", SetLastError = true)>]extern bool UnhookWindowsHookEx(nativeint hhk) [<DllImport("user32.dll", SetLastError = true)>]extern nativeint SetWindowsHookEx(int idhook, LowLevelKeyboardProc proc, nativeint hMod, uint32 threadId) [<DllImport("user32.dll", SetLastError = true)>]extern nativeint CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, KBDLLHOOKSTRUCT lParam) let SetHook (proc: LowLevelKeyboardProc) = use curProc = Process.GetCurrentProcess () use curMod = curProc.MainModule SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curMod.ModuleName), 0u) type App(handler) as x = inherit ApplicationContext() let rec callback (code : int) (wparam : nativeint) (lparam : KBDLLHOOKSTRUCT) : nativeint = match handler code wparam lparam with | Some keys -> SendKeys.Send keys; nativeint 1 | None -> CallNextHookEx(hook, code, wparam, lparam) and proc = new LowLevelKeyboardProc(callback) and hook = SetHook proc override x.ExitThreadCore() = UnhookWindowsHookEx(hook) |> ignore base.ExitThreadCore() printfn "Welcome to Colemak!" Application.Run(new App(fun code wparam lparam -> let key = int >> enum if lparam.flags &&& 0b10010000u = 0u then // key down and not injected match lparam.vkCode |> key with | Keys.D -> Some "s" | Keys.E -> Some "f" | Keys.F -> Some "t" | Keys.G -> Some "d" | Keys.I -> Some "u" | Keys.J -> Some "n" | Keys.K -> Some "e" | Keys.L -> Some "i" | Keys.N -> Some "k" | Keys.O -> Some "y" | Keys.P -> Some ";" | Keys.R -> Some "p" | Keys.S -> Some "r" | Keys.T -> Some "g" | Keys.U -> Some "l" | Keys.Y -> Some "j" | Keys.OemSemicolon -> Some "o" | _ -> None else None))