docs(linkedin-studio): M0-15 — repoint remaining prose families + route ab-tests/plans

This commit is contained in:
Kjell Tore Guttormsen 2026-06-18 13:04:18 +02:00
commit 6bd263144f
35 changed files with 167 additions and 130 deletions

View file

@ -45,10 +45,10 @@ The two modes share the same data sources and analysis framework; they differ in
The plugin has a built-in analytics pipeline. Always check for imported data first — structured data is more reliable than user-reported numbers.
1. **Check for imported data:** Read files in `${CLAUDE_PLUGIN_ROOT}/assets/analytics/posts/` — these contain structured JSON with per-post metrics (impressions, reactions, comments, shares, clicks, engagement rate).
2. **Weekly reports (report mode):** Read `${CLAUDE_PLUGIN_ROOT}/assets/analytics/weekly-reports/*.json` for pre-generated summaries.
3. **Load pattern baselines:** Read `${CLAUDE_PLUGIN_ROOT}/assets/audience-insights/engagement-patterns.md` for the user's tracked engagement patterns (best times, top topics, format performance, hook types that work). Use this as baseline context.
4. **Load audience context:** Read `${CLAUDE_PLUGIN_ROOT}/assets/audience-insights/demographics.md` for audience composition.
1. **Check for imported data:** Read files in `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/posts/` — these contain structured JSON with per-post metrics (impressions, reactions, comments, shares, clicks, engagement rate).
2. **Weekly reports (report mode):** Read `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/weekly-reports/*.json` for pre-generated summaries.
3. **Load pattern baselines:** Read `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/audience-insights/engagement-patterns.md` for the user's tracked engagement patterns (best times, top topics, format performance, hook types that work). Use this as baseline context.
4. **Load audience context:** Read `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/audience-insights/demographics.md` for audience composition.
5. **Run trend analysis:**
```bash
ANALYTICS_ROOT="${CLAUDE_PLUGIN_ROOT}/assets/analytics" node --import tsx "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" trends --period month --metric impressions
@ -64,15 +64,15 @@ When structured data is available, use it as the primary source. This gives you
## Reference Data (both modes)
Always load these for pattern comparison:
- `${CLAUDE_PLUGIN_ROOT}/assets/examples/high-engagement-posts.md` — Proven high-engagement patterns and replicable elements. Compare top posts against these.
- `${CLAUDE_PLUGIN_ROOT}/assets/audience-insights/engagement-patterns.md` — Historical engagement patterns (benchmark for current period).
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/examples/high-engagement-posts.md` — Proven high-engagement patterns and replicable elements. Compare top posts against these.
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/audience-insights/engagement-patterns.md` — Historical engagement patterns (benchmark for current period).
## Manual Data Sources (fallback)
When structured analytics aren't available:
- `~/.claude/linkedin-studio.local.md` — Posting history, streaks, weekly stats
- `${CLAUDE_PLUGIN_ROOT}/assets/plans/` — Planned vs. actual content
- `${CLAUDE_PLUGIN_ROOT}/assets/drafts/` — Draft history
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/plans/` — Planned vs. actual content
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/` — Draft history
- See `${CLAUDE_PLUGIN_ROOT}/assets/analytics/README.md` for data format and directory structure.
## Mission

View file

@ -31,7 +31,7 @@ When you receive content to optimize, analyze it through these lenses:
### 1. Hook Analysis (First 110-140 Characters)
**First, load the user's proven patterns:** Read `${CLAUDE_PLUGIN_ROOT}/assets/examples/high-engagement-posts.md` to identify which hook types and content patterns specifically work for THIS user's audience. Prioritize their proven patterns over generic advice.
**First, load the user's proven patterns:** Read `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/examples/high-engagement-posts.md` to identify which hook types and content patterns specifically work for THIS user's audience. Prioritize their proven patterns over generic advice.
**Check against high-performing hook types:**
- Surprising stat

View file

@ -4,7 +4,7 @@ description: |
Systematic content planning agent that creates weekly and monthly content plans based on
content pillars, 70/20/10 mix, seasonal themes, and publishing gaps. Analyzes previous
plans to avoid repetition, enforces content mix balance, and stores plans in
assets/plans/ for tracking. Can create Linear issues for each planned post.
${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/plans/ for tracking. Can create Linear issues for each planned post.
Use when the user says:
- "plan my content", "what should I post this week", "content calendar"
@ -37,7 +37,7 @@ ${CLAUDE_PLUGIN_ROOT}/assets/templates/weekly-content-calendar-2-3x.md → calen
~/.claude/linkedin-studio.local.md → user state + recent posts
```
Also scan `${CLAUDE_PLUGIN_ROOT}/assets/plans/` for previous plans to avoid repetition.
Also scan `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/plans/` for previous plans to avoid repetition.
## Step 1: Content Audit
@ -461,7 +461,7 @@ After any adjustment, re-run the quality check before saving.
### Save the Plan
Save approved plans to `${CLAUDE_PLUGIN_ROOT}/assets/plans/`:
Save approved plans to `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/plans/`:
- Weekly: `2026-W05.md`
- Monthly: `2026-02.md`

View file

