在之前的文章中,我们学习了 Codex CLI 的基本操作、沙箱模式、后台运行,以及如何将它集成到 CI/CD 流水线和结构化输出。

Session 管理 —— --continue、会话 ID、恢复流程、清理策略

简介

在之前的文章中,我们学习了 Codex CLI 的基本操作、沙箱模式、后台运行,以及如何将它集成到 CI/CD 流水线和结构化输出。

但所有这些讨论都围绕一个假设:每次交互都是独立的、一次性的。

在真实开发场景中,情况往往不是这样:

  • 你需要让 AI 执行一个多步骤的重构任务,中途需要确认某些决定
  • 一个复杂的 debug 任务可能需要多轮对话,AI 需要记住之前的分析
  • 你运行了一个长时间任务,终端意外关闭了,不想从头再来
  • 你想在不同时间继续同一个项目的对话,AI 需要记住上下文

这就是 Session 管理要解决的问题。

本文将深入探讨 Codex CLI 的 Session 管理机制,包括 --continue 标志、会话 ID 的工作原理、会话恢复的最佳实践,以及定期清理策略。

一、Session 基础概念

1.1 什么是 Session

Session(会话)是 Codex CLI 中一个完整的对话上下文。它包含:

text
┌──────────────────────────────────────────┐
│               Session 结构                │
├──────────────────────────────────────────┤
│                                          │
│  Session ID (UUID)                       │
│  ├── 系统提示词 (System Prompt)          │
│  ├── 对话历史 (Messages)                  │
│  │   ├── user: "分析这个项目的架构"      │
│  │   ├── assistant: "该项目采用..."      │
│  │   ├── user: "重构模块 A"              │
│  │   └── assistant: "已完成重构..."      │
│  ├── 文件状态快照                          │
│  ├── 执行历史记录                          │
│  └── 时间戳                                │
│                                          │
└──────────────────────────────────────────┘

1.2 Session 的存储位置

Codex CLI 将会话数据存储在本地:

bash
# 默认存储位置
~/.codex/sessions/

# 目录结构
~/.codex/sessions/
├── session-abc123.json
├── session-def456.json
└── ...

每个 Session 文件包含完整的对话历史,包括用户输入、AI 回复、执行结果等。

1.3 为什么需要 Session

无 Session 的问题:

bash
# 第一次运行
codex exec --full-auto "分析 src/ 目录的架构"
# → AI 分析了架构,给出了报告

# 第二次运行(没有上下文!)
codex exec --full-auto "根据刚才的分析,重构模块 A"
# → AI 不知道"刚才的分析"是什么

有 Session 的优势:

bash
# 第一次运行(创建 Session)
codex exec --full-auto "分析 src/ 目录的架构"
# → Session 创建,包含分析结果

# 第二次运行(继续同一个 Session)
codex exec --continue --full-auto "根据刚才的分析,重构模块 A"
# → AI 知道之前的分析,可以直接执行

二、--continue 标志详解

2.1 基本用法

bash
# 启动新会话
codex exec --full-auto "分析项目的目录结构,找出可以优化的模块"

# 继续上一个会话
codex exec --continue --full-auto "现在针对你刚才找到的问题,进行重构"

--continue 标志告诉 Codex CLI:

  1. 找到最近的活动会话
  2. 加载该会话的完整历史
  3. 将新的指令追加到历史末尾
  4. 基于完整上下文执行

2.2 指定继续的会话

如果你有多个活跃会话,可以指定要继续的会话 ID:

bash
# 列出所有会话
codex sessions list

# 输出示例:
# SESSION ID              CREATED              LAST ACTIVE    MESSAGES
# a1b2c3d4-e5f6-...      2024-01-15 10:30     10:45          12
# f6e5d4c3-b2a1-...      2024-01-15 09:00     09:30          8
# 9876543a-bcde-...      2024-01-14 16:00     16:20          25

# 继续指定会话
codex exec --continue a1b2c3d4-e5f6-... --full-auto "继续重构"

2.3 交互式模式下的继续

在交互式模式(不带 --full-auto)中,--continue 同样有效:

bash
# 开始新的交互会话
codex

# ... 对话一段时间后,退出(Ctrl+D)

# 继续上次的会话
codex --continue
# → 加载完整历史,可以继续对话

2.4 连续多步骤任务示例

bash
#!/bin/bash
# 多步骤重构任务

# Step 1: 分析
codex exec --full-auto "分析 src/auth/ 模块,找出安全隐患和性能瓶颈"
echo "✅ Step 1: Analysis complete"

# Step 2: 设计
codex exec --continue --full-auto \
  "基于刚才的分析,设计重构方案,列出具体步骤"
echo "✅ Step 2: Design complete"

# Step 3: 执行
codex exec --continue --full-auto \
  "按照你设计的方案,逐步执行重构。每次修改后运行测试"
