Skip to content
cccskills
FreePublished on GitHub

pr

Create or update a pull request for the current branch. Trigger when the user asks to create/open/make a PR, or to edit/update/rewrite/fix the PR description, body, summary, or title — including bare phrasings like "update pr" or "update the PR" with no other object — for both new PRs and existing ones. Also trigger when the ask is to re-host, recreate, or duplicate an existing PR under this repo (e.g. "close this PR and open a new one of the same changes, not a fork") — that's still creating a PR even with no new diff to write. Note this runs `/simplify`, `bin/lint`, an AGENTS.md conformance pass and a merge from the base before writing the body — skipped when the ask is only to reword the description — and pushes the result. For frontend diffs, delegates the screenshot phase to `references/screenshots.md`, which captures desktop+mobile shots and posts them as a `## Screenshots` PR comment.

The English summary is being prepared. Showing the original description.

bikeindex/bike_index308 stars(GitHub 308 + cccskills 0)
Works withGitHub

Run score Not tested

See how to install

Files included (3)

  • SKILL.md16.8 KB
  • references/pre-push-cleanup.md17.4 KB
  • references/screenshots.md11.7 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

Pull request workflow

Five sections, run in this order:

  1. Orient — the working tree, and the base branch
  2. Prepare the branch — merge, cleanup, migrations. Skipped for a description-only ask
  3. Publish — read the final diff, write the body, push, create or update
  4. Screenshots — frontend diffs only
  5. What this run taught you — always last, whatever else ran

Shell state does not persist between commands. Each command below runs in its own shell, so a BASE=main in one is gone by the next. Substitute the real values into every command — write origin/main, not origin/$BASE — and carry the base branch and PR number in your head, not in the environment. Every origin/main below means "the base branch from Orient".

Run the gh commands as written. The appendix at the bottom covers the one environment that has no gh.

Orient

Check the working tree

git status (no -uall). Everything below diffs origin/main...HEAD, which only sees committed work, and the merge in Prepare the branch needs a clean tree — so the tree has to be clean before you go further.

  • Uncommitted changes you made in this session: commit them now. Otherwise the cleanup, the classifier and the diff you describe all silently skip them, and the PR body describes the wrong diff.
  • Uncommitted changes you didn't make: stop and ask. Don't sweep someone else's work into a commit.

Determine the base branch

The base is the branch the PR goes off of — main by default. The head is always the current branch (HEAD), so the branch that sets the base is a different one the user points at: "a PR off of release-2", "base this on release-2", "onto/target release-2", "stacked on <branch>", or a --base <branch> argument. Naming the branch you're already on only identifies the head — the base stays main. If it's genuinely unclear whether a named branch is meant as the base, ask rather than guess. Never silently retarget an explicitly-named base to main.

When updating an existing PR, leave its base untouched — run gh pr edit without --base. Only retarget when the user explicitly asks.

Prepare the branch

Skipped in full when the ask is only to reword an existing PR's description — fixing the wording shouldn't rewrite code. Everything else (creating a PR, "get this ready", an update after new commits) runs it.

Update from the base

Bring the branch up to date so the PR reflects the current base and merges without surprises. Follow the merge-conflicts skill: git fetch origin then git merge --no-edit origin/main, merge (never rebase), keep the merge commit to just the merge, and resolve conflicts per that skill.

This has to happen before the cleanup below, which diffs against origin/main.

Simplify, lint, and conform to AGENTS.md

references/pre-push-cleanup.md has this in full: /simplify, bin/lint scoped to the branch's files, branch-scoped specs, a pass over the changed files against AGENTS.md, its audits — spec, documentation, churn, comment, backfill and, when the branch adds them, asset and controller — and the cycle-type translation and product-name checks. The audits are required every run, not just when the diff looks messy. Commit everything it produces before re-dating migrations.

Freshen stale migration timestamps

Migrations this branch adds have to be dated within the past 2 days, or the rollback/rename/re-migrate order in references/pre-push-cleanup.md re-dates them. Skip when the branch adds no migrations.

