# Tufte Press Study Card Generator

An AI agent skill that generates Tufte-inspired study card JSON from conversation, builds PDFs, and prints them.

## Quick Start

Just ask your AI agent:

```
Create a study card about [topic]
```

The agent will extract content from your conversation, generate a structured JSON study card, and optionally build a PDF and print it.

**Example phrases that trigger this skill:**
- "Create a study card about recursion"
- "Make a printable study guide for lambda calculus"
- "Generate a tufte-press card for this topic"
- "Turn our conversation into a study card"
- "Build a study card and print it duplex"

## Overview

This skill provides a **complete workflow** for creating study cards:
1. Extract learning content from conversation history
2. Generate valid JSON following tufte-press schema
3. Build PDF using tufte-press toolchain
4. Print to physical handouts (optional)

## What It Does

When invoked, the agent will:

1. **Extract content** from conversation context
2. **Generate structured JSON** following strict schema validation
3. **Build PDF** using the tufte-press pipeline (JSON → LaTeX → PDF)
4. **Print handouts** with duplex support (optional)

## Installation

### Using Nix Flake (Recommended)

The skill will be deployed via the skills repository flake:

```bash
# Add to your NixOS configuration
inputs.skills.url = "path:/home/dan/proj/skills";

imports = [ inputs.skills.nixosModules.ai-skills ];

services.ai-skills = {
  enable = true;
  selectedSkills = [ "tufte-press" ];
  deployTargets = [ "claude" "opencode" ];
};
```

### Manual Installation

```bash
# Claude Code
cp -r skills/tufte-press ~/.claude/skills/

# OpenCode
cp -r skills/tufte-press ~/.config/opencode/skills/
```

## Prerequisites

**Required:**
- tufte-press repository at `~/proj/tufte-press` (or `$TUFTE_PRESS_REPO`)
- Nix with flakes enabled

**Optional (for printing):**
- CUPS printing system
- Configured printer

**Dependencies (provided by tufte-press):**
- Python 3.11
- Tectonic LaTeX compiler
- jq for JSON validation

## How to Invoke This Skill

The agent automatically recognizes requests related to study cards. You don't need to explicitly mention "skill" or "tufte-press" - just describe what you want:

**Trigger Phrases:**
- "Create a study card about [topic]"
- "Make a study guide for [concept]"
- "Generate a tufte-press card"
- "Turn this conversation into a study card"
- "Build a study card and print it"

**After Conversation:**
If you've been discussing a technical topic, you can ask:
```
Can you create a study card from what we just discussed?
```

The agent will:
1. Review the conversation history
2. Extract key concepts, definitions, and examples
3. Generate structured JSON following the tufte-press schema
4. Optionally build PDF and/or print

**Specifying Details:**
You can guide the content:
```
Create a 2-page study card about dynamic programming with examples and practice problems
```

The agent understands:
- Page count (1-3 pages)
- Depth level (intro, intermediate, advanced)
- Content preferences (examples, equations, practice drills)
- Target audience
- Print options (duplex, copies)

## Usage

### Simple Request

```
Create a study card about binary search trees
```

Agent will:
- Extract BST concepts from conversation
- Generate JSON with proper structure
- Save to file
- Ask if you want to build PDF

### Build PDF

```
Create a study card about recursion and build the PDF
```

Agent will:
- Generate JSON
- Validate against schema
- Build PDF using tufte-press
- Show PDF location

### Print Handout

```
Create a study card about lambda calculus and print it duplex
```

Agent will:
- Generate JSON
- Build PDF
- Send to printer with duplex (2-sided) printing
- Show print queue status

## Example Workflows

### Conversation-Based Card

```
User: I've been learning about hash tables. Can you create a study card?

Agent: 
1. Reviewing our conversation about hash tables...
2. Generating JSON with collision resolution, load factors, etc.
3. Saving to /tmp/study-card-hash-tables-20251110.json
4. Building PDF...
5. PDF ready: /tmp/study-card-hash-tables-20251110.pdf

Would you like me to print it?
```

### Multi-Page Technical Card

```
User: Create a 2-page study card about dynamic programming with examples

Agent:
1. Extracting DP concepts from conversation...
2. Including memoization, tabulation examples
3. Adding complexity analysis in margin notes
4. Generating JSON with practice problems
5. Building PDF (2 pages, two-column layout)
6. Done: study-card-dynamic-programming.pdf
```

### Print Multiple Copies

```
User: Print 5 copies of the study card duplex

Agent:
Running: generate-and-build.sh study-card.json --build --print --copies 5 --duplex
Print job submitted: 5 copies, 2-sided printing
Check status: lpstat -o
```

## Helper Scripts

### `scripts/generate-and-build.sh`

Complete workflow automation:

```bash
# Validate JSON only
./scripts/generate-and-build.sh my-card.json

# Generate PDF
./scripts/generate-and-build.sh my-card.json --build

# Generate and print
./scripts/generate-and-build.sh my-card.json --build --print

# Print with options
./scripts/generate-and-build.sh my-card.json --build --print \
  --printer HP-LaserJet --copies 2 --duplex
```

**Options:**
- `--build`: Build PDF from JSON
- `--print`: Send to printer (requires --build)
- `--printer NAME`: Specify printer
- `--copies N`: Number of copies (default: 1)
- `--duplex`: Enable 2-sided printing

## Features

✅ **Conversation-Aware**: Extracts content from chat history  
✅ **Schema-Validated**: Follows strict tufte-press JSON schema  
✅ **Complete Pipeline**: JSON → LaTeX → PDF in one command  
✅ **Print Integration**: Direct CUPS printer support  
✅ **Duplex Support**: Optimized for handout printing  
✅ **Error Handling**: Clear validation and build messages  
✅ **Production Ready**: Uses validated tufte-press toolchain  

## JSON Schema

The skill generates JSON following this structure:

```json
{
  "metadata": {
    "title": "Study Card: [Topic]",
    "topic": "Brief description",
    "audience": "Target learners",
    "estimated_read_time_minutes": 15,
    "prerequisites": ["prereq1", "prereq2"],
    "learning_objectives": ["objective1", "objective2"],
    "sources": [
      {
        "title": "Source Title",
        "author": "Author Name",
        "year": "2024",
        "citation": "Full citation",
        "link": "https://doi.org/..."
      }
    ],
    "provenance": {
      "model": "Claude 3.5 Sonnet",
      "date": "2025-11-10",
      "version": "1.0",
      "notes": "Generated from conversation"
    }
  },
  "pages": [
    {
      "page_number": 1,
      "layout": "two-column",
      "main_flow": [
        {
          "type": "text",
          "content": "Main content",
          "attributes": { "emphasis": "newthought" }
        },
        {
          "type": "list",
          "content": ["Item 1", "Item 2"],
          "attributes": { "list_style": "bullet" }
        },
        {
          "type": "equation",
          "content": "E = mc^2",
          "attributes": { "equation_latex": "E = mc^{2}" }
        }
      ],
      "margin_notes": [
        {
          "anchor": "term",
          "content": "Term — Self-contained definition",
          "note_type": "definition"
        }
      ]
    }
  ],
  "drills": {
    "practice_strip": [
      {
        "prompt": "Practice question (NO answers here)"
      }
    ],
    "self_check": [
      {
        "question": "Self-assessment question",
        "correct_answer": "Expected answer",
        "why_it_matters": "Importance"
      }
    ]
  }
}
```

## Content Types Supported

- **text**: Paragraphs with emphasis (newthought, bold, summary)
- **list**: Bullet or numbered lists (MUST be JSON arrays)
- **equation**: LaTeX math with inline `$...$` or display mode
- **callout**: Highlighted concept boxes
- **quote**: Citations with attribution
- **drill**: Practice problems

