I found this convincing history on StackOverlow:

  • Vim uses hjkl because vi did.
  • Vi used hjkl because its creator's keyboard didn't have physical cursor keys. Instead, the arrows were printed on the hjkl keys.
  • The arrow keys were printed on hjkl because the corresponding control codes all moved the cursor in directions roughly similar to the cursor keys: ^H for "backspace, ^J for "line feed", ^K for "upline", and ^L for "forward space".

Is that accurate?

If it is, then why were those keys chosen for those control codes? If it isn't, then why did vi use hjkl for movement?

I think stretching the pointer finger left might objectively be less ergonomic than sliding the middle finger up (ergo, jikl is a more ergonomic choice of arrow key layout)


1 Answer 1


Yes, the answer you link to is 100% accurate.

I didn't go further because I didn't think it was particularly relevant. Vi uses HJKL for reasons outside of its creator's control. He didn't "choose" HJKL over JKL; or JIKL. He just used what made most sense in what was his current context.

Bullet point #3 was deep enough for the problem at hand.

Now, the history of ASCII is messy and lots of discussions happened over decades for which we have no minutes left. Control codes were added, removed, and moved around for many reasons, including political, economical, and practical (have you heard about "card lacing"?). FWIW, the first version of ASCII, didn't even have ^H, ^J, ^K, or ^L.

Here is a picture of a teletype (the precursor to the glass terminal), with a dedicated LF, left and up arrows on O and N, etc.

SO, what do we have?

  • ^H, ^J, ^K, and ^L were used in the ADM-3A to move the cursor on screen.

    Here is an overview from the user manual:

    cursor overview

    And here is an explanation of what actually happened when pressing those keys:

    cursor details

    Basically, moving the cursor down implied pressing both CTRL and J, which is not very ergonomic to begin with, let alone touch-typing friendly.

  • What character was used for what control code was mostly a matter of bitwise arithmetics. LF is ^J because J happens to be at the corresponding location in the corresponding column of the table (+ 64 in decimal), not because J happens to be on the home-row or some other nonsense.

    ascii table

    Note that this is a design decision made by the ASCII people, not LSI's.

  • The last piece of the puzzle is the way LSI engineers shoehorned ^K and ^L into this scheme. Per the standard, ^K and ^L don't really move the cursor up or right so it was a conscious decision to pervert their meaning in order to provide cursor movement. What, exactly motivated that decision and how the eventual discussions that led to that decision went is still a mystery and it is likely to stay that way forever.

    A few interesting factoids to take into consideration:

    • Having dedicated cursor keys and grouping them together was already an established practice before the ADM-3A.
    • LSI only produced one single glass terminal without dedicated cursor keys, the ADM-3A.
    • All the other LSI glass terminals had full-ish keyboards.
    • The ADM-3A was meant to be cheap, which justified using a smaller keyboard without cursor keys and numeric pad (the latter being sold separately).
    • The "^H for "left", ^J for "down", ^K for "up", and ^L for "right"" scheme predates the ADM-3A. Previous models already used that scheme even if they had physical cursor keys, and later models did, too.

    That last factoid is key: the physical already sent ^K before someone decided to print ↑ on the side of the K key.

    With all that in mind, I think it is relatively safe to assume they followed a line of reasoning not too far from this one:

    1. We want the terminal to be compact.
    2. Which makes a full keyboard unacceptable.
    3. We remove the numeric pad and the cursor keys.
    4. Numeric pads are kind of useful, though, so we will sell them separately.
    5. But we need a way to move the cursor without physical keys.
    6. We already use ^H for "left", ^J for "down", ^K for "up", and ^L for "right" anyway, so let's print arrows on the H, J, K, and L keys.

In short, pressing the physical already sent the ^K control code in previous terminal models made by LSI and kept doing so in later models. In fact, users could choose to either press CTRLK or , with the exact same effect. In that specific model though, the ADM-3A, the physical keys were removed but the functionality was somewhat preserved. Users could no longer press the physical but they could still press CTRLK and this had to somehow be indicated to the user… by printing the arrows on the corresponding keys.

So when Bill Joy sat at his ADM-3A terminal to work on a screen oriented interface for ex, he of course needed to let the user move the cursor around. The most logical, then and now, would have been the cursor keys, which are literally made for that exact purpose but there were none on his keyboard. There was no standard "UP" control code at the time, though, and what LSI did with ^H, ^J, ^K, and ^L wasn't exactly reliable and cross-platform enough… so no ^<key> either. But the modal concept he was working with allowed him to give super powers to regular keys. He had to find regular alphabetic keys for "Up", "Down", and friends. And what better choice for that than… the keys with the arrows printed on them?


Q: Why HJKL?

A: Because the arrows were printed on HJKL on the author's keyboard.

Q: Why not JKL;, which would have made more sense from a touch-typer POV?

A: Because touch-typing has nothing to do with any of this.

Q: Why not JIKL, which would have made more ergonomic sense from my POV?

A: Because you weren't there to convince Bill Joy, thankfully. And ergonomics have nothing to do with any of this anyway.

More than you ever wanted to know about ASCII

  • I really enjoyed reading your answer. However, the part that "J happens to be at the corresponding location" makes it sound as if it ended there by chance. The designers of ASCII were well aware e.g. how to cheaply convert capital to small letters and vice versa and I simply assume they applied the same thought to control characters. So there may be a good reason (whatever it may be) that J ended up on the same row as LF. The implications remain the same.
    – Friedrich
    Jun 16, 2023 at 14:44
  • The book I linked to as a few chapters about how that table came to be. I didn't read all of it but what I've read doesn't indicate any kind of master plan.
    – romainl
    Jun 16, 2023 at 15:37
  • Apparently, the layout came first, then came the categorization of control characters, then their provisional placement, then the placement of graphic characters, which was ultimately informed by political and economical considerations. The 63 version didn't have LF but it appeared in the 67 version, where, as a "format effector", LF was guaranteed to end up in front of one of HIJKLMNO but why exactly it was put where it is today is unknown to me. Maybe EBCDIC and/or Hollerith have something to do with it? That would point at a punched card reason rather than a keyboard one, though.
    – romainl
    Jun 16, 2023 at 17:07
  • Note also that ASCII puts letters in alphabetic order while keyboards don't, which makes a keyboard reason even more unlikely IMO.
    – romainl
    Jun 16, 2023 at 17:08
  • I don't have a fancy 40 year old book to throw into the ring but Wikipedia mentions maximization of Hamming distance between some control codes. The rest of the control characters were then presumably squeezed in. So this may be the reason I was looking for and it has nothing to do with keyboard layout.
    – Friedrich
    Jun 16, 2023 at 18:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.