@ -36,7 +36,7 @@ ${CLAUDE_PLUGIN_ROOT}/references/articles-strategy-guide.md → article w
${CLAUDE_PLUGIN_ROOT}/references/newsletter-strategy-guide.md → newsletter integration
${CLAUDE_PLUGIN_ROOT}/references/thought-leadership-angles.md → 8 universal angles
${CLAUDE_PLUGIN_ROOT}/assets/case-studies/case-study-template.md → case study structure + 4 LinkedIn post angles
${CLAUDE_PLUGIN_ROOT}/assets/examples/high-engagement-posts.md → proven patterns to replicate
${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/examples/high-engagement-posts.md → proven patterns to replicate
~/.claude/linkedin-studio.local.md → user state + performance data
```
@ -556,7 +556,7 @@ CONTENT LIFECYCLE TRACKER
| "[Hook]" | [date] | [1-7] | [specific action] | [date] |
```
Save tracker to `${CLAUDE_PLUGIN_ROOT}/assets/repurposing-tracker.md`
Save tracker to `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/repurposing-tracker.md`
## Step 7: Batch Repurposing
@ -594,7 +594,7 @@ Expected reach multiplier: [2-5x original]
## Output & Storage
Save repurposed content to `${CLAUDE_PLUGIN_ROOT}/assets/drafts/repurposed/`:
Save repurposed content to `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/repurposed/`:
```
Naming convention:

View file

@ -38,7 +38,7 @@ ${CLAUDE_PLUGIN_ROOT}/skills/linkedin-studio/SKILL.md → user exper
~/.claude/linkedin-studio.local.md → user state + network data
```
Also check `${CLAUDE_PLUGIN_ROOT}/assets/network/` for existing tracker files.
Also check `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/network/` for existing tracker files.
## Step 1: Network Audit
@ -610,7 +610,7 @@ VERDICT: Don't join formal pods. Build genuine Tier 1 instead.
### Tracker Setup
Save and maintain a tracker in `${CLAUDE_PLUGIN_ROOT}/assets/network/`:
Save and maintain a tracker in `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/network/`:
```markdown
# Network Tracker

View file

@ -37,7 +37,7 @@ Before analyzing anything, load these files:
1. **Algorithm knowledge:** Read `${CLAUDE_PLUGIN_ROOT}/references/algorithm-signals-reference.md`
2. **Engagement frameworks:** Read `${CLAUDE_PLUGIN_ROOT}/references/engagement-frameworks.md`
3. **State file:** Read `~/.claude/linkedin-studio.local.md` (if exists)
4. **Latest analytics:** Use Glob to find the most recent file in `${CLAUDE_PLUGIN_ROOT}/assets/analytics/posts/` and read it
4. **Latest analytics:** Use Glob to find the most recent file in `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/posts/` and read it
This gives you the user's baseline performance and algorithm context for accurate benchmarking.

View file

@ -39,9 +39,9 @@ Provide personalized, actionable strategic guidance that accounts for the user's
Read these files for strategic intelligence:
```
${CLAUDE_PLUGIN_ROOT}/assets/audience-insights/demographics.md → audience composition + intended vs actual gaps
${CLAUDE_PLUGIN_ROOT}/assets/audience-insights/engagement-patterns.md → timing, topic, and format patterns
${CLAUDE_PLUGIN_ROOT}/assets/examples/high-engagement-posts.md → proven patterns from top posts
${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/audience-insights/demographics.md → audience composition + intended vs actual gaps
${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/audience-insights/engagement-patterns.md → timing, topic, and format patterns
${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/examples/high-engagement-posts.md → proven patterns from top posts
${CLAUDE_PLUGIN_ROOT}/references/trajectory-strategy-adjustments.md → trajectory-to-action mappings
~/.claude/linkedin-studio.local.md → user state + posting history
```

View file

@ -37,14 +37,14 @@ Find the right trends at the right time with the right angle. Specifically:
Before scanning, load the user's content pillars and expertise areas:
1. **Read user profile:** `${CLAUDE_PLUGIN_ROOT}/config/user-profile.local.md`
1. **Read user profile:** `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/profile/user-profile.md`
- Extract: 5 core expertise areas, target audience, voice preferences
- If file does not exist, ask the user for their 5 content pillars before proceeding
2. **Read voice samples:** `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/voice-samples/` (glob for .md files)
- Understand their typical angle and tone
3. **Check recent posts:** `${CLAUDE_PLUGIN_ROOT}/assets/analytics/posts/` (if available)
3. **Check recent posts:** `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/posts/` (if available)
- Avoid recommending topics they already covered recently
## Source Scanning Framework

View file

@ -35,7 +35,7 @@ ${CLAUDE_PLUGIN_ROOT}/references/linkedin-formats.md → Video
${CLAUDE_PLUGIN_ROOT}/references/engagement-frameworks.md → Hook types, CTAs, story structures
${CLAUDE_PLUGIN_ROOT}/references/thought-leadership-angles.md → 8 universal angles
${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/voice-samples/ → User's authentic voice (ALWAYS read before scripting)
${CLAUDE_PLUGIN_ROOT}/assets/examples/high-engagement-posts.md → Successful content patterns
${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/examples/high-engagement-posts.md → Successful content patterns
~/.claude/linkedin-studio.local.md → User state, recent topics, streak
```
@ -207,7 +207,7 @@ Iterate until satisfied.
## Step 8: Save and Update State
Save the final script to `${CLAUDE_PLUGIN_ROOT}/assets/drafts/`:
Save the final script to `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/`:
```
Naming convention:

View file

@ -114,7 +114,7 @@ each edition:
- Write to `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/voice-samples/chronicle-voice-drift-log.md`
(create if absent). One dated entry per run: which tells recurred, which voice
traits the draft drifted on, and any newly-confirmed gold-standard pattern.
- Do **not** rewrite the general voice profile (`config/user-profile.local.md`) —
- Do **not** rewrite the general voice profile (`${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/profile/user-profile.md`) —
that is `voice-trainer`'s job. This log is the chronicle-specific memory; over
editions it becomes the calibration record for this agent.
- Never auto-update identity-level traits (register, em-dash policy, banned

View file

@ -133,11 +133,11 @@ Architecture: [prose/sectioned/framework]
### Analysis Process
1. **Gather** — Read all files in `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/voice-samples/`, existing profile from `config/user-profile.local.md`, and template from `config/user-profile.template.md`
1. **Gather** — Read all files in `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/voice-samples/`, existing profile from `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/profile/user-profile.md`, and template from `config/user-profile.template.md`
2. **Analyze** — Apply all six dimensions to each sample. Note dates for temporal analysis. Flag inconsistent samples as outliers or evolution.
3. **Synthesize** — Patterns in 70%+ of samples = core traits. 40-70% = situational traits (note context). <40% = experimental traits. Track temporal trends.
4. **Build** — Compile into Voice Profile Document format. Include confidence levels (high/medium/low) and concrete examples for every trait.
5. **Update** — Write voice profile section to `config/user-profile.local.md`. Create from template if needed. Preserve non-voice sections.
5. **Update** — Write voice profile section to `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/profile/user-profile.md`. Create from template if needed. Preserve non-voice sections.
### Sample Quality Priorities
@ -325,6 +325,6 @@ Fixes: [specific corrections with baseline examples]
Read these files for context and methodology:
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/voice-samples/` — Source samples for analysis
- `${CLAUDE_PLUGIN_ROOT}/config/user-profile.template.md` — Profile structure template
- `${CLAUDE_PLUGIN_ROOT}/config/user-profile.local.md` — Current voice profile (if exists)
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/profile/user-profile.md` — Current voice profile (if exists)
- `${CLAUDE_PLUGIN_ROOT}/references/ai-content-framework.md` — AI content anti-patterns and quality checklist
- `${CLAUDE_PLUGIN_ROOT}/references/engagement-frameworks.md` — Hook psychology and tone guidelines

View file

@ -34,11 +34,11 @@ ${CLAUDE_PLUGIN_ROOT}/references/algorithm-signals-reference.md
Check for existing state and analytics data:
```bash
ls -1 ${CLAUDE_PLUGIN_ROOT}/assets/analytics/ab-tests/ 2>/dev/null | head -20
ls -1 ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/ab-tests/ 2>/dev/null | head -20
```
```bash
ls -1 ${CLAUDE_PLUGIN_ROOT}/assets/analytics/posts/ 2>/dev/null | grep -E '\.json$' | head -10
ls -1 ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/posts/ 2>/dev/null | grep -E '\.json$' | head -10
```
If `~/.claude/linkedin-studio.local.md` exists, read it for user context (posting frequency, follower level, topics).
@ -184,13 +184,13 @@ Present the complete test plan:
Create the ab-tests directory if it does not exist:
```bash
mkdir -p ${CLAUDE_PLUGIN_ROOT}/assets/analytics/ab-tests
mkdir -p ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/ab-tests
```
Save the test plan as a markdown file:
```
${CLAUDE_PLUGIN_ROOT}/assets/analytics/ab-tests/[test-name].md
${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/ab-tests/[test-name].md
```
Use the test name slug (e.g., `hook-question-vs-statement.md`).
@ -206,7 +206,7 @@ Confirm to the user: "Test plan saved. When you publish your first post, come ba
Scan for active tests:
```bash
ls -1 ${CLAUDE_PLUGIN_ROOT}/assets/analytics/ab-tests/ 2>/dev/null | grep -E '\.md$'
ls -1 ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/ab-tests/ 2>/dev/null | grep -E '\.md$'
```
If no tests exist, tell the user: "No active tests found. Use option 1 to design a new test first."
@ -218,7 +218,7 @@ If tests exist, present them and ask which test to log for using AskUserQuestion
Read the selected test file:
```bash
cat ${CLAUDE_PLUGIN_ROOT}/assets/analytics/ab-tests/[test-name].md
cat ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/ab-tests/[test-name].md
```
### 2b.3: Collect Post Metrics
@ -267,7 +267,7 @@ If minimum sample size (3 per variant) is reached, suggest: "You have enough dat
List tests with sufficient data (3+ posts per variant):
```bash
ls -1 ${CLAUDE_PLUGIN_ROOT}/assets/analytics/ab-tests/ 2>/dev/null | grep -E '\.md$'
ls -1 ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/ab-tests/ 2>/dev/null | grep -E '\.md$'
```
Read each file and check if both variants have 3+ posts logged. Present only tests ready for analysis. If no tests have sufficient data, tell the user how many more posts are needed.
@ -281,10 +281,10 @@ Read the test file. For each variant:
### 2c.3: Cross-Reference Analytics Data
If analytics CLI data is available in `assets/analytics/posts/`, cross-reference the test period data with weekly reports for additional context (baseline comparison, trend alignment).
If analytics CLI data is available in `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/posts/`, cross-reference the test period data with weekly reports for additional context (baseline comparison, trend alignment).
```bash
ls -1 ${CLAUDE_PLUGIN_ROOT}/assets/analytics/weekly-reports/ 2>/dev/null | grep -E '\.json$' | head -10
ls -1 ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/weekly-reports/ 2>/dev/null | grep -E '\.json$' | head -10
```
### 2c.4: Present Analysis
@ -349,7 +349,7 @@ Update the test file status from ACTIVE to COMPLETED. Add the conclusion and rec
### 2d.1: Scan All Tests
```bash
ls -1 ${CLAUDE_PLUGIN_ROOT}/assets/analytics/ab-tests/ 2>/dev/null | grep -E '\.md$'
ls -1 ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/ab-tests/ 2>/dev/null | grep -E '\.md$'
```
If no tests exist: "No test history yet. Design your first test with option 1."
@ -396,8 +396,8 @@ Read each test file and extract: test name, variable tested, status, verdict, ke
Check what data is available:
1. **Test history:** Read `assets/analytics/ab-tests/` for completed tests
2. **Analytics data:** Check `assets/analytics/posts/` for performance data
1. **Test history:** Read `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/ab-tests/` for completed tests
2. **Analytics data:** Check `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/posts/` for performance data
3. **User context:** Read state file for posting patterns and goals
### 2e.2: Generate Suggestions
@ -472,7 +472,7 @@ After any action, offer relevant next steps:
## Error Handling
### No Tests Directory
If `assets/analytics/ab-tests/` does not exist and the user selects options 2-4:
If `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/ab-tests/` does not exist and the user selects options 2-4:
- Inform the user: "No tests found. The test directory will be created when you design your first test."
- Redirect to option 1 (Design) or option 5 (Suggestions).

View file

@ -38,7 +38,7 @@ Use AskUserQuestion to understand the situation:
## Step 2: Gather Data
If imported analytics data exists (`assets/analytics/`), delegate audience-pattern discovery to the `analytics-interpreter` agent (interpret mode) — invoke it via `Task` with `subagent_type: linkedin-studio:analytics-interpreter` (foreground, from this command layer) — to ground the diagnosis in what the data actually shows before relying on self-report.
If imported analytics data exists (`${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/`), delegate audience-pattern discovery to the `analytics-interpreter` agent (interpret mode) — invoke it via `Task` with `subagent_type: linkedin-studio:analytics-interpreter` (foreground, from this command layer) — to ground the diagnosis in what the data actually shows before relying on self-report.
Based on their answer, ask relevant follow-up questions:

View file

@ -21,12 +21,12 @@ You are a LinkedIn content strategy auditor. Conduct a thorough review of the us
Load all available data:
- Read `~/.claude/linkedin-studio.local.md` for posting history
- Read `${CLAUDE_PLUGIN_ROOT}/assets/plans/` for planned content
- Read `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/plans/` for planned content
- Read `${CLAUDE_PLUGIN_ROOT}/skills/linkedin-studio/SKILL.md` for strategy reference
- Check for any analytics data in `${CLAUDE_PLUGIN_ROOT}/assets/analytics/`
- Read `assets/audience-insights/demographics.md` for audience composition — compare intended vs actual audience
- Read `assets/audience-insights/engagement-patterns.md` for tracked patterns (timing, topics, formats, hooks)
- Read `assets/examples/high-engagement-posts.md` for proven success patterns to benchmark against
- Check for any analytics data in `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/`
- Read `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/audience-insights/demographics.md` for audience composition — compare intended vs actual audience
- Read `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/audience-insights/engagement-patterns.md` for tracked patterns (timing, topics, formats, hooks)
- Read `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/examples/high-engagement-posts.md` for proven success patterns to benchmark against
Ask the user to provide:
- Screenshot of LinkedIn analytics (last 90 days) or key metrics

View file

@ -25,8 +25,8 @@ You are a LinkedIn batch content creator. Help the user create an entire week's
Load state and personalization:
- Read `~/.claude/linkedin-studio.local.md` for recent topics and weekly goals
- Read `${CLAUDE_PLUGIN_ROOT}/skills/linkedin-studio/SKILL.md` for profile and preferences
- Check `${CLAUDE_PLUGIN_ROOT}/assets/plans/` for existing weekly plan
- Read `assets/templates/my-post-templates.md` for proven templates — vary templates across the batch for format diversity
- Check `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/plans/` for existing weekly plan
- Read `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/templates/my-post-templates.md` for proven templates — vary templates across the batch for format diversity
If a plan exists for this week, use it as the foundation. If not, create one first.
@ -99,8 +99,8 @@ Follow the standard structure:
- Voice matches profile
### 3c. Save Draft
Write each post to `${CLAUDE_PLUGIN_ROOT}/assets/drafts/`:
- Create directory if needed: `assets/drafts/week-[WXX]/`
Write each post to `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/`:
- Create directory if needed: `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/week-[WXX]/`
- Filename: `[day]-[topic-slug].md`
- Include metadata header:
@ -122,7 +122,7 @@ status: scheduled
After saving each draft, add it to the queue:
```bash
node --input-type=module -e "import { queueAdd } from '${CLAUDE_PLUGIN_ROOT}/hooks/scripts/queue-manager.mjs'; console.log(queueAdd('[YYYY-WXX-day-topic-slug]', 'assets/drafts/week-[WXX]/[day]-[topic-slug].md', '[YYYY-MM-DD]', '[HH:MM]', '[pillar]', '[format]', '[hook preview first 50 chars]', [character_count]));"
node --input-type=module -e "import { queueAdd } from '${CLAUDE_PLUGIN_ROOT}/hooks/scripts/queue-manager.mjs'; console.log(queueAdd('[YYYY-WXX-day-topic-slug]', '${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/week-[WXX]/[day]-[topic-slug].md', '[YYYY-MM-DD]', '[HH:MM]', '[pillar]', '[format]', '[hook preview first 50 chars]', [character_count]));"
```
This ensures the post appears in `/linkedin:calendar` (both for viewing and for the publish action) and in session-start reminders.
@ -138,7 +138,7 @@ Batch Summary: [X] posts created
2. [Day] — "[Hook preview...]" (X chars) — [format]
3. [Day] — "[Hook preview...]" (X chars) — [format]
Saved to: assets/drafts/week-[WXX]/
Saved to: ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/week-[WXX]/
Content mix: X educational / Y inspirational / Z entertaining
Pillars covered: [list]
@ -180,7 +180,7 @@ import { generateIcalFromQueue, writeIcalFile } from '${CLAUDE_PLUGIN_ROOT}/hook
const upcoming = queueUpcoming(14);
if (upcoming.length === 0) { console.log('No upcoming posts to schedule.'); process.exit(0); }
const events = generateIcalFromQueue(upcoming);
const icsPath = '${CLAUDE_PLUGIN_ROOT}/assets/drafts/week-[WXX]/schedule.ics';
const icsPath = '${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/week-[WXX]/schedule.ics';
writeIcalFile(icsPath, events);
console.log('Calendar file: ' + icsPath + ' (' + events.length + ' events)');
"
@ -191,7 +191,7 @@ Replace `[WXX]` with the actual ISO week number used for the batch directory.
Show the user:
```
Calendar file generated: assets/drafts/week-[WXX]/schedule.ics
Calendar file generated: ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/week-[WXX]/schedule.ics
Import this file into your calendar app:
- macOS: Double-click the .ics file → Calendar.app imports it
@ -209,4 +209,4 @@ Each scheduled post has a 15-minute reminder before posting time.
- `${CLAUDE_PLUGIN_ROOT}/references/scheduling-strategy.md`
- `${CLAUDE_PLUGIN_ROOT}/assets/templates/weekly-content-calendar-2-3x.md`
- `${CLAUDE_PLUGIN_ROOT}/assets/checklists/quality-scorecard.md`
- `${CLAUDE_PLUGIN_ROOT}/assets/drafts/queue.json`
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/queue.json`

View file

@ -199,4 +199,4 @@ After showing the calendar (or after a publish action loops back), provide brief
- `${CLAUDE_PLUGIN_ROOT}/references/scheduling-strategy.md`
- `${CLAUDE_PLUGIN_ROOT}/references/engagement-frameworks.md`
- `${CLAUDE_PLUGIN_ROOT}/assets/drafts/queue.json`
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/queue.json`

View file

@ -130,7 +130,7 @@ Generate a visual for each slide using mcp-image (Nano Banana Pro). If mcp-image
1. **Create output directory:**
```bash
mkdir -p assets/drafts/carousel-$(date +%Y%m%d)-SLUG
mkdir -p ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/carousel-$(date +%Y%m%d)-SLUG
```
Replace SLUG with a short kebab-case version of the carousel topic (e.g., `ai-governance`).
@ -144,11 +144,11 @@ Generate a visual for each slide using mcp-image (Nano Banana Pro). If mcp-image
3. **For each slide (1 through N),** call `mcp__mcp-image__generate_image` with:
- **prompt:** `"Professional LinkedIn carousel slide. [TEMPLATE STYLE from above]. Background: [consistent color scheme across all slides]. Bold header text: '[SLIDE HEADER]' in large white sans-serif font near the top. Body text below: '[SLIDE BODY lines]' in smaller matching font. Slide [N] of [TOTAL]. Portrait orientation, clean minimal professional design."`
- **aspect_ratio:** `"3:4"` (closest available to LinkedIn's 4:5)
- **output_path:** `assets/drafts/carousel-[date]-[slug]/slide-[N].png`
- **output_path:** `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/carousel-[date]-[slug]/slide-[N].png`
4. **After all slides are generated,** verify the output directory contains the expected number of images:
```bash
ls -la assets/drafts/carousel-$(date +%Y%m%d)-SLUG/
ls -la ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/carousel-$(date +%Y%m%d)-SLUG/
```
**On failure:** If any mcp-image call fails, log the error and continue with remaining slides. If ALL calls fail, fall back to the text-only design guide in Step 6.
@ -162,7 +162,7 @@ Show all slides in order with their text content, then the caption.
```
SLIDE IMAGES
━━━━━━━━━━━━
Generated [N] slide images in assets/drafts/carousel-[date]-[slug]/
Generated [N] slide images in ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/carousel-[date]-[slug]/
To publish:
1. Download the slide images from the folder above

View file

@ -34,7 +34,7 @@ For data format details and directory structure, see `assets/analytics/README.md
First, check if any CSV files exist in the exports directory:
```bash
ls -lh ${CLAUDE_PLUGIN_ROOT}/assets/analytics/exports/*.csv 2>/dev/null || echo "No CSV files found"
ls -lh ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/exports/*.csv 2>/dev/null || echo "No CSV files found"
```
**If files found:** Skip to Step 3.
@ -59,7 +59,7 @@ Options:
On file selection, copy the file to the exports directory:
```bash
cp "<selected-file>" ${CLAUDE_PLUGIN_ROOT}/assets/analytics/exports/
cp "<selected-file>" ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/exports/
```
Then continue to Step 4.
@ -88,10 +88,10 @@ After the script completes, continue to Step 4.
1. Go to [linkedin.com/analytics/creator/content/](https://linkedin.com/analytics/creator/content/)
2. Click the **"Export"** button (top right)
3. LinkedIn will download a CSV file
4. Move it to: `${CLAUDE_PLUGIN_ROOT}/assets/analytics/exports/`
4. Move it to: `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/exports/`
```bash
mv ~/Downloads/linkedin_analytics_export*.csv ${CLAUDE_PLUGIN_ROOT}/assets/analytics/exports/
mv ~/Downloads/linkedin_analytics_export*.csv ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/exports/
```
Once done, run `/linkedin:import` again.
@ -152,7 +152,7 @@ Alerts:
- Post "The future of no-code..." (2026-01-22): Viral threshold reached (10k+ impressions)
Data saved to:
- ${CLAUDE_PLUGIN_ROOT}/assets/analytics/posts/YYYY-WXX.json
- ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/posts/YYYY-WXX.json
```
### Step 5b: Import Analysis & Anomaly Detection
@ -174,7 +174,7 @@ Compare the imported week's data against existing baselines (if available from p
**Read baselines for comparison:**
```bash
cat ${CLAUDE_PLUGIN_ROOT}/assets/analytics/baselines.json 2>/dev/null
cat ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/baselines.json 2>/dev/null
```
**If baselines exist**, compare each imported post's metrics against baseline means. If no baselines exist yet, note that this is the first import and baselines will be established.
@ -290,10 +290,10 @@ Present using AskUserQuestion with the top 3 most relevant suggestions.
## Step 8: Demographics Sync Suggestion
After completing the import workflow, check if `assets/audience-insights/demographics.md` still has placeholder data:
After completing the import workflow, check if `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/audience-insights/demographics.md` still has placeholder data:
```bash
grep -c '\[Industry name\]\|\[Function\]\|\[Country\]\|\[X\]%' ${CLAUDE_PLUGIN_ROOT}/assets/audience-insights/demographics.md 2>/dev/null
grep -c '\[Industry name\]\|\[Function\]\|\[Country\]\|\[X\]%' ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/audience-insights/demographics.md 2>/dev/null
```
If placeholder count is > 10 (still mostly unfilled), suggest:
@ -305,7 +305,7 @@ If placeholder count is > 10 (still mostly unfilled), suggest:
If the import fails:
1. **Check the CSV format** - LinkedIn sometimes changes export format
2. **Verify the file path** - Ensure the file is in `assets/analytics/exports/`
2. **Verify the file path** - Ensure the file is in `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/exports/`
3. **Check file permissions** - The CLI needs read access
4. **Show the error message** and suggest solutions
@ -318,9 +318,9 @@ If the import fails:
## Reference Files
The import system creates:
- `assets/analytics/posts/YYYY-WXX.json` - Weekly post data
- `assets/analytics/metadata.json` - Import tracking and baseline metrics
- `assets/analytics/baselines.json` - Statistical baselines for anomaly detection
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/posts/YYYY-WXX.json` - Weekly post data
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/metadata.json` - Import tracking and baseline metrics
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/baselines.json` - Statistical baselines for anomaly detection
## State Tracking

View file

@ -21,7 +21,7 @@ intent in one question and route. **You do not run the analysis here.**
## Step 0: Quick context (optional)
If `assets/analytics/` holds imported data, you may note "last import: [date]" in one
If `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/` holds imported data, you may note "last import: [date]" in one
line so the user knows whether a fresh import is needed first. Do not block on it.
## Step 1: Identify what they need

View file

@ -21,7 +21,7 @@ You are a multi-platform content strategist. Help the user adapt their LinkedIn
## Step 0: Load Source Content
Ask the user to provide their LinkedIn content or read from drafts:
- Read `${CLAUDE_PLUGIN_ROOT}/assets/drafts/` for recent content
- Read `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/` for recent content
- Read `~/.claude/linkedin-studio.local.md` for recent posts
## Step 1: Select Target Platform
@ -106,7 +106,7 @@ YouTube tips:
## Step 2: Adapt and Save
After creating the adaptation:
- Save to `${CLAUDE_PLUGIN_ROOT}/assets/drafts/multiplatform/[platform]-[slug].md`
- Save to `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/multiplatform/[platform]-[slug].md`
- Auto-copy the adapted content to clipboard silently:
```bash
printf '%s' '<ADAPTED_CONTENT>' | node ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/clipboard-helper.mjs

View file

@ -1486,7 +1486,7 @@ now a first-class scheduled post.
node -e 'import("'"${CLAUDE_PLUGIN_ROOT}"'/hooks/scripts/queue-manager.mjs").then(q => q.queueAdd("<series-slug>-NN","<serie-mappe>/linkedin/NN/POST.html","YYYY-MM-DD","HH:MM","<pillar>","newsletter","<hook ~80c>",<charCount>))'
```
The function appends to `assets/drafts/queue.json` with `status:
The function appends to `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/queue.json` with `status:
"scheduled"` and returns the new entry.
3. **Persist + close the edition.** Set the article's `status: "scheduled"`,
@ -1497,7 +1497,7 @@ now a first-class scheduled post.
```
Scheduling.
- Queue entry: <series-slug>-NN → assets/drafts/queue.json (status: scheduled)
- Queue entry: <series-slug>-NN → ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/queue.json (status: scheduled)
- Slot: YYYY-MM-DD HH:MM format: newsletter
- Article status: scheduled
Edition complete. Visible in /linkedin:calendar; mark live via /linkedin:calendar (publish action).

View file

@ -155,7 +155,7 @@ file must contain no `<!-- VOICE_PLACEHOLDER -->`.
4. 5 expertise areas (these become your content pillars)
5. Target audience description
Save to `config/user-profile.local.md`.
Save to `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/profile/user-profile.md`.
After setup, recalculate and show updated score.

View file

@ -27,7 +27,7 @@ Load persistent state and personalization:
- Read `~/.claude/linkedin-studio.local.md` for posting state
- Read `${CLAUDE_PLUGIN_ROOT}/skills/linkedin-studio/SKILL.md` for profile and preferences
- Check `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/voice-samples/` for voice matching
- Read `assets/templates/my-post-templates.md` for proven post templates — use these in Step 2 (Draft)
- Read `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/templates/my-post-templates.md` for proven post templates — use these in Step 2 (Draft)
- Read `assets/frameworks/framework-template.md` if the topic involves a framework or methodology
Display status:
@ -110,7 +110,7 @@ If the user chooses to queue the post:
node --input-type=module -e "import { queueUpcoming, queueFormatSummary } from '${CLAUDE_PLUGIN_ROOT}/hooks/scripts/queue-manager.mjs'; console.log(queueFormatSummary(queueUpcoming(14)));"
```
3. Suggest the next available optimal slot
4. Save the draft to `assets/drafts/week-[WXX]/[day]-[topic-slug].md` with `scheduled_date` and `scheduled_time` in frontmatter
4. Save the draft to `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/week-[WXX]/[day]-[topic-slug].md` with `scheduled_date` and `scheduled_time` in frontmatter
5. Add to queue:
```bash
node --input-type=module -e "import { queueAdd } from '${CLAUDE_PLUGIN_ROOT}/hooks/scripts/queue-manager.mjs'; console.log(queueAdd('[id]', '[draft_path]', '[date]', '[time]', '[pillar]', '[format]', '[hook preview]', [chars]));"
@ -208,4 +208,4 @@ Replace placeholders with actual post data. Set `next_planned_topic` manually if
- `${CLAUDE_PLUGIN_ROOT}/references/scheduling-strategy.md`
- `${CLAUDE_PLUGIN_ROOT}/assets/checklists/quality-scorecard.md`
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/voice-samples/`
- `${CLAUDE_PLUGIN_ROOT}/assets/drafts/queue.json`
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/queue.json`

View file

@ -37,9 +37,9 @@ Check weekly progress:
Check for existing assets:
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/voice-samples/` - Match the user's natural voice
- `assets/examples/high-engagement-posts.md` - Study past successful posts and replicable patterns
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/examples/high-engagement-posts.md` - Study past successful posts and replicable patterns
- `assets/frameworks/framework-template.md` - Reference user's documented frameworks for framework posts
- `assets/templates/my-post-templates.md` - User's proven post templates with success rates. **Prefer these over generic structures.**
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/templates/my-post-templates.md` - User's proven post templates with success rates. **Prefer these over generic structures.**
## Step 1: Understand the Input
@ -65,7 +65,7 @@ If they provide a URL, use WebFetch to extract the content first.
Read `references/thought-leadership-angles.md` for the 8 universal angles.
**Industry-specific angles:** If `config/user-profile.local.md` exists and has an `industry` field, check the "Industry Angle Variants" section in `thought-leadership-angles.md` for the matching industry table. Use the industry-specific starter questions and example hooks to generate more targeted angle suggestions.
**Industry-specific angles:** If `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/profile/user-profile.md` exists and has an `industry` field, check the "Industry Angle Variants" section in `thought-leadership-angles.md` for the matching industry table. Use the industry-specific starter questions and example hooks to generate more targeted angle suggestions.
Select the strongest angle based on the content and user's expertise areas. Present ONE recommended angle with brief reasoning:

View file

@ -27,7 +27,7 @@ For data format details and directory structure, see `assets/analytics/README.md
First, verify that analytics data exists:
```bash
ls -1 ${CLAUDE_PLUGIN_ROOT}/assets/analytics/posts/ 2>/dev/null | grep -E '\.json$' | head -10
ls -1 ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/posts/ 2>/dev/null | grep -E '\.json$' | head -10
```
If no JSON files exist, tell the user:
@ -101,7 +101,7 @@ If the user chose monthly:
"${CLAUDE_PLUGIN_ROOT}/scripts/analytics/node_modules/.bin/tsx" "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" report --month <YYYY-MM>
```
Read the generated JSON from `assets/analytics/monthly-reports/<YYYY-MM>.json`. Present the monthly summary with MoM comparison deltas, weekly breakdown, and top performers. Then jump to Step 7 for deep-dive options.
Read the generated JSON from `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/monthly-reports/<YYYY-MM>.json`. Present the monthly summary with MoM comparison deltas, weekly breakdown, and top performers. Then jump to Step 7 for deep-dive options.
### Step 2c: Heatmap
@ -127,14 +127,14 @@ Execute the report CLI command:
```
The CLI will generate:
- `assets/analytics/weekly-reports/YYYY-WXX.json` - Structured report data
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/weekly-reports/YYYY-WXX.json` - Structured report data
## Step 4: Read Generated Report Data
Read the generated JSON report:
```bash
cat ${CLAUDE_PLUGIN_ROOT}/assets/analytics/weekly-reports/<YYYY-WXX>.json
cat ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/weekly-reports/<YYYY-WXX>.json
```
The report contains:
@ -195,7 +195,7 @@ After the initial trend data, automatically run trend analysis for the key metri
Construct the 4-week table by reading available weekly report files:
```bash
ls ${CLAUDE_PLUGIN_ROOT}/assets/analytics/weekly-reports/*.json 2>/dev/null | sort | tail -4
ls ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/weekly-reports/*.json 2>/dev/null | sort | tail -4
```
Read each file and extract the summary metrics to populate the table columns.
@ -220,7 +220,7 @@ Automatically flag these conditions based on the report data and trend analysis:
**Detect alerts by comparing current week data against baselines:**
```bash
cat ${CLAUDE_PLUGIN_ROOT}/assets/analytics/baselines.json 2>/dev/null
cat ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/baselines.json 2>/dev/null
```
Compare current week's `aggregateMetrics` against baseline means and standard deviations. Flag any metric that is:
@ -372,7 +372,7 @@ If user wants to analyze specific posts:
Read the weekly post data directly:
```bash
cat ${CLAUDE_PLUGIN_ROOT}/assets/analytics/posts/<YYYY-WXX>.json | jq '.posts[] | select(.title | contains("search term"))'
cat ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/posts/<YYYY-WXX>.json | jq '.posts[] | select(.title | contains("search term"))'
```
Show detailed metrics for that post and suggest what made it perform well/poorly.
@ -382,7 +382,7 @@ Show detailed metrics for that post and suggest what made it perform well/poorly
**If report generation fails:**
1. **Week not found**: No data imported for that week
- List available weeks: `ls ${CLAUDE_PLUGIN_ROOT}/assets/analytics/posts/`
- List available weeks: `ls ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/posts/`
- Suggest importing data for that week
2. **No posts in week**: Week file exists but is empty
@ -406,10 +406,10 @@ Read `~/.claude/linkedin-studio.local.md` and suggest:
## Reference Files
Reports use data from:
- `assets/analytics/posts/YYYY-WXX.json` - Raw weekly post data
- `assets/analytics/weekly-reports/YYYY-WXX.json` - Computed report
- `assets/analytics/baselines.json` - Statistical baselines for comparison
- `assets/analytics/metadata.json` - Import history and tracking
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/posts/YYYY-WXX.json` - Raw weekly post data
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/weekly-reports/YYYY-WXX.json` - Computed report
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/baselines.json` - Statistical baselines for comparison
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/metadata.json` - Import history and tracking
## Step 8b: Export Options
@ -419,12 +419,12 @@ If the user chooses option 4 ("Export report as markdown file") from the deep di
1. Read the JSON report data:
```bash
cat ${CLAUDE_PLUGIN_ROOT}/assets/analytics/weekly-reports/<YYYY-WXX>.json
cat ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/weekly-reports/<YYYY-WXX>.json
```
2. Format the data using this template and write to file:
Save to: `${CLAUDE_PLUGIN_ROOT}/assets/analytics/weekly-reports/YYYY-WXX-report.md`
Save to: `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/weekly-reports/YYYY-WXX-report.md`
```markdown
# LinkedIn Performance Report — Week YYYY-WXX
@ -476,13 +476,13 @@ Save to: `${CLAUDE_PLUGIN_ROOT}/assets/analytics/weekly-reports/YYYY-WXX-report.
```
**Important notes:**
- The `assets/analytics/` directory is gitignored — exported reports contain personal analytics data and should not be committed
- The `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/` directory is gitignored — exported reports contain personal analytics data and should not be committed
- Use the `-report.md` suffix to distinguish from the JSON data files (e.g., `2026-W05-report.md` vs `2026-W05.json`)
- Include all sections: metrics, trends, alerts, top performers, and recommendations for a complete standalone document
After saving, confirm to the user:
```
Report exported to: assets/analytics/weekly-reports/YYYY-WXX-report.md
Report exported to: ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/weekly-reports/YYYY-WXX-report.md
Note: This file is in your gitignored analytics directory — it won't be committed to the repository.
```

View file

@ -27,13 +27,13 @@ Read these 8 asset files and detect placeholder patterns to calculate the curren
| Category | Weight | File/Directory | Placeholder Detection |
|----------|--------|----------------|----------------------|
| Voice samples | 25 | `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/voice-samples/authentic-voice-samples.md` | Placeholder if it contains the `<!-- VOICE_PLACEHOLDER -->` sentinel (or has <50 lines) |
| User profile | 20 | `config/user-profile.local.md` | Check if file exists; count `[Your ` placeholders |
| Case studies | 15 | `assets/case-studies/*.md` | Count non-template `.md` files (exclude `case-study-template.md`) |
| Frameworks | 10 | `assets/frameworks/*.md` | Count non-template `.md` files (exclude `framework-template.md`) |
| High-engagement posts | 10 | `assets/examples/high-engagement-posts.md` | Count `## Post N:` headers |
| Demographics | 8 | `assets/audience-insights/demographics.md` | Count `[Industry name]`, `[Function]`, `[Country]`, `[X]%` |
| Engagement patterns | 7 | `assets/audience-insights/engagement-patterns.md` | Count `[Day]`, `[Time]`, `[Topic]`, `[Format]`, `[Hook type]` |
| Post templates | 5 | `assets/templates/my-post-templates.md` | Count `[Name - e.g.` vs total `## Template N:` headers |
| User profile | 20 | `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/profile/user-profile.md` | Check if file exists; count `[Your ` placeholders |
| Case studies | 15 | `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/case-studies/*.md` | Count non-template `.md` files (exclude `case-study-template.md`) |
| Frameworks | 10 | `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/frameworks/*.md` | Count non-template `.md` files (exclude `framework-template.md`) |
| High-engagement posts | 10 | `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/examples/high-engagement-posts.md` | Count `## Post N:` headers |
| Demographics | 8 | `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/audience-insights/demographics.md` | Count `[Industry name]`, `[Function]`, `[Country]`, `[X]%` |
| Engagement patterns | 7 | `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/audience-insights/engagement-patterns.md` | Count `[Day]`, `[Time]`, `[Topic]`, `[Format]`, `[Hook type]` |
| Post templates | 5 | `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/templates/my-post-templates.md` | Count `[Name - e.g.` vs total `## Template N:` headers |
**Scoring rules:**
- Full points: Asset has real data (few/no placeholders remaining)
@ -117,7 +117,7 @@ Based on their answer, run the corresponding sub-workflow below.
## Step 3b: Case Study Builder
**Goal:** Create a new case study file in `assets/case-studies/`.
**Goal:** Create a new case study file in `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/case-studies/`.
Conduct a 6-question interview:
@ -130,7 +130,7 @@ Conduct a 6-question interview:
After the interview, read `assets/case-studies/case-study-template.md` for structure reference, then create a new file:
**Filename:** `assets/case-studies/[slug].md` (derive slug from the challenge topic, e.g., `ai-procurement-transformation.md`)
**Filename:** `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/case-studies/[slug].md` (derive slug from the challenge topic, e.g., `ai-procurement-transformation.md`)
**File structure:**
```markdown
@ -172,7 +172,7 @@ Ask "Would you like to document another case study?" when done.
## Step 3c: Framework Documenter
**Goal:** Create a new framework file in `assets/frameworks/`.
**Goal:** Create a new framework file in `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/frameworks/`.
Conduct a 5-question interview:
@ -184,7 +184,7 @@ Conduct a 5-question interview:
After the interview, read `assets/frameworks/framework-template.md` for structure reference, then create:
**Filename:** `assets/frameworks/[slug].md` (e.g., `ai-maturity-model.md`)
**Filename:** `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/frameworks/[slug].md` (e.g., `ai-maturity-model.md`)
**File structure:**
```markdown
@ -228,12 +228,12 @@ Ask "Would you like to document another framework?" when done.
## Step 3d: Post Analysis
**Goal:** Document high-engagement posts in `assets/examples/high-engagement-posts.md`.
**Goal:** Document high-engagement posts in `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/examples/high-engagement-posts.md`.
Two approaches — ask which they prefer:
### Option A: Analytics Data Available
If the user has imported analytics data (check `assets/analytics/posts/` for JSON files):
If the user has imported analytics data (check `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/posts/` for JSON files):
1. Read the most recent analytics data files
2. Identify the top 3-5 posts by engagement rate
@ -257,7 +257,7 @@ If no analytics data available:
- **Pattern extraction:** What's replicable?
- **Mistakes identified:** What could be improved?
3. Read the existing `assets/examples/high-engagement-posts.md`
3. Read the existing `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/examples/high-engagement-posts.md`
4. **Append** new posts after existing entries (don't overwrite)
5. Update the "Patterns Across All High-Performing Posts" section based on all posts
@ -265,7 +265,7 @@ Ask "Would you like to add more posts?" when done.
## Step 3e: Demographics Sync
**Goal:** Populate `assets/audience-insights/demographics.md` with real LinkedIn Analytics data.
**Goal:** Populate `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/audience-insights/demographics.md` with real LinkedIn Analytics data.
Guide the user step by step through the LinkedIn Analytics UI:
@ -286,7 +286,7 @@ Guide the user step by step through the LinkedIn Analytics UI:
- Record the actual data
- Ask about trends ("Is this similar to previous months?")
5. Read the existing `assets/audience-insights/demographics.md`
5. Read the existing `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/audience-insights/demographics.md`
6. Replace the placeholder tables with real data
7. Fill in the "Key insights" sections based on the data patterns
8. Update the "Last Updated" date
@ -300,7 +300,7 @@ If the user says they don't have LinkedIn Analytics access or data yet, suggest:
## Step 3f: User Profile Setup
**Goal:** Create or update `config/user-profile.local.md`.
**Goal:** Create or update `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/profile/user-profile.md`.
Guide through each section of the profile:
@ -337,7 +337,7 @@ Guide through each section of the profile:
- "90-day growth goal?"
7. Read `config/user-profile.template.md` for structure
8. Write the completed profile to `config/user-profile.local.md`
8. Write the completed profile to `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/profile/user-profile.md`
**Important:** This file is gitignored (`.local.md` pattern), so personal data stays private.

View file

@ -294,7 +294,7 @@ For the canonical profile-alignment audit (headline/About/Experience/Featured/Sk
### Identify Signature Content
Ask the user to identify their top-performing posts (or read analytics from `${CLAUDE_PLUGIN_ROOT}/assets/analytics/`).
Ask the user to identify their top-performing posts (or read analytics from `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/`).
**Signature content criteria:**
- High saves — bookmarking is a strong authority signal; read the count from your native LinkedIn post analytics (this tool does not capture saves)

View file

@ -40,7 +40,7 @@ Load video-specific references:
Check for existing assets:
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/voice-samples/` — Match the user's natural voice (REQUIRED before scripting)
- `assets/examples/high-engagement-posts.md` — Study successful patterns
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/examples/high-engagement-posts.md` — Study successful patterns
## Step 1: Choose Video Type
@ -190,7 +190,7 @@ Iterate until satisfied.
## Step 8: Save and Update State
Save the final script to `assets/drafts/`:
Save the final script to `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/`:
```
video-[YYYY-MM-DD]-[slug]-[type]-[length].md

View file

@ -34,6 +34,43 @@ surviving bare `assets/voice-samples/` is inside the convention doc itself (it d
the in-plugin placeholder-scaffold location for the fallback rule) — Step 16's
no-bare-path assertion must exempt `references/data-path-convention.md`.
### Step 15 — 130 refs / 34 files repointed; shipped read-only preserved
Rule-based repoint (negative-lookahead per subdir): analytics 50, drafts 24,
audience-insights 14, profile/D1 12, examples 11, plans 6, my-post-templates 4,
frameworks 3, case-studies 3, network 2, repurposing-tracker 1. Counts match the
plan's family estimates once the **shipped exclusions** are accounted for
(frameworks 6→3 drops `framework-template.md`; case-studies 5→3 drops
`case-study-template.md`; analytics drops `README.md`; the Step-11 `ANALYTICS_ROOT`
pins were already gone). **Style-A `${CLAUDE_PLUGIN_ROOT}` preserved** for shipped
read-only: `analytics/README.md`, all `*-template.md` seeds, `assets/checklists/`,
`assets/quick-post-resources.md`, the shipped `assets/templates/*` (only the
`my-post-templates.md` *instance* repointed), `config/*.template.*`, and every
`scripts/analytics` / `hooks/scripts` CODE path. **profile/D1:** `config/user-profile.local.md`
`${…}/profile/user-profile.md` (path + filename change, drops `.local`, per
MOVE_FILES). **ab-tests/** routes under `${…}/analytics/ab-tests/` (brief §7.1);
**plans/** at `${…}/plans/` (top-level). Verify: the only in-plugin data-dir paths
left are the three shipped exclusions; full lint Failed:1 = EXPECT_REFS only.
### Step 15 scope notes — two additions, one deferral
- **network/ + repurposing-tracker.md repointed (additions beyond the plan's named
families).** Both are **code-invisible data classes** the agents *write*
(`network-builder.md`, `content-repurposer.md` save trackers into the plugin tree).
They fit Step 15's stated goal ("route the code-invisible data classes so they don't
silently orphan when the default flips"); the plan named ab-tests/plans as examples,
not an exhaustive list. As **write-targets** they are self-sufficient — the agent
creates the file external on first write, no migration entry needed.
- **`config/personas.local.md` deferred — OUT of M0 scope.** Unlike the write-targets,
this is a **read fallback** in a resolution chain (edition-state → series file →
plugin `personas.local.md` → template). Repointing the read external without a
migration dest would break the read, and adding it to `MOVE_FILES` is a `.mjs` change
Step 15's scope fence forbids. Personas are newsletter/series production data (already
external via `$LTL_SERIES_ROOT`); the plugin-level `personas.local.md` is a deliberate
in-plugin fallback library. Left as-is; Step 16's no-bare-path lint targets the
*migrated* data classes only, so it does not flag personas. Track as a follow-up if a
full personas externalization is wanted later.
## Session 3 — Steps 1113 (2026-06-18)
### Environment reality vs. plan assumptions

View file

@ -39,7 +39,7 @@ writeState(content => updateFollowerCount(content, {
**3. Queue Status Check**
If posts were added to the queue during this session (`assets/drafts/queue.json` was modified):
If posts were added to the queue during this session (`${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/queue.json` was modified):
- Confirm how many posts were queued and their scheduled dates
- Remind: "View your full schedule with /linkedin:calendar"

View file

@ -105,7 +105,7 @@ The defensible **ordering** of engagement signals — **saves > shares > quality
### Engagement Velocity
Speed of engagement accumulation in the first hour after posting. 15+ engagements in the first hour unlocks Stage 3 distribution. Monitored at 5/15/30/60/90-minute intervals.
**Used in:** `references/algorithm-signals-reference.md`, `assets/audience-insights/engagement-patterns.md`
**Used in:** `references/algorithm-signals-reference.md`, `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/audience-insights/engagement-patterns.md`
### Evergreen Content
Posts maintaining relevance and engagement potential beyond the initial publication window. Identified through scoring (topical relevance, performance, refresh potential). Suitable for repurposing over 12+ months.

View file

@ -86,7 +86,7 @@ Ensure coverage across expertise areas:
When posts are scheduled via `/linkedin:batch`:
1. Each post gets a `scheduled_date` and `scheduled_time` from this algorithm
2. Entry is added to `assets/drafts/queue.json`
2. Entry is added to `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/queue.json`
3. Session-start hook shows today's scheduled posts
4. `/linkedin:calendar` (publish action) marks posts as published and updates state
5. `/linkedin:calendar` shows the full schedule view

View file

@ -124,7 +124,7 @@ These angles work across all industries because they're about **types of thinkin
## Industry Angle Variants
Concrete starter questions and example hooks per industry. When the user's industry is known (from `config/user-profile.local.md`), surface the relevant table during angle selection.
Concrete starter questions and example hooks per industry. When the user's industry is known (from `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/profile/user-profile.md`), surface the relevant table during angle selection.
### Tech / Software / AI

View file

@ -49,7 +49,7 @@ This skill covers everything related to LinkedIn analytics, performance measurem
Node.js CLI tool for parsing LinkedIn CSV exports into structured JSON.
**Location:** `scripts/analytics/`
**Data:** `assets/analytics/` (gitignored -- personal performance data)
**Data:** `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/` (gitignored -- personal performance data)
**CLI usage:**
```bash
@ -60,7 +60,7 @@ ANALYTICS_ROOT="${CLAUDE_PLUGIN_ROOT}/assets/analytics" node --import tsx "${CLA
**Storage structure:**
```
assets/analytics/
${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/
+-- exports/ # Raw CSV from LinkedIn (drop files here)
+-- posts/ # Imported post data as JSON
+-- weekly-reports/ # Generated weekly reports

View file

@ -10,7 +10,7 @@ description: |
**To customize this skill for your voice and goals:**
1. Copy `config/user-profile.template.md` to `config/user-profile.local.md`
1. Copy `config/user-profile.template.md` to `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/profile/user-profile.md`
2. Fill in your profile, voice preferences, and goals
3. The skill will use your settings when generating content