linkedin-studio/CLAUDE.md
Kjell Tore Guttormsen 9567689c4a docs(claude-md): trim CLAUDE.md to invariants (−2,266 always-tok)
CLAUDE.md is loaded every turn while working in this repo (measured 4,846
always-loaded tokens — the entire per-repo delta, since the repo has no
.claude/rules or .mcp.json). The bulk was a version-history narrative: the
2026-05-31 re-baseline note plus a single paragraph recounting the full
v2.0.0 → v4.1.0 journey (per-version motivation, gate-by-gate evolution).
That is CHANGELOG material, not an invariant for working on the plugin —
CHANGELOG.md (18 version headings) already owns it.

Trimmed to what is invariant: a terse current-maturity intro (v0.5.3, M0
done, v1.0.0 remainder) pointing to CHANGELOG/docs; the architecture,
hooks, command (29) and agent (19) tables, and content-quality rules. The
verbose per-row prose (newsletter phase-list, agent (vX.Y)/Step-tag
motivation) is compressed to one-liners. Agent name/model/color cells,
all counts, and the version stay byte-exact so the structure lint holds.

Verified with the repo's own gates: scripts/test-runner.sh 138/0 ("All
structural checks passed!" — counts, version-consistency, stat-consistency,
model-consistency, render-chain all green); scripts/check-model-consistency.mjs
OK (19 agents, all surface declarations match frontmatter). CLAUDE.md
127→109 lines, 19,572→10,457 B, 4,846→2,580 tok (−47%). Docs-only — no
version bump, no catalog ref change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01683eAqVecv9VZfQzL8CQ9h
2026-06-29 10:14:23 +02:00

109 lines
10 KiB
Markdown

