Project Session Manager (PSM) 技能
psm 是此標準化技能進入點的相容別名。
快速開始 (worktree-first): 當你想要一個隔離的 issue/PR/功能 worktree,且尚未加入任何 tmux/階段編排時,請從
omc teleport開始:omc teleport #123 # 為 issue/PR 建立 worktree omc teleport my-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 支援多個問題追蹤供應商:
| 供應商 | 所需 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"
}
}
}
重要: 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
# 注意:Jira 不支援 'psm review'(沒有 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 |
| 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 審查階段
步驟:
-
解析參考:
# 讀取專案別名 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:
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" # 建立 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 -
更新階段註冊:
# 加入到 ~/.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 (literal) 以避免特殊字元被 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:
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 # 在 claude 啟動後,傳遞任務(請參閱 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:
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_" -
檢查 worktree:
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 # 將公開 ID 轉譯為 tmux 安全名稱 -
附加:
tmux attach -t "psm_${session_id//[.:]/_}"
子指令:kill <session>
目的:終止階段並清理
步驟:
-
終止 tmux 階段:
tmux kill-session -t "psm_${session_id//[.:]/_}" 2>/dev/null -
移除 worktree:
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 和已關閉的 issue
步驟:
-
讀取所有階段
-
對於每個 PR 階段,檢查是否已合併:
gh pr view <pr_number> --repo <repo> --json merged,state -
對於每個 issue 階段,檢查是否已關閉:
gh issue view <issue_number> --repo <repo> --json closed,state -
清理已合併/關閉的階段:
- 終止 tmux 階段
- 移除 worktree
- 更新註冊
-
報告:
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 # 或檢查 cwd 是否在 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
錯誤處理
| 錯誤 | 解決方式 |
|---|---|
| Worktree 已存在 | 提供選項:附加、重新建立或中止 |
| PR 找不到 | 驗證 URL/編號、檢查權限 |
| 無 tmux | 發出警告並跳過階段建立 |
| 無 gh CLI | 回報錯誤並提供安裝說明 |
Teleport 指令
omc teleport 指令提供了一個輕量級的替代方案。它會建立 git worktree,但不會管理 tmux 階段作業 — 非常適合快速、隔離的開發。
用法
# 為 issue 或 PR 建立 worktree
omc teleport #123
omc teleport owner/repo#123
omc teleport https://github.com/owner/repo/issues/42
# 為功能建立 worktree
omc teleport my-feature
# 列出現有 worktree
omc teleport list
# 移除 worktree
omc teleport remove issue/my-repo-123
omc teleport remove --force feat/my-repo-my-feature
選項
| 旗標 | 說明 | 預設值 |
|---|---|---|
--worktree-root | 自訂 worktree 根目錄 | ~/.psm/worktrees |
--base <branch> | 從此分支建立 worktree | 從 property 或 default_base 推斷 |
--no-checkout | 僅建立目錄,不簽出檔案 | false |
--force | 即使 worktree 存在也強制執行 | false |
--verbose | 詳細輸出 | false |
--dry-run | 模擬但不實際執行 | false |
Teleport 與完整 PSM 階段的比較
| 功能 | Teleport | 完整階段 |
|---|---|---|
| 建立 git worktree | ✅ | ✅ |
| 管理 tmux 階段 | ❌ | ✅ |
| 自動啟動 Claude Code | ❌ | ✅ |
階段註冊 (sessions.json) | ❌ | ✅ |
| 自動清理 | ❌ | ✅ |
| 使用案例 | 快速、隔離的開發 | 長時間執行、多工開發 |
何時使用 Teleport 與完整階段:
- Teleport:當你想要一個乾淨的隔離目錄來快速修復、嘗試或檢查時,特別是在不想啟動 tmux 或 Claude Code 的情況下。
- 完整階段:當你正在進行一個長時間執行的任務,需要 tmux 階段管理、自動 Claude Code 啟動,以及能夠從 Claude Code 內部附加/分離階段時。
Teleport 實作
teleport 指令是 oh-my-claudecode 內建的 zsh 函式,而非由 Claude Code 執行。它直接實作於 shell 層級,提供了無需 Claude Code 即可建立 worktree 的快速方法。
# 內部實作(簡化)
omc_teleport() {
local ref="$1"
local action="create"
case "$ref" in
list)
ls -1 ~/.psm/worktrees/*/ 2>/dev/null || echo "No worktrees found."
;;
remove)
# 使用 git worktree remove
;;
*)
# 解析參考,建立分支,git worktree add
;;
esac
}