Community研究與資料分析github.com

unfamiliar-city/skill-ai-mindshare-map

Claude Code skill that measures how visible a company or market is to AI assistants (ChatGPT) and maps who gets recommended and why.

skill-ai-mindshare-map 是什麼?

skill-ai-mindshare-map is a Claude Code agent skill that claude Code skill that measures how visible a company or market is to AI assistants (ChatGPT) and maps who gets recommended and why.

相容平台Claude CodeCodex CLI~Cursor
npx skills add unfamiliar-city/skill-ai-mindshare-map

Installed? Explore more 研究與資料分析 skills: obra/superpowers, affaan-m/quarkus-verification, affaan-m/uspto-database · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

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-validation Skip ICP confirmation (use inferred ICPs; buyer → default tracks, other → trackless)
  • --intents-per-track=N Intents per track in tracked mode (default: 6)
  • --intents=N Intents per ICP in trackless mode (default: 12)

Examples:

  • /mindshare-map --entity https://example.comwork/example-com-20260213/
  • /mindshare-map --market "creative agencies"work/creative-agencies-20260213/
  • /mindshare-map --entity https://foo.com --name=foo-q1-2026work/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

  1. distillation.json — single file with full competitive landscape:
    • meta — schema version, run ID, mode, timestamp, query count, response rate, primary entity types
    • landscape — query_answer entities grouped by type (company, product, …), ranked by reach
    • other_entities — authority_source/platform entities grouped by type
    • by_icp — per-ICP breakdown: { icp_001: { landscape: {…}, other_entities: {…} } }
    • sources.market — by_publisher_type, per-domain assessments (each with source_type, is_competitor, authority, citation_count, citation_count_by_icp)
    • client — position, category_position, salience, visibility, reputation (entity mode only)
  2. 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:

WantTable → column
Source authority reasoning + signalsassessments.resultauthority
Source format + competitor relationshipassessmentssource_type, is_competitor
All cited URLs per domainassessments.resulturls
Per-response mention detail (salience, ICP, query)analysed.mentions
Full GPT response textqueries.response
Fetched source page contentsources.content
Raw entity extractions per sourceextractions.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:

  1. Derive slug from input:
    • --entity: extract domain, slugify → example-com
    • --market: slugify description → creative-agencies
    • --name= flag overrides (no date suffix added)
  2. Add date suffix: ${slug}-${YYYYMMDD} (e.g., creative-agencies-20260213)
    • Skip if --name= was provided (user controls full name)
  3. Set WORK_DIR = work/${slug}-${YYYYMMDD}/
  4. Check if exists: if WORK_DIR already contains data, prompt user:

    work/creative-agencies-20260213/ already exists. Overwrite, or use a different name?

  5. 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:

FrameWith --skip-validationInteractive
BuyerDefault tracks (4)Offer defaults or trackless
CustomTracklessPropose 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:

SlotBuyerInvestorJournalist
motivationsgoalsinvestment thesisbeat and angle
constraintspain pointsdue diligence concernseditorial constraints
contextcurrent situationportfolio contextcurrent 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)*

相關技能