Dotfiles Của Tôi Không Phải Để Khoe. Chúng Để Làm Việc.

Dotfiles Của Tôi Không Phải Để Khoe. Chúng Để Làm Việc.

Cách tôi dùng một bộ dotfiles có kỷ luật để biến bất kỳ cái máy mới nào thành môi trường quen tay, chống nhầm lẫn — trong chưa đầy một giờ.


Mục lục

Về cơ bản, tôi lười. Không phải kiểu “tôi không muốn làm việc” — mà là kiểu “tôi từ chối làm cùng một việc hai lần”. Và không gì kích hoạt phản xạ đó nhanh bằng việc ngồi vào một cái máy mới rồi nhận ra phải cấu hình lại mọi thứ từ đầu. Một lần nữa.

Thế nên tôi build bộ dotfiles của mình. Không phải để có một cái terminal nhìn cho ngầu. Mà để không bao giờ phải khổ sở set up máy mới thêm lần nào nữa. Hóa ra, lười là một động lực kỹ thuật cực mạnh.

Đây không phải tutorial. Tôi không định dạy bạn cách viết dotfiles. Tôi chỉ kể bạn nghe bộ của tôi, giải thích tại sao tôi chọn như vậy, và hy vọng thuyết phục được bạn rằng dotfiles là một trong những thứ bị đánh giá thấp nhất trong kho đồ nghề của developer. Sau đó bạn làm gì với nó là chuyện của bạn.

Đây là Phần 1 của series hai phần. Phần 1 là phần móng: stow, shell, Tmux, Git defaults, và mấy cái rào chắn — tất cả những gì làm cho terminal trở thành nhà. Phần 2 zoom ra cả desktop: tiling cửa sổ, HUD tự build, tooling cho hạ tầng, và một Neovim IDE — vẫn cùng một repo điều khiển hết.

Triết Lý Của Người Lười

Máy mới là một môi trường thù địch. Shell mặc định nhìn thấy ghét. Alias của bạn không có ở đó. Git config lại đang dùng email của người khác. Từng cái khó chịu nhỏ cộng dồn lại, tới mức bạn mất cả ngày chỉ để quay về trạng thái làm việc bình thường. Một ngày công thật sự bị nuốt cho cái màn kịch tên là “setup”.

Triết lý dotfiles của tôi rất đơn giản: version control phần “làm như thế nào”, không phải phần “làm cái gì”.

Cái gì thuộc về dotfiles: config shell (.zshrc), cài đặt Git (.gitconfig), setup editor (nvim/), config terminal multiplexer (.tmux.conf), và mấy cái script gói lại những workflow tôi lặp đi lặp lại. Đám này định nghĩa cách tôi làm việc, độc lập với việc tôi đang làm cái gì.

Cái gì nằm ngoài: secret, API key, dependency của project, file binary lớn. Secret tôi để cho 1Password. Dependency của project thì sống trong package.jsonrequirements.txt — gắn với project, sinh và mất theo project.

Nghe thì hiển nhiên. Nhưng bạn sẽ bất ngờ khi biết có bao nhiêu developer đang symlink AWS key vào thư mục home qua một cái repo dotfiles public. Đừng là người đó.

Vì Sao Là GNU Stow: Công Cụ Duy Nhất Tôi Thực Sự Cần

Trước khi biết Stow, tôi quản lý symlink bằng tay. Vẫn ổn — cho tới khi tôi quên mất mình đã link những file nào, tạo ra một đống con trỏ chết sau mỗi lần update repo, hoặc — khoảnh khắc đáng nhớ nhất — symlink nhầm version config lúc 1 giờ sáng rồi ngồi nửa tiếng tự hỏi tại sao shell trông kỳ kỳ.

Vấn đề thực ra không nằm ở symlink. Vấn đề là khi không có ai đứng ra quản lý, config và symlink dần dần lệch pha. Push thay đổi lên repo? Tốt. Nhưng symlink vẫn đang trỏ về file cũ. Clone xuống máy mới? Lại thêm một mẻ con trỏ chết.

Và GNU Stow bước vào sân khấu. Một “trang trại symlink” từ thập niên 90 mà tới giờ vẫn là chuẩn vàng. Đây là lý do tôi chọn nó thay vì tự viết script (đã thử rồi, dở tệ):

  1. Idempotent (chạy bao nhiêu lần cũng cùng kết quả).stow --adopt . mười lần. Không hỏng, không nhân đôi.
  2. Chế độ Adopt thần kỳ. Nếu ~/.zshrc đã tồn tại nhưng chưa có trong repo, stow --adopt sẽ kéo nó vào repo rồi symlink ngược ra. Tôi đưa được mọi config hiện có vào version control mà không cần động tay chỉnh sửa.
  3. Kiểm soát từng package. Tôi có thể stow zsh, git, nvim, mà vẫn để thư mục experimental đứng ngoài. Chính xác như dao mổ.
  4. Hoàn toàn minh bạch. ls -la ~/.zshrc cho thấy nó trỏ đi đâu. Không phép màu, không trừu tượng hóa, không bất ngờ.

Hãy hình dung repo dotfiles là phòng vẽ kỹ thuật, còn thư mục home là công trường. Không có Stow, bạn đang đi photo bản vẽ phát cho từng đội thi công — sửa bản gốc xong là có ngay ba phiên bản trôi nổi ngoài kia. Stow thì khác: nó đặt một cái “cửa” trực tiếp về bản gốc. Sửa bản gốc một lần, mọi cửa đều cập nhật ngay tức thì.

View diagram source
graph LR
  subgraph REPO["~/.dotfiles/"]
      A[".zshrc"]
      B[".gitconfig"]
      C["nvim/init.lua"]
      D[".tmux.conf"]
  end
  subgraph HOME["~/"]
      E[".zshrc → symlink"]
      F[".gitconfig → symlink"]
      G[".config/nvim/init.lua → symlink"]
      H[".tmux.conf → symlink"]
  end
  A -->|"stow ."| E
  B -->|"stow ."| F
  C -->|"stow ."| G
  D -->|"stow ."| H
#!/usr/bin/env bash
# install.sh — the laziest machine setup possible

# 1. Clone the repo
git clone https://github.com/PhuongTMR/dotfiles.git ~/.dotfiles
cd ~/.dotfiles

# 2. Install prerequisites (macOS example; adjust for your OS)
brew install stow zsh tmux neovim

# 3. One command to link everything
stow --adopt .

# 4. Switch to Zsh
chsh -s /bin/zsh

echo "Done. Go make coffee. You're already set up."

Chạy một lần là xong. Mọi file config được symlink. Push thay đổi lên repo từ bất kỳ máy nào, git pull trong ~/.dotfiles ở máy còn lại, và toàn bộ máy đều cập nhật theo. Hệ thống cài đặt cả đời chỉ có vậy.

Cái bẫy tôi từng sa vào: ngồi viết một script provisioning siêu to, cố gắng tự nhận diện OS, cài package, chỉnh setting hệ thống, và xử lý đủ loại edge case. Mất nguyên tuần. Cuối cùng nó chạy được trên đúng một máy. Stow cộng thêm một script shell mười dòng làm được 90% việc đó, mà không kéo theo gánh nặng bảo trì.

Zsh + Oh My Zsh: Nơi Tôi Sống

Bash thì ở khắp mọi nơi. Bash thì đáng tin. Nhưng sống trong Bash cả ngày giống như đi làm trong một văn phòng mà ngăn kéo nào cũng không nhãn và đèn lúc nào cũng hơi tối. Về kỹ thuật thì chạy được. Về cảm xúc thì khổ thầm.

Zsh + Oh My Zsh không đổi việc tôi làm. Nó đổi cảm giác khi tôi làm.

Khác biệt nằm ngay trong một góc nhìn:

# Before: default bash prompt
user@MacBook-Pro ~ %

# After: Zsh + autosuggestions + syntax highlighting + Starship
~/projects/myapp on  main [!] via 🐍 v3.11
❯ git checkout fea█ture/auth     ← ghost text shows last matching command
  ~~~~~~~~~~~                     ← green = valid command

Đa số mọi người cài Oh My Zsh xong là load luôn mọi plugin tìm được. Rồi tự hỏi vì sao shell mất hai giây mới khởi động. Tôi từng là người đó. Tôi từng ngồi debug cái shell đó. Không bao giờ nữa.

Tôi chạy đúng ba plugin:

  1. git — không phải cho alias (alias sống trong .gitconfig). Mà cho completion. git che<TAB> biết hết branch, remote, stash của bạn. Thiết yếu.
  2. zsh-autosuggestions — gợi ý dạng “ghost text” hiện ngay lệnh khớp gần nhất khi bạn gõ. Nhấn để chấp nhận. Cắt một nửa thời gian gõ những lệnh lặp đi lặp lại. ROI cao đến mức ngại nói ra.
  3. zsh-syntax-highlighting — lệnh của bạn xanh nếu hợp lệ, đỏ nếu không. Trước khi nhấn Enter. Tôi bắt được nhiều typo nhờ cái này hơn mức tôi muốn thừa nhận.
# ~/.zshrc

export ZSH="$HOME/.oh-my-zsh"
ZSH_THEME=""  # Starship handles the prompt — more on that next

plugins=(git zsh-autosuggestions zsh-syntax-highlighting)
source $ZSH/oh-my-zsh.sh

# The aliases I actually use, not the ones I thought I'd use
alias ..="cd .."
alias ...="cd ../.."
alias ll="eza -lah --group-directories-first"  # eza: ls with opinions
alias k="kubectl"
alias g="lazygit"                               # lazygit: Git UI that doesn't suck
alias gs="git status"
alias gp="git push"
alias vim="nvim"                                # muscle memory override

eval "$(starship init zsh)"

Để ý là tôi không bật docker hay kubectl dưới dạng plugin Oh My Zsh đầy đủ. Mấy plugin đó load nguyên bộ completion nặng ngay khi shell khởi động — đắt. Thay vào đó tôi lazy-load chúng, chỉ khi nào dùng:

# Lazy-load heavy completions — only pay the cost when you need them
if [[ $commands[kubectl] ]]; then
  source <(kubectl completion zsh 2>/dev/null)
fi

if [[ $commands[docker] ]]; then
  source <(docker completion zsh 2>/dev/null)
fi

Shell khởi động trong ~200ms. Completion vẫn đầy đủ. Lần đầu gọi kubectl, completion mới được nạp và cache lại. Thoả thuận sòng phẳng.

Cái sai tôi thấy đi thấy lại: cài plugin chỉ vì nghe “có vẻ hữu ích”. “Ồ, cái này thêm completion cho AWS.” Ừ, nhưng bạn có chạy lệnh aws hai mươi lần một ngày không? Không à? Vậy là bạn vừa cõng thêm chi phí khởi động cho một thứ một tháng dùng hai lần. Audit lại danh sách plugin mỗi quý. Xoá không nương tay.

Starship: Cái Dashboard Của Terminal

Prompt shell mặc định cho bạn ba thông tin: bạn là ai, bạn đang ở đâu, máy này tên gì. Hữu ích nếu bạn là sysadmin năm 1998. Với công việc dev hiện đại, nó như cái taplo ô tô chỉ có mỗi cái công tơ mét.

Tôi cần biết mình đang ở Git branch nào. Tôi cần biết lệnh trước đó có lỗi không. Tôi cần biết mình có lỡ tay activate một virtualenv Python mà quên không. Prompt mặc định: không có cái nào. Starship: có hết.

Starship là prompt renderer viết bằng Rust, nghĩa là nó đủ nhanh để bạn không bao giờ nhận ra nó đang chạy. Modular — mỗi phần chỉ hiện khi đáng hiện.

Trong thực tế nó nhìn như sau:

