| name | psm |
| description | Project Session Manager — isolated dev environments with git worktrees and tmux |
| argument-hint | review <ref> | fix <ref> | feature <name> | list | attach <session> | kill <session> | cleanup | status |
| aliases | ["session","worktree-session"] |
| disable-model-invocation | true |
Project Session Manager (/psm)
Manage isolated development sessions with git worktrees and tmux.
All PSM state lives under ~/.maestro-psm/.
User Command
$ARGUMENTS
Supported Subcommands
| Pattern | Action |
|---|
review <ref> | Create PR review session |
fix <ref> | Create issue-fix session |
feature <name> | Create feature session from main |
list | List sessions from state + tmux |
attach <session> | Show attach command for a session |
kill <session> | Kill tmux + remove worktree + delete state |
cleanup | Auto-clean merged PR / closed issue sessions |
status | Show current session context |
Initialization (Always Run First)
STATE_DIR="$HOME/.maestro-psm"
WORKTREE_ROOT="$STATE_DIR/worktrees"
LOG_DIR="$STATE_DIR/logs"
SESSIONS_FILE="$STATE_DIR/sessions.json"
mkdir -p "$WORKTREE_ROOT" "$LOG_DIR"
if [[ ! -f "$SESSIONS_FILE" ]]; then
cat > "$SESSIONS_FILE" <<'EOF'
{"version": 1, "sessions": {}}
EOF
fi
Rules:
- Use
$HOME (expanded ~) for filesystem operations.
- Create parent directories before writing files or creating worktrees.
- Fail fast with clear error messages when prerequisites are missing.
Shared Parsing Rules
GitHub Reference Formats
Support these forms for review and fix:
#123 → current repo
owner/repo#123 → explicit repo
https://github.com/owner/repo/pull/123 → PR URL
https://github.com/owner/repo/issues/123 → issue URL
Parse Outcomes
Normalize parsed data into:
repo: owner/repo
number: numeric ref (123)
kind: pull or issue
Validation
review <ref> accepts PR formats only (#, owner/repo#, or /pull/).
fix <ref> accepts issue formats only (#, owner/repo#, or /issues/).
- If
#123 is used, resolve repo from current directory with gh repo view --json nameWithOwner.
- If parsing fails, stop and show accepted examples.
Shared Session Model
Use this consistent session metadata model in ~/.maestro-psm/sessions.json:
{
"version": 1,
"sessions": {
"project:pr-123": {
"id": "project:pr-123",
"type": "review",
"repo": "owner/repo",
"number": 123,
"ref": "#123",
"title": "Add webhook support",
"branch": "pr-123-review",
"base": "main",
"worktree": "/Users/me/.maestro-psm/worktrees/project/pr-123",
"tmux": "maestro:project:pr-123",
"createdAt": "2026-02-09T00:00:00Z",
"url": "https://github.com/owner/repo/pull/123"
}
}
}
Session naming:
- Session ID:
<alias>:<ref-id>
- Tmux session:
maestro:<session-id>
- Alias default: repo name (from
owner/repo)
Subcommand Workflows
1) review <ref>
Goal: Create a PR review workspace from the PR head branch.
- Parse
<ref> into repo + pr_number.
- Fetch PR metadata:
gh pr view <num> --repo <repo> --json number,title,headRefName,baseRefName,url
- Resolve local repo root:
- Prefer current git repo when remotes match
<repo>.
- Otherwise use a dedicated local clone under
~/.maestro-psm/repos/<owner>__<repo>.
- Create/update review branch + worktree:
git -C <repo_root> fetch origin pull/<num>/head:pr-<num>-review
git -C <repo_root> worktree add <worktree_path> pr-<num>-review
where worktree_path=~/.maestro-psm/worktrees/<alias>/pr-<num>.
- Create tmux session in background:
tmux new-session -d -s maestro:<alias>:pr-<num> -c <worktree_path>
- Update
~/.maestro-psm/sessions.json with session metadata.
- Print Session Ready report including attach command.
2) fix <ref>
Goal: Create issue-fix branch from main, plus isolated worktree + tmux.
- Parse
<ref> into repo + issue_number.
- Fetch issue metadata via
gh issue view.
- Create branch from
main:
git -C <repo_root> fetch origin main
git -C <repo_root> worktree add -b fix/<num>-<slug> <worktree_path> origin/main
where worktree_path=~/.maestro-psm/worktrees/<alias>/issue-<num>.
- Create tmux session:
tmux new-session -d -s maestro:<alias>:issue-<num> -c <worktree_path>
- Update sessions.json.
- Print Session Ready report with attach command.
3) feature <name>
Goal: Create feature branch from main in an isolated session.
- Resolve current repo (
gh repo view --json nameWithOwner).
- Slugify
<name> for branch-safe naming.
- Create branch + worktree:
git -C <repo_root> fetch origin main
git -C <repo_root> worktree add -b feature/<slug> <worktree_path> origin/main
where worktree_path=~/.maestro-psm/worktrees/<alias>/feat-<slug>.
- Create tmux session:
tmux new-session -d -s maestro:<alias>:feat-<slug> -c <worktree_path>
- Update sessions.json.
- Print Session Ready report with attach command.
4) list
Goal: Show persisted sessions and whether tmux is alive.
- Read
~/.maestro-psm/sessions.json.
- Get live tmux sessions:
tmux list-sessions -F "#{session_name}" 2>/dev/null
- Cross-reference each session’s
tmux value.
- Display table:
- Session ID
- Type
- Ref
- Branch
- Status (
active if tmux exists, otherwise dead)
5) attach <session>
Goal: Provide exact attach command.
- Build tmux name:
maestro:<session>.
- Verify session exists:
tmux has-session -t maestro:<session>
- If found, print:
tmux attach -t maestro:<session>
- If missing, show clear error and suggest
/psm list.
6) kill <session>
Goal: Fully remove one session.
- Resolve session record from sessions.json.
- Kill tmux session:
tmux kill-session -t maestro:<session>
- Remove worktree:
git -C <repo_root> worktree remove <worktree_path> --force
- Delete session from sessions.json.
- Report removed tmux/worktree/state entries.
7) cleanup
Goal: Auto-clean completed review/fix sessions.
For each session in sessions.json:
-
If type=review, check merge status:
gh pr view <num> --repo <repo> --json merged
If merged, remove session (same steps as kill).
-
If type=fix, check close status:
gh issue view <num> --repo <repo> --json closed
If closed, remove session (same steps as kill).
-
If type=feature, skip automatic cleanup unless explicitly requested.
Output summary:
- Cleaned sessions
- Skipped sessions
- Any failures with reason
8) status
Goal: Show session context for current environment.
Detection order:
- If inside tmux, read current session name (
tmux display-message -p '#S').
- Else match current working directory against stored worktree paths in sessions.json.
- If a match is found, print full session details:
- ID
- Type
- Repo/Ref
- Branch
- Worktree
- Tmux name
- Attach command
- If no match, report: "Not currently in a managed PSM session."
Session Report Format
Use this exact structure when creating a session:
Session Ready!
ID: project:pr-123
Type: review
PR: #123 - Add webhook support
Worktree: ~/.maestro-psm/worktrees/project/pr-123
Tmux: maestro:project:pr-123
Commands:
Attach: tmux attach -t maestro:project:pr-123
Kill: /psm kill project:pr-123
Cleanup: /psm cleanup
For issue/fix or feature sessions, replace the PR line with the relevant reference label.
Important Notes
- Use
gh CLI for all GitHub operations (auth + repo context).
- Use
~/.maestro-psm/ for all state (never ~/.psm/, never .maestro/).
- Expand
~ to $HOME in real command execution.
- Create parent directories before filesystem operations.
- Tmux sessions launch in background; user remains in current terminal.
- Always tell the user how to attach (
tmux attach -t maestro:<session>).
- Use clear, actionable error messages (invalid ref, missing gh auth, missing tmux session, git worktree errors).