echo "✅ Step 3: Execution complete"

# Step 4: 验证
codex exec --continue --full-auto \
  "运行完整的测试套件,验证重构没有破坏任何功能。生成报告"
echo "✅ Step 4: Verification complete"

注意: 每一步都会创建新的 API 调用,但 AI 都能看到之前的完整上下文。

三、会话 ID 工作原理

3.1 会话 ID 的格式

text
Session ID: a1b2c3d4-e5f6-7890-abcd-ef1234567890
             └────┬────┘ └─┬─┘ └──┬──┘ └─┬─┘ └──────┬──────┘
               Part 1   Part 2  Part 3  Part 4    Part 5

会话 ID 是标准的 UUID v4 格式,确保全局唯一性。

3.2 会话 ID 的生成

text
触发创建 Session 时:
  ├── 生成 UUID v4
  ├── 读取当前工作目录
  ├── 读取系统提示词模板
  ├── 初始化空的消息历史
  └── 写入存储

3.3 工作目录与会话的关联

bash
# 同一个工作目录下可能有多个 Session
~/.codex/sessions/
├── session-a1b2.json   # /path/to/project-A 的分析任务
├── session-c3d4.json   # /path/to/project-A 的重构任务
└── session-e5f6.json   # /path/to/project-B 的审查任务

Codex CLI 通常通过工作目录来筛选相关会话。

3.4 环境变量中的会话信息

bash
# 当前会话 ID 可以通过环境变量获取
echo $CODEX_SESSION_ID

# 在脚本中使用
SESSION_ID=$(codex exec --full-auto "分析项目" --output-format json | jq -r '.session_id')
echo "Created session: $SESSION_ID"

四、会话恢复流程

4.1 自动恢复

Codex CLI 支持自动恢复最近的会话:

bash
# 直接运行 --continue 会自动找到最近的活跃会话
codex exec --continue --full-auto "继续上次的任务"

4.2 手动恢复

bash
# 1. 列出所有会话
codex sessions list --all

# 2. 查看特定会话详情
codex sessions view <session-id>

# 3. 恢复特定会话
codex exec --continue <session-id> --full-auto "继续"

4.3 中断后恢复

当 Codex CLI 进程被意外终止(Ctrl+C、终端关闭、SSH 断开)时:

bash
# 方案 1:使用 --continue
codex exec --continue --full-auto "继续上次未完成的任务"

# 方案 2:使用 --resume(如果有此标志)
codex exec --resume <session-id>

# 方案 3:手动恢复
# 查看最近的会话文件
ls -lt ~/.codex/sessions/ | head -5

4.4 恢复状态检查

bash
# 检查会话是否可以恢复
codex sessions check <session-id>

# 输出示例:
# Session a1b2c3d4:
#   Status: recoverable
#   Last message: assistant
#   Pending actions: 0
#   Files modified: 3
#   Can continue: yes

4.5 完整的恢复脚本

bash
#!/bin/bash
# session-recovery.sh —— 智能会话恢复脚本

set -euo pipefail

# 检查是否有活跃会话
ACTIVE_SESSIONS=$(codex sessions list --format json | jq '[.[] | select(.status == "active")] | length')

if [ "$ACTIVE_SESSIONS" -eq 0 ]; then
  echo "No active sessions found. Starting a new one."
  codex exec --full-auto "$1"
  exit 0
fi

# 获取最近的活跃会话
LATEST=$(codex sessions list --format json | \
  jq -r '[.[] | select(.status == "active")] | sort_by(.last_active) | last | .id')

echo "Found active session: $LATEST"
codex sessions view $LATEST

# 询问用户是否恢复
echo ""
read -p "Continue this session? (y/n) " -n 1 -r
echo

if [[ $REPLY =~ ^[Yy]$ ]]; then
  codex exec --continue $LATEST --full-auto "$1"
else
  echo "Starting a new session."
  codex exec --full-auto "$1"
fi

4.6 从检查点恢复

对于特别长的任务,可以实现检查点机制:

bash
#!/bin/bash
# 带检查点的长任务

TASK="重构整个 authentication 模块"
CHECKPOINT_DIR="/tmp/codex-checkpoints"
mkdir -p $CHECKPOINT_DIR

# Step 1: 分析
echo "=== Step 1: Analyzing ==="
codex exec --full-auto "$TASK - Step 1: Analyze current implementation" > $CHECKPOINT_DIR/step1.txt

# Step 2: 设计方案
echo "=== Step 2: Designing ==="
ANALYSIS=$(cat $CHECKPOINT_DIR/step1.txt)
codex exec --continue --full-auto "$TASK - Step 2: Create refactoring plan based on: $ANALYSIS" > $CHECKPOINT_DIR/step2.txt

