claudecode-omc 5.4.0 → 5.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/.local/guidelines/CLAUDE.md +31 -0
  2. package/README.md +57 -1
  3. package/bundled/manifest.json +2 -2
  4. package/bundled/upstream/oh-my-claudecode/agents/analyst.md +1 -1
  5. package/bundled/upstream/oh-my-claudecode/agents/architect.md +1 -1
  6. package/bundled/upstream/oh-my-claudecode/agents/code-reviewer.md +1 -1
  7. package/bundled/upstream/oh-my-claudecode/agents/code-simplifier.md +1 -1
  8. package/bundled/upstream/oh-my-claudecode/agents/critic.md +1 -1
  9. package/bundled/upstream/oh-my-claudecode/agents/debugger.md +1 -1
  10. package/bundled/upstream/oh-my-claudecode/agents/designer.md +1 -1
  11. package/bundled/upstream/oh-my-claudecode/agents/document-specialist.md +1 -1
  12. package/bundled/upstream/oh-my-claudecode/agents/executor.md +1 -1
  13. package/bundled/upstream/oh-my-claudecode/agents/explore.md +1 -1
  14. package/bundled/upstream/oh-my-claudecode/agents/git-master.md +3 -3
  15. package/bundled/upstream/oh-my-claudecode/agents/planner.md +1 -1
  16. package/bundled/upstream/oh-my-claudecode/agents/qa-tester.md +1 -1
  17. package/bundled/upstream/oh-my-claudecode/agents/scientist.md +1 -1
  18. package/bundled/upstream/oh-my-claudecode/agents/security-reviewer.md +1 -1
  19. package/bundled/upstream/oh-my-claudecode/agents/test-engineer.md +1 -75
  20. package/bundled/upstream/oh-my-claudecode/agents/tracer.md +1 -1
  21. package/bundled/upstream/oh-my-claudecode/agents/verifier.md +1 -1
  22. package/bundled/upstream/oh-my-claudecode/agents/writer.md +1 -1
  23. package/bundled/upstream/oh-my-claudecode/hooks/hooks.json +21 -1
  24. package/bundled/upstream/oh-my-claudecode/skills/AGENTS.md +200 -0
  25. package/bundled/upstream/oh-my-claudecode/skills/autopilot/SKILL.md +17 -10
  26. package/bundled/upstream/oh-my-claudecode/skills/autoresearch/SKILL.md +90 -0
  27. package/bundled/upstream/oh-my-claudecode/skills/cancel/SKILL.md +15 -6
  28. package/bundled/upstream/oh-my-claudecode/skills/configure-notifications/SKILL.md +12 -12
  29. package/bundled/upstream/oh-my-claudecode/skills/debug/SKILL.md +35 -0
  30. package/bundled/upstream/oh-my-claudecode/skills/deep-dive/SKILL.md +4 -0
  31. package/bundled/upstream/oh-my-claudecode/skills/deep-interview/SKILL.md +23 -18
  32. package/bundled/upstream/oh-my-claudecode/skills/hud/SKILL.md +23 -101
  33. package/bundled/upstream/oh-my-claudecode/skills/learner/SKILL.md +27 -2
  34. package/bundled/upstream/oh-my-claudecode/skills/mcp-setup/SKILL.md +67 -8
  35. package/bundled/upstream/oh-my-claudecode/skills/omc-doctor/SKILL.md +32 -47
  36. package/bundled/upstream/oh-my-claudecode/skills/omc-setup/SKILL.md +4 -2
  37. package/bundled/upstream/oh-my-claudecode/skills/omc-setup/phases/01-install-claude-md.md +15 -4
  38. package/bundled/upstream/oh-my-claudecode/skills/omc-setup/phases/02-configure.md +9 -9
  39. package/bundled/upstream/oh-my-claudecode/skills/omc-setup/phases/03-integrations.md +13 -13
  40. package/bundled/upstream/oh-my-claudecode/skills/omc-setup/phases/04-welcome.md +3 -3
  41. package/bundled/upstream/oh-my-claudecode/skills/omc-teams/SKILL.md +28 -0
  42. package/bundled/upstream/oh-my-claudecode/skills/plan/SKILL.md +1 -0
  43. package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/SKILL.md +25 -5
  44. package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/config.sh +2 -15
  45. package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/providers/github.sh +1 -1
  46. package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/session.sh +2 -2
  47. package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/tmux.sh +109 -4
  48. package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/worktree.sh +26 -0
  49. package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/psm.sh +46 -5
  50. package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/templates/pr-review.md +5 -2
  51. package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/templates/projects.json +1 -1
  52. package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/tests/test-psm-prompt-injection.sh +336 -0
  53. package/bundled/upstream/oh-my-claudecode/skills/ralph/SKILL.md +18 -9
  54. package/bundled/upstream/oh-my-claudecode/skills/ralplan/SKILL.md +2 -0
  55. package/bundled/upstream/oh-my-claudecode/skills/release/SKILL.md +167 -57
  56. package/bundled/upstream/oh-my-claudecode/skills/remember/SKILL.md +41 -0
  57. package/bundled/upstream/oh-my-claudecode/skills/self-improve/SKILL.md +391 -0
  58. package/bundled/upstream/oh-my-claudecode/skills/self-improve/data_contracts.md +274 -0
  59. package/bundled/upstream/oh-my-claudecode/skills/self-improve/scripts/plot_progress.py +128 -0
  60. package/bundled/upstream/oh-my-claudecode/skills/self-improve/scripts/resolve-paths.mjs +192 -0
  61. package/bundled/upstream/oh-my-claudecode/skills/self-improve/scripts/validate.sh +404 -0
  62. package/bundled/upstream/oh-my-claudecode/skills/self-improve/si-benchmark-builder.md +79 -0
  63. package/bundled/upstream/oh-my-claudecode/skills/self-improve/si-goal-clarifier.md +94 -0
  64. package/bundled/upstream/oh-my-claudecode/skills/self-improve/si-researcher.md +73 -0
  65. package/bundled/upstream/oh-my-claudecode/skills/self-improve/templates/agent-settings.json +14 -0
  66. package/bundled/upstream/oh-my-claudecode/skills/self-improve/templates/goal.md +22 -0
  67. package/bundled/upstream/oh-my-claudecode/skills/self-improve/templates/harness.md +18 -0
  68. package/bundled/upstream/oh-my-claudecode/skills/self-improve/templates/idea.md +5 -0
  69. package/bundled/upstream/oh-my-claudecode/skills/self-improve/templates/settings.json +23 -0
  70. package/bundled/upstream/oh-my-claudecode/skills/skill/SKILL.md +46 -77
  71. package/bundled/upstream/oh-my-claudecode/skills/skillify/SKILL.md +53 -0
  72. package/bundled/upstream/oh-my-claudecode/skills/team/SKILL.md +83 -11
  73. package/bundled/upstream/oh-my-claudecode/skills/trace/SKILL.md +1 -0
  74. package/bundled/upstream/oh-my-claudecode/skills/ultraqa/SKILL.md +1 -0
  75. package/bundled/upstream/oh-my-claudecode/skills/ultrawork/SKILL.md +1 -0
  76. package/bundled/upstream/oh-my-claudecode/skills/verify/SKILL.md +37 -0
  77. package/bundled/upstream/oh-my-claudecode/skills/wiki/SKILL.md +67 -0
  78. package/package.json +3 -1
  79. package/src/cli/artifact.js +47 -0
  80. package/src/cli/doctor.js +6 -1
  81. package/src/cli/guidelines.js +83 -0
  82. package/src/cli/index.js +13 -1
  83. package/src/cli/setup.js +68 -19
  84. package/src/cli/source.js +35 -1
  85. package/src/config/artifact-types.js +12 -2
  86. package/src/config/paths.js +95 -4
  87. package/src/config/sources.js +29 -5
  88. package/src/guidelines/apply.js +152 -0
  89. package/src/guidelines/optimizer.js +325 -0
  90. package/src/merge/claude-md-merger.js +35 -12
  91. package/bundled/upstream/oh-my-claudecode/skills/omc-doctor/skill-debugger.md +0 -101
@@ -5,7 +5,7 @@
5
5
  ## Step 3.1: Verify Plugin Installation
6
6
 
7
7
  ```bash
8
- grep -q "oh-my-claudecode" ~/.claude/settings.json && echo "Plugin verified" || echo "Plugin NOT found - run: claude /install-plugin oh-my-claudecode"
8
+ grep -q "oh-my-claudecode" "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/settings.json" && echo "Plugin verified" || echo "Plugin NOT found - run: claude /install-plugin oh-my-claudecode"
9
9
  ```
10
10
 
11
11
  ## Step 3.2: Offer MCP Server Configuration
@@ -44,7 +44,7 @@ Use AskUserQuestion:
44
44
  First, read the current settings.json:
45
45
 
46
46
  ```bash
47
- SETTINGS_FILE="$HOME/.claude/settings.json"
47
+ SETTINGS_FILE="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/settings.json"
48
48
 
49
49
  if [ -f "$SETTINGS_FILE" ]; then
50
50
  echo "Current settings.json found"
@@ -54,12 +54,12 @@ else
54
54
  fi
55
55
  ```
56
56
 
57
- Then use the Read tool to read `~/.claude/settings.json` (if it exists). Use the Edit tool to merge the teams configuration while preserving ALL existing settings.
57
+ Then use the Read tool to read `${CLAUDE_CONFIG_DIR:-~/.claude}/settings.json` (if it exists). Use the Edit tool to merge the teams configuration while preserving ALL existing settings.
58
58
 
59
59
  Use jq to safely merge without overwriting existing settings:
60
60
 
61
61
  ```bash
62
- SETTINGS_FILE="$HOME/.claude/settings.json"
62
+ SETTINGS_FILE="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/settings.json"
63
63
 
64
64
  if [ -f "$SETTINGS_FILE" ]; then
65
65
  TEMP_FILE=$(mktemp)
@@ -94,7 +94,7 @@ Use AskUserQuestion:
94
94
  If user chooses anything other than "Auto", add `teammateMode` to settings.json:
95
95
 
96
96
  ```bash
