DEV Community

성현
성현

Posted on

I can barely use Vim, so I built a Vim trainer with AI. Then I failed my own level.

TL;DR: A DevOps engineer who can barely use Vim built a Vim/tmux trainer with Claude Code. Then he couldn't solve his own level. The builder learned Vim before the site launched.

Why: I open a terminal more than an IDE now

The way I work changed. Claude Code and Codex run in a terminal, a few tmux panes show the output, and I watch.

But there's still a moment where a human touches up what the agent wrote. That happens in Vim/Neovim inside the terminal. And I'm not good at Vim. I know :wq. That's roughly it.

Around then I heard DHH say he just builds whatever he needs. Fair enough: if there's no good place to practice, build one.

Goal: that LearnGitBranching feeling

If you've played LearnGitBranching, you know how addictive it is: you see the goal state and close the gap with your own hands.

So nvim-edu looks like this:

Boss level: apply an AI code review

  • Your buffer on the left, the goal on the right. Red lines still differ
  • Beat the par keystroke count for ★★★
  • 41 levels: motions → editing → text objects → visual & macros → real world: cleaning up AI code → tmux → guru combos
  • Drills, a daily challenge (same tasks for everyone that day, with a 🔥 streak) and free practice
  • Deliberately Neovim-looking: neo-tree sidebar, lualine, :colo tokyonight and friends

The real-world boss reads like this: "Review comments: ① remove the DEBUG prints ② rename tot → total." Exactly the moment where a human cleans up agent code.

The tmux chapter: only the keys humans still type

tmux has hundreds of bindings, but while an agent runs, a human presses only a handful:

  • Create, attach, detach sessions (tmux new -s agent, C-b d, tmux a)
  • Split, move, zoom panes (C-b %, C-b o, C-b z)
  • Copy mode to scroll back and copy an error (the one I use most when agent logs get long)

That's the whole chapter. tmux can't run in a browser, so there's a small simulator with a session/window/pane tree.

Incident 1: the builder failed his own level

With the levels done, I was asked to try one by hand. The par solution on screen: 3lxfmx.

Me: "I don't get 3lxfmx."

I was pressing 3 over and over. 😇 Claude broke it down:

Keys Meaning Result
3l move right 3 cursor on the 4th character
x delete under cursor typo gone
fm find the next m on this line cursor on m
x delete done

"Oh, it works."

Since then Claude has a standing rule for me: always explain keys as keys → meaning → result. The builder was the first user, and the first to fail.

Incident 2: typing jjl produced ㅓㅓㅣ

Every Korean (or Japanese, or Chinese) Vim user knows this one. Leave your input method on Korean, press jjl in NORMAL mode, and instead of moving down, down, right you get ㅓㅓㅣ on screen. That happened to me.

So in NORMAL mode, if a non-Latin IME is composing, nvim-edu blocks the text from entering the buffer and tells you to switch to English input. Early levels also block arrow keys and the mouse to build hjkl habits. (After I asked "wait, do arrow keys not work in real nvim?", arrows came back from chapter 2 on.)

Does it behave like real Neovim?

For speed, levels run on a browser Vim emulator (@replit/codemirror-vim). The worry: if the emulator is wrong, the site teaches wrong habits.

So real Neovim is the answer key:

  • The same keys go into nvim --headless and into the site's editor; text, cursor and mode are compared
  • It started at 130/169 matching: search always ignored case, dG left an empty line, Ctrl-a read 007 as octal…
  • After fixing the emulator: 180/180. CI compares against Neovim 0.11.0 on every push

Still skeptical? There's a Real Vim mode (beta): actual Vim 8.2 running in the browser via vim.wasm, solving the same levels.

…except in Safari. 😅 GitHub Pages can't send the required isolation headers, so a service worker adds them, and Safari doesn't like that.

Try it

No install, no config. English and Korean.

👉 https://s3onghyun.github.io/nvim-edu/

A level is one object in src/levels.js, and npm test checks that the par solution really clears it, both in the emulator and in real Vim. Got a situation you wish were a level? Issues and PRs welcome.

Plenty of you already live in Vim. This is for anyone who, like me, is still stuck at :wq. 🙂

Top comments (0)