这里记录我的一周分享,通常在周六或周日发布。
人生可能有的两次觉醒
第一次是弗洛伊德
你明白了,痛苦、自卑、讨好与不安,往往来自童年的匮乏与创伤。你从此不再责备自己。
第二次是阿德勒
你明白了,纵然过去塑造了现在的你,但真正决定自己将来的,是当下的选择。你不再抱怨命运与现实的不公,不再随波逐流,而开始有意识地审视自己的每一个决定。
爽朗君QvQ. 必须学会当面拒绝别人
iklein 你努力回避的,正是你需要面对和反思的。
…more
When you split a window into several panes — say a dev/planner/reviewer layout — it's easy to lose track of which directory each one is actually in. tmux exposes pane_current_path, so you can paint the cwd right onto the pane's top border:
set -g pane-border-status top
set -g pane-border-format " #{pane_index}: #{pane_title} [#{pane_current_path}] "
Full paths get long and crowd out the title. Two ways to trim. #{b:...} gives just the basename (last component):
set -g pane-border-format " #{pane_index}: #{pane_title} [#{b:pane_current_path}] "
Or abbreviate $HOME to ~ with tmux's s/search/replace/ modifier. The neat trick is that the replacement is itself a format, so you can nest #{HOME} inside it — no hardcoded username, so the same dotfile works on every machine:
set -g pane-border-format " #{pane_index}: #{pane_title} [#{s|^#{HOME}|~|:pane_current_path}] "
s takes any delimiter after it; using | keeps the slashes in the path readable, and ^ anchors the match to the start so a directory that merely contains your home path elsewhere isn't touched. A pane in /home/you/Projects/foo now shows [~/Projects/foo].
tmux doesn't watch the config file — after editing, reload the running server with tmux source-file ~/.tmux.conf (or prefix then :source-file ~/.tmux.conf). Without that, only a fresh server start picks up the change.
One caveat worth knowing: pane_current_path is the cwd of the pane's foreground process, and tmux only updates it on chdir(2). A shell reflects it faithfully. But a long-running process that was started in one directory and then operates on files by absolute path — without ever cd-ing — won't move the border, because its cwd never changed. So the border shows the shell's real cwd, which isn't always where a process is "logically" working.
A common pattern for "hop to another session before killing this one" looks like this:
bind Q run-shell 'next=$(tmux list-sessions -F "#{session_name}" 2>/dev/null \
| grep -v "^#{session_name}$" | head -1); \
if [ -n "$next" ]; then tmux switch-client -t "$next"; \
tmux kill-session -t "#{session_name}"; \
else tmux kill-session; fi'
It doesn't work. run-shell expands all #{...} format strings before handing the command to the shell. So list-sessions -F "#{session_name}" becomes list-sessions -F "mysession" — a literal string, not a format specifier. Every session prints "mysession", grep -v strips them all, $next is always empty, and you drop straight to bash.
The fix is one line:
set -g detach-on-destroy off
bind Q kill-session
detach-on-destroy off is a native tmux option: when a session is destroyed, the client automatically switches to another surviving session. It only falls back to exit when there's nothing left. No shell escaping, no format-string footguns, and it covers every exit path — not just prefix+Q.
The standard way to switch to the previous tmux session is prefix + L (or a custom prefix + b). The problem: every switch requires the full prefix chord again. You can't hold Ctrl and keep tapping — tmux swallows the first keypress as the prefix and expects a fresh command key each time.
Use a no-prefix binding instead. Add to ~/.tmux.conf:
# Alt+b to switch to previous session (no prefix needed).
bind -n M-b switch-client -p
The -n flag means "no prefix required." Now you hold Alt and tap b repeatedly to cycle through sessions — no prefix dance, no finger gymnastics.
Why Alt+B and not something else: it's close to the default prefix (Ctrl+B) so it's easy to remember, and it doesn't conflict with any common terminal or shell binding. Your mileage may vary if you use Alt-heavy terminal apps.
Tools like team and adhoc (from the mux-relay framework) derive the project root from $PWD at invocation time. The natural instinct is to open a new tmux window, cd to the target directory, then run the command. That works, but it leaves a ghost window in the original session — and if that window gets cleaned up or the session reshuffles, pane working directories can silently drift to deleted paths.
A subshell avoids all of that:
(j my-project && team)
The parentheses spawn a subshell. Inside it, j (zoxide) changes directory to the project, then team launches the new session with the correct $PWD. Because new-session -d is detached and switch-client handles the jump, the new session is fully independent — no nesting, no leftover windows.
When the subshell exits (right after team returns), the original pane's $PWD is untouched. You never left it.
This pattern works for any command that reads $PWD but doesn't accept a -C / --directory flag:
(cd ~/Projects/something && explore)
(cd $(z resolve another-project) && adhoc claude)
One pane, one command, zero side effects.