Skip to main content

A pure-Python library for generating guitar chord diagram images (SVG and PNG)

Project description

fretsy 🎸

A pure-Python library for generating guitar chord diagram images in SVG and PNG. Ships with 3,000+ built-in chord definitions across all 12 keys.

Install

uv add fretsy

SVG rendering uses only the standard library. For PNG export you also need cairosvg (which requires system libcairo):

# macOS
brew install cairo
uv add fretsy --extra png

# Ubuntu / Debian
sudo apt install libcairo2-dev
uv add fretsy --extra png

Quick start

from fretsy import ChordDiagram, save

# Define a chord by hand
chord = ChordDiagram(
    name="Am",
    frets=[-1, 0, 2, 2, 1, 0],   # one per string, low-E first
    fingers=[0, 0, 2, 3, 1, 0],  # finger numbers shown inside dots
)

save(chord, "Am.svg")   # SVG — no extra deps
save(chord, "Am.png")   # PNG — requires fretsy[png]

Or grab one from the built-in library:

from fretsy import find_chord, save

am = find_chord("Am")[0]
save(am, "Am.svg")

Defining chords

Every chord is a ChordDiagram dataclass. The only required fields are name and frets:

from fretsy import ChordDiagram

# Simple open chord
e_major = ChordDiagram("E", frets=[0, 2, 2, 1, 0, 0])

# With finger numbers
a_minor = ChordDiagram("Am", frets=[-1, 0, 2, 2, 1, 0], fingers=[0, 0, 2, 3, 1, 0])

# Barre chord — barre=(fret, from_string, to_string), 1-indexed
f_major = ChordDiagram(
    "F",
    frets=[1, 1, 2, 3, 3, 1],
    fingers=[1, 1, 2, 4, 3, 1],
    barre=(1, 1, 6),
)

# High-position chord — base_fret auto-detects, or set it explicitly
bb = ChordDiagram("Bb", frets=[6, 6, 7, 8, 8, 6], barre=(6, 1, 6))
# base_fret auto-set to 6

# Optional label (subtitle shown below the chord name)
bb_a_form = ChordDiagram(
    "Bb", frets=[-1, 1, 3, 3, 3, 1], barre=(1, 2, 6), label="A-form"
)

Fret notation

Value Meaning
-1 Muted string (drawn as ✕)
0 Open string (drawn as ○)
1+ Fret number (filled dot on the grid)

The frets list always has 6 elements, ordered low-E → high-E.


Rendering

Save to file

from fretsy import save

save(chord, "chord.svg")              # SVG (format inferred from extension)
save(chord, "chord.png")              # PNG
save(chord, "chord.png", scale=3.0)   # high-res PNG (default scale=2.0)
save(chord, "out.xml", fmt="svg")     # explicit format override

save() creates parent directories automatically and returns the output Path.

Get raw bytes / string

from fretsy import render_svg, render_png

svg_string = render_svg(chord)              # str
png_bytes  = render_png(chord, scale=2.0)   # bytes

Batch export

from fretsy import save_batch, BEGINNER_CHORDS, STYLE_DARK

# Save all beginner chords as PNGs
paths = save_batch(BEGINNER_CHORDS, "output/beginners", fmt="png", scale=2.0)

# Custom filenames
paths = save_batch(
    BEGINNER_CHORDS,
    "output/numbered",
    fmt="svg",
    name_fn=lambda chord, i: f"{i:02d}_{chord.name}",
)

save_batch() auto-deduplicates filenames when multiple chords share the same name, and sanitizes slashes/spaces.


Styles and themes

Pass a DiagramStyle (or a built-in preset) to any render/save function:

from fretsy import save, STYLE_DARK

save(chord, "dark.png", style=STYLE_DARK)

Built-in themes

Preset Look
STYLE_DEFAULT White background, navy dots
STYLE_DARK Dark background, red/pink accents
STYLE_MINIMAL Black and white
STYLE_PASTEL Soft blue dots, light feel

Custom themes

Every visual property is configurable via DiagramStyle:

