Skip to content

Instantly share code, notes, and snippets.

@micjamking
Last active March 5, 2026 06:03
Show Gist options
  • Select an option

  • Save micjamking/88d5bf72d7da16227b5a027930626326 to your computer and use it in GitHub Desktop.

Select an option

Save micjamking/88d5bf72d7da16227b5a027930626326 to your computer and use it in GitHub Desktop.
Terminal Environment Setup Prompt

Terminal Environment Setup Guide

Replication guide for a VS Code-like terminal experience with a cohesive Monokai Pro theme across iTerm2, Neovim, and all CLI tools.

Font: Monaspace Neon (Nerd Font variant) at 14pt Theme: Monokai Pro (from tanvirtin/monokai.nvim palette) Shell: zsh with Starship prompt Terminal: iTerm2 Editor: Neovim 0.11+ with VS Code-like keybindings and plugins


Prerequisites

  • macOS with Homebrew installed
  • iTerm2 installed
  • Git installed

Step 1: Install CLI Tools

brew install \
  neovim \
  starship \
  fzf \
  eza \
  bat \
  fd \
  ripgrep \
  zoxide \
  git-delta \
  zsh-syntax-highlighting \
  zsh-autosuggestions \
  zsh-completions \
  pyenv

Step 2: Install Font

brew install --cask font-monaspace-nerd-font

This installs all Monaspace variants. We use Monaspace Neon (MonaspiceNe).


Step 3: Create ~/.env

Store secrets here instead of .zshrc:

touch ~/.env
chmod 600 ~/.env

Add any tokens/secrets to this file:

# ~/.env
export JIRA_API_TOKEN="your-token-here"

Step 4: Configure ~/.zshrc

Replace your .zshrc with the following:

# ============================================================================
# ZSH Configuration — VS Code-like Terminal Experience
# ============================================================================

# ---------------------------------------------------------------------------
# Secrets (keep tokens out of this file)
# ---------------------------------------------------------------------------
[[ -f ~/.env ]] && source ~/.env

# ---------------------------------------------------------------------------
# PATH
# ---------------------------------------------------------------------------
export PATH="/opt/homebrew/opt/postgresql@17/bin:$PATH"
export PATH="$HOME/.local/bin:$PATH"

# Pyenv
export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init - zsh)"

# ---------------------------------------------------------------------------
# Editor
# ---------------------------------------------------------------------------
export EDITOR="nvim"
export VISUAL="nvim"

# ---------------------------------------------------------------------------
# Completions (must come before compinit)
# ---------------------------------------------------------------------------
if type brew &>/dev/null; then
    FPATH="$(brew --prefix)/share/zsh-completions:$FPATH"
    FPATH="$(brew --prefix)/share/zsh/site-functions:$FPATH"
fi

autoload -Uz compinit
compinit -C

# VS Code-like completion menu
zstyle ':completion:*' menu select
zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' # case-insensitive
zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}"
zstyle ':completion:*' group-name ''
zstyle ':completion:*:descriptions' format '%F{yellow}-- %d --%f'
zstyle ':completion:*:warnings' format '%F{red}-- no matches --%f'
zstyle ':completion:*' special-dirs true

# ---------------------------------------------------------------------------
# History — VS Code-like persistent search
# ---------------------------------------------------------------------------
HISTFILE=~/.zsh_history
HISTSIZE=50000
SAVEHIST=50000
setopt HIST_IGNORE_ALL_DUPS
setopt HIST_SAVE_NO_DUPS
setopt HIST_REDUCE_BLANKS
setopt INC_APPEND_HISTORY
setopt SHARE_HISTORY
setopt EXTENDED_HISTORY

# ---------------------------------------------------------------------------
# Shell options
# ---------------------------------------------------------------------------
setopt AUTO_CD              # cd by typing directory name
setopt AUTO_PUSHD           # push directories on stack
setopt PUSHD_IGNORE_DUPS
setopt CORRECT              # suggest corrections
setopt INTERACTIVE_COMMENTS # allow comments in interactive shell
setopt NO_BEEP

# ---------------------------------------------------------------------------
# Key bindings — VS Code style
# ---------------------------------------------------------------------------
bindkey -e  # emacs mode (Ctrl-based shortcuts like VS Code)

# Word navigation (Option+Arrow like VS Code)
bindkey '^[[1;3D' backward-word    # Option+Left
bindkey '^[[1;3C' forward-word     # Option+Right
bindkey '^[b' backward-word        # Alt+Left fallback
bindkey '^[f' forward-word         # Alt+Right fallback

# Delete word (Option+Backspace / Option+Delete like VS Code)
bindkey '^[^?' backward-kill-word  # Option+Backspace
bindkey '^[[3;3~' kill-word        # Option+Delete

# Line navigation
bindkey '^A' beginning-of-line     # Ctrl+A / Cmd+Left
bindkey '^E' end-of-line           # Ctrl+E / Cmd+Right

# History search with arrows (type prefix, then Up/Down)
autoload -Uz up-line-or-beginning-search down-line-or-beginning-search
zle -N up-line-or-beginning-search
zle -N down-line-or-beginning-search
bindkey '^[[A' up-line-or-beginning-search
bindkey '^[[B' down-line-or-beginning-search

# Ctrl+K to kill to end of line (like VS Code)
bindkey '^K' kill-line

# Ctrl+U to kill entire line
bindkey '^U' backward-kill-line

# ---------------------------------------------------------------------------
# FZF — Ctrl+P file finder, Ctrl+R history search
# ---------------------------------------------------------------------------
eval "$(fzf --zsh)"

