Install
$ agentstack add skill-takechanman1228-claude-persona-persona ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo 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 Used
- ✓ Environment & secrets No
- ✓ 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.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
AI Persona Panels for Customer Research
Build reusable persona panels, ask open-ended customer questions, and run concept tests on messages, offers, and product ideas.
3-Step Workflow
Inspired by TinyTroupe (Generate Personas → Simulate Interactions → Extract & Analyze):
| Step | What happens | Component | |------|-------------|-----------| | 1. Build Panel | Define your market, generate diverse personas | Panel Builder | | 2. Run Ask / Concept Test | Each persona responds independently in its own subprocess | Simulation Engine | | 3. Review Findings | Structured report with themes, cross-tabs, charts, and verbatims | Analysis Pipeline |
Recommended workflow:
/persona generate— build a reusable panel/persona ask— explore motivations, barriers, language, and decision criteria/persona concept-test— compare explicit options when ready for a structured choice task
Quality Guidelines
- Take your time with persona generation. Diverse, detailed personas are the foundation of useful results. Do not skip diversity verification.
- Do not skip validation. Always verify response JSON structure before proceeding to analysis.
- Quality over speed. A 5-persona panel with rich, differentiated responses is more valuable than a 15-persona panel with generic answers.
Quick Reference
| Command | What it does | |---------|-------------| | /persona generate Running shoe shoppers in the US | Build a reusable panel (default 5 personas) | | /persona generate --count 10 Gen Z skincare shoppers in the US | Panel with custom size | | /persona generate --segments Canned coffee drinkers in Japan | Segment-driven panel (default 15) | | /persona ask What frustrates you most about choosing skincare products? | Explore motivations and barriers | | /persona ask Why would you ignore an ad for a new running shoe? | Qualitative reaction before concept test | | /persona concept-test Compare 3 running shoe concepts | Concept test — concepts provided interactively | | /persona concept-test --market japan Evaluate 3 canned coffee concepts | Concept test with Japanese panel |
ask explores open-ended motivations, barriers, and language. concept-test covers any comparison research: product concepts, messaging A/B, packaging, competitive comparisons, feature bundles, and value framing with price context.
For detailed input requirements and output descriptions per command, see references/command-details.md.
Argument Parsing Rules
The text after the command is parsed as follows:
- Command (required):
concept-test,generate,ask - Options (optional):
--count N— Panel size (default: 5; not applicable forask)--market MARKET— Target market/country (default: us). Accepts country codes (us,japan/jp,uk,de,fr,cn,kr) or freeform descriptors ("Southeast Asia", "urban Brazil"). Shorthand codes are expanded:us→ United States,japan/jp→ Japan,uk→ United Kingdom, etc.--segments— Activate segment-driven flow; default panel size becomes 15 (not applicable forask)--panel PANEL— (askonly) Specify the panel survey-id to use (e.g.,running-footwear-us-15p-2026-04). Skips auto-detection.
- Free text (optional): Everything else is the research intent — a natural language
description of what the user wants to research. For ask, the free text is the question itself.
Parsing examples:
/persona concept-test Evaluate 3 new canned coffee concepts
→ type: concept-test, count: 5, intent: "Evaluate 3 new canned coffee concepts"
/persona concept-test --count 8 Compare ad headlines for EV launch
→ type: concept-test, count: 8, intent: "Compare ad headlines for EV launch"
/persona concept-test --segments Canned coffee
→ type: concept-test, count: 15, mode: segment-driven, intent: "Canned coffee"
/persona generate --count 15 Running shoes
→ type: generate, count: 15, market: "United States", intent: "Running shoes"
/persona generate --market japan --count 10 Canned coffee
→ type: generate, count: 10, market: "Japan", intent: "Canned coffee"
/persona concept-test --market japan Evaluate 3 new canned coffee concepts
→ type: concept-test, count: 5, market: "Japan", intent: "Evaluate 3 new canned coffee concepts"
/persona ask What frustrates you most about buying running shoes online?
→ type: ask, question: "What frustrates you most about buying running shoes online?", panel: auto-detect
/persona ask --panel running-footwear-us-15p-2026-04 Why would you ignore this ad?
→ type: ask, question: "Why would you ignore this ad?", panel: "running-footwear-us-15p-2026-04"
/persona ask --market japan What makes this product feel overpriced?
→ type: ask, question: "What makes this product feel overpriced?", market: "Japan", panel: auto-detect
When free text is provided:
- Extract the topic from the intent text
- Determine what information is still missing:
concept-test: concept/option details (names + descriptions) — ask only if not in intentask: the question is the free text; no additional info required- If sufficient information is present, proceed without further questions
When no free text is provided:
- Collect all required information interactively (current behavior)
Orchestration Logic
Step 1: Build Panel
- Parse the user's request to determine:
- Command (concept-test or generate)
- Free-text research intent (if provided)
- Panel size (default: 5; or 15 if
--segments) - Market (default: United States; resolve shorthands like
jp→ Japan) - Mode: topic-only (default) or segment-driven (
--segments)
- Collect missing info:
- Extract topic from free text (e.g., "Evaluate 3 new canned coffee concepts" → topic = "Canned coffee")
- For concept-test: identify concept/option details — ask only if not provided
- If free text provides sufficient context, skip interactive questions
- Persona Panel Decision:
a) User explicit instruction:
- "Use existing panel" / "reuse {name}" → load from specified
personas/{survey-id}/directory - "Generate new personas" or provides segment definitions → new generation
- No instruction → proceed to auto-decision (b)
b) Auto-decision (default is NEW generation):
- Scan
personas/for subdirectories containingmanifest.json(ignore_archive/) - If a manifest's
categoryclosely matches the current topic ANDmarketmatches (or is absent, treated as "United States") → propose reuse, ask user - If no match found → proceed directly to new generation (no confirmation needed)
c) New generation flow — two modes:
Topic-only mode (default):
- Skip segment inference entirely
- Infer diversity dimensions inline and generate all N personas in one batch
- See
references/topic-only-generation-flow.mdfor the 4-step flow
(dimension inference, target assignment, generation, manifest creation)
- Do NOT ask user for segment approval — proceed directly
Segment-driven mode (--segments):
- If user provided segment definitions → use them directly
- If topic only → run segment inference (see
references/segment-inference-prompt.md)
to generate 3-4 segments → present to user for approval
- Default panel size: 15 personas (3 segments × 5 personas)
- Follow the 4-step generation flow below
### Segment-Driven 4-Step Generation Flow
Inspired by TinyTroupe's TinyPersonFactory plan-based approach: instead of letting the LLM freely generate N personas per segment, first build a deterministic sampling plan, then generate each persona from its slot specification.
Step 1a: Deterministic Count Allocation
Compute per-segment counts deterministically — do NOT delegate count management to the LLM. This is the orchestrator's responsibility:
base = floor(count / num_segments)remainder = count mod num_segments- First
remaindersegments getbase + 1; remaining getbase - Verify:
sum(segment_counts) == countbefore proceeding
Examples:
- 30 ÷ 3 = 10 + 10 + 10
- 17 ÷ 4 = 5 + 4 + 4 + 4
- 8 ÷ 3 = 3 + 3 + 2
Record each segment's allocated count. If the sum does not equal the requested count, fix the allocation before generating.
Step 1b: Sampling Plan Generation
Generate a sampling plan that assigns diversity attributes to each persona slot. See references/sampling-plan-prompt.md for the prompt.
The plan is a JSON array with exactly N rows (one per persona). Each row specifies: segment, agebucket, gender, occupationtier, geographytype, regionhint, categorystance, ethnicityhint.
After the LLM returns the plan, verify:
len(plan) == count- Per-segment row counts match the allocation from Step 1a
- If verification fails, regenerate the plan (max 2 attempts)
Step 1c: Persona Generation from Slot Specifications
Generate personas sequentially by segment. For each segment batch:
- Pass all slot rows for that segment to
persona-generation-prompt.md
as {{slot_spec}} — the LLM fleshes out each slot into a full persona
- Pass the exclusion list of already-used names, surnames, and
occupation titles from previous segments as {{exclusion_list}}
- After generation, extract the names, surnames, and occupation titles
from the generated personas and add them to the exclusion list for the next segment
This ensures cross-segment duplicate suppression is built into the generation flow, not left to chance.
Step 1d: Panel Validation
After all personas are generated, run scripts/validate_panel.py programmatically:
``bash python scripts/validate_panel.py --panel-dir personas/{survey-id} --requested-count {count} --json ``
Interpret the results:
- Hard fails (severity: "fail"): The panel has a contract violation.
Attempt to fix the specific issue (e.g., regenerate a duplicate-named persona) and re-validate. Max 2 retry cycles.
- Warnings (severity: "warning"): Note them but do not block.
- If hard fails persist after retries, present the panel with
warnings and let the user decide.
d) Panel confirmation with QA summary:
- Present the panel overview table:
`` | # | Name | Age | Gender | Occupation | Segment | |---|------|-----|--------|------------|---------| | 1 | Marcus Chen | 34 | M | Software Engineer | Serious Runners | | 2 | Diana Okafor | 52 | F | School Principal | Casual Joggers | | 3 | Jake Morales | 23 | M | Barista / Student | Fashion-Conscious | ``
- Below the table, show a QA Summary from validate_panel results:
``` ### Panel QA
- Count: 30/30 ✓
- Segment balance: Serious (10), Casual (10), Fashion (10) ✓
- Names: all unique ✓
- Occupation duplicates: none ✓
- Age spread: OK ✓
- Gender balance: OK ✓
- Big Five near-duplicates: 1 pair (0.985) ⚠
```
- If any hard fail remains, flag it prominently and offer to
regenerate the affected personas
- After user approves → proceed to concept test execution
e) Save personas:
- Save each persona as
personas/{survey-id}/{Name_Underscored}.json - Create
manifest.jsonwith: "generation_mode": "topic-only"or"segment-driven""market": "{resolved market name}""requested_count": {count}"sampling_plan": [...](the slot specifications from Step 1b)"validation_report": {...}(from validate_panel output)- All segments must include
"description"field
- Load survey template from
templates/concept_test.md.
Step 2: Run Concept Test
Read references/simulation-prompt.md for the core simulation prompt.
Before simulation, extract simulation profiles from the full persona JSONs using extract_simulation_profile() in scripts/simulate_survey.py. Pass the compact profiles (~40-50 lines/persona) as {PERSONAS_JSON} instead of the full personas (~300 lines/persona). This saves context window while preserving all response-driving fields.
Agent-Separated Execution (Recommended)
Use simulate_survey.py for production-quality results. This wrapper must force --backend claude-cli, which runs each persona in a fully independent claude -p subprocess — zero inter-persona bias.
python scripts/simulate_survey.py --config {config-path} --backend claude-cli
How it works:
- Builds a per-persona system prompt (simulation instructions + single persona profile + survey questions)
- Launches parallel
claude -pprocesses (controlled by--concurrency, default 5) - Each process uses
--output-format json --tools "" --no-session-persistence, plus
--safe-mode (context isolation: no CLAUDE.md/plugins/hooks leak into persona calls) and --json-schema (server-validated structured output) when the installed CLI supports them
- Parses the response (
structured_outputpreferred, text extraction as fallback),
validates structure, retries on failure (up to 3 attempts)
- Saves
results.json+run_metadata.jsontoconfig.output_dirwhen provided, otherwise tooutputs/{YYYY-MM-DD}/{HHMMSS}/{survey_type}/ - Runs a backend preflight before persona fan-out; if it fails, stop immediately and record
failure_stage: "preflight"
Options: --dry-run, --analyze, --report-llm, --no-adherence-check, --model, --concurrency, --report-backend, --no-structured-output, --no-isolation, --fallback-model, --effort
Model Selection
The default simulation model is sonnet — the best cost/quality balance for 10-15-way persona fan-outs. All claude model aliases and full model IDs work:
| Model | When to use | Notes | |-------|-------------|-------| | sonnet (default) | Standard panels | Best cost balance for fan-out | | haiku | Quick smoke tests, large panels | Cheapest; does NOT support --effort | | fable (Claude Fable 5) | Highest-fidelity simulation, final runs | ~4x sonnet cost (higher price + denser tokenizer); slower turns | | opus | High-fidelity alternative | Between sonnet and fable in cost |
Config keys (all optional, omit for current behavior):
{
"model": "sonnet",
"report_model": "fable",
"fallback_model": "sonnet",
"effort": "medium",
"max_budget_usd_per_call": 0.50,
"structured_output": true,
"isolation": true
}
"report_model": "fable"— recommended upgrade: keep the fan-out on sonnet but
synthesize the final report with Fable 5 (one call, small cost increase, richer narrative).
"fallback_model": "sonnet"— recommended when running the fan-out onfable/opus:
automatically falls back when the primary model is overloaded.
"effort"— lower (low/medium) for cheaper, faster persona answers; not supported by haiku."max_budget_usd_per_call"— hard cost cap per subprocess call.- Run metadata records both the requested alias (
resolved_model) and the exact
model IDs that actually served the calls (actual_model_ids), plus total_cost_usd.
Why agent-separated: Shared-context simulation suffers from anchoring bias, consensus bias, and style contamination. Agent separation eliminates all three. Context isolation (--safe-mode) extends this: persona subprocesses do not read the user's CLAUDE.md, plugins, or hooks, so project context cannot bias responses.
Error handling: If simulate_survey.py exits non-zero, read run_metadata.json for failure_stage, `p
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: takechanman1228
- Source: takechanman1228/claude-persona
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.