Learn Vim motions by solving tiny puzzles, right inside Neovim.

Each level gives you a snippet of text and a goal ("delete the typo", "put the cursor on the last word"). Solve it with Vim keys. You're scored on keystrokes, time and the level's par. Every key counts, so finding the short way is the game.
Try the browser demo, then install the plugin for the real thing.
init.lua: options,
keymaps, autocommands and user commands, checked by running your config in
a sandboxed Neovim.Requires Neovim 0.10+.
lazy.nvim
{ "navasvarela/vimdojo", cmd = "VimDojo", opts = {} }
packer.nvim
use({ "navasvarela/vimdojo" })
vim-plug
Plug 'navasvarela/vimdojo'
rocks.nvim
:Rocks install vimdojo
Then run :VimDojo. Full documentation: :help vimdojo.
| Key / command | Action |
|---|---|
:VimDojo |
Open the level menu (<CR> to play, q to close) |
:VimDojo daily |
Play today's daily challenge, the same level for everyone and on the site |
? on the menu or results card, or :VimDojo help |
How to play, scoring, keys and commands, in a panel |
<leader>h |
Show the hint (caps the attempt at 2 stars) |
<leader>r |
Restart the level |
<Esc><Esc> |
Leave the level |
n / r / y / m |
On the results card: next level, retry, copy a spoiler-free result to share, menu |
The timer starts on your first key. Every physical key counts (d2w is 3
keys, <Esc> is 1), and the game's own control keys never do. A level is
solved as soon as its goal holds in Normal mode.
Stars: 3 for matching par on both keys and time, 2 for up to 1.5× par keys, and 1 for solving it. Par is the shortest solution that uses only the motions taught so far, so if you know more Vim, you can beat it.
require("vimdojo").setup({
unlock_all = false, -- skip progression locks
window = "float", -- "float" | "tab"
config = "clean", -- "clean": levels run in a stock Neovim; "mine": with your config
progress_path = nil, -- defaults to stdpath("data")/vimdojo/progress.json
challenges_dir = nil, -- play your own packs instead of the built-in ones
keymaps = { hint = "<leader>h", reset = "<leader>r", quit = "<Esc><Esc>" },
})
Each level runs in its own clean Neovim inside a terminal window, so your
registers, windows and settings are never touched, and your plugins can't
interfere with par. Set config = "mine" to practice with your own setup.
Optional, and off until you turn them on. The game works with no account and no network either way.
{ "navasvarela/vimdojo", cmd = "VimDojo", opts = { online = { enabled = true } } }
| Command | What it does |
|---|---|
:VimDojo login |
Sign in with GitHub and pick a public handle |
s on the results card |
Submit the run: a server replays it in a clean Neovim and recounts the keys |
b on the results card, or :VimDojo board [level] |
The level's leaderboard, right in Neovim |
:VimDojo scores |
Your verified bests and places, and what you haven't sent |
:VimDojo submit |
Send the best run of every level you've played |
Boards rank by verified keys, then by who got there first, and show handles and counts only, because your keys are that level's solution. Setup levels aren't ranked. They're also at vimdojo.org/boards, and here's what's stored.
Share your daily result (y on the results card copies it without the
solution) and talk levels, beaten pars and ideas in
Discussions.
New levels are the best contribution: they're plain JSON, and the tests prove each one is solvable within par in real Neovim. See docs/authoring-levels.md and CONTRIBUTING.md. Design decisions are logged in docs/decisions.md.