~/projects/myapp on main via Python v3.11.2 took 2.3s

Branch. Bối cảnh Python. Lệnh trước chạy mất bao lâu. Ký tự chuyển đỏ khi lệnh trước đó fail. Vừa đủ. Không nhiễu, tín hiệu tối đa.

# ~/.config/starship.toml

format = """
$directory\
$git_branch\
$git_status\
$python\
$nodejs\
$cmd_duration\
$line_break\
$character"""

[character]
success_symbol = "[❯](bold green)"
error_symbol = "[❯](bold red)"

[directory]
style = "bold cyan"
truncation_length = 3
fish_style_pwd_dir_length = 2

[git_branch]
symbol = " "
style = "bold purple"
format = "on [$symbol$branch]($style) "

[git_status]
style = "bold red"
format = "([$all_status$ahead_behind]($style) )"

[python]
symbol = "🐍 "
style = "bold yellow"
detect_files = [".python-version", "pyproject.toml"]

[cmd_duration]
min_time = 2000          # Only show if the command took >2 seconds
format = "took [$duration](bold yellow) "

Mọi thứ đều có điều kiện. Phiên bản Python chỉ hiện trong project Python. Git status chỉ hiện trong repo. Command duration chỉ hiện khi lệnh mất hơn 2 giây — không làm rối các lệnh nhanh, nhưng luôn báo hiệu khi có gì đó chậm bất thường.

Một điều đáng nhớ: Starship phải hỏi Git để lấy trạng thái. Trong một monorepo khổng lồ, riêng cái câu hỏi đó cũng đã ngốn vài giây. Nếu thấy prompt bỗng dưng ì ạch, thủ phạm gần như luôn là Git, chứ không phải Starship. git config core.preloadindex true cộng git maintenance start xử lý phần lớn.

Tmux: Thứ Đã Cứu Tôi Khỏi Chính Tôi

Tôi từng mất việc đang làm vì đóng nhầm cửa sổ terminal. Đúng một lần. Một lần đó là đủ.

Tmux là terminal multiplexer. Bạn chia màn hình thành các pane, mở nhiều window, và — phần quan trọng nhất — detach khỏi một session rồi quay lại sau. Session của bạn là một process đang chạy trên server, hoàn toàn độc lập với kết nối SSH.

Không có Tmux, việc làm remote bấp bênh kinh khủng. Một cú rớt mạng là mất sạch context. Có Tmux, bạn SSH vào, làm việc, detach, đi về, sáng hôm sau mở laptop ở nhà reattach lại. Mọi thứ y nguyên chỗ cũ. Cái lệnh deploy bạn bấm ba tiếng trước vẫn đang chạy ngoan ngoãn, log vẫn rớt vào đúng cái pane bạn để lại.

# ~/.tmux.conf

# Ctrl-B is default but anatomically inconvenient at speed
unbind C-b
set -g prefix C-a
bind C-a send-prefix

# Reload config without nuking the session
bind r source-file ~/.tmux.conf \; display "Config reloaded!"

# Split with characters that make visual sense
bind | split-window -h    # | for vertical split
bind - split-window -v    # - for horizontal split
unbind '"'
unbind %

# Move between panes with Alt-Arrow — no prefix required
# This is the one that changed how I use Tmux
bind -n M-Left select-pane -L
bind -n M-Right select-pane -R
bind -n M-Up select-pane -U
bind -n M-Down select-pane -D

set -g default-terminal "tmux-256color"
set -ag terminal-overrides ",xterm-256color:RGB"

set -g base-index 1         # Start numbering at 1, not 0
setw -g pane-base-index 1
set -g mouse on             # Yes, mouse support. I know.
set -g history-limit 10000

Cái binding Alt-Mũi tên là thứ tôi khuyên dùng nhất. Chuyển pane không cần prefix nghĩa là bạn sẽ thực sự dùng pane. Trước khi có nó, tôi mở một split, di chuyển lại bằng Ctrl-A Left, và lập tức nghĩ “lằng nhằng quá”, rồi mở luôn một window mới. Bây giờ project nào tôi cũng có ba pane: một cho editor, một cho test, một cho log. Chỉ một dòng config để biến split thành thứ dùng tự nhiên như thở.

┌──────────────────────┬─────────────────┐
│                      │                 │
│                      │   Tests         │
│   Editor (nvim)      │   $ npm test    │
│                      │                 │
│                      ├─────────────────┤
│                      │                 │
│                      │   Logs / Server │
│                      │   $ npm run dev │
│                      │                 │
└──────────────────────┴─────────────────┘
         Ctrl-A + |           Ctrl-A + -
         (vertical)          (horizontal)
# The only Tmux workflow you need to internalize
tmux new-session -s work    # Start a named session
# Ctrl-A + |                # Split vertically
# Ctrl-A + -                # Split horizontally
# Alt-Arrow                 # Move between panes (no prefix!)
# Ctrl-A + d                # Detach (session keeps running)
tmux attach-session -t work # Come back to it anytime

Cái sai tôi hay thấy: mọi người set một loạt keybinding cầu kỳ mà tới lúc cần thì không bao giờ nhớ. Cả ý nghĩa của Tmux nằm ở chỗ nó phải có mặt đúng lúc bạn cần nhất — như khi đang debug production lúc nửa đêm. Nếu khoảnh khắc đó bạn không nhớ ra phím tắt, thì coi như không có. Cứ giữ đơn giản: Ctrl-A + |, Ctrl-A + -, Alt-Mũi tên, và Ctrl-A + d. Năm thứ. Đó là toàn bộ hệ thống.

Neovim: Cái Hang Thỏ Tôi Tự Nguyện Chui Vào

Để rõ ràng trước: tôi không định thuyết phục bạn dùng Neovim. VS Code rất tốt. JetBrains rất tốt. Cứ dùng thứ gì làm bạn năng suất.

Nhưng tôi sống trong Neovim, và dotfiles của tôi sẽ không thành thật nếu thiếu nó. Tôi đã chỉnh nó nhiều năm. Tay tôi quen nó như một nghệ sĩ piano quen cây đàn của họ. Tôi không còn phải nghĩ về phím tắt nữa, tôi chỉ edit.

Câu chuyện Neovim hiện đại tên là lazy.nvim: một plugin manager không load plugin lúc khởi động — chúng load theo nhu cầu. Nhờ vậy startup giữ dưới 50ms mà tôi vẫn có LSP (kiểm lỗi real-time, go-to-definition, autocomplete), fuzzy finding, tích hợp Git, và mọi thứ một IDE đầy đủ có.

-- ~/.config/nvim/init.lua

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)

require("lazy").setup({
  -- Code intelligence: go-to-definition, hover docs, error checking
  {
    "neovim/nvim-lspconfig",
    event = { "BufReadPre", "BufNewFile" },
    dependencies = { "williamboman/mason.nvim", "williamboman/mason-lspconfig.nvim" },
    config = function()
      require("mason").setup()
      require("mason-lspconfig").setup({
        ensure_installed = { "pyright", "tsserver", "rust_analyzer" },
        automatic_installation = true,
      })
      local lspconfig = require("lspconfig")
      lspconfig.pyright.setup({})
      lspconfig.tsserver.setup({})

      -- The only LSP bindings I use daily
      vim.keymap.set("n", "gd", vim.lsp.buf.definition)  -- Go to definition
      vim.keymap.set("n", "K", vim.lsp.buf.hover)        -- Inline docs
      vim.keymap.set("n", "gi", vim.lsp.buf.implementation)
    end,
  },

  -- Find anything, fast
  {
    "nvim-telescope/telescope.nvim",
    event = "VimEnter",
    dependencies = { "nvim-lua/plenary.nvim" },
    config = function()
      local builtin = require("telescope.builtin")
      vim.keymap.set("n", "<leader>ff", builtin.find_files)  -- Find files
      vim.keymap.set("n", "<leader>fg", builtin.live_grep)   -- Search content
      vim.keymap.set("n", "<leader>fb", builtin.buffers)     -- Switch buffers
    end,
  },

  -- Git diff markers in the gutter
  {
    "lewis6991/gitsigns.nvim",
    event = { "BufReadPre", "BufNewFile" },
    config = true,
  },

  -- Autocomplete
  {
    "hrsh7th/nvim-cmp",
    event = "InsertEnter",
    dependencies = { "hrsh7th/cmp-nvim-lsp", "hrsh7th/cmp-buffer", "L3MON4D3/LuaSnip" },
    config = function()
      local cmp = require("cmp")
      cmp.setup({
        snippet = { expand = function(args) require("luasnip").lsp_expand(args.body) end },
        mapping = cmp.mapping.preset.insert({
          ["<C-Space>"] = cmp.mapping.complete(),
          ["<CR>"] = cmp.mapping.confirm({ select = true }),
        }),
        sources = { { name = "nvim_lsp" }, { name = "buffer" } },
      })
    end,
  },
})

