跳至内容

Junyi's Lab

Claude Code 在 tmux 里要求重新登录?八成是 macOS Keychain 的锅

Table of Contents

终端里 claude 好好的,Team Account 也认得,进了 tmux 就让我重新登录。折腾了一会儿才发现是 macOS Security Session 的老问题。

# 现象

Ghostty 里直接跑 claude,没问题。tmux 里跑,要求登录。

排查过程(点击展开)

## 环境变量?

第一反应是 tmux 里环境变量不一样。

env | grep -iE 'claude|anthropic'

两边都没有。Claude Code 认证不存环境变量。

## 配置文件?

cat ~/.claude/.credentials.json 2>/dev/null || echo "no credentials file"

也没有。不在文件系统里。

## Keychain

security dump-keychain 2>&1 | grep -i -A3 'claude\|anthropic'

找到了,存在 macOS Keychain 里,service name 是 Claude Code-credentials

0x00000007 <blob>="Claude Code-credentials"
"acct"<blob>="junyi"
"svce"<blob>="Claude Code-credentials"
keychain: "/Users/junyi/Library/Keychains/login.keychain-db"

然后试了下:

security find-generic-password -s "Claude Code-credentials" -a "junyi" -w

终端里能输出 token,tmux 里报错。问题在这。

# 为什么

macOS 的 Keychain 访问绑在 Security Session 上,底层对应的是 Bootstrap Namespace。你开终端窗口的时候,进程会挂到当前用户的 Aqua session,Keychain 就是通过这个 session 解锁的。

tmux server 是个常驻后台进程,第一次 tmux new 的时候启动,之后就一直活着。你后面 tmux attach 的时候,tmux server fork 出来的 shell 继承的是 server 启动时的那个旧 session,不是你当前的 Aqua session。

正常终端:
  Ghostty → fork shell → 继承 Aqua session → ✅ 能读 Keychain

tmux:
  Ghostty → attach → tmux server (旧进程)
                       → fork shell → 继承旧 session
                                       → ❌ 读不了 Keychain

pbcopy/pbpaste 在 tmux 里挂掉也是这个原因。

# 修复

reattach-to-user-namespace,让 tmux 里的进程重新接入当前用户的 Aqua session:

brew install reattach-to-user-namespace

~/.tmux.conf 加一行:

set-option -g default-command "reattach-to-user-namespace -l ${SHELL}"

然后杀掉整个 tmux server 重开。kill-session 没用,新 window 也没用,都还是从旧 server fork 的:

tmux kill-server
tmux new -s main

验证:

security find-generic-password -s "Claude Code-credentials" -a "$USER" -w 2>&1 | head -c 50

能输出 token 就说明通了。

# 顺带一提

tmux 里这些问题多半也是同一个原因:

  • pbcopy/pbpaste 不工作
  • ssh-agent 访问不了
  • osascript 执行失败
  • gh authop 等 CLI 工具认证挂了

都是 reattach-to-user-namespace 一把搞定。