Skip to content

Repository files navigation

CapoRoute

Plan the guitar state of an entire fixed set, not just one song.

CapoRoute is a local, deterministic CLI for singer-guitarists. You declare the concert keys you can sing, the chord-shape keys you want to play, and the tunings available for each song. CapoRoute finds the globally lowest-cost route through the set while keeping your running order untouched.

It produces a stage sheet like this:

1. Paper Lanterns
   key=D shape=D capo=0 tuning=drop-d
   change: Set tuning to drop-d; Set capo to 0
2. River Signal
   key=D shape=D capo=0 tuning=drop-d
   change: No setup change
3. Borrowed Light
   key=E shape=D capo=2 tuning=drop-d
   change: Move capo 0 -> 2
4. Quiet Machinery
   key=G shape=G capo=0 tuning=standard
   change: Retune drop-d -> standard; Move capo 2 -> 0

The first song may use a slightly less preferred shape if that prevents a much more expensive change before the next song. That whole-set tradeoff is the product.

Why this is different

  • Single-song capo calculators answer “what fret gives me this key?” CapoRoute optimizes adjacent physical states across the whole show.
  • Setlist managers store songs, lyrics, and gigs. CapoRoute stores no copyrighted song content and has no account or database.
  • DJ set optimizers reorder tracks by tempo/key flow. CapoRoute treats your artistic song order as authoritative.
  • CapoRoute does not guess vocal range, detect audio keys, or tell you which key is safe. You provide acceptable concert keys explicitly.

The research and scope decision are documented in docs/ideas/caporoute.md.

Install

CapoRoute 0.1.0 supports Python 3.11 or newer and has no runtime dependencies.

From a GitHub Release wheel:

python -m pip install caporoute-0.1.0-py3-none-any.whl
caporoute --version

From a source checkout with uv:

uv sync --locked
uv run caporoute --version

Try the real example

uv run caporoute check examples/coffeehouse.json
uv run caporoute plan examples/coffeehouse.json
uv run caporoute plan examples/coffeehouse.json --format markdown --output build/coffeehouse.md
uv run caporoute plan examples/coffeehouse.json --format json --output build/coffeehouse.json

Expected check result:

OK: Coffeehouse Proof (6 songs, 9 feasible choices)

Committed outputs are available as docs/demo/coffeehouse.md and docs/demo/coffeehouse.json.

Input format

{
  "set_name": "Small Room",
  "max_capo": 7,
  "weights": {
    "capo_move": 1.5,
    "tuning_change": 8.0,
    "capo_height": 0.1
  },
  "songs": [
    {
      "title": "Northbound",
      "performance_keys": [
        { "key": "D", "preference": 0 },
        { "key": "Eb", "preference": 2 }
      ],
      "shapes": [
        { "key": "C", "preference": 0, "tunings": ["standard"] },
        { "key": "D", "preference": 1, "tunings": ["drop-d"] }
      ]
    }
  ]
}
  • Keys are A through G, optional # or b, and optional m for minor.
  • preference is a non-negative penalty; lower is better.
  • Major performance keys only pair with major shape keys; minor only pairs with minor.
  • max_capo is inclusive and ranges from 0 through 11.
  • Tuning names are labels you control. Equal labels mean no retune is needed.

The full contract is in docs/spec.md.

Cost model

For one playable choice:

local = performance preference + shape preference + capo × capo_height

Between adjacent songs:

transition = |next capo - current capo| × capo_move
           + tuning_change when the tuning label changes

CapoRoute minimizes all local and transition costs across the fixed order with dynamic programming. It reports the selected state, the feasible-choice count, and each cost component. Exact ties are deterministic.

Weights are personal workflow preferences, not universal musical truths. Increase tuning_change if retuning on stage is especially disruptive; increase capo_move if fast fret changes are the main problem.

Commands and exit codes

caporoute check SET.json
caporoute plan SET.json [--format terminal|json|markdown|csv] [--output PATH]
  • 0: valid and feasible.
  • 1: valid input, but at least one named song has no feasible choice.
  • 2: usage, JSON, validation, read, or write error.

--output writes atomically. A failed plan does not leave a partial report. JSON and Markdown preserve source titles; CSV neutralizes formula-like title cells before spreadsheet import.

Acceptance

Run the same release gate used by CI and the tag workflow:

uv sync --locked
uv run python scripts/check.py

The gate checks formatting, lint, strict types, at least 90% branch coverage, dependency audit, valid and impossible examples, deterministic committed reports, wheel/sdist contents, checksums, and a clean-wheel install.

Focused commands:

uv run ruff format --check src tests scripts examples
uv run ruff check src tests scripts examples
uv run mypy src tests scripts
uv run pytest -p no:cacheprovider --basetemp=.tmp/pytest
uv build --clear

When a command fails

Do not skip a test or lower the coverage gate. Start with the error category:

  • error: ... expected valid JSON: validate commas/quotes, then rerun caporoute check FILE.
  • error: ... max_capo: use an integer from 0 through 11.
  • infeasible: song N ...: add an acceptable concert key, add a same-mode shape, or raise max_capo; rerun check before plan.
  • cannot write ...: create the parent directory and verify the target is a file path, not a directory.
  • uv lock --check fails: run uv lock, inspect uv.lock, then rerun the full gate.
  • dependency download fails with a socket/network error: restore network access and rerun; do not remove the audit.

More detail is in docs/TROUBLESHOOTING.md.

Privacy and security

CapoRoute performs no network requests and collects no telemetry. It reads only the input path you provide and writes only an explicit output path. Report titles are untrusted data: terminal controls are made visible, Markdown delimiters are escaped, and CSV formula prefixes are neutralized.

Report security issues using SECURITY.md.

Engineering references

Project metadata, console entry points, CI, and release automation follow current primary documentation:

License

MIT. See LICENSE.

About

Optimize a fixed singer-guitarist set for keys, chord shapes, capo positions, and tunings.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages