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.
- package/.local/guidelines/CLAUDE.md +31 -0
- package/README.md +57 -1
- package/bundled/manifest.json +2 -2
- package/bundled/upstream/oh-my-claudecode/agents/analyst.md +1 -1
- package/bundled/upstream/oh-my-claudecode/agents/architect.md +1 -1
- package/bundled/upstream/oh-my-claudecode/agents/code-reviewer.md +1 -1
- package/bundled/upstream/oh-my-claudecode/agents/code-simplifier.md +1 -1
- package/bundled/upstream/oh-my-claudecode/agents/critic.md +1 -1
- package/bundled/upstream/oh-my-claudecode/agents/debugger.md +1 -1
- package/bundled/upstream/oh-my-claudecode/agents/designer.md +1 -1
- package/bundled/upstream/oh-my-claudecode/agents/document-specialist.md +1 -1
- package/bundled/upstream/oh-my-claudecode/agents/executor.md +1 -1
- package/bundled/upstream/oh-my-claudecode/agents/explore.md +1 -1
- package/bundled/upstream/oh-my-claudecode/agents/git-master.md +3 -3
- package/bundled/upstream/oh-my-claudecode/agents/planner.md +1 -1
- package/bundled/upstream/oh-my-claudecode/agents/qa-tester.md +1 -1
- package/bundled/upstream/oh-my-claudecode/agents/scientist.md +1 -1
- package/bundled/upstream/oh-my-claudecode/agents/security-reviewer.md +1 -1
- package/bundled/upstream/oh-my-claudecode/agents/test-engineer.md +1 -75
- package/bundled/upstream/oh-my-claudecode/agents/tracer.md +1 -1
- package/bundled/upstream/oh-my-claudecode/agents/verifier.md +1 -1
- package/bundled/upstream/oh-my-claudecode/agents/writer.md +1 -1
- package/bundled/upstream/oh-my-claudecode/hooks/hooks.json +21 -1
- package/bundled/upstream/oh-my-claudecode/skills/AGENTS.md +200 -0
- package/bundled/upstream/oh-my-claudecode/skills/autopilot/SKILL.md +17 -10
- package/bundled/upstream/oh-my-claudecode/skills/autoresearch/SKILL.md +90 -0
- package/bundled/upstream/oh-my-claudecode/skills/cancel/SKILL.md +15 -6
- package/bundled/upstream/oh-my-claudecode/skills/configure-notifications/SKILL.md +12 -12
- package/bundled/upstream/oh-my-claudecode/skills/debug/SKILL.md +35 -0
- package/bundled/upstream/oh-my-claudecode/skills/deep-dive/SKILL.md +4 -0
- package/bundled/upstream/oh-my-claudecode/skills/deep-interview/SKILL.md +23 -18
- package/bundled/upstream/oh-my-claudecode/skills/hud/SKILL.md +23 -101
- package/bundled/upstream/oh-my-claudecode/skills/learner/SKILL.md +27 -2
- package/bundled/upstream/oh-my-claudecode/skills/mcp-setup/SKILL.md +67 -8
- package/bundled/upstream/oh-my-claudecode/skills/omc-doctor/SKILL.md +32 -47
- package/bundled/upstream/oh-my-claudecode/skills/omc-setup/SKILL.md +4 -2
- package/bundled/upstream/oh-my-claudecode/skills/omc-setup/phases/01-install-claude-md.md +15 -4
- package/bundled/upstream/oh-my-claudecode/skills/omc-setup/phases/02-configure.md +9 -9
- package/bundled/upstream/oh-my-claudecode/skills/omc-setup/phases/03-integrations.md +13 -13
- package/bundled/upstream/oh-my-claudecode/skills/omc-setup/phases/04-welcome.md +3 -3
- package/bundled/upstream/oh-my-claudecode/skills/omc-teams/SKILL.md +28 -0
- package/bundled/upstream/oh-my-claudecode/skills/plan/SKILL.md +1 -0
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/SKILL.md +25 -5
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/config.sh +2 -15
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/providers/github.sh +1 -1
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/session.sh +2 -2
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/tmux.sh +109 -4
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/worktree.sh +26 -0
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/psm.sh +46 -5
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/templates/pr-review.md +5 -2
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/templates/projects.json +1 -1
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/tests/test-psm-prompt-injection.sh +336 -0
- package/bundled/upstream/oh-my-claudecode/skills/ralph/SKILL.md +18 -9
- package/bundled/upstream/oh-my-claudecode/skills/ralplan/SKILL.md +2 -0
- package/bundled/upstream/oh-my-claudecode/skills/release/SKILL.md +167 -57
- package/bundled/upstream/oh-my-claudecode/skills/remember/SKILL.md +41 -0
- package/bundled/upstream/oh-my-claudecode/skills/self-improve/SKILL.md +391 -0
- package/bundled/upstream/oh-my-claudecode/skills/self-improve/data_contracts.md +274 -0
- package/bundled/upstream/oh-my-claudecode/skills/self-improve/scripts/plot_progress.py +128 -0
- package/bundled/upstream/oh-my-claudecode/skills/self-improve/scripts/resolve-paths.mjs +192 -0
- package/bundled/upstream/oh-my-claudecode/skills/self-improve/scripts/validate.sh +404 -0
- package/bundled/upstream/oh-my-claudecode/skills/self-improve/si-benchmark-builder.md +79 -0
- package/bundled/upstream/oh-my-claudecode/skills/self-improve/si-goal-clarifier.md +94 -0
- package/bundled/upstream/oh-my-claudecode/skills/self-improve/si-researcher.md +73 -0
- package/bundled/upstream/oh-my-claudecode/skills/self-improve/templates/agent-settings.json +14 -0
- package/bundled/upstream/oh-my-claudecode/skills/self-improve/templates/goal.md +22 -0
- package/bundled/upstream/oh-my-claudecode/skills/self-improve/templates/harness.md +18 -0
- package/bundled/upstream/oh-my-claudecode/skills/self-improve/templates/idea.md +5 -0
- package/bundled/upstream/oh-my-claudecode/skills/self-improve/templates/settings.json +23 -0
- package/bundled/upstream/oh-my-claudecode/skills/skill/SKILL.md +46 -77
- package/bundled/upstream/oh-my-claudecode/skills/skillify/SKILL.md +53 -0
- package/bundled/upstream/oh-my-claudecode/skills/team/SKILL.md +83 -11
- package/bundled/upstream/oh-my-claudecode/skills/trace/SKILL.md +1 -0
- package/bundled/upstream/oh-my-claudecode/skills/ultraqa/SKILL.md +1 -0
- package/bundled/upstream/oh-my-claudecode/skills/ultrawork/SKILL.md +1 -0
- package/bundled/upstream/oh-my-claudecode/skills/verify/SKILL.md +37 -0
- package/bundled/upstream/oh-my-claudecode/skills/wiki/SKILL.md +67 -0
- package/package.json +3 -1
- package/src/cli/artifact.js +47 -0
- package/src/cli/doctor.js +6 -1
- package/src/cli/guidelines.js +83 -0
- package/src/cli/index.js +13 -1
- package/src/cli/setup.js +68 -19
- package/src/cli/source.js +35 -1
- package/src/config/artifact-types.js +12 -2
- package/src/config/paths.js +95 -4
- package/src/config/sources.js +29 -5
- package/src/guidelines/apply.js +152 -0
- package/src/guidelines/optimizer.js +325 -0
- package/src/merge/claude-md-merger.js +35 -12
- 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"
|
|
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
|
|
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
|
|
116
|
+
**Question 2:** "Which CLI provider should teammates use by default?"
|
|
117
117
|
|
|
118
118
|
**Options:**
|
|
119
|
-
1. **
|
|
120
|
-
2. **
|
|
121
|
-
3. **
|
|
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
|
|
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
|
|
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": "
|
|
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
|
-
|
|
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
|
|
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**
|
|
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": "
|
|
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
|
-
|
|
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": "
|
|
20
|
+
"repo": "Yeachan-Heo/oh-my-claudecode",
|
|
34
21
|
"local": "~/Workspace/oh-my-claudecode",
|
|
35
22
|
"default_base": "main"
|
|
36
23
|
}
|
package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/providers/github.sh
CHANGED
|
@@ -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
|
-
#
|
|
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
|
-
#
|
|
47
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/templates/pr-review.md
CHANGED
|
@@ -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
|
-
|
|
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
|