vim.opt.number = true
vim.opt.relativenumber = true   -- Relative numbers for fast jump targeting
vim.opt.expandtab = true
vim.opt.shiftwidth = 2
vim.opt.clipboard = "unnamedplus"

Mỗi plugin chỉ load đúng khi cần. Telescope load khi tôi nhấn <leader>ff. LSP load khi tôi mở file thuộc ngôn ngữ được hỗ trợ. Autocomplete load khi tôi vào insert mode. Kết quả: Neovim mở ra là dùng được luôn.

Lời khuyên quan trọng nhất tôi có cho bạn về Neovim: đừng clone nguyên bộ config của người khác. Họ đã chọn cho workflow của họ. Plugin version của họ được pin tại một thời điểm cụ thể. Khi nó hỏng — mà nó sẽ hỏng — bạn sẽ không biết vì sao, đơn giản vì bạn không phải người dựng nên nó. Hãy bắt đầu với LSP và Telescope. Dùng một tuần. Thêm một thứ. Hiểu nó. Rồi thêm cái kế tiếp. Build nó như build mọi hệ thống khác: incremental, có chủ đích.

Những Lan Can Âm Thầm Đáng Giá

Những dòng giá trị nhất trong dotfiles của tôi không phải những dòng ấn tượng. Mà là những dòng đã cứu tôi khỏi những pha ngu ngốc thảm khốc.

Mấy cái flag interactive trên các lệnh xoá nghe phiền — cho tới cái ngày nó cứu một thư mục production. alias rm='rm -i', alias cp='cp -i', alias mv='mv -i'. Mỗi cái thêm một bước xác nhận trước khi ghi đè hoặc xoá. Một chút phiền phức nhỏ. Một khoản bảo hiểm khổng lồ.

Vài default cứng đầu trong Git giúp đỡ phải bực mỗi ngày:

# ~/.gitconfig

[push]
    autoSetupRemote = true  # First push to a new branch just works, no --set-upstream needed

[pull]
    rebase = true           # Linear history, always. Merge commits are noise.

[init]
    defaultBranch = main    # No more renaming from master on every new repo

[alias]
    amend = commit --amend --no-edit     # Fix the last commit, keep the message
    fixup = commit --fixup HEAD          # Prep a commit for interactive rebase

Secret không bao giờ chạm vào repo:

# ~/.zshrc — keeping credentials out of version control

# Source local secrets that live outside the repo
if [[ -f ~/.env.local ]]; then
  set -a
  source ~/.env.local   # AWS keys, tokens, etc. — in .gitignore, never committed
  set +a
fi

# 1Password CLI for everything else
eval "$(op signin)"

.env.local nằm trong .gitignore và chỉ sống trên máy cần nó. Repo vẫn sạch, vẫn chia sẻ được, vẫn an toàn để push lên remote public.

Những Thứ Tôi Cố Ý Không Tự Động Hoá

Lười không có nghĩa là tự động hoá mọi thứ. Lười nghĩa là tự động hoá những thứ đáng tự động hoá.

