Communitygithub.com

项目会话管理器

基于 Git Worktree 的开发者环境管理器,支持问题(Issue)、拉取请求(PR)和功能开发,并可选集成 tmux 会话。

项目会话管理器 是什么?

项目会话管理器(PSM)是一个 AI 代理技能,专为使用 Claude Code 的开发人员设计,用于自动化创建隔离的开发环境。它利用 Git Worktree 技术,允许开发者在并行处理多个任务、项目和仓库时,不会互相干扰。PSM 支持从问题(Issue)、拉取请求(PR)到新功能开发等常见工作流,并可以可选地创建 tmux 会话来持久化这些环境。该技能通过 '/psm' 命令提供一系列子命令,如 `review`(审查)、`fix`(修复)、`feature`(功能)、`list`(列出)、`attach`(附加)、`kill`(终止)、`cleanup`(清理)和 `status`(状态),并集成了 GitHub 和 Jira 等多个问题跟踪提供商。其核心优势在于提供了一种“worktree-first”的方法,特别是通过 `omc teleport` 命令,使开发者能够快速创建隔离的工作区,从而显著提升多任务并行开发的效率和专注度。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Yeachan-Heo/oh-my-claudecode/tree/main/skills/project-session-manager

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

项目会话管理器 (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 (默认)ghowner/repo#123, alias#123, GitHub URLsreview, 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"
    }
  }
}

重要提示: 仍然需要 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-123psm_omc_pr-123~/.psm/worktrees/omc/pr-123
问题修复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, 或 session ID
  3. 选项: --branch, --base, --no-claude, --no-tmux 等

子命令: review <ref>

目的: 创建 PR 审查会话

步骤:

  1. 解析引用:

    # 读取项目别名
    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
    
  2. 获取 PR 信息:

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

    # 如果本地路径不存在,则克隆
    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"
    
    # 获取 PR 分支
    cd "$local_path"
    git fetch origin "pull/$pr_number/head:pr-$pr_number-review"
    
    # 创建工作区
    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. 更新会话注册表:

    # 添加到 ~/.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 可防止 "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
    
  9. 输出会话信息:

    会话已准备就绪!
    
      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>

目的: 创建问题修复会话

步骤:

  1. 解析引用 (同 review)

  2. 获取问题信息:

    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,但传递问题上下文作为初始任务提示:

    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>

目的: 开始功能开发

步骤:

  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 \
      "为项目 $project 实现功能 \"$feature_name\"。分支: $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. 格式化输出:

    活跃 PSM 会话:
    
    ID                 | 类型    | 状态   | 工作区
    -------------------|---------|----------|---------------------------
    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   # 将公共 id 转换为 tmux 安全名称
    
  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. 更新注册表:

    # 从 sessions.json 中移除
    

子命令: cleanup

目的: 清理已合并的 PR 和已关闭的问题

步骤:

  1. 读取所有会话

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

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

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

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

    清理完成:
      已移除: omc:pr-123 (已合并)
      已移除: omc:issue-42 (已关闭)
      已保留: omc:feat-auth (活跃)
    

子命令: status

目的: 显示当前会话信息

步骤:

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

    tmux display-message -p "#{session_name}" 2>/dev/null
    # 或检查 cwd 是否在工作区内部
    
  2. 读取会话元数据:

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

    当前会话: 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 teleportpsm <command>
范围仅工作区工作区 + tmux + claude
速度快速中等 (包括 tmux/启动延迟)
用例快速检查/临时任务深入的代码审查/修复会话
依赖性仅 gitgit + tmux + gh/jira

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

agent-doc-discipline

Writing-time discipline for documents agents consume (the five surfaces, specs, tickets, .omc/skills/) — every rule checkable and carrying a why, steps before reference, one meaning in one home, no restating what the environment already says. Mandatory at drydock seed generation and the launch C5 sediment pass; opt-in for any other agent-facing doc edit. The companion of minimal-code-discipline: that one disciplines code, this one disciplines papers.

ai-slop-cleaner

Clean AI-generated code slop with a regression-safe, deletion-first workflow and optional reviewer-only mode

ask

Process-first advisor routing for Claude, Codex, Gemini, Antigravity, Grok, or Cursor via `omc ask`, with artifact capture and no raw CLI assembly

ask-navigator

Shipyard

autopilot

Full autonomous execution from idea to working code

autoresearch

Stateful single-mission improvement loop with strict evaluator contract, markdown decision logs, and max-runtime stop behavior

cancel

Cancel any active OMC mode (autopilot, ralph, ultragoal, swarm, ultrapilot, pipeline, team) and clean up retired legacy state

configure-notifications

Configure notification integrations (Telegram, Discord, Slack) via natural language

debug

Diagnose the current OMC session or repo state using logs, traces, state, and focused reproduction

deepinit

Deep codebase initialization with hierarchical AGENTS.md documentation

deep-interview

Socratic deep interview with mathematical ambiguity gating before explicit execution approval

drydock

Lay the keel of the shipyard harness in any repo — the 4-pillar shared environment (Context, Rules, Tools, Standards) across 5 surfaces (CLAUDE.md, skills, design-system, mcp/cli, shared context) so that every human and agent inherits the same design language and anyone can ship. Run once per repo; re-run with --check to audit drift.

execute

Carry an approved task through to working, verified code

external-context

Invoke parallel document-specialist agents for external web searches and documentation lookup

graph

Deterministic orchestration graph runtime - declarative DAG pipelines with journal-based crash recovery

harbor

Harbor intake for external work — the captain only handles unresolved decisions. Sweeps incoming issues and PRs, verifies every claim before disposition, reuses every decision already made, and hands the maintainer a docket whose pending items each carry one question with options, recommendation, impact and evidence. Agent-autonomous for facts and for actions covered by standing authorization; signed for every new judgment. Never merges.

hud

Configure HUD display options (layout, presets, display elements)

launch

Shipyard

loft

Loft the shape before cutting steel — answer a design question that prose cannot settle by building a throwaway artifact: a pure logic module in a clickable shell, or structurally different UI variants behind one route. The captain reacts to the artifact; the answer folds into the decision; the artifact never docks. Use when a design question stalls in words, when a navigator map carries a loft ticket, or when a spec discussion reaches

minimal-code-discipline

YAGNI-ladder coding discipline for writing changes — existence-first, reuse before writing, dependency ladder, shortest correct diff, with non-negotiables that must never be minimized away

相关技能