Claude
Skills
Sign in
Back

project-session-manager

Included with Lifetime
$97 forever

Worktree-first dev environment manager for issues, PRs, and features with optional tmux sessions

General

What this skill does


# Project Session Manager (PSM) Skill

`psm` is the compatibility alias for this canonical skill entrypoint.

> **Quick Start (worktree-first):** Start with `omc teleport` when you want an isolated issue/PR/feature worktree before adding any tmux/session orchestration:
> ```bash
> omc teleport #123          # Create worktree for issue/PR
> omc teleport my-feature    # Create worktree for feature
> omc teleport list          # List worktrees
> ```
> See [Teleport Command](#teleport-command) below for details.

Automate isolated development environments using git worktrees and tmux sessions with Claude Code. Enables parallel work across multiple tasks, projects, and repositories.

Canonical slash command: `/oh-my-claudecode:project-session-manager` (alias: `/oh-my-claudecode:psm`).

## Commands

| Command | Description | Example |
|---------|-------------|---------|
| `review <ref>` | PR review session | `/psm review omc#123` |
| `fix <ref>` | Issue fix session | `/psm fix omc#42` |
| `feature <proj> <name>` | Feature development | `/psm feature omc add-webhooks` |
| `list [project]` | List active sessions | `/psm list` |
| `attach <session>` | Attach to session | `/psm attach omc:pr-123` |
| `kill <session>` | Kill session | `/psm kill omc:pr-123` |
| `cleanup` | Clean merged/closed | `/psm cleanup` |
| `status` | Current session info | `/psm status` |

## Project References

Supported formats:
- **Alias**: `omc#123` (requires `~/.psm/projects.json`)
- **Full**: `owner/repo#123`
- **URL**: `https://github.com/owner/repo/pull/123`
- **Current**: `#123` (uses current directory's repo)

## Configuration

### Project Aliases (`~/.psm/projects.json`)

```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
  }
}
```

## Providers

PSM supports multiple issue tracking providers:

| Provider | CLI Required | Reference Formats | Commands |
|----------|--------------|-------------------|----------|
| GitHub (default) | `gh` | `owner/repo#123`, `alias#123`, GitHub URLs | review, fix, feature |
| Jira | `jira` | `PROJ-123` (if PROJ configured), `alias#123` | fix, feature |

### Jira Configuration

To use Jira, add an alias with `jira_project` and `provider: "jira"`:

```json
{
  "aliases": {
    "mywork": {
      "jira_project": "MYPROJ",
      "repo": "mycompany/my-project",
      "local": "~/Workspace/my-project",
      "default_base": "develop",
      "provider": "jira"
    }
  }
}
```

**Important:** The `repo` field is still required for cloning the git repository. Jira tracks issues, but you work in a git repo.

For non-GitHub repos, use `clone_url` instead:
```json
{
  "aliases": {
    "private": {
      "jira_project": "PRIV",
      "clone_url": "[email protected]:team/repo.git",
      "local": "~/Workspace/repo",
      "provider": "jira"
    }
  }
}
```

### Jira Reference Detection

PSM only recognizes `PROJ-123` format as Jira when `PROJ` is explicitly configured as a `jira_project` in your aliases. This prevents false positives from branch names like `FIX-123`.

### Jira Examples

```bash
# 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 Setup

Install the Jira CLI:
```bash
# macOS
brew install ankitpokhrel/jira-cli/jira-cli

# Linux
# See: https://github.com/ankitpokhrel/jira-cli#installation

# Configure (interactive)
jira init
```

The Jira CLI handles authentication separately from PSM.

## Directory Structure

```
~/.psm/
├── projects.json       # Project aliases
├── sessions.json       # Active session registry
└── worktrees/          # Worktree storage
    └── <project>/
        └── <type>-<id>/
```

## Session Naming

| Type | Tmux Session | Worktree Dir |
|------|--------------|--------------|
| PR Review | `psm:omc:pr-123` | `~/.psm/worktrees/omc/pr-123` |
| Issue Fix | `psm:omc:issue-42` | `~/.psm/worktrees/omc/issue-42` |
| Feature | `psm:omc:feat-auth` | `~/.psm/worktrees/omc/feat-auth` |

---

## Implementation Protocol

When the user invokes a PSM command, follow this protocol:

### Parse Arguments

Parse `{{ARGUMENTS}}` to determine:
1. **Subcommand**: review, fix, feature, list, attach, kill, cleanup, status
2. **Reference**: project#number, URL, or session ID
3. **Options**: --branch, --base, --no-claude, --no-tmux, etc.

### Subcommand: `review <ref>`

**Purpose**: Create PR review session

**Steps**:

1. **Resolve reference**:
   ```bash
   # 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. **Fetch PR info**:
   ```bash
   gh pr view <pr_number> --repo <repo> --json number,title,author,headRefName,baseRefName,body,files,url
   ```

3. **Ensure local repo exists**:
   ```bash
   # If local path doesn't exist, clone
   if [[ ! -d "$local_path" ]]; then
     git clone "https://github.com/$repo.git" "$local_path"
   fi
   ```

4. **Create worktree**:
   ```bash
   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. **Create session metadata**:
   ```bash
   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. **Update sessions registry**:
   ```bash
   # Add to ~/.psm/sessions.json
   ```

7. **Create tmux session**:
   ```bash
   tmux new-session -d -s "psm:$project_alias:pr-$pr_number" -c "$worktree_path"
   ```

8. **Launch Claude Code** (unless --no-claude):
   ```bash
   # --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. **Output session info**:
   ```
   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
   ```

### Subcommand: `fix <ref>`

**Purpose**: Create issue fix session

**Steps**:

1. **Resolve reference** (same as review)

2. **Fetch issue info**:
   ```bash
   gh issue view <issue_number> --repo <repo> --json number,title,body,labels,url
   ```

3. **Create feature branch**:
   ```bash
   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. **Create worktree**:
   ```bash
   worktree_path="$HOME/.psm/wo

Related in General