项目会话管理器 (PSM) 技能
psm 是该规范技能入口的兼容别名。
快速入门 (worktree-first): 当你需要一个独立的问题/PR/功能工作区时,从
omc teleport开始,稍后可添加 tmux/会话编排:omc teleport #123 # 为问题/PR创建工作区 omc teleport my-feature # 为功能创建工作区 omc teleport list # 列出所有工作区详情请参阅下方的 Teleport 命令。
使用 Git Worktree 和 tmux 会话配合 Claude Code 自动化创建隔离的开发环境。支持跨多个任务、项目和仓库的并行工作。
规范斜杠命令: /oh-my-claudecode:project-session-manager (别名: /oh-my-claudecode:psm)。
命令
| 命令 | 描述 | 示例 |
|---|---|---|
review <ref> | PR 审查会话 | /psm review omc#123 |
fix <ref> | 问题修复会话 | /psm fix omc#42 |
feature <proj> <name> | 功能开发 | /psm feature omc add-webhooks |
list [project] | 列出活跃会话 | /psm list |
attach <session> | 附加到会话 | /psm attach omc:pr-123 |
kill <session> | 终止会话 | /psm kill omc:pr-123 |
cleanup | 清理已合并/关闭的 | /psm cleanup |
status | 当前会话信息 | /psm status |
项目引用
支持的格式:
- 别名:
omc#123(需要~/.psm/projects.json) - 完整格式:
owner/repo#123 - URL:
https://github.com/owner/repo/pull/123 - 当前:
#123(使用当前目录的仓库)
配置
项目别名 (~/.psm/projects.json)
{
"aliases": {
"omc": {
"repo": "Yeachan-Heo/oh-my-claudecode",
"local": "~/Workspace/oh-my-claudecode",
"default_base": "main"
}
},
"defaults": {
"worktree_root": "~/.psm/worktrees",
"cleanup_after_days": 14
}
}
提供商
PSM 支持多个问题跟踪提供商:
| 提供商 | 所需的 CLI | 引用格式 | 命令 |
|---|---|---|---|
| GitHub (默认) | gh | owner/repo#123, alias#123, GitHub URLs | review, fix, feature |
| Jira | jira | PROJ-123 (如果配置了 PROJ), alias#123 | fix, feature |
Jira 配置
要使用 Jira,需在别名中添加 jira_project 和 provider: "jira":
{
"aliases": {
"mywork": {
"jira_project": "MYPROJ",
"repo": "mycompany/my-project",
"local": "~/Workspace/my-project",
"default_base": "develop",
"provider": "jira"
}
}
}
重要提示: 仍然需要 repo 字段来克隆 git 仓库。Jira 跟踪问题,但你在 git 仓库中工作。
对于非 GitHub 仓库,请改用 clone_url:
{
"aliases": {
"private": {
"jira_project": "PRIV",
"clone_url": "[email protected]:team/repo.git",
"local": "~/Workspace/repo",
"provider": "jira"
}
}
}
Jira 引用检测
PSM 仅在你配置的别名中显式将 PROJ 设置为 jira_project 时,才会将 PROJ-123 格式识别为 Jira 引用。这可以防止像 FIX-123 这样的分支名称被误判。
Jira 示例
# 修复一个 Jira 问题 (必须配置 MYPROJ)
psm fix MYPROJ-123
# 使用别名修复 (推荐)
psm fix mywork#123
# 功能开发 (与 GitHub 工作方式相同)
psm feature mywork add-webhooks
# 注意:'psm review' 在 Jira 中不受支持 (没有 PR 概念)
# 对于 Jira 问题,请使用 'psm fix'
Jira CLI 设置
安装 Jira CLI:
# macOS
brew install ankitpokhrel/jira-cli/jira-cli
# Linux
# 参见:https://github.com/ankitpokhrel/jira-cli#installation
# 配置 (交互式)
jira init
Jira CLI 处理认证,与 PSM 分开。
目录结构
~/.psm/
├── projects.json # 项目别名
├── sessions.json # 活跃会话注册表
└── worktrees/ # Worktree 存储
└── <project>/
└── <type>-<id>/
会话命名
公共会话 ID (冒号形式, 例如 omc:pr-123) 是面向用户的标识符,存储在 sessions.json 中,用于 psm attach/psm kill。tmux 保留 : 和 . 用于其 session:window.pane 目标语法,并静默重写它们,因此实际的 tmux 会话名称使用 tmux 安全的形式,其中这些字符变为 _ (issue #3528)。PSM 在每个 tmux 边界处将公共 ID 转换为 tmux 安全的名称;直接使用 tmux 安全名称附加。
| 类型 | 公共 ID (psm attach/kill) | Tmux 会话 (tmux attach -t) | Worktree 目录 |
|---|---|---|---|
| PR 审查 | omc:pr-123 | psm_omc_pr-123 | ~/.psm/worktrees/omc/pr-123 |
| 问题修复 | omc:issue-42 | psm_omc_issue-42 | ~/.psm/worktrees/omc/issue-42 |
| 功能 | omc:feat-auth | psm_omc_feat-auth | ~/.psm/worktrees/omc/feat-auth |
实现协议
当用户调用 PSM 命令时,请遵循以下协议:
解析参数
解析 {{ARGUMENTS}} 以确定:
- 子命令: review, fix, feature, list, attach, kill, cleanup, status
- 引用: project#number, URL, 或 session ID
- 选项: --branch, --base, --no-claude, --no-tmux 等
子命令: review <ref>
目的: 创建 PR 审查会话
步骤:
-
解析引用:
# 读取项目别名 cat ~/.psm/projects.json 2>/dev/null || echo '{"aliases":{}}' # 解析 ref 格式: alias#num, owner/repo#num, 或 URL # 提取: project_alias, repo (owner/repo), pr_number, local_path -
获取 PR 信息:
gh pr view <pr_number> --repo <repo> --json number,title,author,headRefName,baseRefName,body,files,url -
确保本地仓库存在:
# 如果本地路径不存在,则克隆 if [[ ! -d "$local_path" ]]; then git clone "https://github.com/$repo.git" "$local_path" fi -
创建工作区:
worktree_path="$HOME/.psm/worktrees/$project_alias/pr-$pr_number" # 获取 PR 分支 cd "$local_path" git fetch origin "pull/$pr_number/head:pr-$pr_number-review" # 创建工作区 git worktree add "$worktree_path" "pr-$pr_number-review" -
创建会话元数据:
cat > "$worktree_path/.psm-session.json" << EOF { "id": "$project_alias:pr-$pr_number", "type": "review", "project": "$project_alias", "ref": "pr-$pr_number", "branch": "<head_branch>", "base": "<base_branch>", "created_at": "$(date -Iseconds)", "tmux_session": "psm_${project_alias}_pr-$pr_number", "worktree_path": "$worktree_path", "source_repo": "$local_path", "github": { "pr_number": $pr_number, "pr_title": "<title>", "pr_author": "<author>", "pr_url": "<url>" }, "state": "active" } EOF -
更新会话注册表:
# 添加到 ~/.psm/sessions.json -
创建 tmux 会话 (tmux 安全名称;
:/.被转换为_):tmux new-session -d -s "psm_${project_alias}_pr-$pr_number" -c "$worktree_path" -
启动 Claude Code (除非使用 --no-claude):
# --dangerously-skip-permissions 可防止 "Do you trust this directory?" 提示 # 以及重复的工具审批提示导致会话停滞 (issue #2508)。 tmux send-keys -t "psm_${project_alias}_pr-$pr_number" "claude --dangerously-skip-permissions" Enter # 在 claude 启动后 (PSM_CLAUDE_STARTUP_DELAY, 默认 5 秒),传递任务。 # 使用 -l (字面量) 以避免特殊字符被 tmux 误解释。 sleep "${PSM_CLAUDE_STARTUP_DELAY:-5}" tmux send-keys -t "psm_${project_alias}_pr-$pr_number" -l \ "审查 PR #$pr_number: \"$pr_title\" 由 @$pr_author 提交 ($head_branch → $base_branch)。URL: $pr_url。" Enter -
输出会话信息:
会话已准备就绪! ID: omc:pr-123 工作区: ~/.psm/worktrees/omc/pr-123 Tmux: psm_omc_pr-123 要附加:tmux attach -t psm_omc_pr-123 (或:psm attach omc:pr-123)
子命令: fix <ref>
目的: 创建问题修复会话
步骤:
-
解析引用 (同 review)
-
获取问题信息:
gh issue view <issue_number> --repo <repo> --json number,title,body,labels,url -
创建功能分支:
cd "$local_path" git fetch origin main branch_name="fix/$issue_number-$(echo "$title" | tr ' ' '-' | tr '[:upper:]' '[:lower:]' | head -c 30)" git checkout -b "$branch_name" origin/main -
创建工作区:
worktree_path="$HOME/.psm/worktrees/$project_alias/issue-$issue_number" git worktree add "$worktree_path" "$branch_name" -
创建会话元数据 (类似 review, type="fix")
-
更新注册表, 创建 tmux, 启动 claude: 同 review,但传递问题上下文作为初始任务提示:
tmux send-keys -t "psm_${project_alias}_issue-$issue_number" "claude --dangerously-skip-permissions" Enter # 在 claude 启动后 (参见 PSM_CLAUDE_STARTUP_DELAY): tmux send-keys -t "psm_${project_alias}_issue-$issue_number" -l \ "修复问题 #$issue_number: \"$issue_title\"。URL: $issue_url。分支: $branch_name。" Enter
子命令: feature <project> <name>
目的: 开始功能开发
步骤:
-
解析项目 (从别名或路径)
-
创建功能分支:
cd "$local_path" git fetch origin main branch_name="feature/$feature_name" git checkout -b "$branch_name" origin/main -
创建工作区:
worktree_path="$HOME/.psm/worktrees/$project_alias/feat-$feature_name" git worktree add "$worktree_path" "$branch_name" -
创建会话, tmux, 启动 claude,并传递功能上下文作为初始提示:
tmux send-keys -t "psm_${project_alias}_feat-$feature_name" "claude --dangerously-skip-permissions" Enter tmux send-keys -t "psm_${project_alias}_feat-$feature_name" -l \ "为项目 $project 实现功能 \"$feature_name\"。分支: $branch_name。" Enter
子命令: list [project]
目的: 列出活跃会话
步骤:
-
读取会话注册表:
cat ~/.psm/sessions.json 2>/dev/null || echo '{"sessions":{}}' -
检查 tmux 会话:
tmux list-sessions -F "#{session_name}" 2>/dev/null | grep "^psm_" -
检查工作区:
ls -la ~/.psm/worktrees/*/ 2>/dev/null -
格式化输出:
活跃 PSM 会话: ID | 类型 | 状态 | 工作区 -------------------|---------|----------|--------------------------- omc:pr-123 | review | active | ~/.psm/worktrees/omc/pr-123 omc:issue-42 | fix | detached | ~/.psm/worktrees/omc/issue-42
子命令: attach <session>
目的: 附加到现有会话
步骤:
-
解析会话 ID:
project:type-number -
验证会话存在:
tmux has-session -t "psm_${session_id//[.:]/_}" 2>/dev/null # 将公共 id 转换为 tmux 安全名称 -
附加:
tmux attach -t "psm_${session_id//[.:]/_}"
子命令: kill <session>
目的: 终止会话并进行清理
步骤:
-
终止 tmux 会话:
tmux kill-session -t "psm_${session_id//[.:]/_}" 2>/dev/null -
移除工作区:
worktree_path=$(jq -r ".sessions[\"$session_id\"].worktree" ~/.psm/sessions.json) source_repo=$(jq -r ".sessions[\"$session_id\"].source_repo" ~/.psm/sessions.json) cd "$source_repo" git worktree remove "$worktree_path" --force -
更新注册表:
# 从 sessions.json 中移除
子命令: cleanup
目的: 清理已合并的 PR 和已关闭的问题
步骤:
-
读取所有会话
-
对于每个 PR 会话,检查是否已合并:
gh pr view <pr_number> --repo <repo> --json merged,state -
对于每个问题会话,检查是否已关闭:
gh issue view <issue_number> --repo <repo> --json closed,state -
清理已合并/关闭的会话:
- 终止 tmux 会话
- 移除工作区
- 更新注册表
-
报告:
清理完成: 已移除: omc:pr-123 (已合并) 已移除: omc:issue-42 (已关闭) 已保留: omc:feat-auth (活跃)
子命令: status
目的: 显示当前会话信息
步骤:
-
检测当前会话 来自 tmux 或 cwd:
tmux display-message -p "#{session_name}" 2>/dev/null # 或检查 cwd 是否在工作区内部 -
读取会话元数据:
cat .psm-session.json 2>/dev/null -
显示状态:
当前会话: omc:pr-123 类型: review PR: #123 - 添加 webhook 支持 分支: feature/webhooks 创建于: 2 小时前
错误处理
| 错误 | 解决方案 |
|---|---|
| 工作区已存在 | 提供: 附加, 重建, 或中止 |
| PR 未找到 | 验证 URL/编号, 检查权限 |
| 没有 tmux | 警告并跳过会话创建 |
| 没有 gh CLI | 错误并附上安装说明 |
Teleport 命令
omc teleport 命令提供了一种轻量级的替代方案,用于创建完整的 PSM 会话。它创建 git 工作区,无需 tmux 会话管理 — 非常适合快速、隔离的开发。
用法
# 为问题或 PR 创建工作区
omc teleport #123
omc teleport owner/repo#123
omc teleport https://github.com/owner/repo/issues/42
# 为功能创建工作区
omc teleport my-feature
# 列出现有工作区
omc teleport list
# 移除工作区
omc teleport remove issue/my-repo-123
omc teleport remove --force feat/my-repo-my-feature
选项
| 标志 | 描述 | 默认值 |
|---|---|---|
--worktree-root <path> | 设置不同的工作区根目录 | ~/.psm/worktrees |
--base <branch> | 设置基础分支 | main |
--force | 强制移除工作区 | false |
--dry-run | 仅显示将要执行的操作 | false |
Teleport 与 PSM
| 方面 | omc teleport | psm <command> |
|---|---|---|
| 范围 | 仅工作区 | 工作区 + tmux + claude |
| 速度 | 快速 | 中等 (包括 tmux/启动延迟) |
| 用例 | 快速检查/临时任务 | 深入的代码审查/修复会话 |
| 依赖性 | 仅 git | git + tmux + gh/jira |