pr-gfm-validator
Validate and fix GFM links in PR descriptions. TRIGGERS - PR links, gh pr create, GFM validation, broken PR links.
Best use case
pr-gfm-validator is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Validate and fix GFM links in PR descriptions. TRIGGERS - PR links, gh pr create, GFM validation, broken PR links.
Teams using pr-gfm-validator should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/pr-gfm-validator/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How pr-gfm-validator Compares
| Feature / Agent | pr-gfm-validator | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Validate and fix GFM links in PR descriptions. TRIGGERS - PR links, gh pr create, GFM validation, broken PR links.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# PR GFM Link Validator
Validate and auto-convert GFM links in pull request descriptions to prevent 404 errors.
> **Self-Evolving Skill**: This skill improves through use. If instructions are wrong, parameters drifted, or a workaround was needed — fix this file immediately, don't defer. Only update for real, reproducible issues.
## 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:
```bash
/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:
```python
# 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:
```markdown
# 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:
```bash
/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:
```regex
\[([^\]]+)\]\((/[^)]+|\.\.?/[^)]+)\)
```
Breakdown:
- `\[([^\]]+)\]` - Capture link text
- `\(` - Opening parenthesis
- `(/[^)]+|\.\.?/[^)]+)` - Capture path starting with `/`, `./`, or `../`
- `\)` - Closing parenthesis
---
## Examples
### Example 1: Simple Repo-Relative Link
**Input:**
```markdown
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:**
```markdown
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:**
```markdown
## 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:**
```markdown
## 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:**
```markdown
**See [`.env.clickhouse`](/.env.clickhouse)** for credentials.
```
**Output:**
```markdown
**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
- [GitHub Blob URLs](https://docs.github.com/en/repositories/working-with-files/using-files/getting-permanent-links-to-files)
- [GFM Link Syntax](https://github.github.com/gfm/#links)
- [gh CLI Documentation](https://cli.github.com/manual/gh_pr_create)
---
## Troubleshooting
| Issue | Cause | Solution |
| ------------------------ | ------------------------------ | ------------------------------------------------- |
| Links still 404 after PR | File not pushed to branch yet | Push commits before creating PR |
| Regex not matching links | Escaped parentheses in content | Use raw string regex pattern |
| Branch name has slashes | URL encoding needed | Encode branch name for URL construction |
| External links converted | Pattern too broad | Check link starts with `/`, `./`, or `../` only |
| gh repo view fails | Not in a git repository | Run from repository root directory |
| Anchor links broken | Incorrectly included in scan | Skip links starting with `#` |
| Wrong repo detected | Remote not set correctly | Check `git remote -v` output |
| Conversion duplicated | Running validator twice | Check if links already absolute before converting |
## Post-Execution Reflection
After this skill completes, reflect before closing the task:
0. **Locate yourself.** — Find this SKILL.md's canonical path before editing.
1. **What failed?** — Fix the instruction that caused it.
2. **What worked better than expected?** — Promote to recommended practice.
3. **What drifted?** — Fix any script, reference, or dependency that no longer matches reality.
4. **Log it.** — Evolution-log entry with trigger, fix, and evidence.
Do NOT defer. The next invocation inherits whatever you leave behind.Related Skills
plugin-validator
Validate plugin structure and silent failures. TRIGGERS - plugin validation, check plugin, hook audit.
link-validator
Validate markdown link portability in skills. TRIGGERS - check links, validate portability, fix broken links, relative paths.
ascii-diagram-validator
Validate ASCII diagram alignment in markdown. TRIGGERS - diagram alignment, ASCII art, box-drawing diagrams.
voice-quality-audition
Audition Kokoro TTS voices to compare quality and grade. TRIGGERS - audition voices, kokoro voices, voice comparison, tts voice, voice quality, compare voices.
settings-and-tuning
Configure TTS voices, speed, timeouts, queue depth, and bot settings. TRIGGERS - configure tts, change voice, tts speed, queue depth, tts timeout, bot config, tune settings, adjust parameters.
full-stack-bootstrap
One-time bootstrap for Kokoro TTS engine, Telegram bot, and BotFather setup. TRIGGERS - setup tts, install kokoro, botfather, bootstrap tts-tg-sync, configure telegram bot, full stack setup.
diagnostic-issue-resolver
Diagnose and resolve TTS and Telegram bot issues. TRIGGERS - tts not working, bot not responding, kokoro error, audio not playing, lock stuck, telegram bot troubleshoot, diagnose issue.
component-version-upgrade
Upgrade Kokoro model, bot dependencies, or TTS components. TRIGGERS - upgrade kokoro, update model, upgrade bot, update dependencies, version bump, component update.
clean-component-removal
Remove TTS and Telegram sync components cleanly. TRIGGERS - uninstall tts, remove telegram bot, uninstall kokoro, clean tts, teardown, component removal.
send-message
Use when user wants to send a text message on Telegram as their personal account via MTProto, text someone, or message a contact by username, phone, or chat ID.
send-media
Use when user wants to send or upload a file, photo, video, voice note, or document on Telegram via their personal account.
search-messages
Use when user wants to search for messages across all Telegram chats or within a specific chat, find old messages by text, or look up Telegram message history filtered by sender.