Automatically detect references to music albums and songs in LaTeX newsletters and insert Songlink/Odesli-style smart links.
Define these commands in your preamble:
\newcommand{\album}[1]{\textit{#1}} % Italicize album titles
\newcommand{\song}[1]{``#1''} % Quote song titlesThen use \album{Title} and \song{Title} in your document.
The latex-music-linker tool:
- Scans your LaTeX document for
\album{...}and\song{...}commands. - Uses either a heuristic parser or an LLM-based agent (recommended) to infer context like artist names from surrounding text, that can be used to improve search accuracy.
- For each musical item (e.g. song, album), calls the Apple Music API to get an Apple Music link. Why Apple Music? Simply because the Apple Music API and search functions are free, and much better in my hands than e.g. Spotify's. Plus, I use Apple Music myself, so it's easier to check correctness.
- Passes the Apple Music link to the Songlink/Odesli API to get a universal redirector link.
- Inserts the resolved link back into the LaTeX output, wrapping the
\album{...}and\song{...}commands in\href{...}{...}commands.
uv run latex-music-linker examples/newsletter_example.tex examples/newsletter_example_linked.texThis is equivalent to using the heuristic agent.
The parser can be enriched by pluggable agents:
heuristic(default) – uses only local LaTeX cues.llm– shells out via thellmCLI usingdocs/prompts/agent_prompt.mdplus the tool schema indocs/tools/music_resolvers.yaml. You can use a local model, but it is easiest to obtain an API key and use a hosted model like Gemini 3.0 Flash (cheap, fast, good). See below (andllmdocs) for setup instructions.claude-code(experimental) – uses the Claude Code CLI which works with claude.ai consumer subscriptions (no API key required).
Select an agent with --agent llm (or set LATEX_MUSIC_LINKER_AGENT). Select a model with --llm-model (or set LATEX_MUSIC_LINKER_LLM_MODEL). Override prompt/tool paths with --agent-prompt and --agent-tools.
If an agent fails or returns nothing, the CLI logs a warning and falls back to the heuristic spans.
Custom backends can register an entry point in the latex_music_linker.agents group to appear alongside the built-ins.
For example, to use Gemini 3.0 Flash, first setup the llm CLI:
uv tool install llm
uv run llm install gemini
uv run llm keys set gemini
# Paste Gemini API key herethen invoke with:
uv run latex-music-linker \
examples/newsletter_example.tex \
examples/newsletter_example_linked.tex \
--agent llm \
--llm-model gemini-3-flash-previewor
export LATEX_MUSIC_LINKER_AGENT=llm
export LATEX_MUSIC_LINKER_LLM_MODEL=gemini-3-flash-preview
uv run latex-music-linker \
examples/newsletter_example.tex \
examples/newsletter_example_linked.texsrc/latex_music_linker/– core librarydocs/– specification and tool schemasexamples/– example LaTeX inputstests/– basic testsscripts/– helper scripts
# Preview the agent payload without making API calls
uv run latex-music-linker examples/newsletter_example.tex --dry-run
# Run with verbose logging to see debug output
uv run latex-music-linker input.tex output.tex -v --agent llm- The LLM and heuristic agents should be instructed to also extract year, if it is possible to do so with high confidence.
- Verify that albums are extracted and used to improve song search accuracy.
- Explore using the Anthropic Agent SDK, because single-shot prompting is brittle.
- Test more LLM models. Gemini 3.0 Flash is fast, cheat, and works well-enough, but I suspect better models exist.
- Add more support for testing and debugging the agent integration, especially agent outputs.
- Add much more comprehensive and difficult tests, including observed failure modes.
- Handle
https://song.link/not-found. Add retry flag.
- Handle
- Add caching layer for resolved links to avoid repeated API calls.
- Ask song.link devs for an API key.
- Some links do not inserted at all, investigate why.