When you build something on Claude Desktop and want to show your work — whether the entire transcript IS the story, or it's an appendix to a broader piece, or just a snippet you want to drop into a Notion doc — you need clean HTML that renders the chat the way you saw it. The distro-desktop-transcript skill handles that formatting work.
Hand it the current conversation (or a portion of it), and it produces a fenced HTML block in chat with bold all-caps speaker labels, horizontal rules between turns, monospace pills for tool calls, and faithful preservation of the original prose. Copy it into a Distro story, a blog post, an email — wherever you want it.
It's a formatter, not a publisher. Default output is HTML in chat. If you explicitly ask, it can chain into distro_content_publish to file a new draft, or into distro_content_update to append a transcript to an existing story.
What you'll need
An ongoing Claude Desktop conversation you want to capture
Optional: the Distro Publisher MCP connected, if you want the skill to chain into publishing
What it does
Defaults to formatting the entire conversation up through the message before the invocation (no infinite-mirror recursion)
Supports natural-language range overrides ("the last 10 turns," "from when we discussed X," "just the part about my edits") — confirms fuzzy ranges before rendering
Renders each turn with a bold all-caps speaker label (
👤 BRAD:/🤖 CLAUDE:) and an<hr>rule between turns — visually unmissable, survives Tiptap and other HTML-to-markdown convertersRenders tool calls as inline
<code>🔧 Tool name</code>pills with human-readable names (distro_content_publish→Distro content publish)Optionally surfaces interesting tool results in a single italic line beneath the pill (e.g., "Filed as content ID 874")
Converts em dashes (
—) in assistant messages to spaced en dashes (–) to match house style — user messages stay verbatimHonors user overrides: custom labels, no emojis, different roles ("Q and A")
Outputs as a fenced HTML code block in chat, ready to copy
Install the skill
Ask Claude:
"Please fetch the distro-desktop-transcript skill from Distro Skills and give me a
.skillfile I can install."
Claude will pull this story, extract the SKILL.md from the fenced block below, and package it as distro-desktop-transcript.skill. The file will appear in your chat with a Save skill button — click it to install directly.
Requires the Distro Reader or Distro Publisher MCP connected so Claude can pull the story.
Claude Code users: ask Claude to drop the unzipped folder into ~/.claude/skills/distro-desktop-transcript/ and restart the session.
No Distro MCP connected? Copy the SKILL.md contents from the fenced block below into a file called SKILL.md inside a folder called distro-desktop-transcript, zip it (folder as zip root), and upload through Settings → Capabilities → Skills → Upload skill.
The skill source
This is the canonical SKILL.md:
---
name: distro-desktop-transcript
description: Use this skill when the user asks to format the current Claude conversation (or a portion of it) as an HTML transcript — for use in a Distro story, a blog post, a Notion doc, an email, or anywhere else they want a clean, readable record of the chat. Triggers on requests like "format this conversation as a transcript," "give me a transcript of our chat," "make a build-in-public transcript of what we just did," "turn the last 10 turns into HTML I can paste into [story]," or any request that pairs the current chat with a transcript-output goal. The skill is fundamentally a formatter — it produces HTML in chat for the user to copy or hand off to a publishing tool. It can be used to produce an entire piece (the transcript IS the story), an appendix to a broader piece, or a snippet embedded in something else.
---
# Distro desktop transcript skill
Turn the current Claude conversation — or a portion of it — into clean, readable HTML that the user can paste into a Distro story, a Notion doc, a blog post, an email, or anywhere else.
This skill is a **formatter**, not a publisher. Default output is the rendered HTML in chat. The user takes it from there.
## When this skill applies
The user wants to capture the chat as a transcript. Common framings:
- "Format this conversation as a transcript"
- "Make a build-in-public transcript of what we just did"
- "Give me HTML for the last [N] turns I can paste into [somewhere]"
- "Turn the part where we discussed [topic] into a transcript"
- "I want to show my work — render this chat for the appendix"
If the user is asking for transcript HTML, this skill applies. If they're asking to publish a Distro story that happens to *contain* a transcript section, this skill produces the transcript portion; the publishing happens via `distro_content_publish` separately (or via `distro-release-rewrite` or another publishing skill).
## Scoping the transcript: which turns to include
Default to **the entire current conversation up through the message before the one that invoked this skill.** The invocation itself is not part of the transcript (that's a "show your work" recursion artifact users don't want).
If the user specifies a different range, honor it. Examples:
- "From when we started discussing the press release" → find that turn, include from there
- "The last 10 turns" → count back 10 user-or-assistant turns
- "Just the part where you analyzed my edits" → identify that section, include only those turns
- "Everything except the part about [topic]" → include all but that section
When the range is fuzzy ("the build-in-public part," "the interesting bit"), summarize what you understand the range to be and confirm with the user before rendering. Don't guess silently.
The cutoff is always **inclusive on both ends** — if the user says "from message X through message Y," include X and Y.
## The "current message" cutoff rule
The transcript should never include the assistant message that contains the rendered transcript itself. That creates an infinite mirror. Cut cleanly at the end of the message immediately before the one that invoked this skill.
If that creates an awkward stopping point (e.g., the user invoked the skill mid-question), tell them and ask whether to include or exclude the final partial turn.
## HTML structure
Each turn opens with a bold all-caps speaker label, followed by the message content. Turns are separated by `<hr>` rules. This survives Tiptap and other HTML-to-markdown converters cleanly.
```html
<p><strong>👤 [USER LABEL]:</strong></p>
<p>User message content...</p>
<hr>
<p><strong>🤖 [ASSISTANT LABEL]:</strong></p>
<p>Assistant message content...</p>
<p><code>🔧 Tool name</code></p>
<p>More assistant content...</p>
<hr>
```
### Speaker labels
Default labels:
- User: `👤 [USER'S NAME]:` — use the user's first name or preferred handle if known from earlier in the conversation. Falls back to `👤 USER:` if unknown.
- Assistant: `🤖 CLAUDE:`
The user can override: "use my full name," "no emojis," "label me as 'Q' and Claude as 'A'." Honor any explicit override.
If the user asks for no emojis, drop both the 👤 and the 🤖 — keep the bold all-caps labels with colons.
### Tool calls
Render each tool call inline as a monospace pill on its own line:
```html
<p><code>🔧 Tool name</code></p>
```
Use the human-readable tool name as it appears in the Claude Desktop UI — `Distro content publish`, `Web fetch`, `View file`, `Create file`, `Bash`, `Present files`, `Distro content update`, etc. Strip technical underscores: `distro_content_list` → `Distro content list`.
For consecutive tool calls of the same type (e.g., five `Distro content get` calls in a row), render each on its own line with `<br>` between them, inside one `<p>` block:
```html
<p><code>🔧 Distro content get</code><br>
<code>🔧 Distro content get</code><br>
<code>🔧 Distro content get</code></p>
```
If a tool result is interesting and worth surfacing (e.g., "filed as content ID 874"), add a single italic line under the pill:
```html
<p><code>🔧 Distro content publish</code><br>
<em>Filed as content ID 874 (draft).</em></p>
```
Skip uninteresting tool results. Don't dump JSON payloads. The signifier is the point — show the user what *kind* of work happened, not the raw machinery.
### Inline formatting inside messages
Preserve the formatting that was actually in the messages:
- Code spans → `<code>...</code>`
- Bold → `<strong>...</strong>`
- Italics → `<em>...</em>`
- Lists → `<ol>` / `<ul>` with `<li>`
- Block quotes → `<blockquote>...</blockquote>`
- URLs → `<a target="_blank" rel="noopener noreferrer nofollow" class="tiptap-link" href="...">...</a>` — the same anchor attributes the Distro editor produces, so the link survives a paste into a Distro story without losing styling
- Line breaks within a paragraph → `<br>`
- New paragraphs → new `<p>` blocks
### Em dash conversion
If the original assistant messages contain em dashes (`—`), **convert them to spaced en dashes (` – `)** in the rendered transcript. This matches Brad's style guide (em dashes read as AI slop; spaced en dashes are the house standard). User messages stay verbatim — don't edit what the user actually typed.
### Closing marker (optional)
For full-conversation transcripts being published as a complete piece, end with a centered italic marker:
```html
<p style="text-align: center; color: #71717a; font-size: 0.9em; margin-top: 2em;"><em>— end of transcript —</em></p>
```
Skip this for snippets or appendices — it's a "this is the whole thing" signal, not a "this is one section" signal.
## Output flow
1. **Confirm the cutoff** if the user's request is fuzzy. Otherwise, default to the full conversation up through the message before the invocation.
2. **Confirm the speaker labels** if the user might want a non-default (e.g., long conversations where you've referenced them by name — defer to that name).
3. **Render the HTML** in chat as a fenced code block (```` ```html ... ``` ````) so the user can copy it cleanly.
4. **Tell them what to do with it.** Default suggestion: paste into the Distro editor for a story they're drafting, or wherever else they want it. If they've previously mentioned a target (a Distro draft they're working on, a Notion doc), name it.
## When to chain into publishing
If the user explicitly says "publish this transcript as a story on [newslode]" or "use this as the appendix to [content ID]," the formatting work is done by this skill, but the publishing is handed off:
- **New story** → call `distro_content_publish` with the rendered HTML as the `content`. Ask for title, preview, and any editorial top before filing. Default to `status: "draft"`.
- **Append to existing story** → fetch the existing content via `distro_content_get`, append the transcript HTML to the body, and update via `distro_content_update` with `contentFormat: "html"`.
Don't chain into publishing without an explicit request. The default mode is "render and hand back."
## What this skill does NOT do
- **Does not publish anything by default.** Output is HTML in chat. Publishing requires an explicit user request.
- **Does not edit the conversation content.** Verbatim reproduction is the point. The only allowed transformation is em-dash-to-en-dash conversion in *assistant* messages (to match house style); user messages are never edited.
- **Does not include tool-call JSON or parameter dumps.** The pill signifier is enough. If the user wants raw tool detail for some reason, they'll ask.
- **Does not include the invoking message or the response that contains the rendered transcript.** Cut at the message before the invocation.
- **Does not include system prompts, tool schemas, or other infrastructure** — only the user-and-assistant turns the user actually saw in chat.
## Example invocations
### Example 1 — full conversation, default everything
> User: "Format this whole chat as a transcript."
Steps:
1. Identify cutoff: end of the message before this invocation.
2. Default labels: `👤 [User's name from context]:` and `🤖 CLAUDE:`.
3. Render full conversation as HTML in a fenced code block.
4. Tell the user: "Here's the transcript. Paste it wherever you want it."
### Example 2 — partial range, embedded in another story
> User: "Take the part where you analyzed my edits and the part where we built the skill — I want to use it as the appendix to the build-in-public post I'm drafting."
Steps:
1. Identify the range: from the user's "ok i have made some edits" message through the message before this invocation. Confirm the range with the user before rendering.
2. Render as HTML in a fenced code block.
3. Tell the user: "Here's the appendix HTML. Paste it after the editorial top of your draft."
### Example 3 — chain into publishing a new story
> User: "Render this conversation as a transcript and file it as a draft on Liqquidity's Newslode. Title: 'How I built the X skill.'"
Steps:
1. Render the transcript HTML.
2. Show the user the rendered HTML and confirm they want to publish.
3. Resolve `Liqquidity's Newslode` → `publicationId: 69` via `distro_content_list` (same lookup pattern as `distro-release-rewrite`).
4. Ask for a `preview` (~120 chars) if not provided.
5. Call `distro_content_publish` with the HTML content, title, preview, `contentFormat: "html"`, `status: "draft"`.
6. Report the content ID and edit link.
### Example 4 — append to an existing story
> User: "Append a transcript of this chat to content ID 876."
Steps:
1. Fetch existing content via `distro_content_get(contentId: 876)`.
2. Render the transcript HTML.
3. Show the user the new transcript section and confirm before merging.
4. Update with the existing body + a `<hr>` divider + the new transcript, via `distro_content_update` with `contentFormat: "html"`.
## Style notes
- **No CSS-in-style-blocks for layout.** Inline `style=""` attributes are okay for the closing `— end of transcript —` marker, but don't rely on `<style>` blocks at the top of the body — Tiptap may strip them. Use markdown-friendly structure (bold labels, `<hr>` rules, monospace `<code>` for tool calls) so the transcript reads correctly even if styling is stripped.
- **Keep the speaker labels visually unmissable.** Bold + all caps + emoji + colon. The whole point is that a reader scrolling through can instantly tell when the speaker changes.
- **Emoji choice:** 👤 for user, 🤖 for assistant. Distinctive, easy to scan, survives any encoding. If the user asks for no emojis, drop them.
## When not to use this skill
- **The user wants to summarize the chat**, not reproduce it verbatim. That's a different task — write a summary, don't render a transcript.
- **The user wants raw conversation export** (e.g., JSON, markdown without formatting). Hand them what they asked for; don't apply this skill's HTML conventions.
- **The conversation includes content that shouldn't be reproduced** (sensitive info, content the user later asked you to forget). Flag this and ask the user how to handle it before rendering.
When to use this skill
Capturing a Claude Desktop conversation as part of a "build in public" Distro story
Producing an appendix transcript for a story whose editorial top is already written
Pulling a snippet of a chat into a Notion doc, blog post, or email
Documenting an agentic workflow for transparency or training purposes
When not to use this skill
Summarizing a conversation — write a summary in prose; don't apply transcript formatting
Raw export (JSON, plain markdown) — hand the user what they asked for without HTML conventions
Conversations with sensitive content the user has asked you to forget — flag and ask before rendering
Feedback
This is v1.0. Edge cases or suggestions → reply or ping Brad.