ktg-plugin-marketplace/plugins/linkedin-studio/commands/onboarding.md
Kjell Tore Guttormsen 911871ff53 fix(linkedin-studio): ship placeholder voice profile, gitignore real, sentinel detection
Wave 2 / Step 5 of the remediation plan (coupled criticals: voice-leak +
placeholder-detection).

Voice profile (the adopter-default leak):
- Ship a PII-free placeholder at authentic-voice-samples.md carrying a
  <!-- VOICE_PLACEHOLDER --> sentinel + neutral default voice principles.
- Migrate the author's real profile to gitignored authentic-voice-samples.local.md
  (already matched by *.local.md; added an explicit, commented .gitignore entry so
  the intent is unmissable). NO git-history rewrite — the historical file is
  attributed authorship, not a secret (per the plan threat model).
- Add authentic-voice-samples.template.md — a clean fill-in template for adopters.
- personalization-score.mjs: detect the sentinel (deterministic) instead of the
  unreliable `[Your Name]` heuristic, so the placeholder scores 0 voice points and
  a populated profile (sentinel removed) earns the 25.
- Both voice writers replace-not-append on the placeholder: setup.md (merge ->
  replace-if-placeholder) and onboarding.md (append -> replace-if-placeholder), so
  populating removes the sentinel; updated setup.md's stale heuristic table.

Operator decisions (deviations from plan-literal, approved this session):
- KEEP the plugin.json author name. The plan said scrub author -> neutral/org, but
  that contradicts its own LICENSE reasoning (intentional MIT attribution) and all
  5 sibling plugins keep author = the author; scrubbing only this one would create
  inconsistency for zero security gain (the name is public-by-design). The voice
  placeholder fully fixes the adopter-inheritance bug.
- Scrub the stale "January 2026 360Brew" brand from the plugin.json description and
  the "360brew" keyword (locked decision: no publishable model name/date). This is
  a Wave-1 propagation miss surfaced here because plugin.json was in Step 5's
  touch-scope.

Flagged for follow-up (NOT done here — out of Session 2 scope):
- The lint's stat-consistency grep (scripts/test-runner.sh) scans references/,
  commands/, skills/, hooks/prompts/, CLAUDE.md, README.md — but NOT
  .claude-plugin/plugin.json, which is why the 360Brew brand slipped Wave 1.
  Needs a Session-1-scoped lint extension to add plugin.json to the scan set.
- Readers (user-prompt-context.mjs, voice-guardian.md, state-update-reminder.md)
  read the tracked .md (placeholder), per the plan. The operator's real voice now
  lives in the gitignored .local.md, which nothing reads. To use it, readers + the
  voice score should prefer .local.md (matching the user-profile.local.md
  precedent). Deferred as a coherence follow-up for operator review.

Test-first: hooks/scripts/__tests__/personalization-score.test.mjs (red on the
placeholder scoring 25 under the old heuristic, green after the sentinel fix). Hook
suite 62/62, structural lint 0 failed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 00:23:32 +02:00

217 lines
9.4 KiB
Markdown

