Claude Code Plugins

Community-maintained marketplace

Feedback

pr-gfm-validator

@terrylica/cc-skills
1
0

Validate and auto-fix GitHub Flavored Markdown links in PR descriptions. Use when creating pull requests, mentioning PR links, gh pr create, GFM validation, or fixing broken PR links. Converts repo-relative paths to branch-specific blob URLs.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name pr-gfm-validator
description Validate and auto-fix GitHub Flavored Markdown links in PR descriptions. Use when creating pull requests, mentioning PR links, gh pr create, GFM validation, or fixing broken PR links. Converts repo-relative paths to branch-specific blob URLs.

PR GFM Link Validator

Validate and auto-convert GFM links in pull request descriptions to prevent 404 errors.

When to Use This Skill

This skill triggers when:

  • Creating a pull request from a feature branch
  • Discussing PR descriptions or body content
  • Mentioning GFM links, PR links, or link validation
  • Using gh pr create or gh pr edit

The Problem

Repository-relative links in PR descriptions resolve to the base branch (main), not the feature branch:

Link in PR Body GitHub Resolves To Result
[ADR](/docs/adr/file.md) /blob/main/docs/adr/file.md 404 (file only on feature branch)

The Solution

Convert repo-relative links to absolute blob URLs with the correct branch:

/docs/adr/file.md
    ↓
https://github.com/{owner}/{repo}/blob/{branch}/docs/adr/file.md

Workflow

Step 1: Detect Context

Before any PR operation, gather repository context:

/usr/bin/env bash << 'PREFLIGHT_EOF'
# Get repo owner and name
gh repo view --json nameWithOwner --jq '.nameWithOwner'

# Get current branch
git rev-parse --abbrev-ref HEAD

# Check if on feature branch (not main/master)
BRANCH=$(git rev-parse --abbrev-ref HEAD)
if [[ "$BRANCH" == "main" || "$BRANCH" == "master" ]]; then
  echo "On default branch - no conversion needed"
  exit 0
fi
PREFLIGHT_EOF

Step 2: Identify Links to Convert

Scan PR body for GFM links matching these patterns:

CONVERT these patterns:

  • /path/to/file.md - Repo-root relative
  • ./relative/path.md - Current-directory relative
  • ../parent/path.md - Parent-directory relative

SKIP these patterns:

  • https://... - Already absolute URLs
  • http://... - Already absolute URLs
  • #anchor - In-page anchors
  • mailto:... - Email links

Step 3: Construct Blob URLs

For each link to convert:

# Pattern
f"https://github.com/{owner}/{repo}/blob/{branch}/{path}"

# Example
owner = "Eon-Labs"
repo = "alpha-forge"
branch = "feat/2025-12-01-eth-block-metrics"
path = "docs/adr/2025-12-01-file.md"

# Result
"https://github.com/Eon-Labs/alpha-forge/blob/feat/2025-12-01-eth-block-metrics/docs/adr/2025-12-01-file.md"

Step 4: Apply Conversions

Replace all identified links in the PR body:

# Before

[Plugin Design](/docs/adr/2025-12-01-slug.md)

# After

[Plugin Design](https://github.com/Eon-Labs/alpha-forge/blob/feat/branch/docs/adr/2025-12-01-slug.md)

Step 5: Validate Result

After conversion, verify:

  1. All repo-relative links are now absolute blob URLs
  2. External links remain unchanged
  3. Anchor links remain unchanged

Integration with gh pr create

When creating a PR, apply this workflow automatically:

/usr/bin/env bash << 'GIT_EOF'
# 1. Get context
REPO_INFO=$(gh repo view --json nameWithOwner --jq '.nameWithOwner')
OWNER=$(echo "$REPO_INFO" | cut -d'/' -f1)
REPO=$(echo "$REPO_INFO" | cut -d'/' -f2)
BRANCH=$(git rev-parse --abbrev-ref HEAD)

# 2. Process PR body (convert links)
# ... link conversion logic ...

# 3. Create PR with converted body
gh pr create --title "..." --body "$CONVERTED_BODY"
GIT_EOF

Link Detection Regex

Use this regex pattern to find GFM links:

\[([^\]]+)\]\((/[^)]+|\.\.?/[^)]+)\)

Breakdown:

  • \[([^\]]+)\] - Capture link text
  • \( - Opening parenthesis
  • (/[^)]+|\.\.?/[^)]+) - Capture path starting with /, ./, or ../
  • \) - Closing parenthesis

Examples

Example 1: Simple Repo-Relative Link

Input:

See the [ADR](/docs/adr/2025-12-01-eth-block-metrics.md) for details.

Context:

  • Owner: Eon-Labs
  • Repo: alpha-forge
  • Branch: feat/2025-12-01-eth-block-metrics-data-plugin

Output:

See the [ADR](https://github.com/Eon-Labs/alpha-forge/blob/feat/2025-12-01-eth-block-metrics-data-plugin/docs/adr/2025-12-01-eth-block-metrics.md) for details.

Example 2: Multiple Links

Input:

## References

- [Plugin Design](/docs/adr/2025-12-01-slug.md)
- [Probe Integration](/docs/adr/2025-12-02-slug.md)
- [External Guide](https://example.com/guide)

Output:

## References

- [Plugin Design](https://github.com/Eon-Labs/alpha-forge/blob/feat/branch/docs/adr/2025-12-01-slug.md)
- [Probe Integration](https://github.com/Eon-Labs/alpha-forge/blob/feat/branch/docs/adr/2025-12-02-slug.md)
- [External Guide](https://example.com/guide)

Note: External link unchanged.

Example 3: Credential File Link

Input:

**See [`.env.clickhouse`](/.env.clickhouse)** for credentials.

Output:

**See [`.env.clickhouse`](https://github.com/Eon-Labs/alpha-forge/blob/feat/branch/.env.clickhouse)** for credentials.

Edge Cases

Already on main/master

  • Skip conversion entirely
  • Repo-relative links will work correctly

Empty PR Body

  • Nothing to convert
  • Proceed with PR creation

No GFM Links Found

  • Nothing to convert
  • Proceed with PR creation

Mixed Link Types

  • Convert only repo-relative links
  • Preserve external URLs, anchors, mailto links

Post-Change Checklist

After modifying this skill:

  1. Regex patterns still match intended link formats
  2. Examples reflect current behavior
  3. Edge cases documented
  4. Workflow steps are executable

References