
1. t3code 不是又一个笔记软件我到底想用它解决什么t3code 是我用 Node.js 写的一个命令行代码片段管理工具名字是自己拼的三个 T 分别代表 Terminal、Tag、Template。说白了我写它只是因为烦透了在 VS Code 的 User Snippets、Notion 页面、项目的.code-snippets文件和一堆聊天记录里反复翻同一段代码的日子。如果你也有类似经历应该能马上 get 到痛点某段认证逻辑你三个月前写过一次现在要用第一反应是去旧项目里grep某个 Docker Compose 编排你说“先存到笔记里”结果存进去之后再也没打开过团队群里出现过一次很好用的 Git 钩子但因为没人把它整理成正式资产后来每个新人都要重写一遍。t3code 就是把我这些“散落的可执行知识”统一收进一个本地目录用命令行随时检索、复制、插入并且通过 Git 做版本管理和多设备同步。名字里的三个 T 实际上也是这个工具的三个核心设计维度Tag 负责给片段做结构化标签Template 负责在插入时自动替换变量Trace 负责记录片段的使用情况。它不是一个知识管理软件也不是 IDE 插件它更像是“代码片段层面的本地资产管理系统”。适合的人群很明确经常在多个项目之间切换、依赖终端工作、需要把个人代码片段变成可复用资产的前端、后端或者 DevOps 工程师。1.1 我的片段散落在四个地方最后谁也找不着在写 t3code 之前我的可复用代码基本分布在四类地方编辑器自带的 snippet 配置、公司的 Wiki / 个人笔记、GitHub Gist、旧项目本身。这四类地方各有各的毛病。编辑器自带 snippet 的问题在于它和编辑器强绑定而且作用域通常很有限。同一个片段在 VS Code 里能感知到当前文件的语言但如果我在终端里想复制一段fetch封装给同事得先把配置文件路径翻出来。项目里的旧代码看起来最可靠但为了找一段工具函数要打开整个项目通常还要处理依赖关系只是复制一小段的话成本太高。笔记软件又有另一个问题内容塞进去容易检索出来难。你记得自己写过“分页组件”但想不起来当时放在了哪一页更别说 HTML 里那些代码块复制出来还带着样式。Gist 虽然能存公开片段但默认的搜索体验很原始也没有标签和分类的概念。t3code 的核心思路其实特别朴素每个片段就是一个带 YAML Front Matter 的 Markdown 文件文件名是稳定 ID正文是代码本身元数据全部写在开头的---块里。这样我可以用任何文本工具打开、编辑、浏览也可以直接从一个地方全部同步走。1.2 三个 TTag、Template、Trace 分别承担什么Tag 是检索的基础。每个片段除了标题之外必须有一组标签和一个或多个别名。比如我经常用的 axios 请求封装标签是http、axios、typescript别名是req、request、http。这样搜索的时候我不但可以按完整标题搜还能用缩略词快速命中。别小看这个设计它解决的是“我记得大概是什么但记不住准确名字”的典型场景。Template 是插入时的变量替换层。很多片段不是纯静态代码比如 React 函数组件、定时任务脚本、数据库连接配置里面总有几个会因为项目不同而变化的地方组件名、超时时间、API 地址、用户名。t3code 用{{变量名}}这种占位符标记动态部分插入时自动弹交互式提示把变量问你一遍然后生成完整代码。这一步直接省掉了“粘贴之后逐行改名字”的无聊劳动。Trace 是我后来加进去的。以前我总觉得自己有些片段“看起来很厉害”但只有真正统计使用次数才知道哪些是高价值资产。t3code 会在每次insert或copy时更新本地统计文件记录使用次数和最后使用时间。配合 Git 历史还能看到这个片段什么时候创建、什么时候改过、改了几次。它不会把任何数据上传到远端默认所有统计都留在自己的机器上。1.3 t3code 的定位给“个人知识库里的可执行部分”一个家如果你搜索 t3code 这个名字可能首先会看到 T3 Stack 相关的项目那个是 Next.js、tRPC、Tailwind、TypeScript 的组合和我说的工具不是一回事。我这里的 t3code 只是一个很轻的本地 CLI没有服务端没有数据库也没有复杂的插件体系。但它解决了一个真实问题个人知识库里最值钱的部分往往不是网盘里那些资料而是你反复写过的、已经验证过能跑的代码。这些代码值得拥有比“旧项目里的某一个文件”更稳定的存放位置。t3code 做的就是这件事让代码片段成为一种可以被搜索、被版本控制、被团队共享的普通文件资产。2. 存储、检索、插入t3code 的三个底层设计决策写工具最怕一上来就堆功能。我给自己定的原则是能用纯文本解决就不上数据库能用成熟外部工具解决就不自己实现能少暴露配置就少暴露配置。所以 t3code 的架构非常朴素但每一层都经过了比较实际的取舍。2.1 为什么每个片段就是一个 Markdown 文件而不是 SQLite有人可能会问片段管理系统难道不应该用 SQLite 或者 JSON 文件存索引吗我在最开始确实试过 SQLite但很快就放弃了。最大的原因是数据库文件不方便人工查看和合并也不方便用git diff看变更记录。对于一个以“片段”为单位的工具文件系统本身就是足够好的索引。每个片段保存成~/.t3code/snippets/id.md格式大概是这样--- id: axios-request-wrapper title: axios 请求封装超时 拦截器 tags: [http, axios, typescript, 请求] alias: [req, request] lang: typescript created: 2024-03-12T10:20:00Z updated: 2024-11-03T09:15:00Z --- import axios from axios const http axios.create({ baseURL: {{BASE_URL}}, timeout: {{TIMEOUT}}, }) http.interceptors.request.use((config) { const token localStorage.getItem(token) if (token) { config.headers.Authorization Bearer ${token} } return config }) export default http选择 Markdown 文件的原因有三个第一可 grep任何时候我都能直接grep -rn interceptors ~/.t3code/snippets完全不依赖 t3code 本身的搜索逻辑第二可 diff修改一个片段之后Git 里能看到精确到行级的变更而不是一个整块的二进制差异第三可迁移未来就算 t3code 不维护了这些文件仍然是普通的文本文件没有绑定任何私有格式。这套设计也有代价如果你有几千个片段文件数量会比较多但现代操作系统处理几万个文件根本不是问题。对我来说片段是“少而精”的资产数量到几百已经很可观了。2.2 为什么不自己写搜索而是把选择权交给 fzf搜索模块我一开始准备自己实现模糊匹配写了几天之后意识到这是在重复造轮子。t3code 的本地搜索能力无论如何都不可能超过 fzf所以我干脆做了一个决定CLI 里直接调用 fzf如果不希望依赖外部工具就退回到简单的关键词过滤模式。实际使用时的体验大概是这样的t3 search --fzft3 search会先读取所有片段文件把id、title、tags、alias、lang拼成几列文本然后喂给 fzf 做模糊搜索。fzf 本身就是为终端里的交互式选择而生的支持键盘上下选择、多列预览、颜色高亮我只需要把结果解析回来就行。t3 list | fzf --preview bat --coloralways -l {}这样做的好处是我不需要维护一套复杂的检索算法也不需要担心中文分词、拼音首字母这些细节。用户如果不想用 fzf可以直接t3 search req命令行参数里带关键词也能完成搜索。外部工具的边界拿捏得很清楚没有 fzf 的时候功能不瘫痪有 fzf 的时候体验直接上一个档次。2.3 模板变量和剪贴板插入这件事的完整链路如果你只是把代码片段搜出来复制到剪贴板那很多工具都能做到。t3code 真正让我觉得好用的是模板变量和剪贴板的无缝衔接。插入一个动态片段的流程是这样的t3 insert reqt3code 会先根据别名req找到对应片段文件然后扫描正文里的{{BASE_URL}}、{{TIMEOUT}}这类变量再逐个询问? 请输入 BASE_URL: https://api.example.com ? 请输入 TIMEOUT: 8000 ✔ 生成结果已复制到剪贴板生成结果之后它会调用当前系统的剪贴板命令。macOS 上是pbcopyLinux 上有xsel或wl-copyWindows 上是clip。安装时 t3code 会探测一次系统类型把对应的命令缓存到配置里。如果探测不到也不会直接报错而是把最终结果打印到终端让你手动复制。这一步看似简单但对工作流的影响很大。以前用 VS Code snippet 的时候虽然编辑器能自动展开变量但只能在编辑器内部用。t3code 把能力扩展到了整个终端我可以从终端里复制一段 curl、一段 nginx 配置、一段 SQL往任何地方粘贴。2.4 配置文件的默认路径与跨平台处理t3code 的配置文件放在~/.config/t3code/config.yml内容很克制snippet_dir: ~/.t3code/snippets editor: nvim clipboard: auto sync: enable: true remote: gitgithub.com:yourname/t3code-snippets.git branch: mainsnippet_dir是片段仓库的位置默认在用户目录下。editor用来指定执行t3 edit时打开哪个编辑器。clipboard可以设成auto也可以手动指定具体命令。sync这部分主要是针对走 Git 同步的场景。跨平台处理里最麻烦的其实是路径分隔符和剪贴板命令。我一开始只考虑了自己的 macOS 环境后来同事在 Windows 上装了之后发现路径拼接有问题才加了一个统一的路径抽象层。现在不管是~/.t3code/snippets还是C:\Users\xxx\.t3code\snippets内部统一用path.join处理不再手写斜杠字符串拼接。3. 从安装到日常使用一套可以直接抄的工作流工具只有真正进入日常开发流程才有价值。下面这套工作流是我自己用了半年之后沉淀下来的从初始化到日常新增、检索、同步每一步都能直接照做。3.1 安装和初始化t3code 目前以源码方式分发没有发布到 npm 的正式包名。安装步骤很简单git clone gitgithub.com:yourname/t3code.git cd t3code npm install npm run build npm link t3 --versionNode.js 版本建议 18 以上因为代码里用了比较新的原生 API。装完之后第一步是初始化t3 init这个命令会在~/.t3code下创建snippets目录、一份README.md、一套默认.gitignore以及上面的config.yml。如果~/.t3code还不是一个 Git 仓库它会自动帮你执行git init然后生成最初的 commit。3.2 录入第一个片段交互式 t3 add添加片段我用的是交互式表单刻意避免让你一行命令写太多参数。运行t3 add之后它会问你几个问题? 片段标题: axios 请求封装 ? 标签逗号分隔: http, axios, typescript ? 别名逗号分隔: req, request ? 语言: typescript ? 输入片段内容以 line 包含 #END 结束:它会根据alias的第一个值生成文件名比如req.md。如果没填别名就从英文标题生成 kebab-case 文件名如果是纯中文标题又没给别名那就要你补一个英文别名避免文件名变成一串 URL 编码。这个设计是在实际踩坑之后加进去的后面专门讲。保存好之后可以马上试一下搜索t3 search req提示t3 add只是一个交互式外壳你可以直接用文本编辑器往snippets/目录里加.md文件效果完全一样。这个习惯对团队协作很重要因为片段本质上就是普通文本文件。3.3 检索和插入我推荐的两条高频路径日常使用我基本只需要两条路径。第一条是“只复制不改变量”用t3 copy例如t3 copy req它会把片段正文里的变量替换成默认值如果没设默认值就原样保留然后复制到剪贴板。适合拷贝纯静态代码。第二条是“需要填变量”用t3 insert就是前面提到的交互式变量替换流程。适合拷贝组件模板、配置样板、带有项目相关参数的脚本。如果你不习惯记命令也可以只记一个t3 s reqs是search的别名输出会包含片段 ID、标题、标签和语言。配合 fzf 使用的时候按回车之后还可以选择把结果直接复制还是用编辑器打开一步到位。3.4 团队共享为什么 Git 同步比云同步靠谱我见过很多团队用在线文档的“代码块”维护共享代码片段结果代码一多文档就乱成一锅粥。t3code 的选择是直接拥抱 Git因为团队本来就在用 Git 管代码为什么破例用另一个系统去管代码片段在团队内共享的时候你只需要把~/.t3code里的snippets目录提交到一个单独的 Git 仓库然后让其他成员把仓库地址写到各自的config.yml里。t3code 的t3 sync命令本质上就是对 Git 的封装t3 sync --pull t3 sync --push使用 Git 有三个额外的好处第一天然有审计记录谁在什么时候加了什么、改了什么都清清楚楚第二可以走代码评审流程PR 和 MR 的老规矩照样用第三可以 fork别人在你片段的基础上做修改形成自己的分支不会污染主仓库。这一点是任何在线文档平台都很难做到的。3.5 常用命令速查表命令作用t3 init初始化本地片段仓库和配置t3 add交互式新增片段t3 list列出所有片段t3 search query按标题、标签、别名搜索t3 search --fzf用 fzf 做交互式模糊搜索t3 copy pattern找到片段并复制到剪贴板t3 insert pattern找到片段填变量然后复制t3 edit pattern用配置指定的编辑器打开片段t3 stats查看片段使用统计t3 sync --push/--pull同步远程 Git 仓库这套命令表基本覆盖了我所有关于“片段”的操作。不需要一个常驻的后台进程也不需要打开某个 GUI 窗口所有事情都在终端里完成。4. 用了半年以后真正踩到的坑任何工具光看设计都觉得挺好真正用起来才会暴露问题。t3code 也是下面这几个坑我基本都真实踩过写出来帮你避开。4.1 中文文件名的坑最早我允许直接用中文标题作为文件名比如axios请求封装.md。在 macOS 上看起来没问题但放到 Linux 服务器或者 Windows 上编码和文件名长度的问题就开始冒头。更麻烦的是如果同一个片段在多台设备之间合并中文文件名在某些旧系统的 Git 配置里会显示成转义序列看得人一头雾水。后来我改成文件名只允许英文小写、数字、连字符优先取第一个alias如果别名没填就取英文标题的 kebab-case如果都没有会生成一个短随机 ID。中文信息全部留在 Front Matter 的title字段里。这个改动之后多设备同步和跨平台使用都没再出过文件系统层面的问题。4.2 模板语法和代码本身撞车的处理模板变量的设计早期有个大坑我用的是{{变量名}}但很多前端模板本身也用这个语法。比如 Vue 文件里到处都是{{ message }}如果我把这样的代码存成片段t3 insert就会误把它当成变量弹出提示问我message是什么直接乱套。解决方案是在片段文件里用\{{表示字面量。比如 Vue 模板里的插值需要写成这样div\{{ message }}/divt3code 在解析变量之前会先扫描转义占位符把它们替换成特殊标记等所有真实变量都替换完之后再把标记还原成{{ message }}。第一次意识到这个问题的场景我记得特别清楚我把一个 Vue 组件的完整模板存进片段第二天用的时候t3code 一口气问了十几个变量我差点以为是程序坏了。这个问题解决之后模板语法的适用面就宽了很多不管是 Vue、Handlebars 还是 Go Template都能正常存档和插入。4.3 多设备冲突与 Git 操作的细节用 Git 同步片段最常见的坑是两台设备同时改了同一个片段。t3code 的sync命令默认会先git add -A git commit -m sync然后git pull --rebase最后git push。大部分情况下 rebase 能顺利解决但如果你在两台设备上分别添加了同一个alias的不同片段文件名相同就一定会产生冲突。我的处理经验是首先不要用编辑器去解决这种冲突直接在终端里看冲突标记确认哪一版是你想要的如果两个都想要就把其中一个改名为新的id和alias让它们变成两个独立片段。另外我把stats/usage.json放进了.gitignore因为使用次数统计是一种本地状态没必要在每台设备之间来回合并冲突只会添乱。4.4 一个我差点忽略的权限问题还有一次遇到的很隐蔽的问题是~/.t3code目录的权限设置得太开放导致别的用户或者某些自动化脚本也能读到片段内容。因为片段里偶尔会包含数据库连接串、内部 API 地址这类敏感信息即使仓库是私有 Git本机权限也应该收紧。所以我添加了安装时的一个检查项如果~/.t3code的目录权限不是700就给出警告提醒你执行chmod -R 700 ~/.t3code这个细节很容易被忽略但非常重要。代码片段管理工具的核心资产就是文本文件本身文件系统的权限策略某种程度上就相当于你的“数据安全防线”。5. 和常见工具对比之后我的推荐边界在哪里每次跟别人聊 t3code都会被问到它和 VS Code Snippets、massCode、AI 补全这些方案比有什么优势。坦白说它们不是完全替代关系但在某些维度上 t3code 确实更顺手。5.1 t3code vs VS Code 自带 SnippetsVS Code 的 User Snippets 很成熟但它的本质是编辑器配置文件而不是资产管理系统。它只活在编辑器内部不能在终端里复制也不能脱离当前工作区使用。t3code 的片段就是普通文件可以用任意编辑器打开可以在 shell 管道里被处理也可以在 CI 脚本里调用。不过如果你是纯 VS Code 用户并且大部分代码都在编辑器里完成那 VS Code Snippets 的体验依然很顺滑毕竟它原生、零依赖。我自己的用法是两者共存编辑器里高频的那几个片段还是会在 VS Code 里定义但是跨项目、跨终端、需要长期维护的代码资产一律放进 t3code。5.2 t3code vs 图形化片段库massCode、SnippetsLab 这类工具界面更好看预览更直观适合“看”代码。但它们的共同问题是数据格式封闭、命令行支持弱、自动化困难。我手动整理过几百个片段之后非常在意数据的可迁移性和可脚本化能力这一点纯文本 Git 的路径明显更稳。当然如果你想给片段添加截图、写详细的长文笔记、甚至做标签云可视化图形化工具体验更好。t3code 故意没有做这些因为它的定位就是“终端里的确定性工作流”不是“知识花园”。5.3 t3code vs AI 补全AI 补全对生成一次性代码很有用但它维护不了“确定性资产”。我今天想让团队所有人都使用同一版认证封装AI 每次生成的结果都可能不一样或者说会有“合理漂移”。t3code 里的片段是固定的经过 review、测试、实际项目验证过的版本。它不是帮你写代码而是帮你在写代码时快速取出已经写好的最优版本。所以我的建议是让 AI 做它擅长的方案探索和初稿生成用 t3code 沉淀那些你愿意反复使用的、已经验证过的代码。两者并不冲突甚至可以说 AI 让片段产生的速度更快了t3code 让这些片段真正留得下来。5.4 我不建议用 t3code 的几种情况也有一些人我明确不建议用 t3code。第一种是只做前端页面、所有代码都在编辑器和框架脚手架里完成很少跨项目复用代码那没必要多学一个 CLI。第二种是你需要的是“富文档 截图 可视化标签管理”的完整知识库t3code 给不了。第三种是对数据安全有严格合规要求、不允许在本地和远程仓库之间同步代码片段的团队那应该使用公司统一的内部代码片段服务。一句话总结我的推荐边界如果你经常在终端工作、对代码资产的版本管理和可迁移性有执念、并且愿意用文本文件来管理“可执行知识”t3code 会很合拍。6. 下一步我要把它从“我的玩具”变成“能分享的玩具”t3code 目前已经在我自己每天的工作里跑了大半年稳定性和易用性基本达到我自己的标准。但作为个人项目下一步我规划了两件很具体的事。第一件事是把模板变量升级成更正式的 schema。现在的{{变量名}}很轻但缺少默认值、枚举值、必填提示这些能力。我打算在 Front Matter 里增加一个params字段让一个片段可以声明变量的类型、默认值和说明。比如params: BASE_URL: type: string default: https://api.example.com required: true help: 接口服务地址 TIMEOUT: type: number default: 8000这样交互式提示就能更友好也可以支持从命令行直接传参比如t3 insert req --BASE_URLhttps://dev.api.local。第二件事是做一个只读的静态分享页。想法很简单t3 share pattern会把选中的片段渲染成一个独立的 HTML 文件带上语法高亮和说明信息方便发到团队文档或者内部 Wiki 里。它不会引入在线服务也不会把你的片段上传到任何服务器只是在本地生成一个文件。最后分享一个我一直在用的整理习惯每周五跑一次t3 stats看看哪些片段使用次数最高哪些从创建之后就再也没被碰过。连续三个月都是零次使用的片段我会考虑删除或者归档。这个习惯让 t3code 不只是“随手存代码”的地方而是真正会帮我审视自己技术资产价值的入口。工具永远会迭代但这种“定期清点”的习惯才是让代码片段仓库保持干净的核心。