Auto-generate searchable slide decks from Claude Code conversation transcripts. Every session becomes a rich markdown document rendered as a navigable HTML page with sidebar navigation, search, project/date filtering, dark/light mode, and session resume.
- Stop hook fires when a Claude Code session ends
- A background
claude -preads the transcript and writes a.mdfile with frontmatter + rich markdown - Rails renders
.mdto HTML on the fly through redcarpet + custom extensions - Browse all decks at
http://127.0.0.1:4747
- Ruby 4.0+
- Bundler
- Claude Code CLI
git clone https://github.com/yourusername/claudecks.git
cd claudecks
bundle install
bin/claudecks installThe install command:
- Copies the skill to
~/.claude/skills/session-deck/ - Copies the stop hook to
~/.claude/hooks/ - Registers the hook in
~/.claude/settings.json - Creates
~/.claude/session-decks/for deck storage
# Start the viewer
bin/claudecks serve
# Start on a custom port
bin/claudecks serve 4848
# Backfill historic sessions
bin/claudecks backfill --min-lines 50 --cwd-prefix ~/projects
# Backfill with options
bin/claudecks backfill --min-lines 50 --since 2026-01-01 --concurrency 4 --model sonnet
# Dry run (list what would be processed)
bin/claudecks backfill --min-lines 50 --dry-run
# Generate a deck from the current session
# (invoke /session-deck from within Claude Code)- Dynamic index — always fresh, no rebuild needed
- Resume session — click the play button to reopen a Claude Code session in cmux at the original project directory
- Live reload — new decks appear automatically when sessions end
- Server-side search — full-text search across all deck content
- Dark/light theme — toggleable, persisted in localStorage
- Trash management — soft delete with restore and purge
- Keyboard navigation —
/search,j/kscroll, arrows paginate - Rich markdown — columns, code panes with labels, tag chips, file references
Decks are stored as .md files at ~/.claude/session-decks/ with YAML frontmatter:
---
title: Fix Login Bug
subtitle: Fixed OAuth callback redirect
project: myapp
tags: [oauth, bugfix, auth]
---
# Research
- Found the redirect handler in `app/controllers/auth_controller.rb`
# Implementation
:::cols-2
:::
## Before
- Redirect went to root
:::
## After
- Redirect goes to stored return path
:::
```ruby title="Fix" path="app/controllers/auth_controller.rb:42"
def callback
redirect_to stored_location || root_path
endtags: Read, Edit, Bash refs: app/controllers/auth_controller.rb:42
### Rich extensions
| Syntax | Renders as |
|---|---|
| `:::cols-2` ... `:::` ... `:::` | Multi-column layout |
| `## Label` | Small-caps teal sub-header |
| `` ```ruby title="X" path="file.rb" `` | Labeled code block with file path |
| `> tags: Read, Grep` | Tool/skill tag chips |
| `> refs: path:line` | File reference links |
## Configuration
### Known repos (worktree normalization)
If you use git worktrees, set `CLAUDECKS_KNOWN_REPOS` so the resume button can fall back to the main repo when a worktree is deleted:
```bash
export CLAUDECKS_KNOWN_REPOS=myapp,backend,frontend
bin/claudecks serve 4848Decks are stored at ~/.claude/session-decks/ by default. To sync across machines, move them to a cloud-synced folder and symlink back:
# Move to iCloud (or Dropbox, Google Drive, etc.)
mv ~/.claude/session-decks ~/Library/Mobile\ Documents/com~apple~CloudDocs/session-decks
ln -s ~/Library/Mobile\ Documents/com~apple~CloudDocs/session-decks ~/.claude/session-decksOn each additional machine, just create the symlink:
ln -s ~/Library/Mobile\ Documents/com~apple~CloudDocs/session-decks ~/.claude/session-decksThe hook, skill, and server all use ~/.claude/session-decks/ so the symlink is transparent.
Alternatively, set a custom path in ~/.claude/claudecks.yml:
decks_dir: ~/Library/Mobile Documents/com~apple~CloudDocs/session-decksapp/
├── models/
│ ├── deck.rb # Domain model: parsing, metadata, validation
│ └── frontmatter_parser.rb # YAML frontmatter splitter
├── services/
│ ├── render_deck.rb # Orchestrate .md → structured HTML
│ ├── render_markdown.rb # Pre-process → redcarpet → post-process
│ ├── list_decks.rb # Scan directory, return deck metadata
│ ├── scan_decks.rb # Lightweight file listing
│ ├── search_decks.rb # Full-text search across decks
│ ├── trash_deck.rb # Move to .trash/
│ ├── restore_deck.rb # Restore from .trash/
│ ├── purge_trash.rb # Empty .trash/
│ └── resume_session.rb # Open cmux workspace + claude --resume
├── controllers/
│ ├── decks_controller.rb # Index, show, search
│ └── api/decks_controller.rb # JSON API (health, list, trash, restore, resume)
├── views/
│ ├── layouts/
│ │ ├── application.html.erb # Index layout
│ │ └── deck.html.erb # Deck viewer layout (sidebar + slides)
│ └── decks/
│ ├── index.html.erb # Card grid with filtering
│ ├── show.html.erb # Slide content
│ ├── search.html.erb # Search results
│ └── _card.html.erb # Deck card partial
├── assets/
│ ├── stylesheets/ # shared.css, deck.css, index.css, search.css
│ └── javascripts/ # shared.js, deck.js, index.js
lib/
├── install/
│ ├── hook.sh # Stop hook (fires on session end)
│ └── SKILL.md # Claude skill for /session-deck
└── tasks/
├── backfill.rake # Batch process historic transcripts
├── install.rake # Install skill + hook
└── rename_backfill.rake # One-time: rename HHMMSS → session ID
- Ruby 4.0 / Rails 8.1 (minimal: no ActiveRecord, ActionCable, ActionJob)
- Redcarpet for markdown rendering
- Propshaft for asset serving
- Puma web server
- Zero JavaScript build tools
bundle exec rspec # 87 specs
bundle exec rubocop # Shopify style guide
bin/rails server -p 4747 # Start dev serverMIT