<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Tmux on 飘逝的风</title><link>https://gameapp.club/tags/tmux/</link><description>Recent content in Tmux on 飘逝的风</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Thu, 14 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://gameapp.club/tags/tmux/index.xml" rel="self" type="application/rss+xml"/><item><title>逃离 IDE：我的纯终端 AI 编程工作流实践</title><link>https://gameapp.club/post/2026-05-14-terminal-centric-development/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://gameapp.club/post/2026-05-14-terminal-centric-development/</guid><description>&lt;img src="https://gameapp.club/" alt="Featured image of post 逃离 IDE：我的纯终端 AI 编程工作流实践" /&gt;
 &lt;blockquote&gt;
 &lt;p&gt;在 AI Coding 时代，我反而比以前更频繁地使用终端。这听起来有点反直觉——既然有 Cursor 这类把 AI 深度集成进 IDE 的工具，为什么还要&amp;quot;回到&amp;quot;终端？如果你以为我讲终端就是聊 Claude Code 等 CLI，其实并不是！我们开发者还有很多要解决的体验问题，本文尝试给一整套可照抄的纯终端开发解决方案，希望对你有启发。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="前言"&gt;前言
&lt;/h2&gt;&lt;p&gt;很多年前，我是个彻底的 Vimer，所有编辑都在终端里完成，随便精进着 Vim 的技巧，运指如飞，手不离键，并且很享受这种状态。我的博客陆续分享过多次相关经验，但随着 VSCode + Copilot、Cursor 这些 AI 加持的 IDE 出现，效率提升明显，我别无他法只能改换门庭 —— 投入了 VSCode / Cursor 的怀抱。直到最近一年，当我开始频繁使用 Codex、Claude Code、OpenCode 这类终端 Agent，我们甚至不再需要去手工编辑代码，程序员的工作模式发生了根本的变化，突然我发现，是时候”回家”了。&lt;/p&gt;
&lt;p&gt;回家不是因为恋旧，是因为当前模式有一些痛，比如我受不了每天要将 N 多个 Cursor（VSCode）的界面重连一遍，受不了在无数个窗口中来回寻找，受不了合上盖子它就停止工作。而这些痛点，其实都有解法。&lt;/p&gt;
&lt;p&gt;AI 如是说：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;终端不是退化，而是一个更稳定、可恢复、可长期运行的工作台。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;我说：“你说得对！”。&lt;/p&gt;
&lt;h2 id="我的终端开发工作流总览"&gt;我的终端开发工作流总览
&lt;/h2&gt;&lt;p&gt;我主要使用 macOS 系统，我的方案主要是基于 iTerm2 + tmux + Agent 开发定制功能实现的全流程开发工作流。&lt;/p&gt;
&lt;p&gt;简单示意大概是这样的：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;iTerm2 Profile（本地入口）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;SSH / 本地 Shell
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tmux session（每个 session 对应一个项目）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├── window: agent ← Codex / Claude Code 在跑
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├── window: test ← 跑测试 / 看输出
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├── window: logs ← tail -f 一类的常驻日志
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├── window: lazygit ← 提交前驾驶舱
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── popup: temp shell（临时命令，关掉即销毁）
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;效果图大概是这样的：
&lt;img alt="tmux纯终端开发效果" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://img.gameapp.club/images/2026/05/tmux-snapshot.png"&gt;&lt;/p&gt;
&lt;p&gt;几个关键组件的分工：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;iTerm2：它是我爱用的终端，当然你可以选择自己喜欢的。作为本地入口，我设定了 profile 区分不同机器、不同环境。&lt;/li&gt;
&lt;li&gt;tmux：提供了会话复用，我再基于它的理念设计了一套工作编排方式，并且在 tmux 上进行了比较丰富的设定与扩展，下文会详细道来。&lt;/li&gt;
&lt;li&gt;AI Agent（Codex / Claude Code）：选个你喜欢的 Agent cli 跑，它们总是跑在 tmux window 里，提供了任务的连续性。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="基于-iterm2-的多终端区分与管理"&gt;基于 iTerm2 的多终端区分与管理
&lt;/h2&gt;&lt;p&gt;iTerm2 我用得比较克制，比如我知道它有类似 Tmux 的分屏（pane）等功能，但是我不用，因为我们并不想被绑死在某一个终端软件上，不过我还是利用它的 &lt;strong&gt;Profile&lt;/strong&gt; 机制做&amp;quot;环境区分&amp;quot;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每个常用机器（家里设备、办公电脑、腾讯云 dev等）一个 profile；&lt;/li&gt;
&lt;li&gt;不同 profile 用不同的背景色——这是一个非常便宜但有效的&amp;quot;误操作防护&amp;quot;。比如生产机用偏红的背景，开发机用偏绿的背景，眼睛一扫就知道当前 shell 在哪。&lt;/li&gt;
&lt;li&gt;每个 profile 的 &amp;ldquo;Login Shell&amp;rdquo; 配置成 SSH 到目标机器后&lt;strong&gt;自动 attach 到一个固定名字的 tmux session&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最后一条很关键。比如我在 iTerm2 的 Profile 的 Command 部分像这样：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh -t dev &lt;span class="s1"&gt;&amp;#39;exec &amp;#34;${SHELL:-/bin/bash}&amp;#34; -lc &amp;#34;exec tmux new-session -A -s dev&amp;#34;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;我们确保一进入便是在 Tmux 管理之下，再也不怕会话丢失了。昨天那个打开的窗口在哪里的问题，或许一去不复返了。iTerm2 这边的配置就这么多，接下来才是真正精彩的部分。不过看这个之前，为了后续你更好的利用 Agent，我建议你不要忘了看我另一篇文章：&lt;a class="link" href="https://gameapp.club/post/2026-04-18-coding-with-image/" target="_blank" rel="noopener"
 &gt;Vibe Coding 远程开发时，如何优雅地贴图？&lt;/a&gt;，它会让后面你的开发更加原生和爽快一些。&lt;/p&gt;
