1. 从一行命令到一个趁手工具:t3code 项目的起源
说起 t3code 这个名字,可能有人觉得它是什么神秘框架的名字,其实它是我在本地折腾开发环境时攒出来的一个个人项目代号。t3 这个后缀一看就知道和“三步走”有关系——我的目标非常简单:拿到一台新的开发机,敲一行命令,让常用工具链、代码仓库和开发习惯一次性恢复到熟悉的状态。如果你也是个经常切换设备、重装系统,或者需要反复初始化环境的开发者,一定能理解这个痛点:每次配环境少则半小时,多则半天,装完这缺那,跑完项目又报错,全靠浏览器收藏夹和碎片笔记续命。
t3code 的定位不是某个复杂的自动化平台,就是围绕“快速、可靠、可复现”这三个关键字搭建的本地开发环境初始化脚本和配置管理仓库。它解决的是一类非常具体的问题:怎么把零散的安装步骤、dotfiles、插件列表、常用命令集合拢到一起,让一套配置能在多台设备上保持一致。
这篇文章会完整拆解 t3code 的设计思路、组成结构和实操过程。适合谁看?准备整理自己开发环境的同学、对 dotfiles 管理感兴趣的人、以及想用最小成本实现环境自动化配置的团队。内容偏向真实操作,不会讲虚的,每个环节都有可复现的具体步骤。
2. 设计思路:为什么我不直接用现成的配置管理工具
动手之前我认真对比过 Ansible、Chef 这些重量级配置管理工具。结论很明确:它们适合管理几十台服务器的集群,而不是个人的三五台开发机。我自己维护的机器就那么几台,而且系统还杂——有 macOS,有 Ubuntu,偶尔还有 Windows 的 WSL 环境。为这么点机器引入一套完整的自动化运维体系,学习成本和维护成本都高得离谱。
所以就换了个思路:用最朴素的 Shell 脚本加 dotfiles 仓库来实现。收敛下来就三件事:
- 安装:把每个平台需要的包管理器命令写清楚,要装什么东西列成一个清单。
- 配置:把各种配置文件的软链接指向仓库里的 dotfiles,保持版本一致。
- 验证:装完以后执行一组检查命令,确认关键工具都能正常工作。
这三件事用 shell 写就是最直接的。t3code 不需要常驻服务,不需要 agent,也不需要中心化服务器,每个开发机上都只是一个本地目录加几个脚本。要把一台新机器恢复到熟悉状态,核心动作就是克隆仓库、执行脚本、重启 shell。
这套方案的优势在于:脚本简单透明,出了问题直接看代码就行,不像那些封装很深的工具,出错以后还得先学会怎么排查它们自身的问题。缺点我也清楚:没有幂等性的严格保证,重复执行脚本时偶尔会遇到已经存在的软链接导致报错。所以在后面实操环节,我会特地把幂等处理作为一个重点来讲解,把常见的坑提前填掉。
3. 核心工具选型:每个组件背后都有真实考量
3.1 Shell 脚本:bash 而不是 zsh 或 fish
t3code 的主脚本我统一用 bash 写。为什么不用 zsh?虽然 macOS 默认已经切到 zsh,很多开发者的交互 shell 也是 zsh,但 bash 是所有环境里兼容性最好的,Ubuntu 默认带 bash,WSL 里也是 bash,macOS 虽然默认是 zsh 但 bash 也一直在。考虑到这个脚本主要在干净的机器上运行,还没装任何东西,bash 3.2 以后版本里我用到的那几个语法特性都完全够用。
还有一点,脚本执行时我不会依赖 alias 或者 .zshrc 里自定义的函数,因为新机器上的交互 shell 还没加载我的配置。脚本从一开始就必须做到自包含——依赖的命令要么是系统自带的,要么由脚本自己去安装。
3.2 仓库结构:单仓库多模块
整个 t3code 是一个 git 仓库,目录结构如下:
t3code/ ├── bin/ │ └── t3 # 主入口脚本 ├── modules/ │ ├── brew.sh # macOS 专用 │ ├── apt.sh # Ubuntu / Debian 专用 │ ├── wsl.sh # WSL 专用 │ └── common.sh # 跨平台通用部分 ├── dotfiles/ │ ├── .gitconfig │ ├── .tmux.conf │ ├── .vimrc │ └── init.vim # 如果使用 neovim ├── install.sh # 快速开始脚本 └── README.md模块化是我刻意坚持的。早期版本我试图把所有逻辑写在一个大脚本里,结果随着工具越加越多,脚本膨胀到七八百行,每次改动都要小心会不会影响别的地方。拆成模块以后,每台机器只需要 source 跟自己平台相关的模块。比如 macOS 上根本不跑 apt.sh,Ubuntu 上也不会碰 brew.sh,省事还安全。
3.3 安装清单管理:用文本文件,不用数据库
每个模块里都维护一个工具清单,就是简单的文本数组:
BREW_PACKAGES=( "git" "tmux" "neovim" "ripgrep" "fd" "fzf" "jq" "tree" )我见过有人为这种事情上数据库或者 yaml 配置的,完全没必要。工具清单本质上就是一个名称列表,bash 数组足够表达。真要上 yaml 还得引额外解析器,新机器上未必有,这不是给自己找麻烦么。
3.4 包管理器策略:原生优先,辅助兜底
macOS 上我用 Homebrew 作为主要包管理器,这是 macOS 生态里绕不开的选择。Ubuntu 上以 apt 为主。但这里有个细节值得展开说说:apt 源里的软件版本往往不是最新的,尤其是 neovim、ripgrep 这类更新较快的工具。所以我在 apt.sh 里做了个策略:先用 apt 装基础版本,再用 AppImage 或预编译二进制把关键工具替换成新版。
# apt.sh 中的处理逻辑 install_apt_packages() { sudo apt-get update sudo apt-get install -y "${APT_PACKAGES[@]}" } install_neovim_latest() { # 下载官方预编译包,解压到 ~/.local local version="stable" local url="https://github.com/neovim/neovim/releases/download/${version}/nvim-linux-x86_64.tar.gz" mkdir -p "$HOME/.local/bin" curl -L "$url" | tar xz -C "$HOME/.local" ln -sf "$HOME/.local/nvim-linux-x86_64/bin/nvim" "$HOME/.local/bin/nvim" }这一点在我实际用下来非常管用。Ubuntu 20.04 的 apt 源里 neovim 还停在 0.4.x,而很多插件已经要求 0.5 以上了。如果不做这层二次安装,配置管理得再好,编辑器插件照样跑不起来。
4. 实操过程:从一台空白机器到顺手环境
4.1 快速开始的入口设计
一台全新的机器上,用户要做的事情只有三步。这也是 t3 这个名字的由来——三个字母,三步操作:
# 第一步:克隆仓库 git clone https://github.com/yourname/t3code.git ~/.t3code # 第二步:执行安装脚本 cd ~/.t3code && ./install.sh # 第三步:加载新的 shell 配置 source ~/.bashrc # 或者重新打开终端install.sh 是唯一入口脚本,它的职责是探测操作系统,然后调用对应的模块。核心逻辑很短,但足够清晰:
#!/usr/bin/env bash set -euo pipefail detect_os() { case "$(uname -s)" in Darwin*) echo "macos" ;; Linux*) if grep -qi "microsoft" /proc/version 2>/dev/null; then echo "wsl" else echo "linux" fi ;; *) echo "unsupported" ;; esac } main() { local os os=$(detect_os) echo "检测到系统: $os" case "$os" in macos) source "$(dirname "$0")/modules/brew.sh" source "$(dirname "$0")/modules/common.sh" ;; linux) source "$(dirname "$0")/modules/apt.sh" source "$(dirname "$0")/modules/common.sh" ;; wsl) source "$(dirname "$0")/modules/apt.sh" source "$(dirname "$0")/modules/wsl.sh" source "$(dirname "$0")/modules/common.sh" ;; *) echo "不支持的平台" >&2 exit 1 ;; esac echo "t3code 环境初始化完成" } main "$@"这段脚本看起来简单,但有一个值得注意的设计:set -euo pipefail这行是必须的。它保证任何一个命令失败都会导致脚本立即退出,而不是带着错误继续往下跑。很多人写 shell 脚本不重视这个,导致半路出了问题还继续安装,最后环境处于一种“装了一半”的脏状态,排查起来更麻烦。
4.2 dotfiles 的软链接机制
工具装好只是第一步,真正的环境一致性靠的是配置文件同步。t3code 里的 dotfiles 采用软链接方式关联到仓库:
link_dotfiles() { local repo_dir="$HOME/.t3code/dotfiles" local targets=( ".gitconfig" ".tmux.conf" ".vimrc" ) for target in "${targets[@]}"; do local src="$repo_dir/$target" local dst="$HOME/$target" # 幂等处理:如果目标已存在且是软链接,先删掉再重建 if [ -L "$dst" ]; then echo "移除已有软链接: $dst" rm "$dst" fi # 如果目标是普通文件,备份后跳过 if [ -f "$dst" ] && [ ! -L "$dst" ]; then echo "检测到已有配置文件,备份为: $dst.bak" mv "$dst" "$dst.bak" fi ln -s "$src" "$dst" echo "已链接: $dst -> $src" done }这段代码里的幂等处理是我早期踩过坑之后专门加上的。一开始的做法是弱检查,只判断文件存不存在,存在就直接跳过。结果就是第一次运行没问题,第二次运行发现配置没更新,因为旧的软链接一直停留在一个旧版本上。后来改成“先删旧链再建新链”,这个脚本就可以安全地重复执行了。
还有一个细节:如果是普通文件(不是软链接),我不会直接覆盖,而是把它备份成 .bak 文件。这算是一个安全兜底,万一用户原本有自己的一套配置,误跑我的脚本后还能恢复到原来的状态。我之前就遇到过把同事的 .vimrc 直接覆盖掉的情况,虽然能解释清楚,但那个尴尬场面到现在都记得。
4.3 常用工具的智能安装顺序
工具之间是有依赖关系的。比如装了 neovim 才能运行后续的插件安装命令,装了 python3-pip 才能继续装 python 包。所以 install.sh 里每一步的顺序都不是随意排的,基本原则是:底层工具先装,应用层工具后装,需要交互验证的代码最后执行。
以 Ubuntu 为例,我的 modules/apt.sh 内部按这样的顺序组织函数:
| 阶段 | 包含内容 | 说明 |
|---|---|---|
| 阶段一 | apt 基础更新、系统依赖 | 确保后续安装的前提条件 |
| 阶段二 | 核心开发工具(git、build-essential、curl) | 编译和代码管理的基础 |
| 阶段三 | 编辑器与终端工具(neovim、tmux、ripgrep) | 日常产出工具 |
| 阶段四 | 语言运行时(nodejs、python3-pip) | 根据项目需要配置 |
| 阶段五 | 预编译二进制替换 | 覆盖旧版本包 |
这个顺序的意义在于:如果某一阶段失败,前面的阶段已经完成,那么环境仍然可用,只是少了部分工具。但如果反着来,先装一堆插件再去装语言运行时,插件安装大概率会失败,一团乱麻。
4.4 环境验证脚本:装完不等于装好
很多人的初始化脚本装完工具就结束了。t3code 里专门加了一个验证模块,它的作用是输出一份“体检报告”,确认哪些命令可以正常执行,哪些还欠火候:
verify_tools() { local commands=( "git" "nvim" "tmux" "rg" "python3" "node" ) local results=() for cmd in "${commands[@]}"; do if command -v "$cmd" >/dev/null 2>&1; then results+=("✓ $cmd : $(command -v $cmd)") else results+=("✗ $cmd : 未找到") fi done printf '%s\n' "${results[@]}" }这个函数的输出很直观,一眼能看到哪些工具成功安装,哪些有问题。这里用command -v而不是which,是有讲究的。which在某些发行版里会用别名或者独立程序代替,行为不太标准;而command -v是 POSIX 标准下的内置命令,在 bash、zsh、sh 下行为一致,不管脚本切换解释器都不会出错。
运行 t3code 里的bin/t3 --verify就能看到整个报告。有一次我在一台 Ubuntu 服务器上跑,发现一切正常但 nvim 显示未找到。排查了一下,原来是 HOME 下的 .local/bin 没有加到 PATH 里。这类问题如果不在验证阶段暴露出来,后面往往会在莫名其妙的地方爆发。
5. 实操中的高频问题与排查实录
5.1 软链接冲突
症状:运行 install.sh 第二次时提示 “ln: failed to create symbolic link: File exists”。
原因:之前的软链接已经存在,ln 默认不会覆盖。这个我在设计之初就预料到,但在实际给朋友演示的时候还是翻了一次车——因为那个环境里 .gitconfig 是个普通文件而不是软链接,我的备份逻辑执行了,但 .tmux.conf 是软链接,被清理后重建,中间还有一个字符编码引发的小插曲。
排查方法:先看目标位置是什么类型:
ls -la ~/.gitconfig如果是软链接,直接删掉重链。如果 t3code 的 link_dotfiles 已经包含了幂等逻辑,理论上不该出现这个问题。所以第一建议是先更新本地的 t3code 仓库,再执行一次。大概率是仓库版本太旧,还没包含幂等处理。
如果确实因为某些原因没法更新仓库,手动处理也非常简单:
rm ~/.gitconfig ln -s ~/.t3code/dotfiles/.gitconfig ~/.gitconfig5.2 PATH 不生效,command not found
症状:装完所有工具以后,在终端敲 nvim 报 command not found。但在脚本里执行command -v nvim又能找到路径。
原因:新装的工具目录没有导出到 PATH,或者 .bashrc / .zshrc 里的路径导出语句在脚本执行之后才加载。这是 macOS 和 Linux 开发者都会遇到的经典问题。
排查方法:检查当前 PATH:
echo $PATH看输出里是否包含~/.local/bin或者~/.bin。如果没有,在 .bashrc 里加一行:
export PATH="$HOME/.local/bin:$PATH"t3code 的 common.sh 里专门有一个函数处理这个,它会检查 .bashrc 尾部是否已经有这段导出语句,没有就自动追加。但如果你用了 zsh,还需要在 .zshrc 里做同样的检查。这里有个我之前忽略的坑:不同 shell 的配置文件差异,bash 读 .bashrc,zsh 读 .zshrc,脚本里如果只维护一份,换 shell 之后配置就丢了。
5.3 Homebrew 安装慢或中断
症状:macOS 上执行 brew.sh,安装过程非常慢,或者网络中断导致包装不完整。
排查思路:Homebrew 的安装速度依赖网络,尤其是首次安装时会从 GitHub 下载大量元数据。一个比较有效的做法是配置镜像源。以中科大镜像源为例:
# 替换 Homebrew 默认源 git -C "$(brew --repo)" remote set-url origin https://mirrors.ustc.edu.cn/brew.git但这属于环境相关配置,我一般不会把它写死在 t3code 主脚本里,而是拆成单独的配置说明放在 README 中。因为不同网络环境下,最佳镜像源不一样,写死了反而带来不必要的麻烦。这是一个很典型的“个人项目设计取舍”——越通用,越要留配置的余地;越个性化,越要方便开关。
5.4 WSL 环境下的 Windows 互操作问题
WSL 里跑 t3code 的 apt.sh 基本没大问题,但有个特殊情况:某些工具装好以后在 WSL 里启动不了,会报/usr/bin/env: 'node': No such file or directory。这种情况多数是因为 PATH 里混入了 Windows 路径,比如/mnt/c/Program Files/nodejs/,而 WSL 的 bash 又恰好不兼容 Windows 执行文件格式。
解决办法是在 wsl.sh 模块里加一个清理 PATH 的逻辑,把 /mnt/c 前缀的路径从 PATH 里剥掉:
sanitize_path() { export PATH=$(echo "$PATH" | tr ':' '\n' | grep -v '^/mnt/' | paste -sd:) }这个函数放在 wsl.sh 里,只在 WSL 平台上执行,不影响其他系统。这类环境特有的小问题,如果不专门用一个模块去管理,就会让主逻辑变得越来越复杂,越来越难维护。
6. 不同平台的差异化处理细节
6.1 macOS 与 Linux 的包管理器差异之外,还有路径差异
macOS 下 Homebrew 的默认安装路径在 Apple Silicon 上是/opt/homebrew,而在 Intel 上是/usr/local。这个差异影响到了所有 brew 安装的工具路径,比如 git 和 tmux 的实际可执行文件位置。t3code 在处理时用了动态检测:
detect_brew_prefix() { if [ -d "/opt/homebrew" ]; then echo "/opt/homebrew" else echo "/usr/local" fi }检测完以后,把对应的 bin 目录加入 PATH。如果不做这一步,Apple Silicon 上 brew 装好的工具全都无法直接执行,t3code 的验证模块就会报一堆“未找到”。
Linux 上则需要注意 x86_64 和 aarch64 架构差异。tar 包下载链接里通常要区分这两个架构,我在 apt.sh 里用 uname -m 做个简单判断:
local arch arch=$(uname -m) case "$arch" in x86_64) url="https://github.com/neovim/neovim/releases/download/${version}/nvim-linux-x86_64.tar.gz" ;; aarch64) url="https://github.com/neovim/neovim/releases/download/${version}/nvim-linux-aarch64.tar.gz" ;; *) echo "不支持的架构" >&2; exit 1 ;; esac这些细节写不写,直接决定脚本能不能在新机器上一次跑通。很多 dotfiles 仓库只考虑了自己的机器,所以我见过不少人换了一台 ARM 设备之后发现整个脚本崩了。
6.2 Git 配置里的用户信息管理
.gitconfig 是 dotfiles 里比较敏感的一个文件,因为它包含用户姓名和邮箱。t3code 的做法是:把 .gitconfig 拆成公共部分和工作区部分。
公共部分直接放在仓库里:
[init] defaultBranch = main [alias] st = status co = checkout br = branch lg = log --oneline --graph --all --decorate [core] editor = nvim autocrlf = input用户信息则不放到公共配置里,而是在安装的时候提示用户输入:
setup_git_user() { if ! git config --global user.name >/dev/null 2>&1; then read -p "输入 Git 用户名: " git_name git config --global user.name "$git_name" fi if ! git config --global user.email >/dev/null 2>&1; then read -p "输入 Git 邮箱: " git_email git config --global user.email "$git_email" fi }这样做的原因很简单:仓库文件会被推到远端,个人邮箱暴露在一个公开仓库里不是一个好习惯。即便仓库是私有的,团队协作时共享一个 dotfiles 模板也不应该绑定个人身份信息。安装时交互输入虽然多了一步,但避免了后续的隐私问题。
6.3 Shell 主题与交互体验
作为一个写代码的人,我对终端里面的主题和提示符还是有要求的。t3code 里对 Shell 环境的处理,采用的是“可关闭”的策略。默认配置里只做几件事:
- 设置 TERM 为 xterm-256color(macOS 上尤其需要)
- 启用 vim 模式的命令行编辑
- 如果安装了 starship,才启用 starship 的主题配置
这些都以条件判断执行。starship 没有安装就不去碰它,装了就自动启用。这样脚本既能适配我自己的审美,又不会在别人机器上强加太多个人偏好。
starship 的配置也是一个 toml 文件放在 dotfiles 里,通过软链接方式关联到 ~/.config/starship.toml。我试过几套现成的 theme,最终自己改了一版,只显示目录、分支和运行时长,不搞花哨的图案,信息密度适中。
7. 把 t3code 扩展到团队协作场景
个人用了一段时间之后,我觉得这套东西其实可以推广到小团队。团队新成员入职的时候,最痛苦的就是搭建环境。文档写得再详细,总有遗漏,而且不同成员的系统版本不一样,文档没法穷举所有情况。t3code 的模块化结构恰好可以按团队需求做二次开发。
团队化使用时有几点需要注意。
权限控制。仓库如果是私有的,新成员需要先被加入 GitHub 组织或团队成员列表,才能克隆。如果团队规模不大,直接用 GitHub 的 Private 仓库就行,也不需要额外搭 Git 服务。
代码审查。既然是共享配置,脚本改动就不能像个人项目那样随性。至少要在合并前过一遍 code review,确认安装脚本没有破坏性操作。我在个人使用时不太在意这个,但团队环境里一个不小心把所有人的 .bashrc 覆盖了,那就是事故。
环境分化。每个项目可能需要不同的语言运行时版本。t3code 作为基础环境安装工具,不会去解决项目级依赖。团队可以约定 t3code 只负责“通用层”——git、编辑器、终端、系统工具;项目层的 nodejs 版本、python 虚拟环境、依赖安装,由项目内的 dockerfile 或 mise 之类的工具负责。这样分层清晰,不容易乱。
8. 常见问题速查表
整理了一份我在使用 t3code 过程中遇到的典型问题和解决方案,方便直接对照排查:
| 问题 | 可能原因 | 快速解决 |
|---|---|---|
| 运行 install.sh 时提示权限不足 | 脚本需要 sudo 执行 apt 安装 | 先执行sudo apt-get update,再运行 install.sh;或者确保当前用户有 sudo 权限 |
| dotfiles 软链接建立失败 | 目标位置已经有文件/文件夹 | 手动备份后删除,重新运行 link_dotfiles |
| 安装后 nodenv/nvm 不可用 | shell 配置未重新加载 | 执行source ~/.bashrc或重新打开终端 |
| nvim 插件无法加载 | neovim 版本过低,不满足插件要求 | 通过预编译二进制升级 nvim 到稳定版 |
| brew.sh 执行极慢 | Homebrew 元数据下载受网络影响 | 替换镜像源,或在网络好的时段执行 |
| WSL 中工具无法启动 | PATH 混入 /mnt/c Windows 路径 | 执行 wsl.sh 中的 sanitize_path,或手动清理 |
| git 提交时提示身份未知 | .gitconfig 没有 user.name 和 user.email | 重新执行 setup_git_user 函数完成设置 |
| fzf 按键绑定不生效 | 缺少 fzf 的 shell 集成段 | 在 .bashrc 中追加eval "$(fzf --bash)",或手动 source |
| tmux 复制模式兼容性差 | macOS 自带终端可能与 tmux 行为不一致 | 安装并使用 iTerm2,或在 .tmux.conf 里调整复制相关绑定 |
| 脚本执行到一半中断,环境处于中间状态 | 网络抖动或手动 Ctrl-C | 重新执行 install.sh,幂等逻辑会跳过已完成部分 |
这张表给出的不只是操作命令,每一条背后都对应着一次真实翻车。特别是团队新成员使用的时候,最常卡在“Git 身份未知”这一步,因为在公司环境里全局 git config 往往已经有设置,但换到个人机器上就会触发这个坑。setup_git_user 函数的交互式输入正是针对这一点设计的。
9. 常见问题排查思路详解
9.1 错误输出定位
排查脚本问题时,我的第一个动作永远是开启调试模式重新执行脚本。具体操作很简单,在脚本开头已经加好了set -euo pipefail,但我还会在排查时手动追加set -x或者直接执行:
bash -x install.sh这样每一步命令都会打印出来,错误就出现在最后一条输出附近。这个方法说起来大家都知道,但我在实际帮朋友调脚本时发现,大多数人第一反应是盯着“Error”关键字找,而不是看完整的命令流。在 bash 脚本里,真正的错误往往藏在输出流的倒数几行之外,只看报错信息容易误导排查方向。
9.2 日志与中间产物
t3code 里我给 install.sh 加了一个--debug参数,开启后会把执行过程记录到/tmp/t3code_install.log。这个日志文件在后续排查时价值很大,尤其是在脚本输出被终端滚动丢失的情况下。
设计时我用了tee来同时输出到终端和文件:
exec > >(tee -a "$LOG_FILE") 2>&1注意这行必须放在脚本已经创建 LOG_FILE 之后,而且只适合交互式执行。加这个功能的时候我没有放进默认路径,而是通过参数控制,避免每台机器都偷偷写日志造成混淆。
9.3 脚本维护者的自查清单
如果你也准备维护一套自己的 t3code 类项目,有几个自查点值得写进 README:
- 是否支持重复执行?幂等性处理是否完善?
- 依赖命令是否都有安装逻辑兜底?
- 是否有验证模块,可以快速确认安装结果?
- 平台判断是否覆盖了 macOS、Linux、WSL?
- 是否备份了已存在的配置文件,而不是直接覆盖?
- 敏感信息(邮箱、密钥)是否都被隔离在仓库之外?
这些自查点看起来简单,但每个都对应着一个真实的踩坑场景。把它们写成检查清单放进 README,团队协作时可以大幅减少低级问题。
10. 从 t3code 沉淀下来的开发环境管理经验
t3code 这个项目本身不大,但它带来的收益远超预期。最初我只是想解决“换机器太痛苦”这个痛点,后来发现它改变了我的整个开发机器管理模式。
大概经验可以落在三点上。
配置和工具分离。早期我把“要装哪些工具”和“工具装好后怎么配置”混在一起,导致想换一个编辑器都要翻大段脚本。拆开之后,工具清单是数据,安装逻辑是执行,配置是另一层。三者独立变化,互不干扰。
一切皆可重装。有了 t3code 的脚本和 dotfiles,我敢在自己的主力机上随便折腾。系统弄坏了、配置改乱了,克隆仓库跑一遍就回来。这种安全感对想尝试新工具的人来说特别重要,不再怕把环境搞坏。
文档即代码。写 README 时,我把每条命令的用途都写清楚,把每个设计决策的原因也写了。一开始只是应付自己健忘,后来发现新成员居然能看着 README 自己走通整个流程。这说明把“为什么”写下来比单纯的命令清单有用得多。
最后再分享一个实际操作中的体会:t3code 这类脚本不需要一次写完,它是随着你每次遇到问题、每次换新机器而逐渐生长的。第一次写可能只要半天,照着自己的需求做一版能跑的版本就行。后面每遇到一个新的“环境坑”,顺手补一个函数进去。用不了几次,它就会从一份简单脚本长成一套真正属于你的开发环境管理系统。