SOPs
Filing GitHub Issues and PRs via /gh-issue
The flow
Section titled “The flow”- Trigger. I say “file a bug on freeflow” or similar, and the
/gh-issueskill fires. The skill is defined in~/apps/github-helper/commands/gh-issue.mdand runs cross-repo — defaults toanthropics/claude-codebut follows any public repo’sCONTRIBUTING.mdand issue templates. - Environment capture. Deterministic block of version strings, hardware, extensions. For Mac apps the skill pulls
CFBundleShortVersionStringplus any richer build tag likeFreeFlowBuildTagso maintainers can map the report to a specific commit. - Duplicate search. Short 2–3 word
gh search issuesqueries. The skill runs at least three phrasings — noun, symptom, error keyword. If anything matches, I get a pointer before drafting and either upvote the existing issue or keep going. - Draft. Pre-built templates for
[BUG],[FEATURE],[MODEL],[DOCS]onanthropics/claude-code. Other repos follow their own templates fetched from.github/ISSUE_TEMPLATE/. PII is scrubbed before I ever see the draft. - Preview. Generator produces GitHub-light HTML. Mandatory — see below.
- File. Only after I say “file it.” The hook blocks every
gh issue createthat skipped step 5. - Log. Issues on
anthropics/claude-codeget appended to theOpentable at claude-code-issues. Other repos get a planned-but-not-yet cross-repo log (tracked in the repo’svision.md).
The preview generator
Section titled “The preview generator”~/apps/github-helper/render-preview.py is the single source of truth for preview styling. It produces deterministic, GitHub-light-matching HTML every time. Hand-rolling HTML leads to style drift (dark mode, wrong colors, missing banner), so the skill mandates the generator and treats hand-rolled HTML as a deviation.
cat > /tmp/myrepo-preview-body.md <<'EOF'Summary sentence.
## The problemExplanation with `code` and **bold**.
## The fix...EOF
python3 ~/apps/github-helper/render-preview.py \ --kind pr \ # or "issue" --repo owner/name \ --title "Short title" \ --author ojhurst \ --branch feat/my-branch \ # PRs only; omit for issues --body-file /tmp/myrepo-preview-body.md \ --labels "enhancement,needs-triage" \ --output /tmp/myrepo-slug-preview.html
bash ~/apps/cc/open-html.sh /tmp/myrepo-slug-preview.htmlMarkdown subset supported: headers (# through ###), paragraphs, fenced code blocks, inline code, bold, links, unordered lists, blockquotes. Enough for any normal PR/issue body.
The HTML it emits uses GitHub’s light-mode palette (#ffffff bg, #1f2328 text, #d0d7de borders, #0969da links), a yellow PREVIEW — nothing filed yet banner, and a sidebar with Labels/Assignees/Projects/Milestone/Development. The output path must contain the literal word preview — the stamp hook keys on that.
Hook enforcement
Section titled “Hook enforcement”Two shell hooks make the preview non-bypassable:
| Hook | Event | Purpose |
|---|---|---|
hooks/gh-issue-preview-guard.sh | PreToolUse on Bash | Blocks any gh issue create unless a preview file was opened via open-html.sh in the last 15 minutes |
hooks/issue-preview-stamp.sh | PostToolUse on Bash | Touches /tmp/.claude-issue-preview-stamp whenever open-html.sh <anything>preview<anything>.html runs |
If the stamp is missing or stale, the guard refuses. No preview = no file. The guard also catches gh pr create — PRs go through the same flow.
Bypass (rare, require justification):
GH_ISSUE_PREVIEW_OVERRIDE=1 gh issue create --repo owner/repo --title "..." --body "..."Images — Cloudflare R2
Section titled “Images — Cloudflare R2”Every image embedded in an issue or PR uploads to Cloudflare R2 before the preview renders. Canonical host is https://assets.themarketingshow.com, backed by the themarketingshow-assets bucket. Path convention: bugs/<target-repo>/<descriptive-name>-<YYYY-MM-DD>.png. Upload command and auth live in the /gh-issue skill; the rule is never commit screenshots into third-party forks (especially affaan-m/everything-claude-code, which is NOT a personal asset host).
Default image width is 480px in both the preview HTML and the filed markdown body — screenshots of dialog boxes go narrower, wide layouts can go wider, but err small. Readers can click to enlarge.
Cross-repo coverage
Section titled “Cross-repo coverage”The flow is deliberately repo-agnostic. The skill hard-codes anthropics/claude-code as the default target but supports any public repo:
- Target is inferred from context or asked up front.
- Templates and labels come from the target repo’s
.github/directory, not the skill’s defaults. - Known repos where I have filed at least one ticket:
anthropics/claude-code,zachlatta/freeflow,affaan-m/everything-claude-code.
How to update this page
Section titled “How to update this page”- Adding a new repo’s quirks — drop them into
commands/gh-issue.mdunder a repo-specific subsection. The pattern is already established foranthropics/claude-codeandzachlatta/freeflow. - Extending the generator — edit
render-preview.py. It is intentionally a single file with no external dependencies. Bumpbuild.txt, commitBuild X: <change>, push. - Teaching the skill a new issue type — new section in
commands/gh-issue.mdwith the template, the title prefix, and any bot quirks. No code change needed unless the type needs a new preview surface.
Precedent
Section titled “Precedent”- 2026-04-16 — preview step added after I pointed out that a visual mock catches issues plain markdown does not.
- 2026-04-22 — preview hardened with deterministic hook enforcement after Claude skipped it on a small FreeFlow issue.
- 2026-04-23 —
render-preview.pygenerator replaced hand-rolled HTML after Claude drifted into dark-mode styling on a FreeFlow PR. Generator is now the mandated source of truth; the rule covers bothgh issue createandgh pr create.
Related
Section titled “Related”- Skill source:
~/apps/github-helper/commands/gh-issue.md - Generator:
~/apps/github-helper/render-preview.py - Hooks:
~/apps/github-helper/hooks/ - Filed issue log: claude-code-issues
- Repo naming rules: Naming a New Repo