&lt;h2 id="基于-tmux-的终端复用"&gt;基于 Tmux 的终端复用
&lt;/h2&gt;&lt;p&gt;Tmux 是这套工作流真正的”地基”，有人说：这么一款神器软件，它居然是完全免费可随意使用的，不用真的很亏。我觉得他说得很对。&lt;/p&gt;
&lt;p&gt;它的几个核心抽象——session、window、pane——刚好对应我们开发中的三个层次：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;session = 项目。每个项目一个 session，互不干扰；加上我们各种自主命名和可定制化的界面管理，让你”身轻如燕”般穿梭于各个项目。&lt;/li&gt;
&lt;li&gt;window = 这个项目下的一个工作任务：跑 Agent、跑测试、看日志、操作 git，对于这个项目的各种场景，随便开个跑；我的习惯专事专办，用完随便关掉。&lt;/li&gt;
&lt;li&gt;pane = 临时分屏：有时跑个测试、编译啥的要盯着可以。以前我爱用 pane，慢慢的其实分层清晰后，它用得更少了，真到要临时分屏时，我另有招数（下文会讲）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;关于 Tmux 有太多文章介绍，我觉得抄什么功能介绍是毫无价值的，但我要说的有点不一样，我们谈点真实感受和技巧。相关配置我已经放到 GitHub中 &lt;a class="link" href="https://github.com/kevin1sMe/dotfiles-example" target="_blank" rel="noopener"
 &gt;dotfiles-example&lt;/a&gt;，你可以随时取用。&lt;/p&gt;