# Monokai Pro theme for fzf
export FZF_DEFAULT_OPTS="
  --color=bg+:#2E323C,bg:#26292C,spinner:#78DCE8,hl:#A9DC76
  --color=fg:#FFF1F3,header:#A9DC76,info:#FFD866,pointer:#FF6188
  --color=marker:#A9DC76,fg+:#FFF1F3,prompt:#AB9DF2,hl+:#78DCE8
  --height=40% --layout=reverse --border --margin=0,1
"
export FZF_CTRL_T_COMMAND='fd --type f --hidden --follow --exclude .git'
export FZF_ALT_C_COMMAND='fd --type d --hidden --follow --exclude .git'
export FZF_CTRL_T_OPTS="--preview 'bat --style=numbers --color=always --line-range :200 {}'"

# ---------------------------------------------------------------------------
# Zoxide — smart cd (replaces cd with z)
# ---------------------------------------------------------------------------
eval "$(zoxide init zsh --cmd cd)"

# ---------------------------------------------------------------------------
# Tool configs
# ---------------------------------------------------------------------------
# bat — Monokai theme
export BAT_THEME="Monokai Extended"

# delta — git diff pager
export GIT_PAGER="delta"

# eza colors
export EZA_COLORS="da=36:uu=33:gu=33"

# ---------------------------------------------------------------------------
# Aliases — modern replacements
# ---------------------------------------------------------------------------
alias neo="nvim"
alias ls="eza --icons --group-directories-first"
alias ll="eza --icons --group-directories-first -la --git"
alias lt="eza --icons --group-directories-first --tree --level=2"
alias la="eza --icons --group-directories-first -a"
alias cat="bat --paging=never"
alias grep="rg"
alias find="fd"
alias diff="delta"
alias tree="eza --tree --icons"

# Git shortcuts (VS Code-like quick commands)
alias gs="git status"
alias ga="git add"
alias gc="git commit"
alias gp="git push"
alias gl="git log --oneline --graph --decorate -20"
alias gd="git diff"
alias gco="git checkout"
alias gb="git branch"

# Quick open
alias e="$EDITOR"
alias o="open ."

# ---------------------------------------------------------------------------
# ZSH Plugins (must be last)
# ---------------------------------------------------------------------------
source /opt/homebrew/share/zsh-autosuggestions/zsh-autosuggestions.zsh
source /opt/homebrew/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh

# Autosuggestion style — subtle like VS Code ghost text
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=#72696A"
ZSH_AUTOSUGGEST_STRATEGY=(history completion)

# Syntax highlighting colors — Monokai Pro
typeset -A ZSH_HIGHLIGHT_STYLES
ZSH_HIGHLIGHT_STYLES[command]='fg=#A9DC76'
ZSH_HIGHLIGHT_STYLES[builtin]='fg=#78DCE8'
ZSH_HIGHLIGHT_STYLES[alias]='fg=#A9DC76,bold'
ZSH_HIGHLIGHT_STYLES[function]='fg=#A9DC76'
ZSH_HIGHLIGHT_STYLES[path]='fg=#FFD866,underline'
ZSH_HIGHLIGHT_STYLES[single-quoted-argument]='fg=#FFD866'
ZSH_HIGHLIGHT_STYLES[double-quoted-argument]='fg=#FFD866'
ZSH_HIGHLIGHT_STYLES[dollar-quoted-argument]='fg=#FFD866'
ZSH_HIGHLIGHT_STYLES[unknown-token]='fg=#FF6188'
ZSH_HIGHLIGHT_STYLES[reserved-word]='fg=#AB9DF2'
ZSH_HIGHLIGHT_STYLES[globbing]='fg=#FF6188'
ZSH_HIGHLIGHT_STYLES[commandseparator]='fg=#FF6188'
ZSH_HIGHLIGHT_STYLES[redirection]='fg=#AB9DF2'
ZSH_HIGHLIGHT_STYLES[assign]='fg=#FFF1F3'
ZSH_HIGHLIGHT_STYLES[comment]='fg=#72696A'

# ---------------------------------------------------------------------------
# Starship prompt (must be last)
# ---------------------------------------------------------------------------
eval "$(starship init zsh)"

Step 5: Configure Starship Prompt

Create ~/.config/starship.toml:

# Starship Prompt — Monokai Pro / VS Code Status Bar Style
# https://starship.rs/config/

format = """
$directory\
$git_branch\
$git_status\
$python\
$nodejs\
$rust\
$golang\
$java\
$docker_context\
$cmd_duration\
$line_break\
$character"""

# Prompt character
[character]
success_symbol = "[>](bold green)"
error_symbol = "[>](bold red)"

# Directory — VS Code breadcrumb style
[directory]
style = "bold #78DCE8"
truncation_length = 4
truncate_to_repo = true
format = "[$path]($style)[$read_only]($read_only_style) "
read_only = " ro"
read_only_style = "red"

# Git branch — like VS Code bottom-left
[git_branch]
style = "bold #A9DC76"
format = "on [$symbol$branch(:$remote_branch)]($style) "
symbol = " "

# Git status — inline indicators
[git_status]
style = "bold #FFD866"
format = '([\[$all_status$ahead_behind\]]($style) )'
conflicted = "="
ahead = "^${count}"
behind = "v${count}"
diverged = "^${ahead_count}v${behind_count}"
untracked = "?${count}"
stashed = "\\$"
modified = "!${count}"
staged = "+${count}"
renamed = "r${count}"
deleted = "x${count}"

# Python
[python]
style = "#FFD866"
format = '[py ${version}(\($virtualenv\))]($style) '
detect_extensions = ["py"]

# Node.js
[nodejs]
style = "#A9DC76"
format = '[node ${version}]($style) '
detect_extensions = ["js", "ts"]

# Rust
[rust]
style = "#FF6188"
format = '[rs ${version}]($style) '