# Step 3: 逐步执行
echo "=== Step 3: Executing ==="
PLAN=$(cat $CHECKPOINT_DIR/step2.txt)
codex exec --continue --full-auto "$TASK - Step 3: Execute the plan: $PLAN" > $CHECKPOINT_DIR/step3.txt

# 如果某一步失败,可以从检查点恢复
# 不需要重新运行前面的步骤

五、清理策略

5.1 为什么需要清理

text
如果不定期清理 Session 数据:

~/.codex/sessions/
├── session-001.json    (2024-01-01)  ← 6 个月前的会话
├── session-002.json    (2024-01-02)
├── session-003.json    (2024-01-03)
├── ...
├── session-999.json    (2024-06-30)
└── session-1000.json   (2024-07-01)  ← 今天的会话

磁盘占用:数百 MB 甚至 GB

5.2 自动清理策略

bash
#!/bin/bash
# session-cleanup.sh —— Session 清理脚本

set -euo pipefail

SESSION_DIR="${CODEX_SESSION_DIR:-$HOME/.codex/sessions}"
RETENTION_DAYS="${CODEX_RETENTION_DAYS:-30}"

echo "🧹 Session Cleanup"
echo "   Directory: $SESSION_DIR"
echo "   Retention: $RETENTION_DAYS days"
echo ""

# 统计
TOTAL=$(ls -1 $SESSION_DIR/*.json 2>/dev/null | wc -l)
echo "Total sessions: $TOTAL"

# 查找过期会话
EXPIRED=$(find $SESSION_DIR -name "*.json" -mtime +$RETENTION_DAYS)
EXPIRED_COUNT=$(echo "$EXPIRED" | grep -c "." || true)

if [ "$EXPIRED_COUNT" -eq 0 ]; then
  echo "No sessions to clean up."
  exit 0
fi

echo "Sessions to clean: $EXPIRED_COUNT"
echo ""

# 显示过期会话
echo "Expired sessions:"
echo "$EXPIRED" | while read -r f; do
  NAME=$(basename "$f")
  MODIFIED=$(stat -c %y "$f" | cut -d' ' -f1)
  SIZE=$(du -h "$f" | cut -f1)
  echo "  $NAME ($MODIFIED, $SIZE)"
done

echo ""
read -p "Delete these sessions? (y/n) " -n 1 -r
echo

if [[ $REPLY =~ ^[Yy]$ ]]; then
  echo "$EXPIRED" | while read -r f; do
    rm -v "$f"
  done
  echo ""
  echo "✅ Cleanup complete"
else
  echo "Cleanup cancelled"
fi

5.3 按大小清理

bash
#!/bin/bash
# cleanup-by-size.sh —— 按大小清理

SESSION_DIR="$HOME/.codex/sessions"

# 设置最大目录大小(MB)
MAX_SIZE_MB=500

# 计算当前大小
CURRENT_SIZE=$(du -sm "$SESSION_DIR" | cut -f1)

echo "Current session directory size: ${CURRENT_SIZE_MB}MB"
echo "Maximum allowed: ${MAX_SIZE_MB}MB"

if [ "$CURRENT_SIZE" -le "$MAX_SIZE_MB" ]; then
  echo "No cleanup needed."
  exit 0
fi

# 删除最旧的会话,直到大小符合要求
find "$SESSION_DIR" -name "*.json" -printf '%T@ %p\n' | \
  sort -n | \
  while read -r timestamp file; do
    rm -v "$file"
    NEW_SIZE=$(du -sm "$SESSION_DIR" | cut -f1)
    if [ "$NEW_SIZE" -le "$MAX_SIZE_MB" ]; then
      break
    fi
  done

echo "✅ Cleanup complete"

5.4 按会话类型清理

bash
#!/bin/bash
# cleanup-by-type.sh —— 按会话类型清理

SESSION_DIR="$HOME/.codex/sessions"

# 删除失败的会话(执行结果为错误的)
echo "🗑️ Cleaning up failed sessions..."
find "$SESSION_DIR" -name "*.json" -exec grep -l '"status":"failed"' {} \; | \
  while read -r f; do
    rm -v "$f"
  done

# 删除已完成的旧会话(保留最近的 10 个)
echo "🗑️ Cleaning up old completed sessions..."
find "$SESSION_DIR" -name "*.json" -exec grep -l '"status":"completed"' {} \; | \
  xargs ls -t | tail -n +11 | \
  while read -r f; do
    rm -v "$f"
  done

echo "✅ Cleanup complete"

5.5 定时清理(Cron)

bash
# 添加定时任务:每周日凌晨 3 点清理
crontab -e

# 添加以下行
0 3 * * 0 ~/.codex/scripts/cleanup.sh --retention 30 --max-size 500 --dry-run=false >> ~/.codex/logs/cleanup.log 2>&1

5.6 导出重要会话

在清理之前,你可能需要导出重要的会话:

bash
#!/bin/bash
# export-session.sh —— 导出会话为可读格式

SESSION_ID=$1
OUTPUT_FILE="${2:-session-${SESSION_ID}.md}"

# 加载会话数据
SESSION_FILE="$HOME/.codex/sessions/session-${SESSION_ID}.json"

if [ ! -f "$SESSION_FILE" ]; then
  echo "Session not found: $SESSION_ID"
  exit 1
fi

# 转换为 Markdown 格式
jq -r '
"# Session: \(.id)
## Created: \(.created_at)
## Last Active: \(.last_active)

---

" +
(.messages | map(
  if .role == "user" then
    "### 👤 User\n\n" + .content + "\n\n---\n"
  else
    "### 🤖 Assistant\n\n" + .content + "\n\n---\n"
  end
) | join(""))
' "$SESSION_FILE" > "$OUTPUT_FILE"

echo "✅ Session exported to $OUTPUT_FILE"

六、高级 Session 管理

6.1 会话分支

类似 Git 的分支概念,你可以从一个会话创建分支:

bash
# 从当前会话创建一个分支,尝试不同的方向
codex exec --continue --branch refactor-v2 --full-auto "尝试另一种重构方案"

# 原会话保持不变,新分支有独立的后续历史

6.2 会话合并

bash
# 将两个相关会话合并(概念性操作)
codex sessions merge <session-a> <session-b> --output merged-session

6.3 会话搜索

bash
# 按关键词搜索会话
codex sessions search "authentication refactor"

# 按时间范围搜索
codex sessions search --after "2024-06-01" --before "2024-06-30"

# 按文件搜索
codex sessions search --file "src/auth/login.ts"

6.4 会话统计

bash
# 查看会话使用统计
codex sessions stats

# 输出示例:
# Total sessions: 156
# Active sessions: 3
# Average messages per session: 12.5
# Total API calls: 1,950
# Disk usage: 45MB
#
# Top projects:
#   project-a: 45 sessions
#   project-b: 38 sessions
#   project-c: 22 sessions

6.5 会话同步(多设备)

如果你需要在多台设备上共享会话:

bash
# 将会话目录同步到云端
rclone sync ~/.codex/sessions remote:codex-sessions --exclude "*.tmp"

# 从云端恢复
rclone sync remote:codex-sessions ~/.codex/sessions --exclude "*.tmp"

七、最佳实践

7.1 命名你的会话

bash
# 给会话添加标签/名称(如果支持)
codex exec --name "auth-refactor-june" --full-auto "..."

# 或者在消息中包含标识
codex exec --full-auto "[auth-refactor] 分析当前认证模块..."

7.2 定期提交检查点

bash
# 在关键步骤后,手动创建检查点
codex exec --continue --full-auto "[CHECKPOINT] 保存当前进度"

7.3 保持会话简洁

bash
# 如果会话历史太长,考虑开启新会话
# 用简短的上下文摘要传递给新会话

# Step 1: 长会话完成
codex exec --full-auto "分析整个项目的架构..."  # 20+ 轮对话

# Step 2: 总结后开新会话
SUMMARY=$(codex exec --continue --full-auto "用 200 字总结之前的分析结果")

# Step 3: 新会话,注入摘要
codex exec --full-auto "之前的分析摘要: $SUMMARY。现在开始重构..."

7.4 CI/CD 中的 Session 管理

yaml
      - name: Cache Session
        uses: actions/cache@v4
        with:
          path: ~/.codex/sessions
          key: ${{ runner.os }}-codex-session-${{ github.run_id }}

      - name: Restore Session
        if: steps.cache.outputs.cache-hit == 'true'
        run: |
          codex exec --continue --full-auto "Continue from previous run"

总结

Session 管理是 Codex CLI 从"单次问答工具"进化为"长期协作伙伴"的核心能力。本文覆盖了:

1. --continue 标志: 如何继续最近的会话或指定会话,多步骤任务的连续执行。

2. 会话 ID 工作原理: UUID 格式、存储位置、工作目录关联、环境变量。

3. 恢复流程: 自动恢复、手动恢复、中断后恢复、检查点机制。

4. 清理策略: 按时间清理、按大小清理、按类型清理、定时清理、导出备份。

关键要点:

  • 使用 --continue 保持多步骤任务的上下文连续性
  • 定期清理过期会话,避免磁盘空间浪费
  • 重要的会话记得导出备份
  • 会话过长时考虑总结后开启新会话

下篇预告

下一篇我们将深入 提示词工程(Prompt Engineering) 的实战技巧:如何有效地分解复杂任务、注入精确的上下文、使用文件引用提高准确率,以及利用管道输入构建高效的 AI 工作流。这是本 Codex CLI 系列文章的收官之作!