&lt;h3 id="1-快捷键设置"&gt;1. 快捷键设置
&lt;/h3&gt;&lt;p&gt;我个人长期使用过另一个窗口管理软件，Ubuntu 上带的 byobu。它底层可基于 Tmux或 Screen等。它定义了不少快捷键其实挺好用的。不过用久了后有几个问题，太多键位其实你也用不上，多了反而容易误按以及和自建的冲突。为了追求极简我重新设定了一些规则。我挑几个重点说下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;tmux 默认 prefix 是 &lt;code&gt;C-b&lt;/code&gt;，按起来不顺。byobu 默认是 &lt;code&gt;C-a&lt;/code&gt; 或者是 &lt;code&gt;F12&lt;/code&gt;，这也不顺手，用 &lt;code&gt;C-a&lt;/code&gt; 对快捷键党更不友好（会冲突跳行首）。我建议换成 &lt;code&gt;C-s&lt;/code&gt;，反正你早就习惯 Ctrl + s 了：）&lt;/li&gt;
&lt;li&gt;byobu 风格的直接快捷键以 Fn 功能键居多，其实挺好用，我也继承和改良了一些，同时去掉我较少用的。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;F2&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;#{pane_current_path}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;F3&lt;/span&gt; &lt;span class="n"&gt;previous&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;F4&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;F6&lt;/span&gt; &lt;span class="n"&gt;detach&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;F7&lt;/span&gt; &lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;F8&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;(rename-window) &amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;rename-window &amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%%&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;F11&lt;/span&gt; &lt;span class="n"&gt;resize&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pane&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;F5&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;~/.&lt;/span&gt;&lt;span class="n"&gt;tmux&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt; \&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;tmux config reloaded&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;F2&lt;/code&gt; 新建 window 时一定要 &lt;code&gt;-c &amp;quot;#{pane_current_path}&amp;quot;&lt;/code&gt;，&lt;strong&gt;新 window 默认继承当前目录&lt;/strong&gt;——包括 tmux 默认新建 window 的行为，我也建议都改成进入当前 pane 所在目录，这会让你开心不少；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;F5&lt;/code&gt; reload 配置，byobu就是这么设定的，特别是咱们调整 tmux 配置的时候一键生效还是很便捷的。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;更多的设定看仓库中相关文档，有byobu风格的延续，也有 VIMER 喜欢的各种切换和跳转，不在这里赘述。&lt;/p&gt;
&lt;h3 id="2-关键且有用的几个配置项"&gt;2. 关键且有用的几个配置项
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 鼠标模式：可以点击切 pane、拖边框调大小、滚轮翻历史
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;set -g mouse on
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 自动命名 window，但禁止应用程序通过 OSC 改名
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;set -g automatic-rename on
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;set -g allow-rename off
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 滚屏历史尽量大
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;set -g history-limit 100000
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 跟系统剪贴板打通
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;set -g set-clipboard external
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;allow-rename off&lt;/code&gt; 这一条是被 Claude Code 教育出来的——某些 CLI 工具会通过 OSC 转义序列把版本号、临时状态写到 window 名里，眼花缭乱。关掉之后，window 名只受 tmux 和我自己控制，整洁多了。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;automatic-rename&lt;/code&gt; 的 format 我也做了一点定制：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;set -g automatic-rename-format &amp;#39;#{?#{==:#{pane_current_command},zsh},#{b:pane_current_path},#{?#{m/r:^(node|python3?)$,#{pane_current_command}},#(~/.config/tmux/bin/tmux-window-name #{pane_pid} #{pane_current_command}),#{pane_current_command}}}&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;逻辑很简单：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;zsh 空闲时显示当前目录名；&lt;/li&gt;
&lt;li&gt;node / python 解释器在跑脚本时，显示实际脚本名而不是干巴巴的 &lt;code&gt;node&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;其他进程直接显示进程名。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这样状态栏一眼就能看出每个 window 在干嘛。&lt;/p&gt;
&lt;h3 id="3-复制粘贴tmux-yank--选区按键"&gt;3. 复制粘贴：tmux-yank + 选区按键
&lt;/h3&gt;&lt;p&gt;复制粘贴在 tmux 中我们可以借助 &lt;code&gt;tmux-yank&lt;/code&gt; 插件解决了&amp;quot;跨平台复制到系统剪贴板&amp;quot;的问题：macOS 上自动调用 &lt;code&gt;pbcopy&lt;/code&gt;，Linux 上自动选 &lt;code&gt;xclip / xsel / wl-clipboard&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;然后剩下的选区控制我用了 vim 风格：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bind-key -T copy-mode-vi v send-keys -X begin-selection
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bind-key -T copy-mode-vi V send-keys -X select-line
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bind-key -T copy-mode-vi C-v send-keys -X rectangle-toggle
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;v / V / C-v&lt;/code&gt; 分别是字符选区、行选区、矩形选区——和 vim visual mode 一模一样。&lt;/p&gt;
&lt;p&gt;我觉得这还不够，想起来 Cursor 这类 IDE 有个把终端内容一键发送到 AI 聊天框的功能，我也想实现类似，怎么办？&lt;/p&gt;
&lt;p&gt;如下这样配置一键抓取 pane 最后 N 行写到 tmux 粘贴缓冲区，然后在另一个pane中 &lt;code&gt;prefix + ]&lt;/code&gt; 贴上去。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;shell&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;tmux capture-pane -pJ -S - | tail -n 10 | tmux load-buffer -&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;shell&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;tmux capture-pane -pJ -S - | tail -n 20 | tmux load-buffer -&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;shell&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;tmux capture-pane -pJ -S - | tail -n 50 | tmux load-buffer -&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;使用时，大概估摸个数，用 &lt;code&gt;prefix + 1/2/5&lt;/code&gt; 抓最近 X 行报错粘贴到比如你的 Agent window 里说：&amp;ldquo;看看这个错&amp;rdquo;，比手动选区快很多。&lt;/p&gt;
&lt;h3 id="4-弹出式终端临时命令的好去处"&gt;4. 弹出式终端：临时命令的好去处
&lt;/h3&gt;&lt;p&gt;我之前在用一套 Neovim 配置时，有个弹出式终端是我喜爱的功能，咱虽然不用再开 vim 了，但这个功能 tmux就可以提供：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bind-key t display-popup -E -w 90% -h 90% -d &amp;#34;#{pane_current_path}&amp;#34; &amp;#34;TMUX_POPUP=1 exec zsh -i&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;按下 &lt;code&gt;prefix + t&lt;/code&gt;，浮起一个铺满 90% 屏幕的临时 shell，关掉就销毁，完全不影响当前 window 的布局。我经常用它做临时查看或修改某个文件的内容等，这还是蛮舒适的。&lt;/p&gt;
&lt;p&gt;添加这个功能时，我注意到起初它弹出终端感觉有点延迟，于是配置里我塞了一个 &lt;code&gt;TMUX_POPUP=1&lt;/code&gt; 的环境变量。popup 里&lt;strong&gt;跳过 nvm、goenv 这类重型版本管理器初始化&lt;/strong&gt;，把弹窗打开速度从 1 秒降到 0.1 秒以内，秒开的感觉真爽。如果要用到完整的各种环境参数，则创建独立的 windows即可。速度优先，职责清晰。&lt;/p&gt;
&lt;h3 id="5-会话保存与恢复"&gt;5. 会话保存与恢复
&lt;/h3&gt;&lt;p&gt;其实我本来不喜欢用会话保存这种功能的，感觉能少就少，直到几次莫名其妙的会话丢失。这里我使用了 &lt;code&gt;tmux-resurrect&lt;/code&gt; + &lt;code&gt;tmux-continuum&lt;/code&gt; 是 tmux 老用户的两大神器。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;set -g @plugin &amp;#39;tmux-plugins/tmux-resurrect&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;set -g @plugin &amp;#39;tmux-plugins/tmux-continuum&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;set -g @continuum-interval &amp;#39;15&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;set -g @resurrect-save &amp;#39;S&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;set -g @resurrect-restore &amp;#39;R&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;continuum&lt;/code&gt; 每 15 分钟自动调用 &lt;code&gt;resurrect&lt;/code&gt; 保存当前 session 布局；&lt;/li&gt;
&lt;li&gt;想要恢复时，手动按 &lt;code&gt;prefix + R&lt;/code&gt;；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;或许除了异常丢失会话，重启机器时也能派上用场。这玩意会话快照也太省了，我还想着要不要定时清理，7 天可能都用不了几 MB，放心大胆的“瞎搞”吧。&lt;/p&gt;
&lt;h2 id="基于-lazygit-的审查"&gt;基于 Lazygit 的审查
&lt;/h2&gt;&lt;p&gt;现在不兴提 Vibe Coding 了是吗？你们写的代码会不会自己再审查下呢？反正多数时候我是需要的。有时候 Agent 改完一堆文件，我心里是没底的。当前多数的编码 Agent 在修改内容的呈现上都不太理想。特别是 cli 模式的，靠那”惊鸿一瞥”根本不足以判断它有没有夹带私货。所以我需要比较直接的呈现修改的 Diff，这点 Codex App 以及 Cursor Agent (cli) 表现稍好，它们给 Diff 设计了独立的展示 UI。&lt;/p&gt;
&lt;p&gt;而纯终端下，我们有 lazygit 不光比较好的呈现了修改面，而且把 Git 管理也集成了进来，所有操作收敛到一个 TUI 里，键盘党友好。&lt;/p&gt;
&lt;p&gt;我把 lazygit 集成进 tmux 的方式有两种：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 在当前目录打开 lazygit 浮窗
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bind-key g display-popup -E -w 90% -h 90% -d &amp;#34;#{pane_current_path}&amp;#34; &amp;#34;lazygit&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 在当前目录打开 lazygit 专用 window，退出后自动关闭
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bind-key G new-window -n lazygit -c &amp;#34;#{pane_current_path}&amp;#34; &amp;#34;lazygit&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;prefix + g&lt;/code&gt; 是&amp;quot;快进快出&amp;quot;的浮窗模式，适合扫一眼现状；&lt;code&gt;prefix + G&lt;/code&gt; 是开一个专用 window，请好好审查你的改动吧。
&lt;img alt="lazygit 默认 diff 风格" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://img.gameapp.club/images/2026/05/lazygit-diff-origin.png"&gt;&lt;/p&gt;
&lt;p&gt;这是lazygit的默认 Diff 方式，其实不太友好，我还是喜欢双栏对照着看，这也简单：&lt;/p&gt;
&lt;p&gt;diff 渲染接上 &lt;a class="link" href="https://github.com/dandavison/delta" target="_blank" rel="noopener"
 &gt;delta&lt;/a&gt; 作为 lazygit 的 pager：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;git&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pagers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;pager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;delta --paging=never&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;colorArg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;always&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;delta 的 diff 排版、语法高亮、行内差异显示都比原生 &lt;code&gt;git diff&lt;/code&gt; 强一个量级，配上 lazygit 之后，我基本不再为了看 diff 而专门打开 VSCode 跑 Code Agent 了。&lt;/p&gt;
