Skill ai mindshare map
AI Mindshare Map measures how visible a company or market is to AI assistants: which companies ChatGPT recommends, how prominently, and which sources shape the answer. Roleplays audience personas, runs their questions through GPT-5.2 under a ChatGPT-like system prompt with web search, and builds a competitive leaderboard from the answers and their citations. Data collection and analysis only; produces structured JSON for downstream orchestrators. Use when: AI visibility mapping, competitive mapping, citation analysis, source gap identification. Triggers: "mindshare map", "AI mindshare", "AI visibility map", "AI visibility", "competitive mapping", "citation analysis", "source gap analysis", "who does AI recommend".From its SKILL.md
npx -y skills add unfamiliar-city/skill-ai-mindshare-mapAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
12.5 KB, ~3.0k tokens by cl100k_base, as published. Nobody here has run it
AI Mindshare Map
Competitive intelligence tool: discover your audience, query AI systems, analyze responses, build competitive leaderboards, identify source gaps.
Command Syntax
/mindshare-map --entity <url> [--frame "..."] [--name <slug>] [--skip-validation] [--intents-per-track=N] [--intents=N]
Entity mode: tracks a specific company/brand.
/mindshare-map --market "<description>" [--frame "..."] [--name <slug>] [--skip-validation] [--intents-per-track=N] [--intents=N]
Market mode: landscape analysis without a focal entity.
Options:
--frame "..."Intent/persona dial — who is searching and why (default: buyers researching options)--name <slug>Work directory name (default: derived from URL domain or market description)--skip-validationSkip ICP confirmation (use inferred ICPs; buyer → default tracks, other → trackless)--intents-per-track=NIntents per track in tracked mode (default: 6)--intents=NIntents per ICP in trackless mode (default: 12)
Examples:
/mindshare-map --entity https://example.com→work/example-com-20260213//mindshare-map --market "creative agencies"→work/creative-agencies-20260213//mindshare-map --entity https://foo.com --name=foo-q1-2026→work/foo-q1-2026//mindshare-map --entity https://foo.com --frame "investors assessing category leaders"
Dependencies
- Playwright MCP: Audience discovery research
- WebFetch: Audience discovery research
- Bash: Running pipeline
- OpenAI API: GPT-5.2 for queries, GPT-5-mini for full-tier source assessment, GPT-5-nano for extraction/analysis/light-tier assessment
- tuff-lil-unit: Pipeline execution — crash recovery, step memoisation, concurrency
Work Directory
Each run gets a dated directory under work/:
work/creative-agencies-20260213/
audience-profile.json # ICPs + intents + target_focus (project identity)
subject-context.json # Research knowledge
tuff.db # SQLite: tuff steps + domain tables (queryable)
distillation.json # Full competitive landscape output
Outputs
- distillation.json — single file with full competitive landscape:
meta— schema version, run ID, mode, timestamp, query count, response rate, primary entity typeslandscape— query_answer entities grouped by type (company, product, …), ranked by reachother_entities— authority_source/platform entities grouped by typeby_icp— per-ICP breakdown:{ icp_001: { landscape: {…}, other_entities: {…} } }sources.market— by_publisher_type, per-domain assessments (each withsource_type,is_competitor,authority,citation_count,citation_count_by_icp)client— position, category_position, salience, visibility, reputation (entity mode only)
- tuff.db — queryable via
sqlite3: step status, token usage, domain tables
DB: detail behind distillation summaries
tuff.db retains full detail that distillation summarises. Query with sqlite3 tuff.db:
| Want | Table → column |
|---|---|
| Source authority reasoning + signals | assessments.result → authority |
| Source format + competitor relationship | assessments → source_type, is_competitor |
| All cited URLs per domain | assessments.result → urls |
| Per-response mention detail (salience, ICP, query) | analysed.mentions |
| Full GPT response text | queries.response |
| Fetched source page content | sources.content |
| Raw entity extractions per source | extractions.entities |
Setup (first run)
A SessionStart hook installs tuff-lil-unit into ${CLAUDE_PLUGIN_DATA} automatically and re-runs if package.json changes. Confirm OPENAI_API_KEY is set via shell (Keychain-backed recommended, exported from ~/.zshenv — see README). Playwright MCP is optional (entity-mode site research falls back to WebFetch without it).
If a pipeline phase fails with Could not locate the bindings file (a better-sqlite3 native-binding error), the install skipped its native build step. Fix: cd ${CLAUDE_PLUGIN_DATA} && npm rebuild better-sqlite3, then retry the phase.
Phase 0: Work Directory Setup
Before anything else, resolve the work directory:
- Derive slug from input:
--entity: extract domain, slugify →example-com--market: slugify description →creative-agencies--name=flag overrides (no date suffix added)
- Add date suffix:
${slug}-${YYYYMMDD}(e.g.,creative-agencies-20260213)- Skip if
--name=was provided (user controls full name)
- Skip if
- Set
WORK_DIR=work/${slug}-${YYYYMMDD}/ - Check if exists: if
WORK_DIRalready contains data, prompt user:work/creative-agencies-20260213/ already exists. Overwrite, or use a different name? - Create directory:
mkdir -p ${WORK_DIR}
All subsequent phases use --work-dir=${WORK_DIR}.
Phase 1: Audience Discovery
Subagent-driven research + user validation. Produces audience-profile.json.
Step 1.0: Frame
Capture --frame flag (default: buyer frame).
Step 1.1: Generate ICPs
Task({
subagent_type: 'general-purpose',
prompt: `Execute: references/${'entity' in subject
? 'entity-mode-instructions' : 'market-mode-instructions'}.md\n\n${
'entity' in subject ? `Entity URL: ${subject.entity}` : `Market: "${subject.market}"`}\n\nWORK_DIR: ${WORK_DIR} — write subject-context.json into this directory, not a hardcoded work/ path.`
})
Step 1.2: Validate ICPs
Present proposed ICPs to user. Collect feedback, refine if needed. Skip if --skip-validation.
If discovery returned research_limited (entity mode, a JS-rendered site WebFetch couldn't read), tell the user — even under --skip-validation:
{entity}looks JS-rendered, so these ICPs lean more on general web research than on its site. Installing Playwright MCP would let me read the full site — add it and re-run discovery, or proceed with these?
Step 1.2a: Track Selection
After ICPs are confirmed, decide market-mapping tracks:
| Frame | With --skip-validation | Interactive |
|---|---|---|
| Buyer | Default tracks (4) | Offer defaults or trackless |
| Custom | Trackless | Propose custom tracks or trackless |
Default tracks: landscape, recommendation, specialization, scenario. All tracks must be entity-surfacing. See references/intent-query-generation-instructions.md for phrasing guidance.
Step 1.3: Generate Intents + Queries
One subagent per ICP, in parallel. Build a roleplay brief for each ICP using three neutral slots interpreted through the frame:
| Slot | Buyer | Investor | Journalist |
|---|---|---|---|
motivations | goals | investment thesis | beat and angle |
constraints | pain points | due diligence concerns | editorial constraints |
context | current situation | portfolio context | current assignments |
Record the constructed brief in the ICP's brief block in audience-profile.json before sending to the subagent.
Use tracked or trackless template from references/intent-query-generation-instructions.md. Tracked: --intents-per-track=N (default 6), intent JSON includes track. Trackless: --intents=N (default 12), track omitted.
const icpResults = await Promise.all(confirmedICPs.map(icp =>
Task({
subagent_type: 'general-purpose',
model: 'sonnet',
prompt: buildRoleplayBrief(icp, confirmedTracks, trackless)
})
))
Step 1.3b: Query Review
Single review subagent (Sonnet) scans all generated queries for methodology problems. Returns flagged queries with reasons; orchestrator fixes or drops before presenting to user.
Task({
subagent_type: 'general-purpose',
model: 'sonnet',
prompt: `Review these generated queries for research methodology problems...\n${allQueries}`
// See references/query-review-instructions.md for criteria and output format
})
Step 1.4: Validate Intents + Write Profile
Present intents to user, collect feedback. Write ${WORK_DIR}/audience-profile.json. Skip validation if --skip-validation.
Phase 2: Pipeline (task-based, background jobs)
Step 2.1: Create Tasks + Set Dependencies
const query = TaskCreate({
subject: "Query GPT for all ICPs",
description: "Bash({ run_in_background: true, command: 'NODE_PATH=${CLAUDE_PLUGIN_DATA}/node_modules npm run --prefix ${CLAUDE_PLUGIN_ROOT} pipeline:query -- --work-dir=${WORK_DIR}' })",
activeForm: "Querying GPT"
})
const fetch = TaskCreate({
subject: "Fetch cited URLs",
description: "Bash({ run_in_background: true, command: 'NODE_PATH=${CLAUDE_PLUGIN_DATA}/node_modules npm run --prefix ${CLAUDE_PLUGIN_ROOT} pipeline:fetch -- --work-dir=${WORK_DIR}' })",
activeForm: "Fetching URLs"
})
const extract = TaskCreate({
subject: "Extract entities from sources",
description: "Bash({ run_in_background: true, command: 'NODE_PATH=${CLAUDE_PLUGIN_DATA}/node_modules npm run --prefix ${CLAUDE_PLUGIN_ROOT} pipeline:extract -- --work-dir=${WORK_DIR}' })",
activeForm: "Extracting entities"
})
const assess = TaskCreate({
subject: "Assess source authority",
description: "Bash({ run_in_background: true, command: 'NODE_PATH=${CLAUDE_PLUGIN_DATA}/node_modules npm run --prefix ${CLAUDE_PLUGIN_ROOT} pipeline:assess -- --work-dir=${WORK_DIR}' })",
activeForm: "Assessing sources"
})
const analyse = TaskCreate({
subject: "Analyse GPT responses",
description: "Bash({ run_in_background: true, command: 'NODE_PATH=${CLAUDE_PLUGIN_DATA}/node_modules npm run --prefix ${CLAUDE_PLUGIN_ROOT} pipeline:analyse -- --work-dir=${WORK_DIR}' })",
activeForm: "Analysing responses"
})
const distill = TaskCreate({
subject: "Distill competitive landscape",
description: "Bash({ run_in_background: true, command: 'NODE_PATH=${CLAUDE_PLUGIN_DATA}/node_modules npm run --prefix ${CLAUDE_PLUGIN_ROOT} pipeline:distill -- --work-dir=${WORK_DIR}' }). Outputs: distillation.json",
activeForm: "Distilling landscape"
})
// Dependency graph:
// Query → Fetch → Extract → Assess ─┐
// └──→ Analyse ────────────────────┴→ Distill
TaskUpdate({ taskId: fetch.id, addBlockedBy: [query.id] })
TaskUpdate({ taskId: extract.id, addBlockedBy: [fetch.id] })
TaskUpdate({ taskId: assess.id, addBlockedBy: [extract.id] })
TaskUpdate({ taskId: analyse.id, addBlockedBy: [query.id] })
TaskUpdate({ taskId: distill.id, addBlockedBy: [assess.id, analyse.id] })
Step 2.2: Execute Task Graph
Begin with query. On each completion: mark task done, start unblocked dependents.
Monitoring progress — each phase writes to DB per-item. Check progress any time:
NODE_PATH=${CLAUDE_PLUGIN_DATA}/node_modules npm run --prefix ${CLAUDE_PLUGIN_ROOT} pipeline:progress -- --work-dir=${WORK_DIR} query # single phase: "query: 24/24"
NODE_PATH=${CLAUDE_PLUGIN_DATA}/node_modules npm run --prefix ${CLAUDE_PLUGIN_ROOT} pipeline:progress -- --work-dir=${WORK_DIR} # all phases
On crash or interruption: re-run the failed phase — tuff step memoisation skips completed items.
Full pipeline (non-interactive): NODE_PATH=${CLAUDE_PLUGIN_DATA}/node_modules npm run --prefix ${CLAUDE_PLUGIN_ROOT} pipeline -- --work-dir=${WORK_DIR} runs all 6 phases sequentially.
Phase 3: Delivery
Once pipeline completes, present outputs to user:
**AI Mindshare Map complete** → `${WORK_DIR}/`
**Outputs:**
- `${WORK_DIR}/distillation.json` — competitive landscape data
- `${WORK_DIR}/audience-profile.json` — ICPs + intents
**Key Findings:**
- Entities discovered: {{entities_discovered}}
- Source-backed: {{source_backed_count}}
- Target rank: #{{rank}} of {{rank_of}} *(entity mode only)*
What ships with it: 53 files
242.1 KB alongside SKILL.md, 37 of them executable
.claude/
- settings.json92 B
assets/
docs/
- vendoring-system-prompts.md10.6 KB
evals/
- evals.json1.9 KB
hooks/
- hooks.json459 B
references/
scripts/
- db/progress.mjsruns3.3 KB
- db/readers.mjsruns1.9 KB
- db/schema.mjsruns1.7 KB
- execution-config.mjsruns3.5 KB
- logic/analyze.mjsruns13.7 KB
- logic/citation-analysis.mjsruns3.9 KB
- logic/competitive/index.mjsruns387 B
- logic/competitive/leaderboard.mjsruns5.3 KB
- logic/competitive/scoring.mjsruns2.7 KB
- logic/competitive/visibility.mjsruns6.9 KB
- logic/content-analysis.mjsruns4.0 KB
- logic/distillation/citation-assessment.mjsruns2.4 KB
- logic/distillation/index.mjsruns5.0 KB
- logic/distillation/metrics.mjsruns4.3 KB
- logic/distillation/reputation.mjsruns6.1 KB
- logic/extract-sources.mjsruns1.9 KB
- logic/fetch-urls.mjsruns9.5 KB
- logic/followup.mjsruns2.6 KB
- logic/llm.mjsruns5.7 KB
- logic/prompts/followup.mjsruns2.6 KB
- logic/prompts/gpt-5.5-instant.md26.2 KB
- logic/prompts/index.mjsruns587 B
- logic/prompts/README.md3.4 KB
- logic/prompts/reputation-themes.mjsruns2.6 KB
- logic/prompts/response-analysis.mjsruns9.4 KB
- logic/prompts/source-extraction.mjsruns1.7 KB
- logic/prompts/source-quality.mjsruns7.7 KB
- .gitignore394 B
- package.json772 B
- README.md6.9 KB
13 more files not listed here. See all 53 in the repository.