97
- SETTINGS_FILE="$HOME/.claude/settings.json"
97
+ SETTINGS_FILE="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/settings.json"
98
98
 
99
99
  # TEAMMATE_MODE is "in-process" or "tmux" based on user choice
100
100
  # Skip this if user chose "Auto" (that's the default)
@@ -113,17 +113,17 @@ Use AskUserQuestion with multiple questions:
113
113
  2. **5 agents (maximum)** - Maximum parallelism for large tasks
114
114
  3. **2 agents** - Conservative, for smaller projects
115
115
 
116
- **Question 2:** "Which agent type should teammates use by default?"
116
+ **Question 2:** "Which CLI provider should teammates use by default?"
117
117
 
118
118
  **Options:**
119
- 1. **executor (Recommended)** - General-purpose code implementation agent
120
- 2. **debugger** - Specialized for build/type error fixing and debugging
121
- 3. **designer** - Specialized for UI/frontend work
119
+ 1. **claude (Recommended)** - Default provider with the widest compatibility
120
+ 2. **codex** - Use Codex CLI workers by default when installed
121
+ 3. **gemini** - Use Gemini CLI workers by default when installed
122
122
 
123
123
  Store the team configuration in `~/.claude/.omc-config.json`:
124
124
 
125
125
  ```bash
126
- CONFIG_FILE="$HOME/.claude/.omc-config.json"
126
+ CONFIG_FILE="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/.omc-config.json"
127
127
  mkdir -p "$(dirname "$CONFIG_FILE")"
128
128
 
129
129
  if [ -f "$CONFIG_FILE" ]; then
@@ -136,11 +136,11 @@ fi
136
136
  echo "$EXISTING" | jq \
137
137
  --argjson maxAgents MAX_AGENTS \
138
138
  --arg agentType "AGENT_TYPE" \
139
- '. + {team: {maxAgents: $maxAgents, defaultAgentType: $agentType, monitorIntervalMs: 30000, shutdownTimeoutMs: 15000}}' > "$CONFIG_FILE"
139
+ '. + {team: {ops: {maxAgents: $maxAgents, defaultAgentType: $agentType, monitorIntervalMs: 30000, shutdownTimeoutMs: 15000}}}' > "$CONFIG_FILE"
140
140
 
141
141
  echo "Team configuration saved:"
142
142
  echo " Max agents: MAX_AGENTS"
143
- echo " Default agent: AGENT_TYPE"
143
+ echo " Default provider: AGENT_TYPE"
144
144
  echo " Model: teammates inherit your session model"
145
145
  ```
146
146
 
@@ -151,7 +151,7 @@ echo " Model: teammates inherit your session model"
151
151
  After all modifications, verify settings.json is valid JSON and contains the expected keys:
152
152
 
153
153
  ```bash
154
- SETTINGS_FILE="$HOME/.claude/settings.json"
154
+ SETTINGS_FILE="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/settings.json"
155
155
 
156
156
  if jq empty "$SETTINGS_FILE" 2>/dev/null; then
157
157
  echo "settings.json: valid JSON"
@@ -5,7 +5,7 @@
5
5
  Check if user has existing 2.x configuration:
6
6
 
7
7
  ```bash
8
- ls ~/.claude/commands/ralph-loop.md 2>/dev/null || ls ~/.claude/commands/ultrawork.md 2>/dev/null
8
+ ls "${CLAUDE_CONFIG_DIR:-$HOME/.claude}"/commands/ralph-loop.md 2>/dev/null || ls "${CLAUDE_CONFIG_DIR:-$HOME/.claude}"/commands/ultrawork.md 2>/dev/null
9
9
  ```
10
10
 
11
11
  If found, this is an upgrade from 2.x. Set `IS_UPGRADE=true`.
@@ -178,8 +178,8 @@ Get the current OMC version and mark setup complete:
178
178
  OMC_VERSION=""
179
179
  if [ -f ".claude/CLAUDE.md" ]; then
180
180
  OMC_VERSION=$(grep -m1 'OMC:VERSION:' .claude/CLAUDE.md 2>/dev/null | sed -E 's/.*OMC:VERSION:([^ ]+).*/\1/' || true)
181
- elif [ -f "$HOME/.claude/CLAUDE.md" ]; then
182
- OMC_VERSION=$(grep -m1 'OMC:VERSION:' "$HOME/.claude/CLAUDE.md" 2>/dev/null | sed -E 's/.*OMC:VERSION:([^ ]+).*/\1/' || true)
181
+ elif [ -f "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/CLAUDE.md" ]; then
182
+ OMC_VERSION=$(grep -m1 'OMC:VERSION:' "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/CLAUDE.md" 2>/dev/null | sed -E 's/.*OMC:VERSION:([^ ]+).*/\1/' || true)
183
183
  fi
184
184
  if [ -z "$OMC_VERSION" ]; then
185
185
  OMC_VERSION=$(omc --version 2>/dev/null | head -1 || true)
@@ -79,6 +79,27 @@ Validate before decomposing or running anything:
79
79
 
80
80
  Break work into N independent subtasks (file- or concern-scoped) to avoid write conflicts.
81
81
 
82
+ ### Phase 2.5: Resolve workspace root for multi-repo plans
83
+
84
+ `omc team` launches all workers with one shared working directory. For single-repo
85
+ tasks, the current repo is usually correct. For multi-repo tasks, especially when a
86
+ plan lives in one repo but the implementation touches sibling repos, resolve the
87
+ working directory before launch:
88
+
89
+ - If the task references a plan artifact under one repo (for example
90
+ `tool/.omc/plans/task-1200-gwd-gifs.md`) and target paths in sibling repos
91
+ (for example `api/` and `admin/`), choose the shared workspace root that contains
92
+ all participating repos (for example the parent `inter/` directory).
93
+ - Use an **absolute plan path** in the task text so the workers can still find the
94
+ plan after `--cwd` changes the launch directory.
95
+ - Include the explicit repo paths or repo names in the task text and subtasks.
96
+ - Do not anchor the launch cwd to only the repo containing `.omc/plans/...` when
97
+ target repos are siblings; that strands `codex`, `claude`, and `gemini` workers in
98
+ the plan repo instead of the implementation workspace.
99
+ - If no safe shared workspace root can be identified, do not launch `/omc-teams`.
100
+ Report the single-cwd constraint and ask for, or derive from evidence, the intended
101
+ workspace root.
102
+
82
103
  ### Phase 3: Start CLI team runtime
83
104
 
84
105
  Activate mode state (recommended):
@@ -93,6 +114,13 @@ Start workers via CLI:
93
114
  omc team <N>:<claude|codex|gemini> "<task>"
94
115
  ```