# Go
[golang]
style = "#78DCE8"
format = '[go ${version}]($style) '

# Java
[java]
style = "#FF6188"
format = '[java ${version}]($style) '

# Docker
[docker_context]
style = "#78DCE8"
format = '[docker $context]($style) '
only_with_files = true

# Command duration — like VS Code task timer
[cmd_duration]
style = "#AB9DF2"
format = "[took $duration]($style) "
min_time = 2000

Step 6: Configure Git with Delta

Add to ~/.gitconfig:

[core]
    pager = delta
[interactive]
    diffFilter = delta --color-only
[delta]
    navigate = true
    side-by-side = true
    line-numbers = true
    syntax-theme = Monokai Extended
[merge]
    conflictstyle = diff3
[diff]
    colorMoved = default

Step 7: iTerm2 Monokai Pro Dynamic Profile

Create the directory and file:

mkdir -p ~/Library/Application\ Support/iTerm2/DynamicProfiles/

Save the following as ~/Library/Application Support/iTerm2/DynamicProfiles/MonokaiPro.json:

{
  "Profiles": [
    {
      "Name": "Monokai Pro",
      "Guid": "monokai-pro-dynamic-001",
      "Dynamic Profile Parent Name": "Default",

      "Ansi 0 Color": {
        "Red Component": 0.1313725490,
        "Green Component": 0.1235294118,
        "Blue Component": 0.1352941176,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },
      "Ansi 1 Color": {
        "Red Component": 1.0019607843,
        "Green Component": 0.3823529412,
        "Blue Component": 0.5352941176,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },
      "Ansi 2 Color": {
        "Red Component": 0.6647058824,
        "Green Component": 0.8647058824,
        "Blue Component": 0.4647058824,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },
      "Ansi 3 Color": {
        "Red Component": 1.0019607843,
        "Green Component": 0.8490196078,
        "Blue Component": 0.4019607843,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },
      "Ansi 4 Color": {
        "Red Component": 0.4725490196,
        "Green Component": 0.8647058824,
        "Blue Component": 0.9117647059,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },
      "Ansi 5 Color": {
        "Red Component": 0.6725490196,
        "Green Component": 0.6176470588,
        "Blue Component": 0.9509803922,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },
      "Ansi 6 Color": {
        "Red Component": 0.4725490196,
        "Green Component": 0.8647058824,
        "Blue Component": 0.9117647059,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },
      "Ansi 7 Color": {
        "Red Component": 1.0019607843,
        "Green Component": 0.9470588235,
        "Blue Component": 0.9549019608,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },
      "Ansi 8 Color": {
        "Red Component": 0.3039215686,
        "Green Component": 0.3196078431,
        "Blue Component": 0.3313725490,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },
      "Ansi 9 Color": {
        "Red Component": 0.9941176471,
        "Green Component": 0.4098039216,
        "Blue Component": 0.5156862745,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },
      "Ansi 10 Color": {
        "Red Component": 0.6647058824,
        "Green Component": 0.8647058824,
        "Blue Component": 0.4647058824,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },
      "Ansi 11 Color": {
        "Red Component": 1.0019607843,
        "Green Component": 0.8490196078,
        "Blue Component": 0.4019607843,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },
      "Ansi 12 Color": {
        "Red Component": 0.4725490196,
        "Green Component": 0.8647058824,
        "Blue Component": 0.9117647059,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },
      "Ansi 13 Color": {
        "Red Component": 0.6725490196,
        "Green Component": 0.6176470588,
        "Blue Component": 0.9509803922,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },
      "Ansi 14 Color": {
        "Red Component": 0.4725490196,
        "Green Component": 0.8647058824,
        "Blue Component": 0.9117647059,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },
      "Ansi 15 Color": {
        "Red Component": 1.0019607843,
        "Green Component": 0.9470588235,
        "Blue Component": 0.9549019608,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },

      "Background Color": {
        "Red Component": 0.1509803922,
        "Green Component": 0.1627450980,
        "Blue Component": 0.1745098039,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },
      "Foreground Color": {
        "Red Component": 1.0019607843,
        "Green Component": 0.9470588235,
        "Blue Component": 0.9549019608,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },
      "Bold Color": {
        "Red Component": 1.0019607843,
        "Green Component": 0.9470588235,
        "Blue Component": 0.9549019608,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },
      "Cursor Color": {
        "Red Component": 1.0019607843,
        "Green Component": 0.9470588235,
        "Blue Component": 0.9549019608,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },
      "Cursor Text Color": {
        "Red Component": 0.1509803922,
        "Green Component": 0.1627450980,
        "Blue Component": 0.1745098039,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },
      "Cursor Guide Color": {
        "Red Component": 0.1823529412,
        "Green Component": 0.1980392157,
        "Blue Component": 0.2372549020,
        "Alpha Component": 0.25,
        "Color Space": "sRGB"
      },
      "Selection Color": {
        "Red Component": 0.2019607843,
        "Green Component": 0.2215686275,
        "Blue Component": 0.2607843137,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },
      "Selected Text Color": {
        "Red Component": 1.0019607843,
        "Green Component": 0.9470588235,
        "Blue Component": 0.9549019608,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },
      "Badge Color": {
        "Red Component": 1.0019607843,
        "Green Component": 0.3823529412,
        "Blue Component": 0.5352941176,
        "Alpha Component": 0.5,
        "Color Space": "sRGB"
      },
      "Link Color": {
        "Red Component": 0.4725490196,
        "Green Component": 0.8647058824,
        "Blue Component": 0.9117647059,
        "Alpha Component": 1,
        "Color Space": "sRGB"
      },

      "Use Cursor Guide": true,
      "Minimum Contrast": 0.0,
      "Cursor Type": 1,
      "Blinking Cursor": true,
      "Use Non-ASCII Font": false,
      "Transparency": 0.0,
      "Blur": false,
      "ASCII Anti Aliased": true,
      "Non-ASCII Anti Aliased": true,
      "Scrollback Lines": 10000,
      "Unlimited Scrollback": false,
      "Terminal Type": "xterm-256color",

      "Normal Font": "MonaspiceNeNFM-Regular 14",
      "Non Ascii Font": "MonaspiceNeNFM-Regular 14",
      "Horizontal Spacing": 1.0,
      "Vertical Spacing": 1.1,

      "Option Key Sends": 2,
      "Right Option Key Sends": 2
    }
  ]
}

