# Generate Outline

> Produce outline.md (structured presentation/document skeleton) from a brief. Shared content-pipeline sub-skill, solo-invokable.

- Skill: `jokerman89/generate-outline` (Agent Skill)
- Install (CLI): `npx skillmds@latest add jokerman89/generate-outline`
- Raw SKILL.md: https://api.skillmd.com/api/skills/jokerman89/generate-outline/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: jokerman89 (https://skillmd.com/u/jokerman89)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/jokerman89/generate-outline

---


You are the `generate-outline` skill — first stage of the v3.5 shared content pipeline. Produces an outline.md from a brief.

## What this skill does

Reads a brief (path or inline text) + audience + arc + target-format hints, then produces a structured outline.md with frontmatter (title, audience, arc, target_formats, slide_count_target) + per-section/per-slide entries with key_message + voice-technique hint + source-material reference.

Used by `generate` orchestrator as Step 3, or solo when operator wants only an outline to fill in manually.

Replaces brief-parsing logic previously inline in `generate-ppt` / `generate-web` / `generate-word` (consolidated here so the three renderers share one parser).

## When to use

- First step of `/li:generate` orchestrator chain
- Operator wants ideation-only — "give me an outline I can fill in manually"
- Re-outline an existing run with different audience/arc (rerun against same brief)
- Outline-tinder: produce N candidate outlines, operator picks one

## When NOT to use

- Operator already has a content.md — skip directly to `/li:generate-design`
- Single-slide quick mockup — bypass outline, write content directly
- Re-render of existing run without content changes — use format-builder solo with `--from-pipeline`

## Inputs

- Required `--brief <path|inline>` — content brief
- Required `--target-formats <ppt,web,word,...>` — comma-separated format list (affects slide_count_target + arc choice)
- Optional `--audience <text>` — primary audience (default: "general business")
- Optional `--arc <name>` — narrative arc (see Arcs section)
- Optional `--slide-count <N>` — target slide count (default: agent decides based on material volume)
- Optional `--language <sv|en>` — output language (default: match brief)
- Optional `--out <path>` — output path (default: `${run_dir}/outline.md` or `./outline.md`)

## Narrative arcs

| Arc | Structure | Best for |
|-----|-----------|----------|
| problem-solution | Problem → Solution → Proof → CTA | Customer pitch |
| deep-dive | Context → Analysis → Implications → Next steps | Technical review |
| keynote | Hook → Story → Data → Takeaway | Conference talk |
| scr | Situation → Complication → Resolution | Executive briefing |
| status | Recap → Progress → Blockers → Plan | Internal update |

If no arc specified, agent picks based on audience + brief signal.

## Output schema (outline.md)

```markdown
---
title: <string, max 12 words>
audience: <string>
arc: <name from arcs table>
language: <sv|en>
target_formats: [ppt, web, word]
slide_count_target: <int>
generated_at: <iso-8601>
source_brief_hash: <sha256 of brief>
---

# <title>

## §1 — <Slide/Section title, max 8 words>
- **type:** title | agenda | section-header | content | content-image | two-column | comparison | data-viz | quote | timeline | demo | thank-you
- **key_message:** <one sentence — the one thing this section communicates>
- **source_material:** <brief paragraph or "agent synthesis">
- **voice_technique:** <REVEAL/Understatement | INSPIRE/Marvel | PROVOKE/Skewer | ...>
- **notes_for_writer:** <guidance for the write step>

## §2 — <next section title>
...
```

Sections are numbered §1, §2, ... — a consistent §-pattern across content artifacts.

## Workflow

### Step 1 — Parse brief

Read brief content. If brief is a path: load file. If inline: use text directly. Compute sha256 hash for traceability.

### Step 2 — Detect language + audience signal

Default language matches brief language. Audience cues from brief (mention of "CTO", "engineers", "customer", etc.) inform default arc if `--arc` not specified.

### Step 3 — Pick arc

If `--arc` provided: use it. Otherwise:
- Brief mentions customer + pitch words → `problem-solution`
- Brief is technical-deep → `deep-dive`
- Brief mentions executive / board → `scr`
- Brief is status / progress → `status`
- Brief is keynote / conference → `keynote`

### Step 4 — Choose slide_count_target

If `--slide-count` provided: use it. Otherwise:
- `ppt` in target_formats: 8-15 slides (default 12) based on material volume
- `word` only: section_count 5-8
- `web` only: 3-5 hero/sections

### Step 5 — Generate section/slide list

For each section/slide:
- Pick type from available list
- Write title (max 8 words, no period)
- Write key_message (one sentence, distinct from every other key_message)
- Map source_material reference (which part of brief, or "agent synthesis")
- Pick voice_technique appropriate for type + arc position
- Write notes_for_writer (guidance)

### Step 6 — Validate

- All key_messages distinct
- Arc internally consistent (matches first → middle → last structure for chosen arc)
- Slide types vary (no 5 content slides in a row)
- Total within ±2 of slide_count_target

### Step 7 — Write outline.md + return path

Write to `--out` path. Surface summary (slide_count, section types, language, arc) to operator.

## Status protocol

- **DONE** — outline.md written, validation passed
- **DONE_WITH_CONCERNS** — outline.md written but slide-count drift > ±2 from target, or arc consistency questionable
- **BLOCKED** — brief is unparseable, missing, or too vague to outline
- **NEEDS_CONTEXT** — `--target-formats` not specified (ambiguous slide-count target)

## Pause-points

- Brief is too vague to outline (less than 50 words): surface back + offer to gather more context
- Multiple plausible arcs detected: surface options + recommendation

## Integration

**Reads:**
- Brief (path or inline)
- `~/.lintel/voice/arc-defaults.yaml` (optional — operator's arc-preference overrides)

**Writes:**
- `outline.md` to `--out` path

**Consumed by:**
- `/li:generate` orchestrator (Step 3)
- `/li:generate-write` (input → content.md)
- Operator (solo-invocation use case)

## Anti-patterns

- **Generating content INSIDE outline.md** — outline holds structure + key_messages only. Content (bodies, bullets) belongs in content.md (generate-write).
- **Duplicate key_messages across sections** — every key_message must be distinct. If two sections have the same message, collapse them.
- **Inferring `--target-formats`** — slide_count_target depends on this. Block on missing instead of guessing.
- **Hard-coded English when brief is in Swedish** — language must match brief unless `--language` overrides.

## Failure recovery

- Brief too short: surface back with prompt for at least 100 words of substantive content
- All arcs deadlock (each scores equal): pick `problem-solution` (most-versatile default), flag in notes
- Slide_count drift > ±2: regenerate with explicit constraint, flag if drift persists

## Recommended next steps after invocation

- For full chain: invoke `/li:generate-write --outline <outline.md>` to produce content.md
- For solo-iteration: operator edits outline.md manually, then resumes chain
- For format-specific outline: re-invoke with single `--target-formats` to optimize slide_count for that format

