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 createorgh 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:
- •All repo-relative links are now absolute blob URLs
- •External links remain unchanged
- •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:
- • Regex patterns still match intended link formats
- • Examples reflect current behavior
- • Edge cases documented
- • Workflow steps are executable