After saving, go to iTerm2 > Settings > Profiles, select "Monokai Pro", click Other Actions > Set as Default.


Step 8: Neovim Configuration

Create the directory structure:

mkdir -p ~/.config/nvim/lua/plugins

~/.config/nvim/init.lua

-- ============================================================================
-- Neovim Configuration — VS Code-like Experience
-- ============================================================================

-- ---------------------------------------------------------------------------
-- Core Settings
-- ---------------------------------------------------------------------------
local opt = vim.opt

-- Line numbers (like VS Code)
opt.number = true
opt.relativenumber = true

-- Indentation (VS Code defaults)
opt.tabstop = 4
opt.shiftwidth = 4
opt.expandtab = true
opt.smartindent = true
opt.autoindent = true

-- Search
opt.ignorecase = true
opt.smartcase = true
opt.hlsearch = true
opt.incsearch = true

-- Appearance
opt.termguicolors = true
opt.signcolumn = "yes"
opt.cursorline = true
opt.scrolloff = 8
opt.sidescrolloff = 8
opt.wrap = false
opt.showmode = false -- lualine shows the mode
opt.guifont = "MonaspiceNeNerdFontMono:h14"

-- Splits (like VS Code: open right and below)
opt.splitright = true
opt.splitbelow = true

-- System clipboard (like VS Code: yank/paste works with system clipboard)
opt.clipboard = "unnamedplus"

-- File handling
opt.undofile = true
opt.swapfile = false
opt.backup = false
opt.updatetime = 250
opt.timeoutlen = 300

-- Completion
opt.completeopt = { "menu", "menuone", "noselect" }

-- Mouse support (like VS Code)
opt.mouse = "a"