95
116
 
117
+ For the multi-repo case resolved in Phase 2.5, launch from the shared workspace root
118
+ with the existing `--cwd` contract and keep the plan reference absolute:
119
+
120
+ ```bash
121
+ omc team <N>:<claude|codex|gemini> "<task with absolute plan path and explicit repo paths>" --cwd <workspace-root>
122
+ ```
123
+
96
124
  Team name defaults to a slug from the task text (example: `review-auth-flow`).
97
125
 
98
126
  After launch, verify the command actually executed instead of assuming Enter fired. Check pane output and confirm the command or worker bootstrap text appears in pane history:
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: omc-plan
3
3
  description: Strategic planning with optional interview workflow
4
+ argument-hint: "[--direct|--consensus|--review] [--interactive] [--deliberate] <task description>"
4
5
  pipeline: [deep-interview, omc-plan, autopilot]
5
6
  next-skill: autopilot
6
7
  handoff: .omc/plans/ralplan-*.md
@@ -50,7 +50,7 @@ Supported formats:
50
50
  {
51
51
  "aliases": {
52
52
  "omc": {
53
- "repo": "owner/oh-my-claudecode",
53
+ "repo": "Yeachan-Heo/oh-my-claudecode",
54
54
  "local": "~/Workspace/oh-my-claudecode",
55
55
  "default_base": "main"
56
56
  }
@@ -250,7 +250,15 @@ Parse `{{ARGUMENTS}}` to determine:
250
250
 
251
251
  8. **Launch Claude Code** (unless --no-claude):
252
252
  ```bash
253
- tmux send-keys -t "psm:$project_alias:pr-$pr_number" "claude" Enter
253
+ # --dangerously-skip-permissions prevents the "Do you trust this directory?" prompt
254
+ # and repeated tool-approval prompts from stalling the session (issue #2508).
255
+ tmux send-keys -t "psm:$project_alias:pr-$pr_number" "claude --dangerously-skip-permissions" Enter
256
+
257
+ # After claude boots (PSM_CLAUDE_STARTUP_DELAY, default 5s), deliver the task.
258
+ # Use -l (literal) so special characters are not misinterpreted by tmux.
259
+ sleep "${PSM_CLAUDE_STARTUP_DELAY:-5}"
260
+ tmux send-keys -t "psm:$project_alias:pr-$pr_number" -l \
261
+ "Review PR #$pr_number: \"$pr_title\" by @$pr_author ($head_branch → $base_branch). URL: $pr_url." Enter
254
262
  ```
255
263
 
256
264
  9. **Output session info**:
@@ -293,7 +301,14 @@ Parse `{{ARGUMENTS}}` to determine:
293
301
 
294
302
  5. **Create session metadata** (similar to review, type="fix")
295
303
 
296
- 6. **Update registry, create tmux, launch claude** (same as review)
304
+ 6. **Update registry, create tmux, launch claude**:
305
+ Same as review, but pass issue context as the initial task prompt:
306
+ ```bash
307
+ tmux send-keys -t "psm:$project_alias:issue-$issue_number" "claude --dangerously-skip-permissions" Enter
308
+ # After claude boots, deliver the task (see PSM_CLAUDE_STARTUP_DELAY):
309
+ tmux send-keys -t "psm:$project_alias:issue-$issue_number" -l \
310
+ "Fix issue #$issue_number: \"$issue_title\". URL: $issue_url. Branch: $branch_name." Enter
311
+ ```
297
312
 
298
313
  ### Subcommand: `feature <project> <name>`
299
314
 
@@ -317,7 +332,12 @@ Parse `{{ARGUMENTS}}` to determine:
317
332
  git worktree add "$worktree_path" "$branch_name"
318
333
  ```
319
334
 
320
- 4. **Create session, tmux, launch claude** (same pattern)
335
+ 4. **Create session, tmux, launch claude** with feature context as initial prompt:
336
+ ```bash
337
+ tmux send-keys -t "psm:$project_alias:feat-$feature_name" "claude --dangerously-skip-permissions" Enter
338
+ tmux send-keys -t "psm:$project_alias:feat-$feature_name" -l \
339
+ "Implement feature \"$feature_name\" for project $project. Branch: $branch_name." Enter
340
+ ```
321
341
 
322
342
  ### Subcommand: `list [project]`
323
343
 
@@ -544,7 +564,7 @@ if [[ ! -f ~/.psm/projects.json ]]; then
544
564
  {
545
565
  "aliases": {
546
566
  "omc": {
547
- "repo": "owner/oh-my-claudecode",
567
+ "repo": "Yeachan-Heo/oh-my-claudecode",
548
568
  "local": "~/Workspace/oh-my-claudecode",
549
569
  "default_base": "main"
550
570
  }
@@ -13,24 +13,11 @@ psm_init() {
13
13
 
14
14
  # Create default projects.json if not exists
15
15
  if [[ ! -f "$PSM_PROJECTS" ]]; then
16
- local default_repo="${OMC_REPO:-}"
17
- local cfg_file="$HOME/.claude/.omc-config.json"
18
-
19
- if [[ -z "$default_repo" && -f "$cfg_file" ]]; then
20
- default_repo=$(jq -r '.updateRepository // empty' "$cfg_file" 2>/dev/null)
21
- fi
22
- if [[ -z "$default_repo" && -n "${CLAUDE_PLUGIN_ROOT:-}" && -d "$CLAUDE_PLUGIN_ROOT/.git" ]]; then
23
- default_repo=$(git -C "$CLAUDE_PLUGIN_ROOT" remote get-url origin 2>/dev/null | sed -E 's#^git@github.com:##; s#^https://github.com/##; s#\\.git$##')
24
- fi
25
- if [[ -z "$default_repo" ]]; then
26
- default_repo="Yeachan-Heo/oh-my-claudecode"
27
- fi
28
-
29
- cat > "$PSM_PROJECTS" << EOF
16
+ cat > "$PSM_PROJECTS" << 'EOF'
30
17
  {
31
18
  "aliases": {
32
19
  "omc": {
33
- "repo": "$default_repo",
20
+ "repo": "Yeachan-Heo/oh-my-claudecode",
34
21
  "local": "~/Workspace/oh-my-claudecode",
35
22
  "default_base": "main"
36
23
  }
@@ -14,7 +14,7 @@ provider_github_detect_ref() {
14
14
  provider_github_fetch_pr() {
15
15
  local pr_number="$1"
16
16
  local repo="$2"
17
- gh pr view "$pr_number" --repo "$repo" --json number,title,author,headRefName,baseRefName,body,url 2>/dev/null
17
+ gh pr view "$pr_number" --repo "$repo" --json number,title,author,headRefName,baseRefName,body,files,url 2>/dev/null
18
18
  }
19
19
 
20
20
  provider_github_fetch_issue() {
@@ -161,9 +161,9 @@ psm_read_session_metadata() {
161
161
 
162
162
  # Get all session IDs for cleanup check
163
163
  psm_get_review_sessions() {
164
- jq -r '.sessions | to_entries[] | select(.value.type == "review") | "\(.value.id)|\(.value.metadata.pr_number // empty)|\(.value.project)"' "$PSM_SESSIONS"
164
+ jq -r '.sessions | to_entries[] | select(.value.type == "review" and (.value.state // "active") == "active") | "\(.value.id)|\(.value.metadata.pr_number // empty)|\(.value.project)"' "$PSM_SESSIONS"
165
165
  }
166
166
 
167
167
  psm_get_fix_sessions() {
168
- jq -r '.sessions | to_entries[] | select(.value.type == "fix") | "\(.value.id)|\(.value.metadata.issue_number // empty)|\(.value.project)"' "$PSM_SESSIONS"
168
+ jq -r '.sessions | to_entries[] | select(.value.type == "fix" and (.value.state // "active") == "active") | "\(.value.id)|\(.value.metadata.issue_number // empty)|\(.value.project)"' "$PSM_SESSIONS"
169
169
  }
@@ -33,23 +33,128 @@ psm_create_tmux_session() {
33
33
  return 0
34
34
  }
35
35
 
36
- # Launch Claude Code in tmux session
37
- # Usage: psm_launch_claude <session_name>
36
+ # Launch Claude Code in tmux session, optionally injecting either a context-file
37
+ # trigger prompt or a literal initial prompt.
38
+ # Usage: psm_launch_claude <session_name> [initial_context]
39
+ # initial_context may be either:
40
+ # - a path relative to the worktree root (e.g. .psm/review.md), or
41
+ # - a literal prompt string to send after Claude boots.
42
+ #
43
+ # Passes --dangerously-skip-permissions so the session does not stall on
44
+ # directory-trust or repeated tool-approval prompts (issue #2508).
45
+ # Set PSM_CLAUDE_STARTUP_DELAY (default: 5s) to tune literal-prompt delivery.
38
46
  psm_launch_claude() {
39
47
  local session_name="$1"
48
+ local initial_context="${2:-}"
40
49
 
41
50
  if ! tmux has-session -t "$session_name" 2>/dev/null; then
42
51
  echo "error|Session not found: $session_name"
43
52
  return 1
44
53
  fi
45
54
 
46
- # Send claude command to the session
47
- tmux send-keys -t "$session_name" "claude" Enter
55
+ # --dangerously-skip-permissions bypasses both the directory-trust prompt and
56
+ # every per-tool approval prompt. Without this flag, unattended PSM sessions
57
+ # can block indefinitely on the first tool call (issue #2508).
58
+ tmux send-keys -t "$session_name" "claude --dangerously-skip-permissions" Enter
59
+
60
+ if [[ -n "$initial_context" ]]; then
61
+ local session_path=""
62
+ session_path=$(tmux display-message -p -t "$session_name" '#{pane_current_path}' 2>/dev/null || true)
63
+
64
+ # If the second arg resolves to a file in the worktree, preserve the
65
+ # existing context-file flow. Otherwise treat it as a literal prompt.
66
+ if [[ -n "$session_path" && -f "$session_path/$initial_context" ]]; then
67
+ psm_inject_prompt "$session_name" "$initial_context"
68
+ else
69
+ local startup_delay="${PSM_CLAUDE_STARTUP_DELAY:-5}"
70
+ (
71
+ sleep "$startup_delay"
72
+ tmux send-keys -t "$session_name" -l -- "$initial_context" 2>/dev/null || true
73
+ tmux send-keys -t "$session_name" Enter 2>/dev/null || true
74
+ ) &
75
+ fi
76
+ fi
48
77
 
49
78
  echo "launched|$session_name"
50
79
  return 0
51
80
  }
52
81
 
82
+ # Render a PSM template file by substituting {{KEY}} placeholders.
83
+ # Usage: psm_render_template <template_file> [KEY=VALUE ...]
84
+ # Outputs rendered content to stdout; returns 1 if template not found.
85
+ psm_render_template() {
86
+ local template_file="$1"
87
+ shift
88
+
89
+ if [[ ! -f "$template_file" ]]; then
90
+ echo "error|Template not found: $template_file" >&2
91
+ return 1
92
+ fi
93
+
94
+ local content
95
+ content=$(cat "$template_file")
96
+
97
+ for assignment in "$@"; do
98
+ local key="${assignment%%=*}"
99
+ local value="${assignment#*=}"
100
+ # Bash parameter expansion handles multiline values safely
101
+ content="${content//\{\{${key}\}\}/$value}"
102
+ done
103
+
104
+ printf '%s\n' "$content"
105
+ }
106
+
107
+ # Returns 0 if the captured pane text shows Claude's interactive input prompt.
108
+ # Matches '>' (standard prompt) or '?' (trust prompt) as the sole content of a line.
109
+ # Usage: _psm_pane_has_claude_prompt <pane_text>
110
+ _psm_pane_has_claude_prompt() {
111
+ local pane_text="$1"
112
+ printf '%s' "$pane_text" | grep -qE '^[[:space:]]*(>|\?)[[:space:]]*$'
113
+ }
114
+
115
+ # Poll the tmux pane until Claude's REPL prompt appears.
116
+ # Usage: psm_wait_for_claude_prompt <session_name> [max_seconds]
117
+ # Returns 0 when prompt detected; 1 on timeout.
118
+ psm_wait_for_claude_prompt() {
119
+ local session_name="$1"
120
+ local max_wait="${2:-30}"
121
+ local waited=0
122
+
123
+ while [[ $waited -lt $max_wait ]]; do
124
+ local pane_content
125
+ pane_content=$(tmux capture-pane -t "$session_name" -p 2>/dev/null) || return 1
126
+ if _psm_pane_has_claude_prompt "$pane_content"; then
127
+ return 0
128
+ fi
129
+ sleep 1
130
+ (( waited++ )) || true
131
+ done
132
+
133
+ return 1
134
+ }
135
+
136
+ # Wait for Claude's REPL to be ready then inject a context-file trigger prompt.
137
+ # Non-fatal: warns on timeout but does not fail the session creation.
138
+ # Usage: psm_inject_prompt <session_name> <context_file_relative_path>
139
+ psm_inject_prompt() {
140
+ local session_name="$1"
141
+ local context_file="$2"
142
+
143
+ if ! psm_wait_for_claude_prompt "$session_name"; then
144
+ echo "warn|Timed out waiting for Claude prompt; task context not injected" >&2
145
+ return 0
146
+ fi
147
+
148
+ local trigger="Read ${context_file} for full task context, then begin."
149
+
150
+ # Use literal mode (-l) to prevent tmux from interpreting key names in the text
151
+ tmux send-keys -t "$session_name" -l -- "$trigger"
152
+ sleep 0.15
153
+ tmux send-keys -t "$session_name" Enter
154
+
155
+ return 0
156
+ }
157
+
53
158
  # Kill a tmux session
54
159
  # Usage: psm_kill_tmux_session <session_name>
55
160
  psm_kill_tmux_session() {
@@ -27,6 +27,30 @@ validate_worktree_path() {
27
27
  return 0
28
28
  }
29
29
 
30
+ # Best-effort dependency bootstrap for clean PR review worktrees.
31
+ # Reuses the source repo node_modules only when package.json matches exactly.
32
+ # This keeps focused test commands like `npm run test:run -- ...` usable
33
+ # without forcing a full install in every review worktree.
34
+ psm_bootstrap_review_dependencies() {
35
+ local local_repo="$1"
36
+ local worktree_path="$2"
37
+
38
+ local source_package_json="${local_repo}/package.json"
39
+ local target_package_json="${worktree_path}/package.json"
40
+ local source_node_modules="${local_repo}/node_modules"
41
+ local target_node_modules="${worktree_path}/node_modules"
42
+
43
+ [[ -f "$source_package_json" ]] || return 0
44
+ [[ -f "$target_package_json" ]] || return 0
45
+ [[ -d "$source_node_modules" ]] || return 0
46
+ [[ ! -e "$target_node_modules" ]] || return 0
47
+
48
+ cmp -s "$source_package_json" "$target_package_json" || return 0
49
+
50
+ ln -s "$source_node_modules" "$target_node_modules" 2>/dev/null || true
51
+ return 0
52
+ }
53
+
30
54
  # Create a worktree for PR review
31
55
  # Usage: psm_create_pr_worktree <local_repo> <alias> <pr_number> <pr_branch>
32
56
  psm_create_pr_worktree() {
@@ -60,6 +84,8 @@ psm_create_pr_worktree() {
60
84
  return 1
61
85
  }
62
86
 
87
+ psm_bootstrap_review_dependencies "$local_repo" "$worktree_path"
88
+
63
89
  echo "created|$worktree_path"
64
90
  return 0
65
91
  }
@@ -85,7 +85,7 @@ Reference formats:
85
85
 
86
86
  Examples:
87
87
  psm review omc#123
88
- psm fix owner/oh-my-claudecode#42
88
+ psm fix Yeachan-Heo/oh-my-claudecode#42
89
89
  psm feature omc add-webhooks
90
90
  psm list
91
91
  psm attach omc:pr-123
@@ -145,6 +145,8 @@ cmd_review() {
145
145
  local head_branch=$(echo "$pr_info" | jq -r '.headRefName')
146
146
  local base_branch=$(echo "$pr_info" | jq -r '.baseRefName')
147
147
  local pr_url=$(echo "$pr_info" | jq -r '.url')
148
+ local pr_body=$(echo "$pr_info" | jq -r '.body // ""')
149
+ local changed_files=$(echo "$pr_info" | jq -r '.files[]?.path // empty' 2>/dev/null | head -50 || true)
148
150
 
149
151
  log_info "PR: #${pr_number} - ${pr_title}"
150
152
  log_info "Author: @${pr_author}"
@@ -190,6 +192,24 @@ cmd_review() {
190
192
 
191
193
  log_success "Worktree created at $worktree_path"
192
194
 
195
+ # Render PR review context file into the worktree so Claude starts with full task context
196
+ local context_rel=".psm/review.md"
197
+ local context_file="${worktree_path}/${context_rel}"
198
+ mkdir -p "$(dirname "$context_file")"
199
+ if ! psm_render_template "$SCRIPT_DIR/templates/pr-review.md" \
200
+ "PR_NUMBER=${pr_number}" \
201
+ "PR_TITLE=${pr_title}" \
202
+ "PR_AUTHOR=${pr_author}" \
203
+ "PR_URL=${pr_url}" \
204
+ "HEAD_BRANCH=${head_branch}" \
205
+ "BASE_BRANCH=${base_branch}" \
206
+ "PR_BODY=${pr_body}" \
207
+ "CHANGED_FILES=${changed_files}" \
208
+ > "$context_file"; then
209
+ log_warn "Failed to render review template; Claude will start without task context"
210
+ context_rel=""
211
+ fi
212
+
193
213
  # Create tmux session
194
214
  local session_name="psm:${alias}:pr-${pr_number}"
195
215
  local session_id="${alias}:pr-${pr_number}"
@@ -209,10 +229,10 @@ cmd_review() {
209
229
  else
210
230
  log_success "Tmux session created: $session_name"
211
231
 
212
- # Launch Claude Code
232
+ # Launch Claude Code with review context so it starts on the PR task
213
233
  if [[ "$no_claude" != "true" ]]; then
214
234
  log_info "Launching Claude Code..."
215
- psm_launch_claude "$session_name"
235
+ psm_launch_claude "$session_name" "$context_rel"
216
236
  fi
217
237
  fi
218
238
  fi
@@ -284,6 +304,7 @@ cmd_fix() {
284
304
 
285
305
  # Fetch issue info
286
306
  local issue_info
307
+ local issue_body="" issue_labels=""
287
308
  if [[ "$provider" == "jira" ]]; then
288
309
  issue_info=$(provider_call "jira" fetch_issue "$provider_ref") || {
289
310
  log_error "Failed to fetch Jira issue ${provider_ref}"
@@ -291,6 +312,7 @@ cmd_fix() {
291
312
  }
292
313
  local issue_title=$(echo "$issue_info" | jq -r '.fields.summary')
293
314
  local issue_url=$(echo "$issue_info" | jq -r '.self // empty')
315
+ issue_body=$(echo "$issue_info" | jq -r '.fields.description // ""')
294
316
  else
295
317
  issue_info=$(provider_call "github" fetch_issue "$issue_number" "$repo") || {
296
318
  log_error "Failed to fetch issue #${issue_number}"
@@ -298,6 +320,8 @@ cmd_fix() {
298
320
  }
299
321
  local issue_title=$(echo "$issue_info" | jq -r '.title')
300
322
  local issue_url=$(echo "$issue_info" | jq -r '.url')
323
+ issue_body=$(echo "$issue_info" | jq -r '.body // ""')
324
+ issue_labels=$(echo "$issue_info" | jq -r '[.labels[].name] | join(", ")' 2>/dev/null || true)
301
325
  fi
302
326
  local slug=$(psm_slugify "$issue_title" 20)
303
327
 
@@ -345,6 +369,22 @@ cmd_fix() {
345
369
  log_success "Worktree created at $worktree_path"
346
370
  log_info "Branch: $branch_name"
347
371
 
372
+ # Render issue fix context file into the worktree so Claude starts with full task context
373
+ local fix_context_rel=".psm/fix.md"
374
+ local fix_context_file="${worktree_path}/${fix_context_rel}"
375
+ mkdir -p "$(dirname "$fix_context_file")"
376
+ if ! psm_render_template "$SCRIPT_DIR/templates/issue-fix.md" \
377
+ "ISSUE_NUMBER=${issue_number}" \
378
+ "ISSUE_TITLE=${issue_title}" \
379
+ "ISSUE_URL=${issue_url}" \
380
+ "ISSUE_LABELS=${issue_labels}" \
381
+ "ISSUE_BODY=${issue_body}" \
382
+ "BRANCH_NAME=${branch_name}" \
383
+ > "$fix_context_file"; then
384
+ log_warn "Failed to render issue fix template; Claude will start without task context"
385
+ fix_context_rel=""
386
+ fi
387
+
348
388
  # Create tmux session
349
389
  local session_name="psm:${alias}:issue-${issue_number}"
350
390
  local session_id="${alias}:issue-${issue_number}"
@@ -353,7 +393,7 @@ cmd_fix() {
353
393
  psm_create_tmux_session "$session_name" "$worktree_path"
354
394
 
355
395
  if [[ "$no_claude" != "true" ]]; then
356
- psm_launch_claude "$session_name"
396
+ psm_launch_claude "$session_name" "$fix_context_rel"
357
397
  fi
358
398
 
359
399
  # Create metadata
@@ -423,7 +463,8 @@ cmd_feature() {
423
463
  local session_id="${project}:feat-${safe_name}"
424
464
 
425
465
  psm_create_tmux_session "$session_name" "$worktree_path"
426
- psm_launch_claude "$session_name"
466
+ local feature_prompt="Implement feature \"${feature_name}\" for project ${project}. Working branch: ${branch_name}. Build the feature, add tests, and open a PR when ready: gh pr create --title \"feat: ${feature_name}\""
467
+ psm_launch_claude "$session_name" "$feature_prompt"
427
468
 
428
469
  psm_add_session "$session_id" "feature" "$project" "feat-${safe_name}" "$branch_name" "$base" "$session_name" "$worktree_path" "$local_path" "{}"
429
470
 
@@ -49,8 +49,11 @@ You are reviewing PR #{{PR_NUMBER}}: **{{PR_TITLE}}**
49
49
  # View diff
50
50
  git diff {{BASE_BRANCH}}...HEAD
51
51
 
52
- # Run tests
53
- npm test # or appropriate test command
52
+ # Run the narrowest relevant tests first
53
+ # If this clean review worktree has a symlinked node_modules from the source repo,
54
+ # focused vitest commands should work without a fresh install.
55
+ npm run test:run -- <changed-test-paths> # preferred focused verification
56
+ npm test # or appropriate full test command if focused coverage is insufficient
54
57
 
55
58
  # Check build
56
59
  npm run build # or appropriate build command
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "aliases": {
3
3
  "omc": {
4
- "repo": "owner/oh-my-claudecode",
4
+ "repo": "Yeachan-Heo/oh-my-claudecode",
5
5
  "local": "~/Workspace/oh-my-claudecode",
6
6
  "default_base": "main"
7
7
  },