Claude
Skills
Sign in
Back

bookclub

Included with Lifetime
$97 forever

Book club management: generate Slack announcements, reminders, article roundups, eve (day-before + spark questions), one-pagers, and communication timelines. Use when user mentions book club, reading group, book of the month, or wants book-club-related communications or materials.

Productivity

What this skill does


# Book Club Management

Automate every aspect of running a recurring book club: research books, generate Slack messages, create session materials, and plan communication schedules.

## Configuration

Read **`.claude/bookclub.local.md`** in the project root if it exists. Parse the **YAML frontmatter** for the fields below. If the file is missing, use the defaults. Do not block init or generate.

**Template to copy:** [settings-template.md](../../settings-template.md) → save as `.claude/bookclub.local.md`.

| Field | Default (no config file) | Description |
|-------|--------------------------|-------------|
| `output_root` | `.` | Root directory; each book is a subfolder `<folder_slug>/` with its own `book-profile.json` and `bookclub-*` files. Relative paths resolve from the workspace root. |
| `bookclub_name` | *(unset)* | Full name for branding (e.g. "Digital Science Reads"). See Slack headers below. |
| `bookclub_short_name` | *(unset)* | Short label for one-pagers or buttons when space is tight. |
| `slack_channel` | *(unset)* | e.g. `#book-club`; include in runbooks or timeline notes when useful. |
| `discussion_venue` | *(unset)* | Default "where / how we meet" line for reminders if not in the book profile. |
| `organizer_contact` | *(unset)* | Facilitator contact (Slack handle, email). |
| `timezone` | *(unset)* | IANA timezone for schedule wording when you need explicit TZ context. |
| `current_book_folder` | *(unset)* | Name of the book subfolder under `output_root` (e.g. `klara_and_the_sun`). **Required when more than one book folder exists**; optional when only one book. |

**Per-book layout**

Each book has its own directory under `output_root`:

- `book_dir` = `<output_root>/<folder_slug>/`
- `book_profile_path` = `<book_dir>/book-profile.json`
- Generated files (`bookclub-announce.md`, `bookclub-timeline.json`, etc.) live in the same `book_dir`.

**`folder_slug` (directory name)** is derived from the book `title` at init time:

1. Lowercase; replace `&` with ` and `.
2. Replace any sequence of non-alphanumeric characters with a single `_`.
3. Trim leading/trailing `_`. If the result is empty, use `book`.
4. **Collisions:** If `<output_root>/<folder_slug>/` already exists and contains a `book-profile.json` for a *different* book (different normalized title+author), append `_2`, `_3`, … until the path is free or matches the same book (then reuse the folder for re-init).

**Resolving `book_dir` for generate / timeline**

1. Read config: `output_root`, optional `current_book_folder`.
2. If `current_book_folder` is set: `book_dir` = `<output_root>/<current_book_folder>`; require `book-profile.json` there.
3. Else if `<output_root>/book-profile.json` exists **and** no immediate child directory of `output_root` contains a `book-profile.json`: **legacy layout**; then `book_dir` = `output_root`.
4. Else: collect each immediate child directory of `output_root` that contains `book-profile.json`. If exactly one, use it as `book_dir`. If zero, tell the user to run `/bookclub:init`. If more than one, tell the user to set `current_book_folder` or pass `--book <folder_slug>` on the command.

Create `output_root` and `book_dir` with `mkdir -p` before writing when they do not exist.

**Slack headers:** Prefix announcement-style titles with `{bookclub_name} · ` only when `bookclub_name` is set to a non-empty value in `bookclub.local.md` (e.g. `*DS Reads · Book of the Month: _{title}_*`). If there is no config file or the key is blank, use the template headline without that prefix. For generic copy in documents when no name is configured, you may use the words "book club" in normal sentence case.

## When to Use This Skill

Trigger when the user:
- Mentions "book club", "reading group", or "book of the month"
- Asks to generate Slack messages about a book
- Asks for discussion questions or session materials
- Wants to announce, remind, or promote a book reading
- Asks for a QR code, one-pager, or visual summary for a book
- Wants a timeline or schedule for book club communications
- Asks to scrape or look up book data from a URL

