Publish SEO Batch
PramodDutta/qaskills
A skill your agent uses when publishing SEO blog articles to qaskills.sh, e.g.
Counts and compares blog posts across a target and competitors, audits content freshness via sitemap lastmod dates, and maps competitor organic keywords (US, non-branded, informational) against the…
$ npx skills add Infrasity-Labs/dev-gtm-claude-skills --skill blog-post-counter -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install Infrasity-Labs/dev-gtm-claude-skills blog-post-counter --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/Infrasity-Labs/dev-gtm-claude-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/blog-post-counter .claude/skills/blog-post-counter && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "blog-post-counter" agent skill from https://github.com/Infrasity-Labs/dev-gtm-claude-skills/tree/main/skills/blog-post-counter into .claude/skills/blog-post-counter/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "blog-post-counter", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/Infrasity-Labs/dev-gtm-claude-skills/tree/main/skills/blog-post-counterType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add Infrasity-Labs/dev-gtm-claude-skills --skill blog-post-counter -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install Infrasity-Labs/dev-gtm-claude-skills blog-post-counter --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Infrasity-Labs/dev-gtm-claude-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/blog-post-counter .agents/skills/blog-post-counter && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "blog-post-counter" agent skill from https://github.com/Infrasity-Labs/dev-gtm-claude-skills/tree/main/skills/blog-post-counter into .agents/skills/blog-post-counter/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "blog-post-counter", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Infrasity-Labs/dev-gtm-claude-skills --skill blog-post-counter -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install Infrasity-Labs/dev-gtm-claude-skills blog-post-counter --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Infrasity-Labs/dev-gtm-claude-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/blog-post-counter .cursor/skills/blog-post-counter && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "blog-post-counter" agent skill from https://github.com/Infrasity-Labs/dev-gtm-claude-skills/tree/main/skills/blog-post-counter into .cursor/skills/blog-post-counter/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "blog-post-counter", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/Infrasity-Labs/dev-gtm-claude-skills.git --path skills/blog-post-counter--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add Infrasity-Labs/dev-gtm-claude-skills --skill blog-post-counter -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install Infrasity-Labs/dev-gtm-claude-skills blog-post-counter --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Infrasity-Labs/dev-gtm-claude-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/blog-post-counter .gemini/skills/blog-post-counter && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "blog-post-counter" agent skill from https://github.com/Infrasity-Labs/dev-gtm-claude-skills/tree/main/skills/blog-post-counter into .gemini/skills/blog-post-counter/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "blog-post-counter", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install Infrasity-Labs/dev-gtm-claude-skills blog-post-counterInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add Infrasity-Labs/dev-gtm-claude-skills --skill blog-post-counter -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/Infrasity-Labs/dev-gtm-claude-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/blog-post-counter .github/skills/blog-post-counter && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "blog-post-counter" agent skill from https://github.com/Infrasity-Labs/dev-gtm-claude-skills/tree/main/skills/blog-post-counter into .github/skills/blog-post-counter/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "blog-post-counter", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Infrasity-Labs/dev-gtm-claude-skills --skill blog-post-counter -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install Infrasity-Labs/dev-gtm-claude-skills blog-post-counter --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Infrasity-Labs/dev-gtm-claude-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/blog-post-counter .opencode/skills/blog-post-counter && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "blog-post-counter" agent skill from https://github.com/Infrasity-Labs/dev-gtm-claude-skills/tree/main/skills/blog-post-counter into .opencode/skills/blog-post-counter/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "blog-post-counter", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
blog-post-counterCounts and compares blog posts across a target and competitors, audits content freshness via sitemap lastmod dates, and maps competitor organic keywords (US, non-branded, informational) against the…
Blog Post Counter is an agent skill from Infrasity-Labs/dev-gtm-claude-skills. Counts and compares blog posts across a target and competitors, audits content freshness via sitemap lastmod dates, and maps competitor organic keywords (US, non-branded, informational) against the target to surface ranking gaps. Use when asked to compare blog counts, content volume, publishing cadence, content freshness, keyword mapping, keyword gap analysis, or competitor keyword reports — e.g. "how many blog posts does X have vs Y", "how fresh is content on X", "where does [target] rank for [competitor]…
Its SKILL.md is about 3.9k tokens, which your agent loads only when the skill is triggered. The skill folder holds 1 other file (for example `README.md`).
It sits in Writing & Content, covering Blog and article writing and Keyword research. The repository describes itself as: Open-source Claude skills for GEO, AI discoverability, and developer GTM workflows. Built for developer-focused companies that want their documentation to be found, parsed, and… The licence is MIT.
8 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 02cfefb. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
curlpython3From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use curl, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Blog Post Counter loads about 3.9k tokens when it runs. Until then it costs about 170 tokens; SKILL.md has 1,640 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from Infrasity-Labs/dev-gtm-claude-skills at commit 02cfefb, republished under its MIT licence (© Infrasity-Labs). 1,640 words, ~3,859 tokens.
.claude/skills/blog-post-counter/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.Two workflows in one skill:
For each company name provided:
curl -sL "https://<likely-domain>/robots.txt" to confirm the site exists and find the sitemap. If that 404s, do a quick web search for "<company name>" official website to get the correct domain.From the robots.txt, extract the Sitemap: line(s). Common patterns:
Sitemap: https://example.com/sitemap.xmlSitemap: lines, or a sitemap-index.xml that references sub-sitemapsIf no sitemap is in robots.txt, try these fallbacks in order:
/sitemap.xml
/sitemap_index.xml
/sitemap-index.xml
/blog/sitemap.xmlFetch the sitemap and count URLs that are blog posts. Use this bash pattern:
curl -sL -A "Mozilla/5.0" "https://example.com/sitemap.xml" \
| grep -o '<loc>[^<]*</loc>' \
| grep -iE '/blog/|/posts?/|/articles?/|/news/' \
| grep -v -E '^<loc>https://[^/]+/blog/?</loc>$' \
| wc -lImportant: Exclude the blog index page itself (e.g. /blog or /blog/) — count only individual post URLs.
Sitemap index handling: If the sitemap is an index (contains <sitemap> tags rather than <url> tags), extract the sub-sitemap URLs and fetch the blog-specific one:
curl -sL -A "Mozilla/5.0" "https://example.com/sitemap-index.xml" \
| grep -o '<loc>[^<]*</loc>' \
| grep -i 'blog'
# Then fetch that sub-sitemap and countJS-rendered sites: Some blog pages render via JavaScript and may not expose counts through sitemaps. In that case, fall back to site:example.com/blog search operator to estimate.
Edge cases:
/resources/, /insights/, /learn/, or /hub/ instead of /blog/ — check the sitemap structure if a /blog/ grep returns 0.Once all counts are collected, produce a ranked table with the target company highlighted:
Blog Post Count — [Target] vs Competitors
==========================================
Rank Company Posts URL
──── ─────────────── ────── ──────────────────────
1 Hackmamba 137 hackmamba.io ← COMPETITOR
2 Infrasity 137 infrasity.com ← COMPETITOR
3 ▶ Kubiya 95 kubiya.ai ← TARGET
4 Orgn 7 orgn.com ← COMPETITOR
▶ = your company Total companies analysed: 4Then add a brief summary:
Run this audit whenever the user asks about content freshness, recency, publishing cadence, or when it adds useful context to the blog count comparison.
For each domain, extract only blog post URLs and their lastmod dates from the sitemap:
curl -sL "https://example.com/sitemap.xml" \
| python3 -c "
import sys, re
content = sys.stdin.read()
urls = re.findall(r'<url>(.*?)</url>', content, re.DOTALL)
for u in urls:
loc = re.search(r'<loc>(.*?)</loc>', u)
lastmod = re.search(r'<lastmod>(.*?)</lastmod>', u)
if loc and lastmod:
l = loc.group(1)
if re.search(r'/blog/|/posts?/|/articles?/|/news/', l) and not re.match(r'https?://[^/]+/(blog|posts?|articles?|news)/?$', l):
print(lastmod.group(1), l)
"Before treating lastmod dates as real signals, check whether they are genuine per-post edit dates or build-time bulk stamps:
from datetime import datetime, timezone
dates = [...] # all lastmod values for blog posts
unique_dates = set(d[:10] for d in dates) # compare date part only
if not dates:
stamp_type = "UNKNOWN"
elif len(unique_dates) <= 3:
# Likely build-time stamps — flag as unreliable
stamp_type = "BUILD-TIME"
else:
stamp_type = "REAL"Build-time stamps = all (or nearly all) blog posts share the same date, usually within a narrow time window (seconds to minutes). This is common with Next.js/Vercel and similar SSG frameworks that regenerate the sitemap on every deploy. These dates do NOT reflect when content was actually written or updated.
Real dates = each post has a distinct lastmod that varies across weeks or months. These are trustworthy freshness signals.
Always flag build-time stamps clearly in the output so the user understands the dates are not meaningful for SEO or content analysis.
Using today's date, bucket each blog post's lastmod into:
| Bucket | Age |
|---|---|
| Last 30 days | < 30 days old |
| 30–90 days | 30–89 days old |
| 91–180 days | 90–179 days old |
| 181–365 days | 180–364 days old |
| Over 365 days | 365+ days old |
from datetime import datetime, timezone
today = datetime.now(timezone.utc)
buckets = {"<30d": 0, "30-90d": 0, "91-180d": 0, "181-365d": 0, ">365d": 0}
for date_str in lastmod_dates:
dt = datetime.fromisoformat(date_str.replace('Z', '+00:00'))
if dt.tzinfo is None:
dt = dt.replace(tzinfo=timezone.utc)
days = (today - dt).days
if days < 30: buckets["<30d"] += 1
elif days < 90: buckets["30-90d"] += 1
elif days < 180: buckets["91-180d"] += 1
elif days < 365: buckets["181-365d"] += 1
else: buckets[">365d"] += 1Also compute:
YYYY-MM to show volume over timeProduce a per-domain freshness summary alongside (or below) the blog count table. Use the visualiser to render a side-by-side comparison widget when comparing multiple domains. The widget must show:
SEO freshness interpretation to include in the summary:
/blog index page should never be counted as a post.Maps a competitor's organic keyword footprint against a target domain to surface content gaps and ranking opportunities.
Pull org_keywords and org_traffic for both competitor and target via Ahrefs site-explorer-metrics:
tool: site-explorer-metrics
params:
target: <domain>
mode: subdomains
date: <latest>
select: org_keywords, org_trafficDo this for both domains. The org_keywords count tells you how many batches you'll need to capture the full keyword set.
Pull the competitor's full keyword set using Ahrefs site-explorer-organic-keywords with these fixed filters:
tool: site-explorer-organic-keywords
params:
target: <competitor domain>
country: us
mode: subdomains
is_branded: false
is_informational: true
limit: 500
select: keyword, volume, best_position, sum_traffic, best_position_url, is_brandedPull multiple batches using different order_by values to maximize coverage:
order_by: sum_traffic:descorder_by: volume:descorder_by: best_position:ascAfter each batch, deduplicate by keyword across all batches collected so far. Keep the entry with the lowest (best) best_position per keyword.
Continue batching until no new keywords appear across two consecutive batches, or until batch count exceeds the expected keyword universe from Step 1.
Exact same pull for the target domain — same filters, same multiple sort orderings, same deduplication logic.
tool: site-explorer-organic-keywords
params:
target: <target domain>
country: us
mode: subdomains
is_branded: false
is_informational: true
limit: 500
select: keyword, volume, best_position, sum_traffic, best_position_url, is_brandedStore the result as a lookup map: { keyword → { best_position, sum_traffic, best_position_url } }
For each competitor keyword from Step 2, look it up in the target map from Step 3. Assign a status:
Both rank:
WINNING — target position < competitor position (target is ahead)IMPROVE — competitor position < target position (competitor is ahead)Target does not rank:
CRITICAL — volume ≥ 1,000HIGH — volume 500–999MEDIUM — volume 200–499LOW — volume 100–199NEW — volume < 100Each row in the output represents one competitor keyword. Fields per row:
keywordvolumecompetitor_rank (best_position)competitor_traffic (sum_traffic)target_rank (best_position, or null)target_traffic (sum_traffic, or null)target_url (best_position_url, or null)statusis_branded=false and is_informational=true filters are applied at pull time — not as post-processing. This keeps the dataset clean from the start.Both workflows feed into a single HTML report file. Run Workflow A and Workflow B fully first, collect all data, then generate the report in one pass.
[Target] vs [Competitor] — Content & Keyword Reportorg_keywords and org_traffic for each.html file — no external dependencies except Google Fonts CDN/mnt/user-data/outputs/report-[target]-vs-[competitor].htmlpresent_files after saving© Infrasity-Labs, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 1 other file in skills/blog-post-counter of Infrasity-Labs/dev-gtm-claude-skills.
Open the folder on GitHubat commit 02cfefb
Blog Post Counter next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Blog Post Counter this skillInfrasity-Labs/dev-gtm-claude-skills | 136 | — | ~3.9k | Automated safety check: Pass | MIT | |
| Publish SEO BatchPramodDutta/qaskills | 235 | — | ~2.2k | Automated safety check: Pass | MIT | |
| Blog CannibalizationAgriciDaniel/claude-blog | 2.3k | 1 repos | ~2.2k | Automated safety check: Pass | MIT | |
| Article Writingericrisco/rsc-harness | 180 | — | ~2.9k | Automated safety check: Pass | MIT | |
| Ink Briefjeremylongshore/tons-of-skills-marketplace | 2.8k | — | ~1.2k | Automated safety check: Notes | MIT | |
| SEO Keyword ResearchVarnan-Tech/opendirectory | 674 | — | ~1.8k | Automated safety check: Pass | MIT |
PramodDutta/qaskills
A skill your agent uses when publishing SEO blog articles to qaskills.sh, e.g.
AgriciDaniel/claude-blog
Detect keyword cannibalization across blog posts by extracting primary keywords from titles and headings, clustering semantically similar targets, and flagging posts competing for the same search…
ericrisco/rsc-harness
A skill your agent uses when writing one long-form article end to end — answer-first lede, question-shaped headings, plus its on-page surface (title, meta, slug, FAQ, Article/FAQPage JSON-LD) — or…
jeremylongshore/tons-of-skills-marketplace
Content brief generator — takes a topic or keyword and produces a complete content brief with target keyword, search intent, recommended structure, internal link targets, word count, CTA, and…
Varnan-Tech/opendirectory
SEO keyword research workflow for blog generation using Google Trends data.
sickn33/agentic-awesome-skills
Writes search-intent-led long-form articles with answer-first structure, FAQ coverage, internal links, and conversion paths for SEO and AEO.
Infrasity-Labs/dev-gtm-claude-skills
Generates a fully structured SEO content outline (not a finished brief) and exports it as a formatted .docx Word document.
Infrasity-Labs/dev-gtm-claude-skills
Generates a fully structured SEO content brief for a target keyword and optionally pushes it to a Notion database.
Infrasity-Labs/dev-gtm-claude-skills
Audits any API documentation site by crawling every endpoint page and scoring each one across 5 checks: description quality, OpenAPI spec presence, body param descriptions, response codes, and…
Infrasity-Labs/dev-gtm-claude-skills
Audits any developer documentation site across 33 checks in 7 categories and produces a scored report (out of 100) with Pass / Warn / Fail status per check.
Infrasity-Labs/dev-gtm-claude-skills
Generates a 3-month SEO performance HTML report for any domain using DataForSEO data.
Infrasity-Labs/dev-gtm-claude-skills
Email triage system that handles both one-time setup and recurring triage in a single skill.
Categories
Counts and compares blog posts across a target and competitors, audits content freshness via sitemap lastmod dates, and maps competitor organic keywords (US, non-branded, informational) against the…. Blog Post Counter is an agent skill from Infrasity-Labs/dev-gtm-claude-skills. Counts and compares blog posts across a target and competitors, audits content freshness via sitemap lastmod dates, and maps competitor organic keywords (US, non-branded, informational) against the target to surface ranking gaps.
Blog Post Counter fits situations like: asked to compare blog counts; publishing cadence; content freshness; keyword mapping.
Run `npx skills add Infrasity-Labs/dev-gtm-claude-skills --skill blog-post-counter -a claude-code`. Or copy the skill folder (skills/blog-post-counter in Infrasity-Labs/dev-gtm-claude-skills) into .claude/skills/blog-post-counter in your project. Claude Code loads it when a task matches its description.
Run `npx skills add Infrasity-Labs/dev-gtm-claude-skills --skill blog-post-counter -a codex`. Or copy the skill folder (skills/blog-post-counter in Infrasity-Labs/dev-gtm-claude-skills) into .agents/skills/blog-post-counter in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Infrasity-Labs/dev-gtm-claude-skills --skill blog-post-counter -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/blog-post-counter, .gemini/skills/blog-post-counter, .github/skills/blog-post-counter and .opencode/skills/blog-post-counter in your project.
Going by SKILL.md and its folder, Blog Post Counter needs the command-line tools its instructions call (curl and python3). Our summary lists: Python 3.
SKILL.md contains no URLs. Its commands use curl, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Blog Post Counter is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3.9k tokens (SKILL.md is roughly 15k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Blog Post Counter: Publish SEO Batch (PramodDutta/qaskills, 235 stars), Blog Cannibalization (AgriciDaniel/claude-blog, 2.3k stars), Article Writing (ericrisco/rsc-harness, 180 stars) and Ink Brief (jeremylongshore/tons-of-skills-marketplace, 2.8k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
Infrasity-Labs (a GitHub user) maintains it in Infrasity-Labs/dev-gtm-claude-skills, which has 136 GitHub stars. The repository holds 26 skills in this directory. The repository was last updated on June 28, 2026.
Source: Infrasity-Labs/dev-gtm-claude-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.