App GUI: Slack, trình duyệt, Docker Desktop — tôi cài tay. Đám này thay đổi quá nhanh, đặc thù theo máy, và ROI của việc script hoá thực ra là âm. Một script cài đặt mong manh ba tháng hỏng một lần không phải lười — đó chỉ là một dạng bảo trì khác.

Cài đặt cấp hệ thống: tốc độ lặp phím, độ phân giải màn hình, cài đặt nguồn điện. Mấy thứ này tôi mở System Settings click chuột. Năm phút cho mỗi máy, xong. Tự động hoá chúng thì phụ thuộc nền tảng, mong manh, và là kiểu “yak shaving” cho cảm giác năng suất nhưng thực ra chẳng đâu vào đâu.

Dependency của project: thuộc về project, không phải dotfiles. package.json, requirements.txt, go.mod. Dotfiles là cá nhân; dependency là ngữ cảnh.

Tóm lại: dotfiles là cho workflow kỹ thuật của tôi, không phải để provision cả cái máy. Khi cần provision toàn bộ, tôi viết Ansible playbook hoặc script CloudInit. Công cụ khác, công việc khác.

Từ Số Không Đến Sẵn Sàng Làm Việc Dưới 15 Phút

Trên một máy mới, đây là timeline thật:

  1. Cài Git và Homebrew: 3 phút
  2. Clone và stow dotfiles: 1 phút
  3. Cài plugin Neovim (lazy.nvim): 2 phút
  4. Tinh chỉnh tay (tốc độ phím, màn hình, nguồn): 5 phút

Tổng cộng khoảng 11 phút. Sau đó tôi đã ở trong đúng môi trường của mình. Alias chạy. Phím tắt editor đúng. Terminal hiển thị đúng những gì tôi cần. Không bỡ ngỡ, không phải đóng “thuế setup” vào ngày làm việc đầu tiên.

Lãi kép trả về mỗi ngày. Năm giây tiết kiệm nhờ một alias. Một pha sai Git tránh được vì prompt cho thấy đang ở sai branch. Một remote session sống lại vì Tmux vẫn còn chạy.

Hãy bắt đầu bằng một file .gitconfig và năm cái alias. Viết một install.sh gọi stow. Dùng nó. Rồi để chính những điểm khó chịu thật sự dẫn bạn tới bước tiếp theo.

Dotfiles của bạn nên cảm giác như phần nối dài của cách bạn suy nghĩ — không phải tủ kính trưng bày những thứ bạn đọc đâu đó thấy ngầu. Mục tiêu không phải làm dotfiles cho ấn tượng. Mục tiêu là không bao giờ phải khổ sở set up máy mới thêm lần nào nữa.

Đó là toàn bộ “kế hoạch lớn” của kẻ lười — ít nhất là phần terminal.

Vì đây là điều tôi chưa kể: terminal mới chỉ là một cửa sổ trong một màn hình đầy cửa sổ. Stow, alias và shell config cho tôi một terminal nhanh. Nhưng chúng chưa giải quyết phần còn lại — quản lý cửa sổ, thanh menu, truy cập hạ tầng, một editor đúng nghĩa, hay hơn 80 công cụ CLI đã âm thầm thay thế những default tôi lớn lên cùng. Đó là một lớp dotfiles hoàn toàn khác, và là phần tiếp theo của series này.

Phần 2 lấy mọi thứ phía trên shell — tiling cửa sổ với AeroSpace, một SketchyBar HUD scriptable, ba terminal cho ba mục đích, một “buồng lái” hạ tầng chạy bằng Nushell, và một bộ Neovim đã tiến hoá thành một Django IDE đầy đủ — và cho thấy cách stow . vẫn gắn kết tất cả lại.

Phần 2 — Dotfiles cho macOS: Từ Terminal đến Desktop Environment →

Luồng

0
⌘/Ctrl+Enter để gửiGõ / để xem lệnh · Tab để @nhắc tên