## Commands

| Command | Description |
|---------|-------------|
| `/bookclub:init [title] by [author]` | Set up book of the month: research, enrich, create `<output_root>/<folder_slug>/`, save profile there |
| `/bookclub:generate [type]` | Generate any message or material (optional `--book <folder_slug>` when multiple books) |
| `/bookclub:timeline [cadence]` | Generate full communication schedule (optional `--book <folder_slug>`) |

### Generate Types

**Slack messages** (output: Block Kit JSON + mrkdwn):
- `announce`: Book announcement with hook, dates, factoids, links
- `remind`: 1-week-out reading reminder with page count, factoid, purchase link
- `articles`: Related articles/interviews roundup
- `eve`: Day-before reminder plus 3 low-pressure spark questions (default): **1 generic** (any book), **1 book-specific** (~first half), **1 theme** (last). Only use 4 if message stays under 170 words. See [slack-templates.md Eve → Question Guidelines](references/slack-templates.md#eve)

**Documents** (output: Markdown, optionally PDF with `--pdf`):
- `one-pager`: Visual summary with QR code

## Workflow

```
1. /bookclub:init "Book Title" by Author Name
   → Researches book, creates `<output_root>/<folder_slug>/`, saves `book-profile.json` there

2. /bookclub:timeline monthly
   → Generates full schedule under that book folder

3. /bookclub:generate announce
   → Writes outputs into the same book folder (repeat for each type as scheduled)
```

The `book-profile.json` inside each book folder is the single source of truth for that title. Resolve which folder using config + rules above.

## Book Profile

The init command creates a `book-profile.json` containing:
- **Paths**: `folder_slug` is the directory name under `output_root` (snake_case from title; set at init)
- **Metadata**: title, author, author_bio, publication_year, genre, page_count, isbn
- **Content**: synopsis (paraphrased), themes, factoids, awards
- **Links**: amazon_de, buch7, medimops, goodreads, publisher, library
- **Articles**: 3-5 related articles with title, source, url, summary
- **Dates**: announcement_date, reading_date, discussion_date
- **Assets**: cover_image_url, qr_target_url

Full schema: [references/book-profile-schema.md](references/book-profile-schema.md)

## Handling Null Dates

If `reading_dates` fields in `book-profile.json` are `null` or missing, derive sensible defaults from today's date:
- `announcement_date` = today
- `reading_date` = 3 weeks from today
- `discussion_date` = 4 weeks from today
Never output "TBD" or leave date placeholders empty. Always show concrete dates.

## Slack Message Guidelines

- **Tone**: Enthusiastic but not cheesy. Smart-casual. The friend who always has great book recommendations
- **Structure**: Hook -> Body -> CTA. Every message ends with a clear call to action
- **Format**: Slack mrkdwn (`*bold*`, `_italic_`, `:emoji:`, `>` quotes)
- **Punctuation in generated copy**: Do not use em dashes (—) in member-facing Slack text. Use commas, periods, colons, or parentheses instead (see [slack-style-guide.md](references/slack-style-guide.md#punctuation-in-generated-copy)).
- **Length (STRICT hard limits — violations are failures)**:
  - Announcements: 120-220 words
  - Reminders: 80-115 words
  - Articles roundup: 100-145 words
  - Eve: 120-175 words
  Count every word in your final output before emitting it. If over the limit, remove words until compliant. URLs count as one word each. Emoji shortcodes (`:emoji:`) count as one word each.
- **Output only the message**: Never append explanations, notes, commentary, or instructions after the message. The output must be the Slack message and nothing else.
- **Emoji**: 2-4 relevant emojis per message. Prefer: :books: :book: :brain: :bulb: :calendar:
- **Links**: Use labeled full URLs (one per line) under a :link: section, not `<url|label>` mrkdwn, which breaks when copy-pasted o

Related in Productivity