from fretsy import DiagramStyle, save

solarized = DiagramStyle(
    background_color="#fdf6e3",
    dot_color="#268bd2",
    barre_color="#268bd2",
    chord_name_color="#073642",
    chord_name_font="'Comic Sans MS', cursive",
    width=220,
    height=260,
    num_frets=5,
)
save(chord, "solarized.svg", style=solarized)

For transparent backgrounds (useful for embedding in web pages):

transparent = DiagramStyle(background_opacity=0.0)
svg = render_svg(chord, style=transparent)

Built-in chord library

fretsy ships with 3,000+ chord definitions covering all 12 keys, multiple voicings, and a wide range of qualities. All chords live in a single CHORDS list, and convenience sublists filter by technique or quality:

from fretsy import (
    CHORDS,            # master list — all 3,000+ chords
    find_chord,        # lookup by name

    # By technique
    OPEN_CHORDS,       # no barre, open strings, first position
    BARRE_CHORDS,      # uses a barre
    POWER_CHORDS,      # root + fifth (E5, A5, etc.)

    # By quality
    MAJOR_CHORDS,
    MINOR_CHORDS,      # m, m7, m9, mmaj7, etc.
    DOMINANT_CHORDS,   # 7, 9, 11, 13, 6
    DIMINISHED_CHORDS, # dim, dim7
    AUGMENTED_CHORDS,  # aug, aug7, aug9
    SUSPENDED_CHORDS,  # sus2, sus4, 7sus4

    # Special
    JAZZ_CHORDS,       # maj7, 9, 11, 13, altered
    SLASH_CHORDS,      # inversions (Am/G, C/E, etc.)
    PRIMARY_CHORDS,    # first voicing only (no "var." variants)
    BEGINNER_CHORDS,   # E, A, D, G, C, Em, Am, Dm
)

Searching

from fretsy import find_chord, BEGINNER_CHORDS

# All voicings of Bb (returns list[ChordDiagram])
all_bb = find_chord("Bb")

# Search within a subset
find_chord("C", chords=BEGINNER_CHORDS)  # just the open C

Every sublist references the same objects in CHORDS — no data is duplicated.


Development

# Clone and set up
git clone https://github.com/OWNER/fretsy.git
cd fretsy
uv sync

# Run tests
uv run pytest

# Dump all 3,000+ chords to a directory (great for visual QA)
uv run fretsy output/              # SVGs with default theme
uv run fretsy output/ --fmt png    # PNGs
uv run fretsy output/ --style dark # dark theme
uv run fretsy output/ --scale 3    # high-res

# Also works as a module
uv run python -m fretsy output/

# Lint
uv run ruff check src/ tests/

# Auto-fix lint issues
uv run ruff check --fix src/ tests/

# Format
uv run ruff format src/ tests/

# Type check
uv run pyrefly check

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fretsy-0.1.1.tar.gz (86.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fretsy-0.1.1-py3-none-any.whl (57.8 kB view details)

Uploaded Python 3

File details

Details for the file fretsy-0.1.1.tar.gz.

File metadata

  • Download URL: fretsy-0.1.1.tar.gz
  • Upload date:
  • Size: 86.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for fretsy-0.1.1.tar.gz
Algorithm Hash digest
SHA256 c269a49f138a4484d6664ee959ba641ce1e772111dfe47d9959cbc6ff3d6f0bd
MD5 cee0e493b7cce3ac5c7c24e23a9d6207
BLAKE2b-256 264cd891f4ec83d79daac3aa0ec6106de925e2ff3d2c73b3d9ded7eaaf0cc7ce

See more details on using hashes here.

File details

Details for the file fretsy-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: fretsy-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 57.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for fretsy-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 11e96de36ef0ac474b244ca8b7744fd8fc7d4a084b2c56e906bcb9ae0ba071b8
MD5 a7cd8264463a546c6f7dbe06cf7ebbb4
BLAKE2b-256 9164913c5ef759dfae57298a9b7cd3670ff393f9ac9de61c08593c8a4ad8243d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page