AgentStack
SKILL verified MIT Self-run

Hoo Keyword Intel

skill-shalintripathi-organic-os-hoo-keyword-intel · by shalintripathi

Use for keyword research, competitor keyword gaps, "what should we rank for", "keyword ideas for X", or the /organic-os:keywords command. Detects the user's Google Ads access tier and degrades honestly.

No reviews yet
0 installs
1 views
0.0% view→install

Install

$ agentstack add skill-shalintripathi-organic-os-hoo-keyword-intel

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Hoo Keyword Intel? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Keyword intelligence (tiered)

  1. Read site-profile.yaml (google_ads.status, keywords.targets, competitors,

geos, languages). Source env from ~/.config/organic-os/.env if present.

Tier detection (once per session)

Run: PYTHONPATH="$CLAUDE_PLUGIN_ROOT/lib" python3 -c "..." snippet importing hoo.google_ads.tier: if env vars missing -> tier "none". Else build real_client() and tier.detect() -> basic|explorer. Tell the user which tier is active and what that enables.

basic (or standard)

  1. Ideas: keyword_ideas.run with profile target keywords as seeds AND, per

competitor, site_seed=. Cache dir: /keywords/cache/.

  1. Gap: ideas(own siteseed) vs ideas(competitor siteseed) - keywords in

their set, absent from ours, volume >= 100. Rank by volume x profile fit.

  1. Metrics for the shortlist: historical.run (batches of 200 handled inside).
  2. Write runs/YYYYMMDD-keywords/ (01-ideas.json, 02-gaps.json, REPORT.md)

and update keywords/tracking.yaml targets the user confirms (additions are a strategy mutation -> create_item kind="strategy" + approval gate).

explorer

Own-account GAQL only: searchtermview mining (queries with impressions and no matching target), keywordview quality scores. State plainly: "Planner blocked at Explorer tier - apply for Basic (https://github.com/shalintripathi/organic-os/blob/main/plugin/docs/credentials/google-ads-token.md, also at $CLAUDEPLUGIN_ROOT/docs/credentials/google-ads-token.md in a local checkout)".

none (no token)

GSC query mining via the user's GSC connector: 16 months, queries with impressions > 100 and position 8-30 = the opportunity set. If no GSC either: offer CSV import.

csv (always available)

Accept a Keyword Planner UI export: csv_import.load_planner_csv(path). Auction Insights CSVs: summarize overlap/position trends per competitor.

Tracked-keyword management: add keywords to track by editing keywords/tracking.yaml or asking in-session; the weekly run records their GSC history (skills/hoo-weekly, Keyword portfolio section).

Output in every tier: REPORT.md with the top 20 opportunities, each carrying volume (or proxy), difficulty proxy, intent guess, recommended action (new page | optimize existing | ignore), and the evidence line.

Cluster the ideas

Runs when the pull above produced 30 or more ideas (any tier). Fewer than 30: skip silently - too few ideas cluster into noise, and a skip note would only add chrome.

  1. Group the ideas by intent + lexical family into named clusters

(shared head term, shared modifiers, same question family).

  1. For each cluster: pick the hub - the highest-volume informational head

term - and list the spokes (the remaining ideas that belong to it).

  1. Check existing coverage: map each cluster against the site's published

pages via the sitemap and, when the GSC connector is available, the pages already earning impressions for the cluster's queries. A cluster whose hub and spokes are already covered is reported as covered, not re-proposed.

  1. Per UNCOVERED cluster, write ONE architecture signal (append_signal):

the hub topic, 3-5 spoke topics, and the internal-linking rule - every spoke links the hub, the hub links every spoke. This is the build-time complement of the link-graph dimension's shallow striking-distance play (skills/onsite-audit step 4): pages born inside a cluster never start with fewer than 2 inbound internal links.

  1. At most ONE cluster per run becomes a gated brief: for the best

uncovered cluster, create_item(kind="content-brief", ...) targeting the hub, brief_type per the hub's intent (comparison-intent hub -> brief_type="comparison"; absence means explainer). Gated through the approval queue like every other proposal; the remaining clusters stay signals until a future run.

Pattern credit: claude-seo's SERP clustering (https://github.com/AgriciDaniel/claude-seo), adapted here to consume keyword-intel output instead of running its own SERP pulls.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.