关于 project-session-manager
Project Session Manager(PSM)通过 git worktree 和 tmux 创建隔离开发会话,支持评审、修复问题和开发功能。它可处理 GitHub 与已配置的 Jira 引用,也能通过 `omc teleport` 仅创建 worktree。
主要功能
- 01为评审、修复和功能开发创建 worktree
- 02使用 tmux 管理会话
- 03列出、连接、终止和清理会话
- 04解析 GitHub 与已配置的 Jira 引用
- 05通过 `omc teleport` 创建 worktree
适用场景
- 01在隔离的 worktree 中评审拉取请求
- 02在不修改主检出目录的情况下修复问题
- 03在独立会话中开始功能开发
- 04列出或清理开发会话
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ yeachan-heo/ oh-my-claudecode --skill project-session-manager安装后在 Claude Code 中输入/project-session-manager确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
psm.shlib/config.shparse.shsession.shtmux.shworktree.shlib/providers/azure-devops.shbitbucket.shgitea.shgithub.shgitlab.shinterface.shjira.shtemplates/feature.mdissue-fix.mdpr-review.mdprojects.jsontests/test-jira-provider.shtest-psm-prompt-injection.sh详细介绍
项目会话管理器(PSM)技能
psm 是这个规范技能入口的兼容别名。
快速开始(worktree 优先): 当你想在添加任何 tmux/会话编排之前先创建一个隔离的 issue/PR/feature worktree 时,从
omc teleport开始:omc teleport #123 # 为 issue/PR 创建 worktree omc teleport my-feature # 为 feature 创建 worktree omc teleport list # 列出 worktree详情请参见下方的 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> | Issue 修复会话 | /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 支持多个 issue 跟踪提供商:
| 提供商 | 所需 CLI | 引用格式 | 命令 |
|---|---|---|---|
| GitHub(默认) | gh | owner/repo#123、alias#123、GitHub URL | 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"
}
}
}
重要: 克隆 git 仓库时仍然需要 repo 字段。Jira 跟踪 issue,但你在 git 仓库中工作。
对于非 GitHub 仓库,请改用 clone_url:
{
"aliases": {
"private": {
"jira_project": "PRIV",
"clone_url": "[email protected]:team/repo.git",
"local": "~/Workspace/repo",
"provider": "jira"
}
}
}
Jira 引用检测
只有当 PROJ 在你的别名中被显式配置为 jira_project 时,PSM 才会将 PROJ-123 格式识别为 Jira。这可以防止像 FIX-123 这样的分支名被误判。
Jira 示例
# Fix a Jira issue (MYPROJ must be configured)
psm fix MYPROJ-123
# Fix using alias (recommended)
psm fix mywork#123
# Feature development (works same as GitHub)
psm feature mywork add-webhooks
# Note: 'psm review' is not supported for Jira (no PR concept)
# Use 'psm fix' for Jira issues
Jira CLI 设置
安装 Jira CLI:
# macOS
brew install ankitpokhrel/jira-cli/jira-cli
# Linux
# See: https://github.com/ankitpokhrel/jira-cli#installation
# Configure (interactive)
jira init
Jira CLI 独立于 PSM 处理身份验证。
目录结构
~/.psm/
├── projects.json # Project aliases
├── sessions.json # Active session registry
└── worktrees/ # Worktree storage
└── <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 |
| Issue 修复 | 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 或会话 ID
- 选项:--branch、--base、--no-claude、--no-tmux 等。
子命令:review <ref>
用途:创建 PR 审查会话
步骤:
-
解析引用:
# Read project aliases cat ~/.psm/projects.json 2>/dev/null || echo '{"aliases":{}}' # Parse ref format: alias#num, owner/repo#num, or URL # Extract: 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 local path doesn't exist, clone 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" # Fetch PR branch cd "$local_path" git fetch origin "pull/$pr_number/head:pr-$pr_number-review" # Create worktree 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 -
更新会话注册表:
# Add to ~/.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 prevents the "Do you trust this directory?" prompt # and repeated tool-approval prompts from stalling the session (issue #2508). tmux send-keys -t "psm_${project_alias}_pr-$pr_number" "claude --dangerously-skip-permissions" Enter # After claude boots (PSM_CLAUDE_STARTUP_DELAY, default 5s), deliver the task. # Use -l (literal) so special characters are not misinterpreted by tmux. sleep "${PSM_CLAUDE_STARTUP_DELAY:-5}" tmux send-keys -t "psm_${project_alias}_pr-$pr_number" -l \ "Review PR #$pr_number: \"$pr_title\" by @$pr_author ($head_branch → $base_branch). URL: $pr_url." Enter -
输出会话信息:
Session ready! ID: omc:pr-123 Worktree: ~/.psm/worktrees/omc/pr-123 Tmux: psm_omc_pr-123 To attach: tmux attach -t psm_omc_pr-123 (or: psm attach omc:pr-123)
子命令:fix <ref>
用途:创建 issue 修复会话
步骤:
-
解析引用(与 review 相同)
-
获取 issue 信息:
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 相同,但将 issue 上下文作为初始任务提示词传入:
tmux send-keys -t "psm_${project_alias}_issue-$issue_number" "claude --dangerously-skip-permissions" Enter # After claude boots, deliver the task (see PSM_CLAUDE_STARTUP_DELAY): tmux send-keys -t "psm_${project_alias}_issue-$issue_number" -l \ "Fix issue #$issue_number: \"$issue_title\". URL: $issue_url. Branch: $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 \ "Implement feature \"$feature_name\" for project $project. Branch: $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 -
格式化输出:
Active PSM Sessions: ID | Type | Status | Worktree -------------------|---------|----------|--------------------------- 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 # translate public id to tmux-safe name -
附加:
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 -
更新注册表:
# Remove from sessions.json
子命令:cleanup
用途:清理已合并的 PR 和已关闭的 issue
步骤:
-
读取所有会话
-
对每个 PR 会话,检查是否已合并:
gh pr view <pr_number> --repo <repo> --json merged,state -
对每个 issue 会话,检查是否已关闭:
gh issue view <issue_number> --repo <repo> --json closed,state -
清理已合并/已关闭的会话:
- 终止 tmux 会话
- 移除工作树
- 更新注册表
-
报告:
Cleanup complete: Removed: omc:pr-123 (merged) Removed: omc:issue-42 (closed) Kept: omc:feat-auth (active)
子命令:status
用途:显示当前会话信息
步骤:
-
从 tmux 或 cwd 检测当前会话:
tmux display-message -p "#{session_name}" 2>/dev/null # or check if cwd is inside a worktree -
读取会话元数据:
cat .psm-session.json 2>/dev/null -
显示状态:
Current Session: omc:pr-123 Type: review PR: #123 - Add webhook support Branch: feature/webhooks Created: 2 hours ago
错误处理
| 错误 | 解决方案 |
|---|---|
| 工作树已存在 | 提供选项:附加、重新创建或中止 |
| 未找到 PR | 验证 URL/编号,检查权限 |
| 无 tmux | 警告并跳过会话创建 |
| 无 gh CLI | 报错并提供安装说明 |
Teleport 命令
omc teleport 命令提供了完整 PSM 会话的轻量级替代方案。它在不使用 tmux 会话管理的情况下创建 git 工作树——非常适合快速、隔离的开发。
用法
# Create worktree for an issue or PR
omc teleport #123
omc teleport owner/repo#123
omc teleport https://github.com/owner/repo/issues/42
# Create worktree for a feature
omc teleport my-feature
# List existing worktrees
omc teleport list
# Remove a worktree
omc teleport remove issue/my-repo-123
omc teleport remove --force feat/my-repo-my-feature
选项
| 标志 | 描述 | 默认值 |
|---|---|---|
--worktree | 创建工作树(默认,为兼容性保留) | true |
--path <path> | 自定义工作树根目录 | ~/Workspace/omc-worktrees/ |
--base <branch> | 创建所基于的基础分支 | main |
--json | 以 JSON 输出 | false |
工作树布局
~/Workspace/omc-worktrees/
├── issue/
│ └── my-repo-123/ # Issue worktrees
├── pr/
│ └── my-repo-456/ # PR review worktrees
└── feat/
└── my-repo-my-feature/ # Feature worktrees
PSM vs Teleport
| 功能 | PSM | Teleport |
|---|---|---|
| Git 工作树 | 是 | 是 |
| Tmux 会话 | 是 | 否 |
| Claude Code 启动 | 是 | 否 |
| 会话注册表 | 是 | 否 |
| 自动清理 | 是 | 否 |
| 项目别名 | 是 | 否(使用当前仓库) |
使用 PSM 进行完整管理的会话。使用 teleport 进行快速工作树创建。
要求
必需:
git- 版本控制(支持工作树 v2.5+)jq- JSON 解析tmux- 会话管理(可选,但推荐)
可选(按提供商):
gh- GitHub CLI(用于 GitHub 工作流)jira- Jira CLI(用于 Jira 工作流)
初始化
首次运行时,创建默认配置:
mkdir -p ~/.psm/worktrees ~/.psm/logs
# Create default projects.json if not exists
if [[ ! -f ~/.psm/projects.json ]]; then
cat > ~/.psm/projects.json << 'EOF'
{
"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,
"auto_cleanup_merged": true
}
}
EOF
fi
# Create sessions.json if not exists
if [[ ! -f ~/.psm/sessions.json ]]; then
echo '{"version":1,"sessions":{},"stats":{"total_created":0,"total_cleaned":0}}' > ~/.psm/sessions.json
fi