원클릭으로
create-pr
Create a Pull Request from the current branch — runs local checks, picks target branch, and opens the PR on GitHub
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Create a Pull Request from the current branch — runs local checks, picks target branch, and opens the PR on GitHub
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Reset the OpenRegister development environment (stop, remove volumes, restart, install apps)
Analyze a project's OpenSpec from 8 persona perspectives and suggest additional features
Detect admin settings Vue components registered in the vue-router. Admin settings are rendered by Nextcloud's settings framework via `AdminSettings.php`; adding their Vue components to the in-app router exposes them as publicly-accessible frontend routes, bypassing all server-side access checks. ADR-004 hard rule. Observed 2026-04-30 on doriath where `/settings → AdminRoot` was a route in `src/router/index.js` (commit c7c72e9).
Run `composer audit` to check composer.lock dependencies for known CVEs. Invoked by the builder before push and the reviewer's mandatory block. Mirrors the orchestrator's `composer-audit` quality gate.
Scan lib/ for forbidden debug helpers (var_dump / die / error_log / print_r / dd / dump) that should not ship. Invoked by the builder before push, by the reviewer as Mandatory Step 2, and by the fixer during a retry. Mirrors the orchestrator's `forbidden-patterns` quality gate.
Detect DOM data-attribute reads in `.vue`/`.js`/`.ts` files (e.g. `document.getElementById('x').dataset.version`) used to pull server-side data into the frontend. The Nextcloud-idiomatic pattern is `IInitialState::provideInitialState()` in PHP + `loadState()` from `@nextcloud/initial-state` in Vue. DOM data-attributes break on CSP-hardened instances and bypass the canonical pattern documented in ADR-004. Observed 2026-04-30 on doriath where `AdminRoot.vue` read `document.getElementById('doriath-settings').dataset.version`.
| name | create-pr |
| description | Create a Pull Request from the current branch — runs local checks, picks target branch, and opens the PR on GitHub |
Guides the developer through creating a Pull Request for a Nextcloud app. Confirms the source branch, recommends a target branch based on the branching strategy, optionally runs local quality checks, then creates the PR via the GitHub REST API.
This skill involves parsing CI workflows, detecting branch-protection rules, resolving bootstrap deadlocks, and reasoning about code diffs. Mistakes here have real consequences.
First, check the active model from your system context (it appears as "You are powered by the model named…").
If the active model is Haiku or any model other than Sonnet or Opus: stop immediately and tell the user:
"This command requires Sonnet or Opus — the CI workflow parsing and branch-protection analysis steps need stronger reasoning than Haiku can reliably provide. Please switch models and re-run."
If the active model is Sonnet or Opus: ask the user using AskUserQuestion:
"You're on [active-model]. Which model should I use for this PR?"
| Model | Best for |
|---|---|
| Sonnet | Most PRs — handles CI parsing and branch logic well |
| Opus | Repos with reusable CI workflows, branch-protection rulesets, or a complex branching strategy — that's where it pays off most |
If the chosen model differs from the active model, tell the user:
"You're on [active-model] but chose [chosen-model]. To switch: use
/model [chosen-model]in the chat input, or open the model picker in the Claude Code UI. Then re-run this command." Then stop.
NEVER modify .github/workflows/ files. This skill reads workflow files to understand what CI runs, but must never edit, create, or delete any workflow file or change any job definition — regardless of what checks fail or what the branch protection requires. If a workflow mismatch is detected (e.g. wrong job name for a required status check), report the issue to the user and stop — do not attempt to fix it.
Scan the workspace for available git repositories:
# Scan sibling directories of the current git repo for other repos
WORKSPACE_ROOT="$(git rev-parse --show-toplevel 2>/dev/null)/.."
for dir in "$WORKSPACE_ROOT"/*/; do
if [ -d "$dir/.git" ] || git -C "$dir" rev-parse --git-dir > /dev/null 2>&1; then
echo "$dir"
fi
done
# Also scan common locations that may not be siblings: ~/.github, ~/src, ~/projects
for extra in "$HOME/.github" "$HOME/src" "$HOME/projects"; do
[ -d "$extra" ] || continue
for dir in "$extra"/*/; do
if [ -d "$dir/.git" ] || git -C "$dir" rev-parse --git-dir > /dev/null 2>&1; then
echo "$dir"
fi
done
done
Also include any additional working directories listed in your environment context (they appear as Additional working directories: in the session header). Deduplicate the combined list before presenting it.
For each found repo, also get its remote URL and current branch:
git -C {dir} remote get-url origin 2>/dev/null
git -C {dir} branch --show-current 2>/dev/null
Ask the user using AskUserQuestion:
"Which repository do you want to create a PR for?"
List each repo as: {app-name} [{current-branch}] ({remote-url})
Store the selected repo's absolute path as {REPO_ROOT}.
Run within {REPO_ROOT}:
git -C {REPO_ROOT} branch --show-current
git -C {REPO_ROOT} remote get-url origin
Store:
{CURRENT_BRANCH} — active branch name{REMOTE_URL} — GitHub repo URLAsk the user using AskUserQuestion:
"Your current branch is {CURRENT_BRANCH}. Is this the correct branch to create a PR from?"
{CURRENT_BRANCH}{CURRENT_BRANCH}Based on {CURRENT_BRANCH}, determine the recommended target using the project branching strategy:
| Source branch pattern | Recommended target | Allowed targets |
|---|---|---|
feature/*, bugfix/*, or other non-standard branch | development | development |
development | beta | beta |
beta | main | main |
hotfix/* | main | main, beta, development |
Fetch available remote branches:
git -C {REPO_ROOT} fetch --prune
git -C {REPO_ROOT} branch -r | grep -v HEAD | sed 's|origin/||' | sort
Ask the user using AskUserQuestion:
"Which branch should this PR target?"
List the allowed target branches, marking the recommended one with (recommended). If there is only one valid option, pre-select it and ask for confirmation instead.
Store the answer as {TARGET_BRANCH}.
Read references/branch-protection-guide.md for the full procedure covering: branch-protection workflow validation (Step 3.2), required-check bootstrap deadlock detection (Step 3.2b), and bootstrap deadlock resolution post-push (Step 3.2c). Apply all three steps now.
Only run this step if {REMOTE_URL} contains ConductionNL/.github.
Invoke the /verify-global-settings-version skill now, passing {TARGET_BRANCH} as the compare branch, and follow its steps completely.
If it reports Case A or B (no changes, or correctly bumped) → proceed silently to Step 3.5.
If it reports Case C (VERSION BUMP MISSING) → pause the PR flow. Ask using AskUserQuestion:
"The global-settings VERSION has not been bumped. How do you want to proceed?"
If it reports Case D (VERSION bumped but no file changes) → warn the user but allow the PR to proceed.
Before running any checks, look up whether a PR already exists for this source → target combination:
gh pr list --repo "{REMOTE_URL}" --head "{CURRENT_BRANCH}" --base "{TARGET_BRANCH}" --state open --json number,title,url,createdAt,author
Also check for a closed/merged PR to give full context:
gh pr list --repo "{REMOTE_URL}" --head "{CURRENT_BRANCH}" --base "{TARGET_BRANCH}" --state merged --json number,title,url,mergedAt --limit 1
If an open PR already exists:
Inform the user clearly:
"An open PR already exists for
{CURRENT_BRANCH}→{TARGET_BRANCH}: #{number}: {title} {url} Opened by {author} on {createdAt}"
Then ask using AskUserQuestion:
"A PR for this branch already exists. What would you like to do?"
{EXISTING_PR_NUMBER} and proceed to Step 3.7 as normal; in Step 7 use PATCH instead of POSTIf a merged PR was found but no open PR:
Inform the user:
"Note: A previous PR for
{CURRENT_BRANCH}→{TARGET_BRANCH}was already merged (#{number}: {title}, merged {mergedAt}). You may be re-opening the same work."
Then proceed normally to Step 4.
If no PR exists: proceed silently to Step 4.
Check the working tree and push status of {CURRENT_BRANCH}:
git -C {REPO_ROOT} status --short
git -C {REPO_ROOT} log origin/{CURRENT_BRANCH}...HEAD --oneline 2>/dev/null || echo "(branch not yet on remote)"
If there are uncommitted changes (modified, untracked, or staged files):
Before listing all uncommitted changes, specifically check for lock files that are untracked or modified:
git -C {REPO_ROOT} status --short | grep -E "composer\.lock|package-lock\.json"
If composer.lock or package-lock.json appear as untracked (??) or modified (M), warn prominently:
"⚠️
{filename}is not committed. CI installs dependencies from the lock file — without it, dependency versions may differ between local and CI, causing check failures. This should be committed before creating the PR."
Inform the user of all uncommitted changes, listing the files. Then ask using AskUserQuestion:
"There are uncommitted changes on {CURRENT_BRANCH}. What would you like to do?"
git -C {REPO_ROOT} add -A && git -C {REPO_ROOT} commit -m "{message}", then continuegit -C {REPO_ROOT} stash, continue, and remind user to git stash pop afterwardsIf the branch has commits not yet pushed to origin:
Inform the user. Then ask using AskUserQuestion:
"Branch {CURRENT_BRANCH} has unpushed commits. Push them now before continuing?"
git -C {REPO_ROOT} push -u origin {CURRENT_BRANCH}, then continueMerge-freshness check:
AHEAD=$(git -C {REPO_ROOT} rev-list HEAD..origin/{TARGET_BRANCH} --count 2>/dev/null || echo 0)
BEHIND=$(git -C {REPO_ROOT} rev-list origin/{TARGET_BRANCH}..HEAD --count 2>/dev/null || echo 0)
echo "source is $BEHIND commits ahead of target; target is $AHEAD commits ahead of source"
If {TARGET_BRANCH} is more than 20 commits ahead of {CURRENT_BRANCH}, warn prominently:
"⚠️
{TARGET_BRANCH}is{AHEAD}commits ahead of your branch. Without a merge/rebase first, the PR diff will include all of those commits as deletions — making the PR look much larger than it is and confusing reviewers. It is strongly recommended to merge or rebase first."
Then ask using AskUserQuestion:
"{TARGET_BRANCH} is significantly ahead of your branch. What would you like to do?"
{TARGET_BRANCH} into my branch now — run git -C {REPO_ROOT} fetch origin && git -C {REPO_ROOT} merge origin/{TARGET_BRANCH}, then re-push and continue{TARGET_BRANCH} — run git -C {REPO_ROOT} fetch origin && git -C {REPO_ROOT} rebase origin/{TARGET_BRANCH}, then force-push and continueIf {TARGET_BRANCH} is ≤20 commits ahead, continue silently.
Ask the user using AskUserQuestion: "Do you want to run local quality checks before creating the PR? This mirrors exactly what CI will run and ensures the PR checks pass." (Yes / No, skip checks → proceed to Step 5)
Read references/local-checks.md for the full CI detection, tool verification, execution, and reporting protocol.
Collect the full picture of what is on this branch before drafting anything:
git -C {REPO_ROOT} log origin/{TARGET_BRANCH}...HEAD --oneline
git -C {REPO_ROOT} log origin/{TARGET_BRANCH}...HEAD --format="%H %s%n%b" --no-merges
git -C {REPO_ROOT} diff --stat origin/{TARGET_BRANCH}...HEAD
git -C {REPO_ROOT} diff origin/{TARGET_BRANCH}...HEAD -- "*.php" "*.js" "*.ts" "*.vue" | head -300
Read each changed file's diff to understand what actually changed (not just filenames). This is the basis for the title and description — derive them from the actual code changes, not just commit messages.
Also check if a plan.json exists under {REPO_ROOT}/openspec/changes (excluding archive/) and if found, extract tracking_issue — store as {TRACKING_ISSUE} (or null). This is used in the PR description to auto-close the linked issue on merge.
Before drafting anything, re-read learnings.md — specifically "Mistakes to Avoid" — so known constraints are applied on the first draft, not after a correction.
Pre-draft checklist (verify both before writing a single word):
feat:, fix:, docs:, etc.)-), never - [ ] checkboxesDetect repo title convention before writing the title:
gh pr list --repo "{REMOTE_URL}" --state merged --limit 5 --json title --jq '.[].title'
If the merged PRs consistently use a Conventional Commits prefix (feat:, fix:, docs:, chore:, etc.), apply the same format. If the repo has no consistent convention, default to a feat:/fix:/docs: prefix anyway — it is forward-compatible and costs nothing.
Using the commit log, diff stat, and file-level diffs from Step 5, draft:
Title: Conventional Commits prefix + concise, action-verb phrase describing the main purpose (e.g. feat: Add full-text search to registers). Do not use the branch name verbatim. Do not include app names or ticket numbers unless the commits reference them.
Description:
## Summary
{3–6 bullet points derived from the actual commits and diffs — what changed and why}
## Checks
{one of:}
- ✅ All local checks passed (`composer check:strict`)
- ⚠️ Some checks failed — see CI for details
- ⏭️ Checks skipped
## Test plan
- CI passes
- Tested locally
- Reviewed for regressions
{if TRACKING_ISSUE is set:}
Closes #{TRACKING_ISSUE}
Present the draft to the user in the chat — show both the title and the full description as they would appear on GitHub.
Then ask using AskUserQuestion:
"Does this PR title and description look good?"
{EXISTING_PR_NUMBER} is set)Repeat the review loop until the user approves.
Store the approved title as {PR_TITLE} and description as {PR_BODY}.
Push the branch to origin if not already pushed:
git -C {REPO_ROOT} push -u origin {CURRENT_BRANCH}
Parse {OWNER} and {REPO} from {REMOTE_URL} (e.g. https://github.com/ConductionNL/myapp.git → owner=ConductionNL, repo=myapp).
Always use the GitHub REST API directly — never use gh pr create or gh pr edit (they use GraphQL and may trigger deprecation errors).
{EXISTING_PR_NUMBER} is set):gh api repos/{OWNER}/{REPO}/pulls/{EXISTING_PR_NUMBER} \
--method PATCH \
-f title="{PR_TITLE}" \
-f body="{PR_BODY}" \
--jq '{number: .number, title: .title, url: .html_url}'
gh api repos/{OWNER}/{REPO}/pulls \
--method POST \
-f title="{PR_TITLE}" \
-f head="{CURRENT_BRANCH}" \
-f base="{TARGET_BRANCH}" \
-f body="{PR_BODY}" \
--jq '{number: .number, title: .title, url: .html_url}'
Store the returned PR number as {PR_NUMBER} and URL as {PR_URL}.
After the PR is created, display:
After execution, review what happened and append new observations to learnings.md under the appropriate section:
Each entry must include today's date. One insight per bullet. Skip if nothing new was learned.
💡 If you switched models to run this command, don't forget to switch back to your preferred model with
/model <name>(e.g./model defaultor/model sonnet).