&lt;p&gt;&lt;img alt="lazygit 接入 delta 后的 diff 风格" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://img.gameapp.club/images/2026/05/lazygit-diff-delta.png"&gt;&lt;/p&gt;
&lt;p&gt;我发现 lazygit 除了各种样式可定制外，还支持自定义 commands，这就有意思了。比如当我需要填写 commit message 时，我可以按 &lt;code&gt;C-a&lt;/code&gt;，让 AI 给我生成多个版本的 commit 文案，我还可以交互式的选择一个自己满意的：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;customCommands&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;lt;c-a&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;files&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Pick AI commit message&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;git commit -m {{ .Form.Msg | quote }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;loadingText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Generating AI commit messages...&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;prompts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;menuFromCommand&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;AI Commits&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Msg&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ai-commit-candidates&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;^(?P&amp;lt;msg&amp;gt;.+)$&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;valueFormat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{{ .msg }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;labelFormat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{{ .msg | green }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这也就是一个实验功能，其实多数时候我是开着 Agent的，让它帮我提交生成 commit message往往更符合规范。但你多个选择，随手改了几行功能等，也不失为一个偷懒的方法。&lt;/p&gt;
&lt;h2 id="10x-程序员agent-运行状态可视化"&gt;10x 程序员：Agent 运行状态可视化
&lt;/h2&gt;&lt;p&gt;作为一个熟练驱使各种 Agent 干活的人，他们在做事时你肯定也不想闲着，AI 已经被你“奴役“了，它们进度怎样是你关心的一个事情吧。所以良好的通知机制（状态感知）就至关重要。他们都在想抢你的关注，每一个输入窗口都“嗷嗷待哺“。&lt;/p&gt;
&lt;p&gt;一旦我们多任务并行处理，现在到底应该看哪个 window 便是一个问题：哪个正在干活，哪个已经来汇报工作，哪个正在等你指示。程序员最讨厌低效的轮询了，事件触发是必须的。于是，我们可以利用 Agent 本身的 hook 机制，让它主动通知 tmux 的 window，我选择以修改 window 名称（添加 emoji）来反映状态。&lt;/p&gt;
&lt;p&gt;很多 Agent都提供了hook机制，像如下的 Claude Code 配置，可以在 prompt 提交、运行结束、需要输入时分别触发脚本：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;hooks&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;UserPromptSubmit&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;hooks&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;~/.claude/hooks/notify-tmux.sh running&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;Stop&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;hooks&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;~/.claude/hooks/notify-tmux.sh done&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;Notification&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;matcher&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;permission_prompt&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;hooks&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;~/.claude/hooks/notify-tmux.sh input-required&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;对应的脚本只做一件事：根据当前状态在 window 名前面打一个 emoji 前缀，太简单的脚本都不值得展示。但效果就是tmux 状态栏上的 window 名会变成 &lt;code&gt;🔄 agent-foo&lt;/code&gt; / &lt;code&gt;✅ agent-foo&lt;/code&gt; / &lt;code&gt;❓ agent-foo&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;如前面所说，多个项目同时推进时，每个 session 内部的 Agent 状态就成了一个新问题。同样的思路——让状态在 session list 里直接呈现。这个细节你可能发现我第一张图就有这些信息啦～现在咱们可以安心喝茶、高效监工了：）&lt;/p&gt;
&lt;h2 id="后记"&gt;后记
&lt;/h2&gt;&lt;p&gt;用上这套系统后，解决了我原本的很多琐碎的小烦恼：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;下班前进行到一半的工作，第二天不知道窗口在哪了。而且我受够了不断确认VSCode的远程重连了，它还慢得要命，它还更新的频繁：（&lt;/li&gt;
&lt;li&gt;为了看代码不得不打开“内存杀手“ VSCode/Cursor之流，并且得接受被一些无用的 UI 占据了宝贵的窗口空间。我的 Macbook Pro也只有小小的面积。&lt;/li&gt;
&lt;li&gt;还有很多好处，看完全文的你或能有更多体会：）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;更要命的是，我的整洁的毛病，分门别类的感觉真好！当然，或许在某些需要浏览大量代码的时候，我还是会再次打开 VSCode 们，但显然它们已经失去我的心了。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;我是个爱折腾技术的工程师，也乐于分享。欢迎点赞、关注、分享，更欢迎一起探讨技术问题，共同学习，共同进步。为了获得更及时的文章推送，欢迎关注我的公众号：爱折腾的风&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;&lt;img alt="扫码关注公众号" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://img.gameapp.club/images/qrcode_weixin.jpg"&gt;&lt;/p&gt;</description></item></channel></rss>