-- Whitespace characters (like VS Code's renderWhitespace)
opt.list = true
opt.listchars = { tab = "» ", trail = "·", nbsp = "" }

-- ---------------------------------------------------------------------------
-- Leader Key
-- ---------------------------------------------------------------------------
vim.g.mapleader = " "
vim.g.maplocalleader = " "

-- ---------------------------------------------------------------------------
-- Bootstrap lazy.nvim (plugin manager)
-- ---------------------------------------------------------------------------
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
    vim.fn.system({
        "git", "clone", "--filter=blob:none",
        "https://github.com/folke/lazy.nvim.git",
        "--branch=stable", lazypath,
    })
end
vim.opt.rtp:prepend(lazypath)

-- ---------------------------------------------------------------------------
-- Plugins
-- ---------------------------------------------------------------------------
require("lazy").setup("plugins", {
    change_detection = { notify = false },
})

~/.config/nvim/lua/plugins/theme.lua

-- Monokai theme
return {
    {
        "tanvirtin/monokai.nvim",
        lazy = false,
        priority = 1000,
        config = function()
            local monokai = require("monokai")
            local pro = monokai.pro
            monokai.setup({
                palette = pro,
                custom_hlgroups = {
                    -- Darker sidebar background (base1 instead of base2)
                    NeoTreeNormal = { bg = pro.base1 },
                    NeoTreeNormalNC = { bg = pro.base1 },
                    NeoTreeEndOfBuffer = { fg = pro.base1, bg = pro.base1 },
                    NeoTreeWinSeparator = { fg = pro.base1, bg = pro.base1 },
                },
            })
        end,
    },
}

~/.config/nvim/lua/plugins/ui.lua

-- UI: statusline, bufferline (tabs), file explorer, which-key
return {
    -- File type icons (requires a Nerd Font in your terminal)
    {
        "nvim-tree/nvim-web-devicons",
        lazy = false,
        opts = { default = true },
    },

    -- Status line (like VS Code bottom bar)
    {
        "nvim-lualine/lualine.nvim",
        dependencies = { "nvim-tree/nvim-web-devicons" },
        opts = {
            options = {
                theme = "auto",
                component_separators = { left = "", right = "" },
                section_separators = { left = "", right = "" },
            },
            sections = {
                lualine_a = { "mode" },
                lualine_b = { "branch", "diff", "diagnostics" },
                lualine_c = { { "filename", path = 1 } },
                lualine_x = { "encoding", "fileformat", "filetype" },
                lualine_y = { "progress" },
                lualine_z = { "location" },
            },
        },
    },

    -- Tab bar (like VS Code tabs)
    {
        "akinsho/bufferline.nvim",
        version = "*",
        dependencies = { "nvim-tree/nvim-web-devicons" },
        opts = {
            options = {
                mode = "buffers",
                diagnostics = "nvim_lsp",
                show_buffer_close_icons = true,
                show_close_icon = false,
                separator_style = "slant",
                offsets = {
                    {
                        filetype = "neo-tree",
                        text = "Explorer",
                        highlight = "Directory",
                        separator = true,
                    },
                },
            },
        },
    },

    -- File explorer sidebar (like VS Code's Explorer)
    {
        "nvim-neo-tree/neo-tree.nvim",
        branch = "v3.x",
        dependencies = {
            "nvim-lua/plenary.nvim",
            "nvim-tree/nvim-web-devicons",
            "MunifTanjim/nui.nvim",
        },
        cmd = "Neotree",
        keys = {
            { "<C-b>", "<cmd>Neotree toggle<cr>", desc = "Toggle Explorer" },
            { "<leader>e", "<cmd>Neotree toggle<cr>", desc = "Toggle Explorer" },
        },
        opts = {
            close_if_last_window = true,
            filesystem = {
                follow_current_file = { enabled = true },
                use_libuv_file_watcher = true,
                filtered_items = {
                    hide_dotfiles = false,
                    hide_gitignored = false,
                },
            },
            window = {
                width = 35,
                mappings = {
                    ["<space>"] = "none",
                },
            },
        },
    },

    -- Which-key: shows available keybindings as you type (like VS Code command hints)
    {
        "folke/which-key.nvim",
        event = "VeryLazy",
        opts = {},
    },

    -- Notifications (like VS Code toast notifications)
    {
        "rcarriga/nvim-notify",
        opts = {
            timeout = 3000,
            max_height = function() return math.floor(vim.o.lines * 0.75) end,
            max_width = function() return math.floor(vim.o.columns * 0.75) end,
        },
        config = function(_, opts)
            local notify = require("notify")
            notify.setup(opts)
            vim.notify = notify
        end,
    },
}

~/.config/nvim/lua/plugins/editor.lua

-- Core editor enhancements (autopairs, comments, indent guides, surround)
return {
    -- Auto-close brackets, quotes, etc.
    {
        "windwp/nvim-autopairs",
        event = "InsertEnter",
        config = true,
    },

    -- Toggle comments with gcc (line) / gc (visual) — Ctrl+/ mapped in keymaps
    {
        "numToStr/Comment.nvim",
        event = { "BufReadPost", "BufNewFile" },
        config = true,
    },

    -- Indent guide lines (like VS Code)
    {
        "lukas-reineke/indent-blankline.nvim",
        main = "ibl",
        event = { "BufReadPost", "BufNewFile" },
        opts = {
            indent = { char = "" },
            scope = { enabled = true },
        },
    },

    -- Highlight matching brackets
    {
        "HiPhish/rainbow-delimiters.nvim",
        event = { "BufReadPost", "BufNewFile" },
    },

    -- Surround text objects (like VS Code bracket pair editing)
    {
        "kylechui/nvim-surround",
        event = { "BufReadPost", "BufNewFile" },
        config = true,
    },

    -- Better escape with jk/jj
    {
        "max397574/better-escape.nvim",
        event = "InsertEnter",
        opts = {},
    },

    -- Highlight yanked text briefly
    {
        "machakann/vim-highlightedyank",
        event = { "BufReadPost", "BufNewFile" },
    },
}

~/.config/nvim/lua/plugins/telescope.lua

-- Telescope: fuzzy finder (like VS Code's Ctrl+P, Ctrl+Shift+F, etc.)
return {
    {
        "nvim-telescope/telescope.nvim",
        branch = "0.1.x",
        dependencies = {
            "nvim-lua/plenary.nvim",
            {
                "nvim-telescope/telescope-fzf-native.nvim",
                build = "make",
            },
        },
        cmd = "Telescope",
        keys = {
            { "<C-p>", "<cmd>Telescope find_files<cr>", desc = "Find Files (Ctrl+P)" },
            { "<leader>ff", "<cmd>Telescope find_files<cr>", desc = "Find Files" },
            { "<leader>fg", "<cmd>Telescope live_grep<cr>", desc = "Find in Files (grep)" },
            { "<leader>fb", "<cmd>Telescope buffers<cr>", desc = "Open Buffers" },
            { "<leader>fh", "<cmd>Telescope help_tags<cr>", desc = "Help Tags" },
            { "<leader>fr", "<cmd>Telescope oldfiles<cr>", desc = "Recent Files" },
            { "<leader>fs", "<cmd>Telescope lsp_document_symbols<cr>", desc = "Document Symbols" },
            { "<leader>fd", "<cmd>Telescope diagnostics<cr>", desc = "Diagnostics" },
            { "<leader>fc", "<cmd>Telescope commands<cr>", desc = "Commands" },
        },
        config = function()
            local telescope = require("telescope")
            telescope.setup({
                defaults = {
                    prompt_prefix = "   ",
                    selection_caret = "  ",
                    path_display = { "truncate" },
                    file_ignore_patterns = {
                        "node_modules",
                        ".git/",
                        "__pycache__",
                        "%.pyc",
                    },
                },
                pickers = {
                    find_files = {
                        hidden = true,
                    },
                },
            })
            telescope.load_extension("fzf")
        end,
    },
}

~/.config/nvim/lua/plugins/treesitter.lua

-- Treesitter: superior syntax highlighting and code understanding
return {
    {
        "nvim-treesitter/nvim-treesitter",
        build = function()
            require("nvim-treesitter").install({
                "python", "javascript", "typescript", "tsx",
                "html", "css", "json", "yaml", "toml",
                "markdown", "markdown_inline",
                "bash", "lua", "vim", "vimdoc",
                "gitignore", "dockerfile",
            })
        end,
        event = { "BufReadPost", "BufNewFile" },
        config = function()
            -- Auto-enable treesitter highlighting for all filetypes
            vim.api.nvim_create_autocmd("FileType", {
                callback = function(args)
                    pcall(vim.treesitter.start, args.buf)
                end,
            })
        end,
    },
}

~/.config/nvim/lua/plugins/lsp.lua

-- LSP: Language Server Protocol (autocomplete, go-to-definition, diagnostics)
return {
    -- Mason: auto-install language servers
    {
        "williamboman/mason.nvim",
        cmd = { "Mason", "MasonInstall" },
        opts = {},
    },

    -- Mason-lspconfig: bridge between mason and lspconfig
    -- v3 uses automatic_enable to auto-configure servers via vim.lsp.enable()
    {
        "williamboman/mason-lspconfig.nvim",
        dependencies = {
            "williamboman/mason.nvim",
            "neovim/nvim-lspconfig",
        },
        event = { "BufReadPre", "BufNewFile" },
        opts = {
            ensure_installed = {
                "pyright",          -- Python
                "ts_ls",            -- TypeScript/JavaScript
                "html",             -- HTML
                "cssls",            -- CSS
                "jsonls",           -- JSON
                "lua_ls",           -- Lua (for editing nvim config)
            },
            automatic_enable = true,
        },
    },

    -- LSP config and keybindings
    {
        "neovim/nvim-lspconfig",
        event = { "BufReadPre", "BufNewFile" },
        dependencies = {
            "hrsh7th/cmp-nvim-lsp",
        },
        config = function()
            -- Set default capabilities for all LSP servers (enables autocomplete)
            local capabilities = require("cmp_nvim_lsp").default_capabilities()
            vim.lsp.config("*", {
                capabilities = capabilities,
            })

            -- Lua LSP: special settings for Neovim config editing
            vim.lsp.config("lua_ls", {
                settings = {
                    Lua = {
                        runtime = { version = "LuaJIT" },
                        diagnostics = { globals = { "vim" } },
                        workspace = {
                            library = vim.api.nvim_get_runtime_file("", true),
                            checkThirdParty = false,
                        },
                        telemetry = { enable = false },
                    },
                },
            })

            -- Diagnostic display (like VS Code's Problems panel)
            vim.diagnostic.config({
                virtual_text = {
                    prefix = "",
                    spacing = 4,
                },
                signs = true,
                underline = true,
                update_in_insert = false,
                severity_sort = true,
                float = {
                    border = "rounded",
                    source = true,
                },
            })

            -- Diagnostic signs in gutter (like VS Code)
            local signs = { Error = " ", Warn = " ", Hint = "󰌵 ", Info = " " }
            for type, icon in pairs(signs) do
                local hl = "DiagnosticSign" .. type
                vim.fn.sign_define(hl, { text = icon, texthl = hl, numhl = "" })
            end

            -- LSP keybindings — activate when any LSP server attaches
            vim.api.nvim_create_autocmd("LspAttach", {
                callback = function(event)
                    local map = function(keys, func, desc)
                        vim.keymap.set("n", keys, func, { buffer = event.buf, desc = "LSP: " .. desc })
                    end

                    map("gd", vim.lsp.buf.definition, "Go to Definition (F12)")
                    map("gD", vim.lsp.buf.declaration, "Go to Declaration")
                    map("gr", vim.lsp.buf.references, "Go to References (Shift+F12)")
                    map("gi", vim.lsp.buf.implementation, "Go to Implementation")
                    map("K", vim.lsp.buf.hover, "Hover Info")
                    map("<leader>rn", vim.lsp.buf.rename, "Rename Symbol (F2)")
                    map("<F2>", vim.lsp.buf.rename, "Rename Symbol")
                    map("<leader>ca", vim.lsp.buf.code_action, "Code Action (Ctrl+.)")
                    map("<leader>D", vim.lsp.buf.type_definition, "Type Definition")
                    map("[d", vim.diagnostic.goto_prev, "Previous Diagnostic")
                    map("]d", vim.diagnostic.goto_next, "Next Diagnostic")
                    map("<leader>d", vim.diagnostic.open_float, "Show Diagnostic")
                end,
            })
        end,
    },
}

~/.config/nvim/lua/plugins/completion.lua

-- Autocompletion (like VS Code IntelliSense)
return {
    {
        "hrsh7th/nvim-cmp",
        event = "InsertEnter",
        dependencies = {
            "hrsh7th/cmp-nvim-lsp",     -- LSP completions
            "hrsh7th/cmp-buffer",        -- Buffer word completions
            "hrsh7th/cmp-path",          -- File path completions
            "L3MON4D3/LuaSnip",         -- Snippet engine
            "saadparwaiz1/cmp_luasnip",  -- Snippet completions
            "rafamadriz/friendly-snippets", -- VS Code-like snippets
            "onsails/lspkind.nvim",      -- VS Code-like completion icons
        },
        config = function()
            local cmp = require("cmp")
            local luasnip = require("luasnip")
            local lspkind = require("lspkind")

            -- Load VS Code-style snippets
            require("luasnip.loaders.from_vscode").lazy_load()

            cmp.setup({
                snippet = {
                    expand = function(args)
                        luasnip.lsp_expand(args.body)
                    end,
                },
                window = {
                    completion = cmp.config.window.bordered(),
                    documentation = cmp.config.window.bordered(),
                },
                -- VS Code-like keybindings for completion menu
                mapping = cmp.mapping.preset.insert({
                    ["<C-b>"] = cmp.mapping.scroll_docs(-4),
                    ["<C-f>"] = cmp.mapping.scroll_docs(4),
                    ["<C-Space>"] = cmp.mapping.complete(),
                    ["<C-e>"] = cmp.mapping.abort(),
                    ["<CR>"] = cmp.mapping.confirm({ select = false }),
                    -- Tab to cycle through completions (like VS Code)
                    ["<Tab>"] = cmp.mapping(function(fallback)
                        if cmp.visible() then
                            cmp.select_next_item()
                        elseif luasnip.expand_or_jumpable() then
                            luasnip.expand_or_jump()
                        else
                            fallback()
                        end
                    end, { "i", "s" }),
                    ["<S-Tab>"] = cmp.mapping(function(fallback)
                        if cmp.visible() then
                            cmp.select_prev_item()
                        elseif luasnip.jumpable(-1) then
                            luasnip.jump(-1)
                        else
                            fallback()
                        end
                    end, { "i", "s" }),
                }),
                sources = cmp.config.sources({
                    { name = "nvim_lsp" },
                    { name = "luasnip" },
                    { name = "path" },
                }, {
                    { name = "buffer" },
                }),
                -- VS Code-like icons in completion menu
                formatting = {
                    format = lspkind.cmp_format({
                        mode = "symbol_text",
                        maxwidth = 50,
                        ellipsis_char = "...",
                    }),
                },
            })
        end,
    },
}

~/.config/nvim/lua/plugins/git.lua

-- Git integration (like VS Code's git gutter + blame)
return {
    -- Git signs in gutter (like VS Code's green/red markers)
    {
        "lewis6991/gitsigns.nvim",
        event = { "BufReadPre", "BufNewFile" },
        opts = {
            signs = {
                add = { text = "" },
                change = { text = "" },
                delete = { text = "󰍵" },
                topdelete = { text = "" },
                changedelete = { text = "~" },
            },
            current_line_blame = true, -- like VS Code GitLens inline blame
            current_line_blame_opts = {
                delay = 500,
            },
            on_attach = function(bufnr)
                local gs = package.loaded.gitsigns
                local map = function(mode, l, r, desc)
                    vim.keymap.set(mode, l, r, { buffer = bufnr, desc = desc })
                end

                -- Navigation between hunks
                map("n", "]h", gs.next_hunk, "Next Git Hunk")
                map("n", "[h", gs.prev_hunk, "Previous Git Hunk")

                -- Actions
                map("n", "<leader>hs", gs.stage_hunk, "Stage Hunk")
                map("n", "<leader>hr", gs.reset_hunk, "Reset Hunk")
                map("n", "<leader>hp", gs.preview_hunk, "Preview Hunk")
                map("n", "<leader>hb", gs.blame_line, "Blame Line")
            end,
        },
    },

    -- Git commands (:Git diff, :Git log, etc.)
    {
        "tpope/vim-fugitive",
        cmd = { "Git", "Gvdiffsplit", "Glog" },
    },
}

~/.config/nvim/lua/plugins/terminal.lua

-- Integrated terminal (like VS Code's Ctrl+` terminal)
return {
    {
        "akinsho/toggleterm.nvim",
        version = "*",
        keys = {
            { "<C-`>", "<cmd>ToggleTerm<cr>", desc = "Toggle Terminal" },
            { "<leader>t", "<cmd>ToggleTerm<cr>", desc = "Toggle Terminal" },
        },
        opts = {
            size = function(term)
                if term.direction == "horizontal" then
                    return 15
                elseif term.direction == "vertical" then
                    return vim.o.columns * 0.4
                end
            end,
            open_mapping = [[<C-`>]],
            direction = "horizontal",
            shade_terminals = true,
            float_opts = {
                border = "curved",
            },
        },
    },
}

~/.config/nvim/lua/plugins/keymaps.lua

-- VS Code-like keybindings
return {
    {
        dir = ".",
        name = "keymaps",
        lazy = false,
        config = function()
            local map = vim.keymap.set

            -- ---------------------------------------------------------------
            -- File operations
            -- ---------------------------------------------------------------
            map("n", "<C-s>", "<cmd>w<cr>", { desc = "Save file" })
            map("i", "<C-s>", "<esc><cmd>w<cr>", { desc = "Save file" })
            map("n", "<C-q>", "<cmd>qa<cr>", { desc = "Quit all" })

            -- ---------------------------------------------------------------
            -- Comment toggle: Ctrl+/ (like VS Code)
            -- ---------------------------------------------------------------
            map("n", "<C-/>", function()
                require("Comment.api").toggle.linewise.current()
            end, { desc = "Toggle comment" })
            map("v", "<C-/>", "<esc><cmd>lua require('Comment.api').toggle.linewise(vim.fn.visualmode())<cr>", { desc = "Toggle comment" })

            -- ---------------------------------------------------------------
            -- Buffer/tab navigation (like VS Code Ctrl+Tab)
            -- ---------------------------------------------------------------
            map("n", "<S-l>", "<cmd>BufferLineCycleNext<cr>", { desc = "Next tab" })
            map("n", "<S-h>", "<cmd>BufferLineCyclePrev<cr>", { desc = "Previous tab" })
            map("n", "<leader>x", "<cmd>bdelete<cr>", { desc = "Close buffer" })
            map("n", "<C-w>", "<cmd>bdelete<cr>", { desc = "Close buffer (Ctrl+W)" })

            -- ---------------------------------------------------------------
            -- Window/split management (like VS Code split editor)
            -- ---------------------------------------------------------------
            map("n", "<leader>sv", "<cmd>vsplit<cr>", { desc = "Split vertical" })
            map("n", "<leader>sh", "<cmd>split<cr>", { desc = "Split horizontal" })
            -- Navigate between splits with Ctrl+h/j/k/l
            map("n", "<C-h>", "<C-w>h", { desc = "Move to left split" })
            map("n", "<C-j>", "<C-w>j", { desc = "Move to lower split" })
            map("n", "<C-k>", "<C-w>k", { desc = "Move to upper split" })
            map("n", "<C-l>", "<C-w>l", { desc = "Move to right split" })

            -- ---------------------------------------------------------------
            -- Move lines up/down (like VS Code Alt+Up/Down)
            -- ---------------------------------------------------------------
            map("n", "<A-j>", "<cmd>m .+1<cr>==", { desc = "Move line down" })
            map("n", "<A-k>", "<cmd>m .-2<cr>==", { desc = "Move line up" })
            map("v", "<A-j>", ":m '>+1<cr>gv=gv", { desc = "Move selection down" })
            map("v", "<A-k>", ":m '<-2<cr>gv=gv", { desc = "Move selection up" })

            -- ---------------------------------------------------------------
            -- Duplicate lines (like VS Code Alt+Shift+Down)
            -- ---------------------------------------------------------------
            map("n", "<A-S-j>", "<cmd>t.<cr>", { desc = "Duplicate line down" })
            map("n", "<A-S-k>", "<cmd>t.-1<cr>", { desc = "Duplicate line up" })

            -- ---------------------------------------------------------------
            -- Indentation (like VS Code Tab/Shift+Tab in visual mode)
            -- ---------------------------------------------------------------
            map("v", "<", "<gv", { desc = "Indent left (stay selected)" })
            map("v", ">", ">gv", { desc = "Indent right (stay selected)" })

            -- ---------------------------------------------------------------
            -- Search & Replace (like VS Code Ctrl+H)
            -- ---------------------------------------------------------------
            map("n", "<C-f>", "/", { desc = "Search in file" })
            -- Clear search highlights with Escape
            map("n", "<Esc>", "<cmd>nohlsearch<cr>", { desc = "Clear search highlights" })

            -- ---------------------------------------------------------------
            -- Select all (like VS Code Ctrl+A)
            -- ---------------------------------------------------------------
            map("n", "<C-a>", "ggVG", { desc = "Select all" })

            -- ---------------------------------------------------------------
            -- Undo/Redo (like VS Code)
            -- ---------------------------------------------------------------
            map("n", "<C-z>", "u", { desc = "Undo" })
            map("n", "<C-y>", "<C-r>", { desc = "Redo" })
            map("i", "<C-z>", "<esc>ui", { desc = "Undo" })

            -- ---------------------------------------------------------------
            -- Better terminal escape
            -- ---------------------------------------------------------------
            map("t", "<Esc><Esc>", "<C-\\><C-n>", { desc = "Exit terminal mode" })
        end,
    },
}

~/.config/nvim/lua/plugins/markdown.lua

-- Markdown live preview in browser
return {
    {
        "iamcco/markdown-preview.nvim",
        cmd = { "MarkdownPreviewToggle", "MarkdownPreview", "MarkdownPreviewStop" },
        ft = { "markdown" },
        build = "cd app && npx --yes yarn install",
        keys = {
            { "<leader>mp", "<cmd>MarkdownPreviewToggle<cr>", desc = "Toggle Markdown Preview" },
        },
    },
}

Step 9: Post-Install

# Rebuild zsh completion cache
rm -f ~/.zcompdump; compinit

# Fix potential permission warnings
chmod go-w '/opt/homebrew/share'
chmod -R go-w '/opt/homebrew/share/zsh'

# First launch of neovim will auto-install all plugins via lazy.nvim
nvim

# Inside neovim, install LSP servers:
# :MasonInstall pyright typescript-language-server

# Source the new shell config
source ~/.zshrc

Monokai Pro Color Reference

All colors are sourced from the tanvirtin/monokai.nvim Pro palette to ensure consistency.

Role Hex Used In
Background #26292C iTerm bg, fzf bg, neovim Normal bg (base2)
Sidebar BG #211F22 Neo-tree sidebar (base1)
Foreground #FFF1F3 iTerm fg, fzf fg, neovim Normal fg (white)
Pink #FF6188 Keywords, errors, unknown tokens
Green #A9DC76 Functions, commands, git branch
Aqua #78DCE8 Types, builtins, directory, links
Yellow #FFD866 Strings, paths, git status, Python
Orange #FC9867 Parameters, tags
Purple #AB9DF2 Numbers, reserved words, cmd duration
Red #FD6883 Diagnostics, bright red
Grey #72696A Comments, autosuggestions
Dark Grey #4D5154 Line numbers (base5)
Selection #333842 Visual selection (base4)
Cursor Line #2E323C Cursor line, fzf bg+ (base3)

Shell Shortcuts Reference

Shortcut Action
Ctrl+R Fuzzy history search (fzf)
Ctrl+T Fuzzy file finder with preview
Option+Left/Right Word navigation
Option+Backspace Delete word
Up/Down (after typing) Prefix history search
Tab Interactive completion menu
cd <partial> Smart directory jump (zoxide)

Neovim Shortcuts Reference

VS Code Neovim Description
Ctrl+P Ctrl+P Find file by name
Ctrl+Shift+F Space fg Search in all files (grep)
Ctrl+B Ctrl+B Toggle file explorer sidebar
Ctrl+S Ctrl+S Save file
Ctrl+/ Ctrl+/ Toggle comment
Alt+Up/Down Alt+K / Alt+J Move line up/down
Alt+Shift+Down Alt+Shift+J Duplicate line
Ctrl+Z Ctrl+Z or u Undo
Ctrl+Y Ctrl+Y or Ctrl+R Redo
Ctrl+` Ctrl+` Toggle terminal
F12 gd Go to definition
Shift+F12 gr Find all references
F2 F2 or Space rn Rename symbol
Ctrl+. Space ca Code actions
Hover K Show hover info
Ctrl+Space Ctrl+Space Trigger autocomplete
Shift+L / Shift+H Next / Previous tab
Space x Close buffer
]d / [d Next / Previous diagnostic
]h / [h Next / Previous git hunk
Space mp Toggle markdown preview
Space (wait) Show all keybinding hints (which-key)

Tool Replacement Map

Classic Modern Replacement Notes
ls eza --icons File icons, git status
cat bat Syntax highlighting
grep ripgrep (rg) Faster, respects .gitignore
find fd Simpler syntax, faster
cd zoxide Learns frequent directories
diff delta Side-by-side, syntax-aware
tree eza --tree Icons, respects .gitignore
vim nvim (neo) Neovim with VS Code-like config
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment