视觉画布设计
canvas-design
基于设计原则创作静态视觉作品,用于海报与品牌图形。
product-marketing-context【文档与办公】Creates and maintains `.claude/product-marketing-context.md`, one sourced file that records what the product is, who buys it, what they use instead, the proof behind each claim, customer wording, pricing and goals, so later marketing tasks read facts instead of asking again or guessing. Drafts it from the repository and site, interviews the user for …
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
.claude/product-marketing-context.md, one sourced file that records what
the product is, who buys it, what they use instead, the proof behind each claim, customer
wording, pricing and goals, so later marketing tasks read facts instead of asking again or
guessing. Drafts it from the repository and site, interviews the user for the gaps, tags every
statement with its source, and checks the file with a script. Use when someone says "set up
marketing context", "product context", "positioning document", "write down our messaging", "we
repositioned, update the context", or before the first copywriting, CRO, SEO or email task in a
project.
license: Apache-2.0
compatibility: >-
Any repository. The file is plain Markdown read by Claude Code, Codex, Gemini CLI and Cursor.
The check script needs Python 3.8+.
metadata:
author: terminal-skills
version: "2.0.0"
category: business
tags: ["positioning", "messaging", "product-marketing", "context", "documentation"]Marketing work goes wrong in a predictable way when an agent starts cold: it invents an audience,
borrows claims from the category, and writes in a voice nobody at the company uses. This skill
fixes the inputs once. It produces a single file, .claude/product-marketing-context.md, that
other skills in this catalog (copywriting, page and form optimisation, pricing, email, SEO, ads)
look for before they ask questions.
The file is a record of facts, not a piece of copy. Three properties make it useful:
ls -l .claude/product-marketing-context.md 2>/dev/null
grep -nE "^## |^Last reviewed|TODO\(" .claude/product-marketing-context.md 2>/dev/null
If the file exists, go to step 6 (update). If not, continue.
| Evidence | Where to look | Feeds section |
|---|---|---|
| What the product is and does | README.md, docs/ introduction, package.json description | Product |
| Claims made in public | Landing page source, title and meta description, Open Graph tags | Product, Differentiators |
| Plans, prices, trial | Billing or plan configuration in code, the pricing page | Offers and pricing |
| What shipped recently | CHANGELOG.md, release notes | Differentiators |
| Named alternatives | Comparison or "alternatives" pages, migration guides, importers | Problem and alternatives |
| Worries buyers raise | FAQ, help centre articles, security page | Objections |
| Quotes and results | Testimonial and case-study content, with who said it | Differentiators and proof |
| The action that counts | Analytics event names, signup and checkout routes | Goals and measures |
grep -rnoiE "<title>[^<]+|name=\"description\" content=\"[^\"]+|og:(title|description)\" content=\"[^\"]+" \
--include=*.html --include=*.tsx --include=*.jsx --include=*.astro --include=*.vue . 2>/dev/null | head -20
grep -rnEil "testimonial|case stud|compared to|alternative to| vs " --include=*.md --include=*.mdx --include=*.tsx . 2>/dev/null | head -20
grep -rnE "price|amount|interval|trial" --include=*plan*.ts --include=*pricing*.ts --include=*billing*.ts . 2>/dev/null | head -20
Write down contradictions as you find them (the README says freelancers, the landing page says agencies). They are the most valuable output of this step.
Ask in two short rounds, never as one long form. Offer to read material instead of asking: call notes, interview transcripts, reviews, support tickets, a sales deck.
Round one:
Round two, after showing the draft:
Fixed headings, in this order, so other skills and the check script can find them:
| Section | Holds | Limit |
|---|---|---|
| Header | Product name, Last reviewed: YYYY-MM-DD, owner, sources used | 4 lines |
| Product | What it is, what form it takes, the category a buyer would name | 3 to 5 statements |
| Audience | Who buys, who uses, company type, the event that starts the search | One group per bullet |
| Problem and alternatives | The problem in customer words; what they use instead and why it falls short | Alternatives include "nothing" and "a spreadsheet" |
| Differentiators and proof | What the product does that the alternatives do not, each with evidence | No evidence means [assumption] |
| Objections | Each worry with the true answer | Top three to five |
| Language | Words customers use; words to avoid; product terms | Quotes verbatim |
| Voice | How the company writes: two or three sentences | No source tags needed |
| Offers and pricing | Plans, prices, trial, guarantees | From code or billing, with date |
| Goals and measures | Primary action, current rate, target | Numbers carry their date |
| Open questions | TODO(owner): question | Remove when answered |
Rules for every statement outside Voice and Open questions:
[repo: path], [site: url], [data: system, date], [customer: who, date],
[user: date] for what the user told you, or [assumption].Save the script as scripts/check_context.py (or run it once from a scratch directory):
"""Usage: python3 check_context.py [.claude/product-marketing-context.md]"""
import re, sys
from datetime import date
path = sys.argv[1] if len(sys.argv) > 1 else ".claude/product-marketing-context.md"
lines = open(path, encoding="utf-8").read().splitlines()
text = "\n".join(lines)
SECTIONS = ["Product", "Audience", "Problem and alternatives", "Differentiators and proof", "Objections",
"Language", "Voice", "Offers and pricing", "Goals and measures", "Open questions"]
TAG = re.compile(r"\[(repo|site|user|customer|data|assumption)\b[^\]]*\]")
problems = [f"section missing: ## {s}" for s in SECTIONS if not re.search(rf"^## {re.escape(s)}\s*quot;, text, re.M)]
reviewed = re.search(r"^Last reviewed: (\d{4})-(\d{2})-(\d{2})", text, re.M)
if not reviewed:
problems.append("no 'Last reviewed: YYYY-MM-DD' line")
elif (date.today() - date(*map(int, reviewed.groups()))).days > 90:
problems.append("last review is more than 90 days old")
section = ""
for number, line in enumerate(lines, 1):
if line.startswith("## "):
section = line[3:].strip()
elif line.startswith("- ") and section not in ("", "Voice", "Open questions"):
if not TAG.search(line) and "TODO(" not in line:
problems.append(f"line {number}: statement without a source tag")
if len(lines) > 200:
problems.append(f"{len(lines)} lines; keep it under 200")
print(f"{path}: {len(lines)} lines, {text.count('TODO(')} open questions, {text.count('[assumption')} assumptions")
for p in problems:
print(" FIX " + p)
sys.exit(1 if problems else 0)
Then make sure agents find the file. Add one line to the project instruction file the team's
agent reads (CLAUDE.md, AGENTS.md, GEMINI.md or a Cursor rule):
Marketing facts (audience, claims, proof, pricing, wording) are in `.claude/product-marketing-context.md`.
Read it before writing or reviewing anything customer-facing; do not restate it here.
Keep the path inside backticks. In Claude Code an @ path outside backticks is an import and
would load the whole file into every session, including the ones that fix a build. Commit the
file so teammates and CI agents share it.
Last reviewed to today and add the new sources to the header.grep -rnE 'freelancers?|\$19( |/)|per month' --include=*.md --include=*.mdx --include=*.tsx --include=*.html . | grep -v product-marketing-context
Tell the user, in this order: what the file now says in five lines; contradictions found between sources; open questions with owners; assumptions that need evidence; files that disagree with it.
Request: "Set up the marketing context for Brindle CRM."
The agent reads the README, the landing page, src/billing/plans.ts and six call notes the user
drops into notes/calls/, asks round one, and writes (shortened here):
# Product marketing context: Brindle CRM
Last reviewed: 2026-10-01
Owner: Maya Okafor
Sources: repository, brindlecrm.com, 6 customer calls (September 2026), Stripe export
## Product
- Brindle is a CRM for independent insurance brokers: policies, renewals and client notes in one record. [repo: README.md]
- Category the buyer would name: "broker CRM" or "agency management system". [customer: 4 of 6 calls]
## Audience
- Brokerages with 2 to 15 staff in the UK and Ireland. [data: Stripe export 2026-09-28, 212 of 240 accounts]
- Trigger to look: a missed renewal, or a handler leaving with client knowledge in their inbox. [customer: calls 2, 3, 5]
## Problem and alternatives
- "We found out the policy had lapsed when the client rang to claim." [customer: Oakfield Insurance call, 2026-09-12]
- What they use instead: a shared spreadsheet plus Outlook reminders. [customer: 5 of 6 calls]
## Differentiators and proof
- Renewal calendar built from policy end dates, with handler assignment. [repo: src/renewals/]
- Customers report fewer missed renewals. [assumption] TODO(Maya): get a number and permission to quote.
## Offers and pricing
- £39 per user per month; £390 per user per year; 14-day trial without a card. [repo: src/billing/plans.ts]
## Open questions
- TODO(Jon): the pricing page says "from £29"; the code says £39. Which is right?
Check output and report:
.claude/product-marketing-context.md: 48 lines, 4 open questions, 1 assumptions
"Draft saved. Two things need you: the pricing page and the code disagree on the price (£29 and £39), and the main benefit, fewer missed renewals, has no number behind it yet. Until it does, copy should describe the renewal calendar rather than claim a result."
Request: "Sproutdeck now sells to agencies instead of freelancers, and the plan went from $19 to $49 per workspace. Update the context."
The agent runs the check (file last reviewed 2026-05-14, flagged as stale), rewrites Audience,
Problem and alternatives, Language and Offers and pricing from the user's notes on four agency
calls, moves two freelancer quotes out, marks the old differentiator "works offline" as
[assumption] because no agency mentioned it, and runs the search from step 6:
content/blog/invoice-tips-for-freelancers.mdx:3: description: "For freelancers who ..."
app/(site)/page.tsx:41: <p>Built for freelancers. $19 per month.</p>
emails/welcome-1.mdx:12: As a freelancer, you ...
Report: sections changed, three files that still address freelancers or show $19, and one open question: "TODO(Priya): do agencies need client-level permissions? Two of four calls raised it."
TODO is correct; an
invented persona is a defect that every later task inherits..claude/product-marketing-context.invoicing.md, listed in the header.