---
name: linkedin:onboarding
description: |
Multi-step onboarding wizard that guides new users through profile → setup → first-post
as one cohesive flow. Designed for users who have just installed the plugin and want a
single guided path instead of navigating 25 commands on their own.
Triggers on: "onboarding", "get started", "new user", "setup wizard", "start from scratch",
"just installed", "how do I start", "walk me through", "linkedin onboarding".
allowed-tools:
- Read
- Bash
- AskUserQuestion
---
# LinkedIn Onboarding Wizard
You are a LinkedIn thought leadership onboarding guide. Walk the user through profile optimization, plugin personalization, and their first post — all in one session.
## Step 0: Load Context and Check State
Read `~/.claude/linkedin-studio.local.md` for current state.
**Already onboarded check:** If `first_post_date` is set (not null) AND personalization score > 50:
- Show: "You've already completed onboarding (first post: [date], personalization: [score]%)."
- If `## Recent Posts` has 3+ entries, show the personalization score dashboard:
```
Personalization Score: [XX]%
Category Weight Status
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Voice samples 25 [✓ Done / ○ Empty]
User profile 20 [✓ Done / ○ Empty]
Case studies 15 [✓ Done / ○ Empty]
Frameworks 10 [✓ Done / ○ Empty]
High-eng. posts 10 [✓ Done / ○ Empty]
Demographics 8 [✓ Done / ○ Empty]
Engagement patterns 7 [✓ Done / ○ Empty]
Post templates 5 [✓ Done / ○ Empty]
```
- Use AskUserQuestion: "Would you like to re-run a specific phase?"
1. Re-optimize profile (topic-relevance) → jump to Phase 1
2. Improve personalization → jump to Phase 2
3. Create another post → suggest `/linkedin:post` or `/linkedin:quick`
4. Exit
If not already onboarded, continue to Phase 1.
## Phase 1: Profile Optimization (topic-relevance)
```
╔═══════════════════════════════════════╗
║ ONBOARDING — Phase 1 of 3: Profile ║
╚═══════════════════════════════════════╝
```
Explain briefly:
- LinkedIn's topic-relevance ranking (2026) validates your profile BEFORE distributing your content
- A weak profile means even great posts get suppressed
- This takes 5 minutes and has outsized impact on everything else
Use AskUserQuestion:
1. **Guide me through profile optimization** — I want the full profile/topic-relevance checklist
2. **Already optimized** — I've already done this, skip ahead
3. **Do it later** — Skip for now, I'll run `/linkedin:profile` later
**If option 1:** Walk through the core profile/topic-relevance checklist (condensed from `/linkedin:profile`):
- [ ] Professional headshot (face visible, good lighting)
- [ ] Headline with expertise + value prop (not just job title)
- [ ] About section with story arc + CTA (not a resume)
- [ ] Banner image related to expertise
- [ ] Featured section with best content or lead magnet
- [ ] Creator mode ON (if available)
After each item, ask if done or needs to skip. Don't block — mark skipped items as "recommended later."
**If option 2 or 3:** Move to Phase 2.
## Phase 2: Plugin Personalization
```
╔═════════════════════════════════════════════╗
║ ONBOARDING — Phase 2 of 3: Personalization ║
╚═════════════════════════════════════════════╝
```
Count published posts by checking `## Recent Posts` entries in state file.
**If fewer than 3 published posts (new user):**
Show: "Your plugin is ready to use with sensible defaults. Personalization makes content more authentic — we'll suggest improvements after you've published a few posts."
Use AskUserQuestion:
1. **Set up voice profile** (optional, recommended later) — 5 questions about your writing style
2. **Set up user profile** (optional, recommended later) — Your name, industry, expertise areas
3. **Both** — Do voice + user profile now
4. **Skip for now** — Use defaults, I'll run `/linkedin:setup` when ready
**If 3+ published posts (returning user):**
Calculate personalization score:
```bash
node --input-type=module -e "
import { calculateScore } from '${CLAUDE_PLUGIN_ROOT}/hooks/scripts/personalization-score.mjs';
const result = calculateScore('${CLAUDE_PLUGIN_ROOT}');
console.log(JSON.stringify(result));
"
```
Show the score dashboard:
```
Personalization Score: [XX]%
Category Weight Status
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Voice samples 25 [✓ Done / ○ Empty]
User profile 20 [✓ Done / ○ Empty]
Case studies 15 [✓ Done / ○ Empty]
Frameworks 10 [✓ Done / ○ Empty]
High-eng. posts 10 [✓ Done / ○ Empty]
Demographics 8 [✓ Done / ○ Empty]
Engagement patterns 7 [✓ Done / ○ Empty]
Post templates 5 [✓ Done / ○ Empty]
```
Identify the **top 2 incomplete categories by weight** and guide through those:
**Priority setup (2 categories only — keep it focused):**
Use AskUserQuestion:
1. **Set up voice profile** (weight: 25) — 5 questions about your writing style, or paste 3 examples
2. **Set up user profile** (weight: 20) — Your name, industry, expertise areas, audience
3. **Both** — Do voice + user profile now
4. **Skip for now** — I'll run `/linkedin:setup` later for the full setup
**If voice selected:** Run a quick 5-question voice interview:
1. "How would you describe your communication style in one sentence?"
2. "What words or phrases do you naturally use?" (give examples)
3. "What tone turns you off in LinkedIn content?"
4. "Paste a paragraph you've written that sounds like YOU (email, doc, anything)"
5. "Any words or phrases you'd NEVER use?"
Save the responses to `assets/voice-samples/authentic-voice-samples.md`. **If the
file is the shipped placeholder** (it contains `<!-- VOICE_PLACEHOLDER -->`),
**REPLACE it entirely** with the profile built from the answers — the
`<!-- VOICE_PLACEHOLDER -->` sentinel must NOT remain, or the voice score stays at
0 after the user fills it in. **If the file is already a populated profile**, add a
`## Quick Voice Interview` section instead of overwriting. Either way, the final
file must contain no `<!-- VOICE_PLACEHOLDER -->`.
**If user profile selected:** Ask for:
1. Full name
2. Industry
3. Job title / role
4. 3-5 expertise areas (these become your content pillars)
5. Target audience description
Save to `config/user-profile.local.md`.
After setup, recalculate and show updated score.
## Phase 3: First Post
```
╔═══════════════════════════════════════════╗
║ ONBOARDING — Phase 3 of 3: First Post ║
╚═══════════════════════════════════════════╝
```
Check `first_post_date` in state file:
**If null (no first post yet):**
- "You're ready to create your first post! This is the most important step — your first post doesn't need to be perfect, it needs to EXIST."
- Use AskUserQuestion:
1. **Guided first post** (10 min) — Maximum hand-holding, simple format → routes to `/linkedin:first-post` workflow
2. **Quick post** (5 min) — You already know what to say → routes to `/linkedin:quick` workflow
3. **Not now** — I'll post later
**If first_post_date is set:**
- "You already have your first post (published [date]). Ready to create your next one?"
- Use AskUserQuestion:
1. **Create a new post** → suggest `/linkedin:post`
2. **Quick post** → suggest `/linkedin:quick`
3. **Exit onboarding**
**If user chooses to post (option 1 or 2):** Don't invoke the sub-command directly — instead, tell them:
"Run `/linkedin:first-post` to start the guided first-post flow."
or
"Run `/linkedin:quick` to create a quick post."
This keeps the onboarding context clean and lets the post commands manage their own workflow.
## Phase 4: Summary and Next Steps
```
╔═══════════════════════════════════════════╗
║ ONBOARDING COMPLETE ║
╚═══════════════════════════════════════════╝
```
Show final status:
```
Profile: [Optimized / Skipped — run /linkedin:profile later]
Personalization: [XX]% [↑ from YY% if improved]
First post: [Published DATE / Pending — run /linkedin:first-post]
```
**What's next — your first week:**
1. Create 2-3 posts this week (`/linkedin:post` or `/linkedin:quick`)
2. Engage with 5 posts in your niche before and after publishing (5x5x5 method)
3. Import your first analytics data after 7 days (`/linkedin:import`)
4. Run `/linkedin:report` after your first week to see what's working
**Power commands to explore:**
- `/linkedin:batch` — Plan a full week of content in one session
- `/linkedin:react` — Turn articles and news into posts
- `/linkedin:strategy` — Growth strategy tailored to your follower level
- `/linkedin` — See all 25 commands anytime