Skip to content

zeitraumdev/sprintquest-base

Repository files navigation

SprintQuest

Turn your team's standup logs or git commits into a 6-panel comic strip using AI. Supports multiple visual styles — pixel art, manga, film noir, and more.

Example comic strip

Quick Start

1. Install

# Using uv (recommended)
uv sync

# Or pip
pip install pillow google-genai

2. Set your API key

export GOOGLE_API_KEY="AIza..."

The tool uses Google Gemini for both script writing (Gemini Flash) and image generation.

3. Add character photos

Drop headshots into characters/photos/ — filename is the person's first name:

characters/photos/
├── alice.jpg
├── bob.jpg
└── charlie.png

4. Generate character descriptions and sprites

# Auto-generate text descriptions from photos
uv run python sprintquest.py --demo --refresh-descriptions

# Generate the master style reference + per-character sprites
uv run python sprintquest.py --demo --generate-style --generate-refs all

Review the generated sprites in characters/references/pixel-art/. If any look off, regenerate individuals:

uv run python sprintquest.py --demo --generate-refs alice,bob

5. Generate a comic

# From a standup log file
uv run python sprintquest.py -f standups.txt

# From git log via pipe
git log --since="1 week ago" --pretty=format:"%an|%s" --no-merges | uv run python sprintquest.py --stdin

# Interactive paste mode
uv run python sprintquest.py

# Demo mode (sample data)
uv run python sprintquest.py --demo

Output: a timestamped PNG like comic_strip_pixel-art_0103260120.png.

Input Formats

The tool auto-detects the format.

Standup log (Slack-style):

alice:
Fixed login bug and updated tests

bob:
Refactored API endpoints
Performance improvements on search

Git log (pipe-delimited):

Alice|Fixed login bug
Alice|Updated tests
Bob|Refactored API endpoints

Art Styles

Six built-in styles. Pass --style <name> to switch:

Style Description
pixel-art 16-bit SNES/Genesis era RPG (default)
8-bit Chunky NES-era, strict 4-color palette per sprite
film-noir Sin City B&W, chiaroscuro lighting, red accent
manga Shonen manga, black & white with screentone
60s-superheroes Silver Age comic book style
soviet-propaganda Bold propaganda poster aesthetic

Each style needs its own sprites generated once:

uv run python sprintquest.py --demo --style manga --generate-style --generate-refs all

After that, just use --style manga on any run.

Creating your own style

  1. Create a directory under config/styles/:
config/styles/my-style/
├── panel_style.md            # One-line visual style prefix for panel prompts
├── style_reference.md        # Prompt for generating the master style guide sprite
└── character_reference.md    # Prompt template for per-character sprites
  1. Look at existing styles for reference — copy one and modify the prompts.

  2. character_reference.md uses {name} and {description} template variables.

  3. Generate sprites and test:

uv run python sprintquest.py --demo --style my-style --generate-style --generate-refs all
uv run python sprintquest.py --demo --style my-style

CLI Reference

usage: sprintquest.py [options]

Input:
  -f, --file FILE         Read standup/git log from file
  --stdin                 Read from stdin pipe
  --demo                  Use sample demo data
  -s, --script FILE       Load existing script JSON (skip generation)

Output:
  -o, --output FILE       Output file path (default: comic_strip.png)
  -w, --week N            Calendar week number for header (default: previous week)
  --lang en|de            Language for dialogue and title (default: en)
  --style NAME            Visual style (default: pixel-art)

Panel control:
  -p, --panels 1,4,6      Only regenerate specific panels
  --assemble              Reassemble strip from cached panels (no generation)
  --skip-images           Use placeholder panels (no image API calls)
  --panel-dir DIR         Panel cache directory (default: panels/)

Character setup:
  --refresh-descriptions  Regenerate text descriptions from photos
  --generate-style        Generate master style reference sprite
  --generate-refs [NAMES] Generate character sprites (all, or comma-separated names)
  -c, --characters DIR    Character directory (default: characters/)

Advanced:
  --google-key KEY        Google API key (or set GOOGLE_API_KEY env var)
  --model NAME            Gemini model override

Iteration Workflow

Don't like a panel? Regenerate just that one:

# Regenerate panels 3 and 6, keep the rest
uv run python sprintquest.py -s comic_strip_script.json -p 3,6

# Reassemble from cached panels (no API calls)
uv run python sprintquest.py -s comic_strip_script.json --assemble

Scripts are auto-saved as *_script.json alongside the output PNG.

Project Structure

sprintquest.py          # Entry point (imports cli.main)
cli.py                   # Arg parsing, config loading, orchestration
parsing.py               # Input detection and parsing
script.py                # Gemini Flash script generation
images.py                # Panel/sprite generation + strip assembly (Pillow)

config/
├── script_system.md     # Story generation system prompt
├── panel_instructions.md # Speech bubble and group shot rules
├── language_en.md       # English language prompt
├── language_de.md       # German language prompt
└── styles/
    ├── pixel-art/       # Default style
    ├── 8-bit/
    ├── film-noir/
    ├── manga/
    ├── 60s-superheroes/
    └── soviet-propaganda/

characters/
├── alice.md             # Auto-generated text descriptions
├── photos/              # Input headshots
│   └── alice.jpg
└── references/          # Generated sprites (per style)
    ├── pixel-art/
    │   ├── _style.png   # Master style guide
    │   └── alice.png    # Character sprite
    └── manga/
        ├── _style.png
        └── alice.png

panels/                  # Cached generated panels (per style)
├── pixel-art/
└── manga/

assets/
└── logo/
    ├── sprintquest-small.png  # Logo emblem for footer
    └── sprintquest-text.png   # Text logo for footer

fonts/
├── Silkscreen-Bold.ttf        # Primary pixel font (OFL licensed)
├── Silkscreen-Regular.ttf     # Pixel font regular weight (OFL licensed)
└── PressStart2P-Regular.ttf   # Fallback pixel font (OFL licensed)

How It Works

  1. Parse — Auto-detect input format (standup log or git log), extract per-person entries
  2. Script — Gemini Flash turns the summary into a 6-panel RPG-themed comic script (JSON)
  3. Generate — Gemini image generation creates each panel using character reference sprites for consistency
  4. Assemble — Pillow stitches panels into a strip with header, borders, footer branding, and layout

Character consistency

The hardest problem. Solved with a 3-tier reference system:

  1. Master style reference (_style.png) — Two generic characters that define proportions, shading, and palette for the style
  2. Character sprites (references/{style}/*.png) — Per-person sprites generated from headshot + style ref + text description
  3. Panel generation — Sprites are attached as visual anchors to each panel prompt

Cost

Operation Cost
Script generation (Gemini Flash) ~$0.15
6 panel images (Gemini image gen) ~$0.12
Total per comic ~$0.27
One-time setup (style + 5 sprites) ~$0.13

Automation

Run as a Friday cron job:

# Every Friday at 4pm
0 16 * * 5 cd /path/to/sprintquest && \
  git log --since="1 week ago" --pretty=format:"%an|%s" --no-merges | \
  uv run python sprintquest.py --stdin -o /tmp/comic.png && \
  curl -F file=@/tmp/comic.png $SLACK_WEBHOOK_URL

Acknowledgements

Thanks to my friend Andreas Neukötter for the initial idea.

Environment

About

Turn standup logs and git commits into pixel-art comic strips with AI (Gemini). 6 visual styles, character consistency, and zero config.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages