Skip to content

SOPs

Filing GitHub Issues and PRs via /gh-issue

  1. Trigger. I say “file a bug on freeflow” or similar, and the /gh-issue skill fires. The skill is defined in ~/apps/github-helper/commands/gh-issue.md and runs cross-repo — defaults to anthropics/claude-code but follows any public repo’s CONTRIBUTING.md and issue templates.
  2. Environment capture. Deterministic block of version strings, hardware, extensions. For Mac apps the skill pulls CFBundleShortVersionString plus any richer build tag like FreeFlowBuildTag so maintainers can map the report to a specific commit.
  3. Duplicate search. Short 2–3 word gh search issues queries. 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.
  4. Draft. Pre-built templates for [BUG], [FEATURE], [MODEL], [DOCS] on anthropics/claude-code. Other repos follow their own templates fetched from .github/ISSUE_TEMPLATE/. PII is scrubbed before I ever see the draft.
  5. Preview. Generator produces GitHub-light HTML. Mandatory — see below.
  6. File. Only after I say “file it.” The hook blocks every gh issue create that skipped step 5.
  7. Log. Issues on anthropics/claude-code get appended to the Open table at claude-code-issues. Other repos get a planned-but-not-yet cross-repo log (tracked in the repo’s vision.md).

~/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.

Terminal window
cat > /tmp/myrepo-preview-body.md <<'EOF'
Summary sentence.
## The problem
Explanation 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.html

Markdown 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.

Two shell hooks make the preview non-bypassable:

HookEventPurpose
hooks/gh-issue-preview-guard.shPreToolUse on BashBlocks any gh issue create unless a preview file was opened via open-html.sh in the last 15 minutes
hooks/issue-preview-stamp.shPostToolUse on BashTouches /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):

Terminal window
GH_ISSUE_PREVIEW_OVERRIDE=1 gh issue create --repo owner/repo --title "..." --body "..."

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.

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.
  • Adding a new repo’s quirks — drop them into commands/gh-issue.md under a repo-specific subsection. The pattern is already established for anthropics/claude-code and zachlatta/freeflow.
  • Extending the generator — edit render-preview.py. It is intentionally a single file with no external dependencies. Bump build.txt, commit Build X: <change>, push.
  • Teaching the skill a new issue type — new section in commands/gh-issue.md with the template, the title prefix, and any bot quirks. No code change needed unless the type needs a new preview surface.
  • 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-23render-preview.py generator 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 both gh issue create and gh pr create.
  • 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