Free through lesson 3

Neovim, fish & tmux for Beginners

From installation through configuring fish with its completions, functions and prompt, Neovim motions, Lua config, LSP and plugins, tmux sessions and copy mode, and finally the Lua language itself. Forty lessons that take you to the point where the three work as one environment you can carry around in your dotfiles, and where you can write whatever is missing in Lua yourself. Every command and its output was produced by actually running it.

Curriculum

The 40 lessons are grouped into seven chapters. Working through them in order is the best way, but you are welcome to dip into whatever interests you. Note: config files and key bindings cannot be exercised inside the browser, so install fish, Neovim and tmux and follow along in your own terminal. Chapter 7 (lessons 31–40) is an advanced chapter on the Lua language itself, which underpins the config you build up to lesson 30.

Chapter 1 — Starting with fish (lessons 1–5)

You dispose of the POSIX-incompatibility worry by measuring it, then cover the foundations: config load order, variables and scope, completions and history. By the end, the suggestion is on screen before you finish typing.

Chapter 2 — Making fish your own (lessons 6–11)

You build the parts you touch daily with your own hands: abbreviations, functions, control flow, the prompt and plugins. Finally, fzf and zoxide make moving between directories and finding files noticeably faster.

Chapter 3 — Working in Neovim (lessons 12–16)

You learn the grammar — motions and text objects — then automate editing with registers, macros and search-and-replace. This chapter gets plain Neovim into your fingers before a single plugin goes in.

Chapter 4 — Neovim as a development environment (lessons 17–23)

You write your config in Lua and layer on lazy.nvim, Treesitter, LSP, completion and a fuzzy finder. Git integration and a formatter finish the setup off for real work.

Chapter 5 — Health checks and tmux basics (lessons 24–27)

You clear up the compatibility problems that only appear under fish, and inspect your config with :checkhealth and start-up timing. Then straight into tmux: sessions, windows, panes and .tmux.conf.

Chapter 6 — Tying the three together and taking them with you (lessons 28–30)

You sort out copy mode and the clipboard, and make key bindings and colours consistent across all three tools. Finally you collect it all into dotfiles so you can recreate the same environment on a new machine.

Chapter 7 — Writing your config in Lua (lessons 31–40)

Up to lesson 30 you used Lua as a set of recipes. Now you'll revisit it as a language. You'll cover tables, closures, and modules, then vim.api, autocmds, and async work, and finish by writing a small plugin of your own and making your config crash-proof.

31

Lua inside Neovim

Check the LuaJIT (Lua 5.1) built into Neovim. The three entry points :lua, :=, and nvim -l, plus vim.print, the "0 is true" trap, and forgetting local.

🔒 Basic
32

Tables and vim.tbl_*

Your config is all nested tables. The # trap, assignment vs. copying, the force / keep / error modes of vim.tbl_deep_extend, and the Option object vim.opt returns.

🔒 Basic
33

Functions, closures and varargs

How to pass functions to keymaps and commands. Calling vs. passing, closures that hold state and the loop trap, and what ... and self really are.

🔒 Basic
34

Modules and runtimepath

require searches lua/ along the runtimepath. A module runs only once and is shared, and you can reload it by clearing package.loaded.

🔒 Basic
35

Where vim.api, vim.fn and vim.opt differ

Three ways to touch the editor. 0-based vs. 1-based indexes, type conversion and the 0 trap in vim.fn, the Vimscript left in vim.cmd, and option scopes.

🔒 Basic
36

autocmd and augroup in Lua

Read the args an nvim_create_autocmd callback receives. Avoid duplicates with clear = true, set lifetimes with once and buffer, and pass values via data.

🔒 Basic
37

Keymaps and user commands

expr and buffer in vim.keymap.set; nargs, complete, bang, and range in nvim_create_user_command. Inspect the table each callback actually receives.

🔒 Basic
38

vim.uv and vim.system

Run external commands without freezing the screen. Sync and async vim.system, why callbacks can't call the API and vim.schedule, and a real example: getting the branch name.

🔒 Basic
39

Turning it into a plugin

Extract part of your config into a small plugin, tally.nvim. The setup(opts) convention, plugin/ vs. lua/, a health.lua for :checkhealth, and loading it with lazy.nvim.

🔒 Basic
40

A config that doesn't break

Keep one error from stopping the rest of your config. pcall and vim.notify, a recap of Lua pitfalls, :checkhealth for your own config, and a startup check before committing.

🔒 Basic

Once you have finished all 40 lessons, take on the tool you will use every day in this environment with Git & GitHub, or move to the server side with Linux. Membership unlocks every course.