## Margin Note Types

- **definition**: Key term definitions
- **syntax**: Notation syntax
- **concept**: Core ideas
- **history**: Historical context
- **problem**: Common pitfalls
- **operation**: Procedures
- **equivalence**: Equivalent forms
- **notation**: Symbolic conventions
- **property**: Characteristics
- **example**: Illustrative cases
- **reference**: Cross-references

## Critical Schema Rules

The agent follows these strict rules when generating JSON:

1. **Lists MUST be arrays**: `"content": ["a", "b", "c"]` not `"content": "a\nb\nc"`
2. **Margin notes MUST be self-contained**: Include term name in definition
3. **Equations MUST have equation_latex**: Display math requires LaTeX
4. **Practice strips NO answers**: Only prompts (answers go in self_check)
5. **Self-check INCLUDES answers**: Must have correct_answer and why_it_matters
6. **Sources MUST be real**: Or mark with "[NEEDS CLARIFICATION]"
7. **First paragraph MUST use newthought**: `"emphasis": "newthought"`

## Error Handling

**JSON validation fails:**
```
Error: metadata.sources[0].year must be string in YYYY format
Fix: Change "year": 2024 to "year": "2024"
```

**Build fails:**
```
Error: LaTeX compilation failed
Common causes:
- Missing equation_latex attribute
- Special characters not escaped
- Invalid LaTeX syntax in equations
```

**Print fails:**
```
Error: Printer not found
Check: lpstat -p
Try: Use default printer (omit --printer flag)
```

## Example Files

```
skills/tufte-press/
├── SKILL.md                                # Agent instructions
├── README.md                               # This file
├── scripts/
│   └── generate-and-build.sh              # Workflow automation
└── examples/
    └── lambda-calculus-example.json       # Complete example
```

## Environment Variables

- `TUFTE_PRESS_REPO`: Path to tufte-press repository (default: `~/proj/tufte-press`)

## Related Projects

- **tufte-press** - The build system and LaTeX templates
- **Tufte-LaTeX** - Layout inspiration
- **The Learning Scientists** - Retrieval practice research

## Common Questions

**Q: Does the agent generate JSON itself?**  
A: Yes! The agent acts as the educator-typesetter and generates valid JSON from conversation context.

**Q: Do I need the tufte-press repository?**  
A: Yes, for building PDFs. The skill uses tufte-press toolchain for JSON → PDF conversion.

**Q: Can I customize the generated cards?**  
A: Yes! Edit the JSON file and rebuild: `./scripts/generate-and-build.sh my-card.json --build`

**Q: What if I don't have a printer?**  
A: Skill works fine without printing. Just use `--build` to create PDF files.

**Q: How do I add citations?**  
A: Mention sources in conversation. Agent will include them in metadata.sources with DOI/URLs when available.

**Q: Can I create multi-page cards?**  
A: Yes! Request 1-3 pages. Agent will structure content appropriately.

## Troubleshooting

**Skill not found:**
```bash
# Check skill is deployed
ls ~/.claude/skills/tufte-press/
# Should show SKILL.md, README.md, scripts/, examples/
```

**tufte-press repo not found:**
```bash
# Set environment variable
export TUFTE_PRESS_REPO=/path/to/tufte-press

# Or clone it
git clone <repo> ~/proj/tufte-press
```

**Build fails in Nix:**
```bash
# Enter dev shell manually
cd ~/proj/tufte-press
nix develop
# Then run script
```

**Print queue stuck:**
```bash
# Check queue
lpstat -o
# Cancel job
cancel <job-id>
# Restart CUPS
sudo systemctl restart cups
```

## License

MIT

## Support

For questions about:
- **This skill**: See `SKILL.md` for agent instructions
- **JSON schema**: See `~/proj/tufte-press/cards/metadata-schema.json`
- **PDF building**: See tufte-press repository documentation
- **LaTeX issues**: Check tufte-press build logs in `cards/build/logs/`