# LinkedIn Studio Plugin (v0.5.3)
Full-spectrum LinkedIn content engine — short-form feed posts, carousels, video scripts, and long-form newsletter editions — with the 2026 relevance-ranking model baked in. Maturity v0.5.3: M0 (per-user data dir `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/`, idempotent session-start migration — see `references/data-path-convention.md`) complete; all 29 command surfaces through the interactive quality-gate (`docs/hardening/log.md`). Remaining for v1.0.0: a GUI + independent cold-review coverage (the `/trekreview` artifact `docs/hardening/review.md` persists for S1 only — see `docs/hardening/plan.md`). Version history → `CHANGELOG.md`.
## Architecture
- **State file:** `~/.claude/linkedin-studio.local.md` (YAML frontmatter, auto-initialized from `config/state-file.template.md`)
- **State updater:** `hooks/scripts/state-updater.mjs` — deterministic state mutations (post tracking, streak, content history pruning). Pure functions, tested, no AI involvement
- **Clipboard helper:** `hooks/scripts/clipboard-helper.mjs` — cross-platform clipboard (macOS `pbcopy`, Linux `xclip`/`xsel`, WSL `clip.exe`). All content commands auto-copy
- **iCal generator:** `hooks/scripts/ical-generator.mjs` — RFC 5545 calendar files for batch scheduling. Standalone CLI + importable module
- **Post queue:** `assets/drafts/queue.json` (managed by `hooks/scripts/queue-manager.mjs`)
- **Analytics:** CLI `scripts/analytics/` (TypeScript, needs `tsx` + `npm install`); data `assets/analytics/` (gitignored)
- **Analytics metrics (S16):** parsed CSV columns + an optional, manually-entered `saves` count (count-only in native LinkedIn analytics since ~Sept 2025, no CSV export / no API). `parseOptionalCount()`: blank / non-numeric / negative → `undefined` (`unknown`, never 0), a genuine `0` is kept; saves surfaced per-post + as `totalSaves`, but **not** folded into `engagementRate`. `dwell` stays **explicitly unmeasurable** (internal to LinkedIn, no export/API). All analytics I/O routes through the `getAnalyticsRoot()` seam (M0 per-user data-dir).
## Hooks
9 hooks across 7 events. All Node.js (.mjs). PreToolUse/PostToolUse hooks use parameterized `content-gatekeeper.mjs` with `isLinkedInContent()` check.
| Event | Purpose |
|-------|---------|
| `SessionStart` | Load state, REMEMBER.md, milestone tracker |
| `PreToolUse` (Write\|Edit) | Content quality gate, voice guardian, topic rotation gate |
| `Stop` | State update, pre-publish reminders, content history |
| `UserPromptSubmit` | LinkedIn context enrichment (three-tier matching) |
| `PostToolUse` (Write) | Post-creation automation (5x5x5, posting time) |
| `PreCompact` | Preserve LinkedIn context during compaction |
| `Notification` | Posting reminders (rate-limited 30min) |
**Session markers:** `/tmp/linkedin-hooks/session-active` (Stop hook gating, 12h staleness). **Shared modules:** `linkedin-content-filter.mjs`, `queue-manager.mjs`, `personalization-score.mjs`, `state-updater.mjs`, `clipboard-helper.mjs`.
**State updates:** post tracking, streak, and content history are handled deterministically by `state-updater.mjs` (Stop hook + commands); entries older than 90 days are auto-pruned at session start.
**Hook editing:** edit `hooks/hooks.template.json` + `hooks/prompts/*.md`, then run `python3 hooks/scripts/compile-hooks.py`. Do not edit `hooks.json` directly. Prompts load at runtime via gatekeeper scripts; the compile step is only needed when adding `type: prompt` hooks.
## Commands (29)
All content commands auto-copy output to clipboard via `clipboard-helper.mjs`; interactive steps are minimized (angle/format/post-type inferred from context, max 2 questions per post). Organized into five journeys (Start · Create · Engage · Measure · Grow): `create`/`measure` are guided creation/analytics front-doors, `onboarding`/`strategy` the Start/Grow front-doors, and the 27 atomic commands are the execution tier.
| Command | Purpose |
|---------|---------|
| `/linkedin` | Router — status line + five-journey command menu |
| `/linkedin:create` | Create front-door — routes to the command owning the format (post/quick/react/carousel/video/multiplatform/batch/newsletter); delegates only |
| `/linkedin:measure` | Measure front-door — routes to the analytics command (import/report/analyze/audit/ab-test); delegates only |
| `/linkedin:onboarding` | Multi-step onboarding wizard (profile → setup → first-post); Start-journey front-door |
| `/linkedin:first-post` | First-post accelerator (10 min) |
| `/linkedin:setup` | Guided personalization setup |
| `/linkedin:react` | URL-to-post pipeline |
| `/linkedin:post` | Full post creation (10-15 min) |
| `/linkedin:quick` | 5-minute quick post (3-line formula) + 8 post-type templates |
| `/linkedin:pipeline` | Full end-to-end content pipeline |
| `/linkedin:newsletter` | Long-form orchestrator (newsletter / essay / series article) — multi-session 18-phase pipeline with gates before prose (skeleton + spine), fact-check, editorial-review (Step 5.5), persona sweep, headless adversarial review (Step 6.5), and visual-assets — all before lock |
| `/linkedin:headless-review` | Cold adversarial review package — 3 headless archetypes (`content-reviewer`, `language-reviewer`, `fact-reviewer`) + `persona-reviewer` on a FROZEN draft, no drafting-session context; operator-gated report (Step 6.5 standalone surface) |
| `/linkedin:pivot` | Re-open a long-form edition after a late substantive change so cleared gates re-run before lock (pivot heuristic: >20% word-count or >2 new sections) |
| `/linkedin:batch` | Create a full week of content |
| `/linkedin:calendar` | View/manage post scheduling queue + publish action |
| `/linkedin:firsthour` | Post-publish first-hour / reply-loop sprint — delegates to `engagement-coach`, persists the plan (`recordFirstHourPlan`), hands off to `post-feedback-monitor` |
| `/linkedin:carousel` | Structured multi-slide carousel generator |
| `/linkedin:video` | Video script generator (30s-2min) |
| `/linkedin:multiplatform` | Adapt content for other platforms (long-form → `/linkedin:newsletter`) |
| `/linkedin:analyze` | Content/performance analysis |
| `/linkedin:audit` | Periodic content strategy audit |
| `/linkedin:import` | Import CSV export → structured JSON (delegates analysis to `/linkedin:report`) |
| `/linkedin:report` | Generate weekly performance report |
| `/linkedin:ab-test` | Design and manage A/B content tests |
| `/linkedin:strategy` | Growth strategy + authority building; Grow-journey front-door |
| `/linkedin:competitive` | Competitive analysis of niche |
| `/linkedin:monetize` | Monetization strategy and funnels (unlocks at ~1K followers) |
| `/linkedin:outreach` | Outreach orchestrator — collaborations + speaking (unlocks at ~1K followers) |
| `/linkedin:profile` | Profile/topic-relevance optimization |
## Agents (19)
| Agent | Model | Color | Responsibility |
|-------|-------|-------|----------------|
| `content-optimizer` | Sonnet | Blue | Optimize existing posts |
| `strategy-advisor` | Sonnet | Green | Growth recommendations |
| `analytics-interpreter` | Sonnet | Yellow | Audience pattern analysis + weekly/monthly performance reports (interpret/report modes) |
| `engagement-coach` | Sonnet | Magenta | 5x5x5 + first-hour tactics + CEA commenting + target selection |
| `content-planner` | Sonnet | Cyan | Content audit + weekly/monthly plans |
| `network-builder` | Sonnet | Teal | Strategic networking + outreach |
| `content-repurposer` | Sonnet | Purple | Format conversion + evergreen refresh |
| `trend-spotter` | Sonnet | White | Trending topics + opportunity scores |
| `voice-trainer` | Sonnet | Pink | Voice profile building + drift detection |
| `differentiation-checker` | Sonnet | Gray | Originality scoring + commodity detection |
| `post-feedback-monitor` | Opus | Lime | Post-publish 48h monitoring |
| `video-scripter` | Sonnet | Violet | Video script creation with pacing |
| `fact-checker` | Opus | Brown | Factual-claim verification against primary sources + post-cutoff web-search mandate (longform) |
| `editorial-reviewer` | Opus | Orange | Editor's craft gate (Step 5.5, before persona sweep): prosa-håndverk + narrativ-arkitektur, ≤10 flags BLOCK/REWORK/NICE, operator-gated via `SendUserFile` (longform) |
| `persona-reviewer` | Opus | Olive | Reader-persona gate — skeleton (before prose) + resonance (before lock) + hook-conversion (after lock), blocking hard-fail list (longform) |
| `voice-scrubber` | Opus | Red | De-AI scrub + Norwegian-chronicle voice-drift correction (longform) |
| `content-reviewer` | Opus | Maroon | Cold/headless argument-integrity review on a frozen draft (Step 6.5): logical holes, unsupported assumptions, contradiction, missing concretization, unanswered objection; ≤8 flags (longform) |
| `language-reviewer` | Opus | Navy | Cold/headless Norwegian-language review on a frozen draft (Step 6.5): repetition, anglicisms, stiff register, self-contradiction, rhythm; ≤10 flags (longform) |
| `fact-reviewer` | Opus | Gold | Cold/headless re-verification on the frozen/pivoted version (Step 6.5, web search): verifiable claims, quote precision, number attribution, source quality + pivot-risk (longform) |
**Rule:** Always read `assets/voice-samples/` before generating content.
**Invocation form:** commands invoke plugin agents by their **namespaced** type — `subagent_type: linkedin-studio:<name>`, never the bare `<name>` (a bare type does not resolve and the `Task` call fails).
**Reload requirement:** a NEW agent file under `agents/` registers only after a Claude Code **session reload** (the plugin agent set is built at session start). Reload before invoking a freshly-added agent.
## Content Quality Rules
1. Hook: 110-140 characters (mobile cutoff)
2. Post length: 1,200-1,800 chars (standard), 150-500 chars (quick)
3. No external links in post body (correlate with lower reach; see `references/algorithm-signals-reference.md`)
4. No corporate buzzwords: leverage, synergy, paradigm shift, thought leader, disruptive, value proposition, ecosystem, holistic approach
5. Topic must align with user's 5 core expertise areas (topic-relevance signal)
6. Topic rotation: no back-to-back same pillar, no pillar >50% in 14 days (warn-only)
7. Progressive onboarding: personalization score hidden until 3+ posts; voice guardian suppressed until 5+ voice samples