mcpField
P
project-session-manager

project-session-manager

github.com/yeachan-heo开发40.4k879 次安装1 天前更新
代码仓库

关于 project-session-manager

Project Session Manager(PSM)通过 git worktree 和 tmux 创建隔离开发会话,支持评审、修复问题和开发功能。它可处理 GitHub 与已配置的 Jira 引用,也能通过 `omc teleport` 仅创建 worktree。

主要功能

  1. 01为评审、修复和功能开发创建 worktree
  2. 02使用 tmux 管理会话
  3. 03列出、连接、终止和清理会话
  4. 04解析 GitHub 与已配置的 Jira 引用
  5. 05通过 `omc teleport` 创建 worktree

适用场景

  1. 01在隔离的 worktree 中评审拉取请求
  2. 02在不修改主检出目录的情况下修复问题
  3. 03在独立会话中开始功能开发
  4. 04列出或清理开发会话

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/yeachan-heo/oh-my-claudecode --skill project-session-manager

安装后在 Claude Code 中输入/project-session-manager确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

psm.sh
lib/
config.sh
parse.sh
session.sh
tmux.sh
worktree.sh
lib/providers/
azure-devops.sh
bitbucket.sh
gitea.sh
github.sh
gitlab.sh
interface.sh
jira.sh
templates/
feature.md
issue-fix.md
pr-review.md
projects.json
tests/
test-jira-provider.sh
test-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(默认)ghowner/repo#123、alias#123、GitHub URLreview、fix、feature
JirajiraPROJ-123(如果配置了 PROJ)、alias#123fix、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-123psm_omc_pr-123~/.psm/worktrees/omc/pr-123
Issue 修复omc:issue-42psm_omc_issue-42~/.psm/worktrees/omc/issue-42
功能omc:feat-authpsm_omc_feat-auth~/.psm/worktrees/omc/feat-auth

实现协议

当用户调用 PSM 命令时,请遵循此协议:

解析参数

解析 {{ARGUMENTS}} 以确定:

  1. 子命令:review、fix、feature、list、attach、kill、cleanup、status
  2. 引用:project#number、URL 或会话 ID
  3. 选项:--branch、--base、--no-claude、--no-tmux 等。
子命令:review <ref>

用途:创建 PR 审查会话

步骤:

  1. 解析引用:

    # 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
    
  2. 获取 PR 信息:

    gh pr view <pr_number> --repo <repo> --json number,title,author,headRefName,baseRefName,body,files,url
    
  3. 确保本地仓库存在:

    # If local path doesn't exist, clone
    if [[ ! -d "$local_path" ]]; then
      git clone "https://github.com/$repo.git" "$local_path"
    fi
    
  4. 创建工作树:

    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"
    
  5. 创建会话元数据:

    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
    
  6. 更新会话注册表:

    # Add to ~/.psm/sessions.json
    
  7. 创建 tmux 会话(tmux 安全名称;:/. 会被转换为 _):

    tmux new-session -d -s "psm_${project_alias}_pr-$pr_number" -c "$worktree_path"
    
  8. 启动 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
    
  9. 输出会话信息:

    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 修复会话

步骤:

  1. 解析引用(与 review 相同)

  2. 获取 issue 信息:

    gh issue view <issue_number> --repo <repo> --json number,title,body,labels,url
    
  3. 创建功能分支:

    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
    
  4. 创建工作树:

    worktree_path="$HOME/.psm/worktrees/$project_alias/issue-$issue_number"
    git worktree add "$worktree_path" "$branch_name"
    
  5. 创建会话元数据(与 review 类似,type="fix")

  6. 更新注册表、创建 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>

用途:开始功能开发

步骤:

  1. 解析项目(通过别名或路径)

  2. 创建功能分支:

    cd "$local_path"
    git fetch origin main
    branch_name="feature/$feature_name"
    git checkout -b "$branch_name" origin/main
    
  3. 创建工作树:

    worktree_path="$HOME/.psm/worktrees/$project_alias/feat-$feature_name"
    git worktree add "$worktree_path" "$branch_name"
    
  4. 创建会话、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]

用途:列出活动会话

步骤:

  1. 读取会话注册表:

    cat ~/.psm/sessions.json 2>/dev/null || echo '{"sessions":{}}'
    
  2. 检查 tmux 会话:

    tmux list-sessions -F "#{session_name}" 2>/dev/null | grep "^psm_"
    
  3. 检查工作树:

    ls -la ~/.psm/worktrees/*/ 2>/dev/null
    
  4. 格式化输出:

    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>

用途:附加到现有会话

步骤:

  1. 解析会话 ID:project:type-number

  2. 验证会话存在:

    tmux has-session -t "psm_${session_id//[.:]/_}" 2>/dev/null   # translate public id to tmux-safe name
    
  3. 附加:

    tmux attach -t "psm_${session_id//[.:]/_}"
    
子命令:kill <session>

用途:终止会话并清理

步骤:

  1. 终止 tmux 会话:

    tmux kill-session -t "psm_${session_id//[.:]/_}" 2>/dev/null
    
  2. 移除工作树:

    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
    
  3. 更新注册表:

    # Remove from sessions.json
    
子命令:cleanup

用途:清理已合并的 PR 和已关闭的 issue

步骤:

  1. 读取所有会话

  2. 对每个 PR 会话,检查是否已合并:

    gh pr view <pr_number> --repo <repo> --json merged,state
    
  3. 对每个 issue 会话,检查是否已关闭:

    gh issue view <issue_number> --repo <repo> --json closed,state
    
  4. 清理已合并/已关闭的会话:

    • 终止 tmux 会话
    • 移除工作树
    • 更新注册表
  5. 报告:

    Cleanup complete:
      Removed: omc:pr-123 (merged)
      Removed: omc:issue-42 (closed)
      Kept: omc:feat-auth (active)
    
子命令:status

用途:显示当前会话信息

步骤:

  1. 从 tmux 或 cwd 检测当前会话:

    tmux display-message -p "#{session_name}" 2>/dev/null
    # or check if cwd is inside a worktree
    
  2. 读取会话元数据:

    cat .psm-session.json 2>/dev/null
    
  3. 显示状态:

    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
功能PSMTeleport
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

评论

支持 Markdown