Publish

Gather branch state

Run in parallel:

  • git diff origin/main...HEAD --stat
  • git diff origin/main...HEAD --name-only
  • git log origin/main..HEAD --oneline
  • gh pr view --json number,url,title,state

Diff against origin/main, not the local base branch — in a Conductor worktree the local base often lags the remote, which would inflate or stale the diff. If you skipped Prepare the branch, git fetch origin first. If the branch has no commits ahead of origin/main, stop and tell the user.

rtk proxy the git log — rtk's hook strips merge commits from git log --oneline, so the merge Prepare the branch just made is absent and the branch reads as though it never merged.

gh pr view exits non-zero with "no pull requests found" when the branch has none — that's the answer to the create-or-update question below, not a broken command, and it's the normal case on a first run.

gh pr view returns MERGED and CLOSED PRs too. Only a PR whose state is OPEN counts as existing — for a merged or closed one, create a new PR rather than editing it. Note the number; the push and Screenshots both need it.

No bin/env eval is needed here — it's only relevant to the screenshot phase, and frontend-screenshots runs its own in preflight. Backend-only PRs never touch it.

Classify the diff

The diff is frontend if a changed path matches one of these and renders a page a reviewer could look at:

  • app/views/** (.erb, .html.erb, .haml — deprecated, but still most of the directory)
  • app/components/** (ViewComponent templates or Ruby)
  • app/javascript/**
  • app/assets/**
  • config/tailwind*, tailwind.config.*, postcss.config.*
  • *.scss, *.css, *.coffee, *.js, *.ts

Excluded despite matching: mailer views (app/views/*_mailer/**, app/views/user_emails/**) and email components (app/components/emails/**) — capture those only when the user asks, via the mailer preview frontend-screenshots documents. API and JSON views (app/views/api/**, *.json*, *.jbuilder), and build config (app/assets/config/manifest.js, esbuild.config.js). A diff that only changes comments or non-rendering config isn't frontend either.

Markup a reviewer can't see is also excluded — a tw:hidden field, a data- attribute, an aria- or meta change. It renders, so the paths above match it, but before and after are the same image, and the ## Screenshots comment it produces is two identical captures. Ask what the shot would show, not whether a template changed. #4222 and #4262 (the register honeypot, added to each step) are the pattern; neither posted screenshots.

Record this as frontend true/false — it's what Screenshots gates on.

Write the summary body

Write the body to a file under the repo's own tmp/; a PreToolUse hook refuses writes outside the checkout. Read the last few merged PRs first — gh pr list --state merged --limit 5 --json title,body — they're the tone to match. The house shape is a short intro paragraph saying what was broken or what this is, then 2–4 bullets each opening with a bolded clause. Title under ~70 chars.

Rules:

  • Bias hard toward brevity. Default to a one-line intro plus 2–3 bullets, not the maximum. A bullet that fits on one line beats one that wraps three times.
  • Cut anything visible in the diff. Which HTTP client, file-mode flags, helper names, column renames, the exact files removed — that's the diff's job. Keep only what it doesn't make obvious: what the PR adds, the entry point a reviewer would use, and any non-obvious decision they'd otherwise reverse-engineer.
  • Describe the end state, not the journey. No "first pass" / "second pass", no commit hashes for stages that all land in the same diff, no "originally we tried X then switched to Y". When updating an existing body, rewrite it to describe the current diff — don't append a changelog of edits since the last revision.
  • Reference branches by PR number. A stacked base or a branch this builds on is #3918, not a branch name: gh pr list --head <branch> --state all --json number --jq '.[0].number'. Name the branch only when it has no PR.
  • No "Test plan" section unless the user asks. Never list what CI already covers. Only reviewer-facing manual verification ("click X, confirm Y appears") qualifies, and only on request.
  • No generic "covered by tests" bullet. That a change is tested is assumed, and naming test mechanics (a fixture, a cassette) goes stale. Mention tests only when what is verified is the reviewer-facing point ("adds a regression test for the UTF-8 download crash").
  • No Claude Code attribution footer, here or in any comment this workflow posts. It should read like the human author wrote it. Leaving it out isn't enough where gh is missing: create_pull_request and add_issue_comment append one server-side (the tell is the session id in its link), while the update_* calls don't — so read back what you posted and strip it with an update.
  • A backfill leads the body. When the branch adds a Backfills:: job, the intro says existing rows need one, and the first bullet names the job with the command that runs it once after deploy — Backfills::…Job.perform_async. #4429 is the pattern.
  • Link the issue when there is one. If the branch name, a commit message, or the user's request names an issue, close it from the body — Closes #4103 on its own line. Don't invent a number.

If a bullet is turning into an essay, compress it to one sentence naming the kind of change.

Push and create or update the PR

git push -u origin HEAD

Don't report the local branch name differing from the name in the invocation when the branch has no upstream — pushing HEAD creates a matching remote, so it's benign. Only flag a mismatch when the local branch already tracks a differently-named upstream. If the push is rejected as non-fast-forward, go back to Prepare the branch.

A branch already tracking a differently-named upstream — a Conductor -v1 local on origin/<name> — takes git push origin HEAD:<upstream-branch> instead. git push -u origin HEAD creates a second remote branch and leaves the existing PR behind on the first.

  • Open PR found above: gh pr edit <number> --title "..." --body-file <tmp-body-file>. Refresh the title to match the current diff (that's what "update pr" expects) unless the user gave it a deliberate custom title — if unsure, keep the title and update only the body.

    Read the current body before you replace it. A human may have edited it since your last run — added a caveat, a reviewer note, a deploy instruction. Anything you can't account for as your own writing gets carried into the new body, or asked about. Don't overwrite it silently.

  • Otherwise: gh pr create --draft --base main --title "..." --body-file <tmp-body-file>. Draft by default; only skip --draft if the user asks for ready-for-review. Note the new number for Screenshots.

Always pass the body via --body-file, not inline --body, to preserve formatting.

What goes in a comment

This workflow posts one kind of comment — the ## Screenshots one — and at most one per PR, edited in place on later runs. Everything else you have to say goes in the body when a reviewer needs it, and in your reply to the user otherwise. Findings, caveats, evidence you gathered, what you decided not to fix: none of those earn a comment of their own, however well they'd read as one. Don't invent a comment type because you have something to say.

The one that talks itself into existence is the "still accurate" update — a later push makes you wonder whether an earlier comment went stale, so you post that it hasn't. Re-run whatever produced it and edit that comment, or say nothing. Never reason your way to "it still holds" in place of re-running; whether a claim is still true is something to tell the user in chat.

Screenshots

Two gates, either of which skips the section outright:

  • Not a frontend diff — per the classifier above. Unless a ## Screenshots comment already exists: the user asked for those captures, so a commit since the last one that changes what they show stales them even here. Recapture only those pages.
  • No gh, with $CLAUDE_CODE_REMOTE unset. Then there is nowhere to host or post the images, so don't capture them and don't post anything in their place. Say so in your summary. The web sandbox is not this case, though it has no gh: $CLAUDE_CODE_REMOTE is true there, and the section runs, because github-pr-images hosts through the PR branch's history — see the appendix.

A dev server you believe is down is not a gate. Run curl -fs "$BASE_URL/" now, whatever an earlier check in the session said — the user starts bin/dev whenever, and #4319 went out without screenshots on a stale "isn't running". Only a failing curl this run is a reason to stop and ask.

Otherwise read references/screenshots.md and follow it to capture before/after screenshots and post them as a PR comment. Screenshot tooling never blocks the PR — if it fails, report the failure and carry on to What this run taught you.

What this run taught you

Last, before reporting the PR URL. Look back over the whole run and ask whether the repo's own instructions should change:

  • Did any skill mislead you? A command that failed, a path or version that had moved, a step that didn't match what the repo does now — fix it in that skill. This skill included.
  • Did you work around something undocumented? If the next run would hit the same wall, the fix belongs in the skill, not in your memory.
  • Did the branch establish a convention? A new pattern, a rule you had to infer from existing code, or a guideline you found yourself explaining — that's AGENTS.md (root, or the nested one nearest the code).
  • Did /simplify or the AGENTS.md pass flag the same thing more than once? A repeated correction is a missing written rule.

Most runs turn up nothing — say so and stop.

Two bars before you edit a skill, because a wrong edit here is permanent and costs every future run:

  • Did the skill already say it? Diff the steps you ran against the steps as written. Out of order or skipped is your deviation, so don't stack a new rule on the one you didn't follow. Revise the existing rule instead — reword it, or move it to where it gets read — since a rule you missed is a rule that was missable.
  • Does it pay for itself? Weigh how often the guidance fires against what it saves when it does, and state both. Guidance that runs every time to catch something rare is negative, however cheap each run looks.

Then make the edit — commit it onto the branch, push, and update the body if it's worth a bullet. Prefer editing to reporting: a change you only describe is one the next run rediscovers.

Then return the PR URL.

Appendix: the sandbox with no gh

Only the Claude Code web sandbox (/home/user/bike_index, where $CLAUDE_CODE_REMOTE is true) lacks the GitHub CLI; everywhere else the sections above run as written, and you shouldn't check. If a gh command comes back "command not found", swap in the GitHub MCP equivalents — the rest of the workflow is unchanged, including git push.

WhereghMCP
Publishgh pr view --json …,statelist_pull_requests, state: "open", head: "bikeindex:<branch>"
Publishgh pr list --state mergedlist_pull_requests, state: "closed"
Publishgh pr create --draftcreate_pull_request, draft: true, head: "<branch>"
Publishgh pr edit <n> --body-fileupdate_pull_request

Three traps in that column: head takes owner:branch when listing but a bare branch name when creating; the body is a string parameter, so --body-file has no equivalent; and list_pull_requests reports merged: false even for merged PRs — which is why the branch-state query asks for open PRs rather than filtering all on that field.

Screenshots do run here, though gh doesn't: github-pr-images' references/web-sandbox.md commits the images to the PR's branch, deletes them in a second commit, and posts sha-pinned raw.githubusercontent.com URLs through the MCP tools. Capture as normal and follow that reference for the hosting and posting steps. Those URLs live as long as the branch's objects do, so say in your summary that a merged PR's screenshots aren't archival.

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

Read live production data from Bike Index through the admin OAuth token — Sidekiq and PgHero status, and the user-submitted bug reports — the same data as the cookie-gated dashboards, but agent-friendly JSON. Trigger when the user asks about production queue depth, job backlog, retries/dead jobs, running Sidekiq processes, or Postgres health (slow/blocked queries, index usage, unused/invalid indexes, connection counts, table/db sizes, vacuum/transaction-id danger) — and wants the *live* answer from production rather than logs or Honeybadger. Also trigger for anything about bug reports users have emailed in: what's been reported, searching/filtering them by status, tag or membership, or tagging one / linking it to the PR that fixes it. Also trigger when a request returns 401/expired and the AdminData token needs refreshing/re-authorizing. Not for reading log files (use production-log-inspection) or aggregated exception triage (bin/binx_hb).

The English summary is being prepared. Showing the original description.

bikeindex/bike_index308Updated Oct 29, 2026

How to fix a test that fails intermittently in Bike Index — one that passes locally but fails on CI, fails on one shard, passes on re-run, or is already tagged `:flaky`. **Read this before touching any spec that is failing intermittently, and before adding, raising, or relying on a `flaky:` tag or a `wait:` bump.** Trigger on a CI failure the user calls flaky, unreliable, intermittent, "green locally", "passes on retry", "fix CI", or a pasted `gh run`/Actions URL whose failure isn't reproducible; also whenever you catch yourself about to delete, skip, loosen, or retry an assertion to make a red build go green. **Equally: any spec that fails intermittently while you verify your own work** — deciding whether your change caused a flake, or whether to ship past one, is this skill's problem too, and it arrives with no CI run, no `:flaky` tag, and nobody but you calling it flaky.

The English summary is being prepared. Showing the original description.

bikeindex/bike_index308Updated Oct 29, 2026

Bike Index's frontend conventions — Tailwind class prefixing (`tw:`), the standard `twinput`/`twlabel`/`twlink` form/link classes, the `number_display` helper for numbers, `Counts` for site-wide figures (bikes registered, recoveries, organizations), the UI component library rule (every button is `UI::Button`/`UI::ButtonLink`, every typeahead/autocomplete is `UI::Forms::Combobox`, every FAQ is `UI::Accordion`, never hand-rolled markup), that **helpers are deprecated — render a view component taking full keyword arguments instead of adding or extending one**, ViewComponent rules (when to write a partial instead, keyword arguments, instance variables, `helpers.` prefix in templates), and `UI::Time::Component` for every date/time. Trigger when adding or modifying views (`.html.erb`), view components, Stimulus controllers, Tailwind classes, image or icon files under `app/assets/images` (which usually already exist), or any frontend code that touches styling or interactivity — including admin screens, whose unlayered legacy CSS inverts several of these rules. Stimulus.js is the JavaScript framework; SCSS and CoffeeScript files exist but are deprecated.

The English summary is being prepared. Showing the original description.

bikeindex/bike_index308Updated Oct 29, 2026

Capture desktop+mobile screenshots of Bike Index pages from the local `bin/dev` server via Playwright MCP, with a seeded-user identity gate that keeps PII out of uploaded images. Use whenever a task needs screenshots of local pages — PR documentation, bug repros, before/after comparisons across branches, design review, demos — including mid-interaction states like an open dropdown, a modal showing, a form mid-fill, or a hover. Use it even when the user just says "grab a screenshot" or "show me what this looks like" without naming Playwright. For a component that only renders under an env var / feature flag / hard-to-reach state (e.g. the review-app banner), screenshot its ViewComponent/Lookbook preview URL instead of a full page. **Also read the filename rule here before any `mcp__playwright__browser_take_screenshot` call**, including a one-off capture of some other site — it's what keeps PNGs out of the working tree.

The English summary is being prepared. Showing the original description.

bikeindex/bike_index308Updated Oct 29, 2026

Embed a local image file into an existing GitHub PR — either in the PR body or as a comment. Trigger when a request pairs a local image (screenshot, .png/.jpg, CleanShot capture, before/after) with an existing PR (by #number, URL, branch name, or "the open PR"), regardless of verb — attach, embed, add, put, post, drop, show, document. Also covers visually documenting test runs, bug repros, UI states, or CI failures on an existing PR. Uploads through `gh`'s `--attach` flag — except in the Claude Code web sandbox, which has no `gh` and hosts images through the PR branch's history instead. It also owns the PR's one `## Screenshots` comment — finding, creating, editing and verifying it — so other workflows (the `pr` skill's screenshot phase) hand it a composed body that references local image paths, and it posts it.

The English summary is being prepared. Showing the original description.

bikeindex/bike_index308Updated Oct 29, 2026

Investigate and fix a specific Honeybadger exception in the Bike Index app — pull the fault, read its backtrace, find the offending code, write the fix. Trigger whenever a request names one Honeybadger error: a pasted fault URL (`app.honeybadger.io/projects/…/faults/…`), a fault ID, an error class plus "in production" (`Vips::Error`, `NoMethodError in AfterStolenRecordSaveJob`), or phrasings like "fix this Honeybadger error", "why is this erroring in prod", "what's causing this exception", "look at this HB fault". Use `bin/binx_hb` for fault and notice detail; it is the only Honeybadger reader this repo uses. Not for a broad production health sweep across many sources, and not for reading raw log files (that's production-log-inspection).

The English summary is being prepared. Showing the original description.

bikeindex/bike_index308Updated Oct 29, 2026

See all skills by bikeindex

Report a problem with this skill