AI-powered accessibility text generation and labeling tools for markdown content
Project description
alt-text-llm
AI-powered alt text generation and labeling tools for markdown content. Originally developed for my website (repo).
Features
- Intelligent scanning - Detects images/videos missing meaningful alt text (ignores empty
alt="") - AI-powered generation - Uses LLM of your choice to create context-aware alt text suggestions
- Interactive labeling - Manually review and edit LLM suggestions. Images display directly in your terminal
- Automatic application - Apply approved captions back to your markdown files
Installation
From PyPI
pip install alt-text-llm
Automated setup (includes system dependencies)
git clone https://github.com/alexander-turner/alt-text-llm.git
cd alt-text-llm
./setup.sh
Prerequisites
macOS:
brew install imagemagick ffmpeg imgcat
pip install llm
Linux:
sudo apt-get install imagemagick ffmpeg
pip install llm
# imgcat: curl -sL https://iterm2.com/utilities/imgcat -o ~/.local/bin/imgcat && chmod +x ~/.local/bin/imgcat
Usage
The tool provides four main commands: scan, generate, label, and apply.
1. Scan for missing alt text
Scan your markdown files to find images without meaningful alt text:
alt-text-llm scan --root /path/to/markdown/files
This creates asset_queue.json with all assets needing alt text.
2. Generate AI suggestions
Generate alt text suggestions using an LLM:
alt-text-llm generate \
--root /path/to/markdown/files \
--model gemini-2.5-flash \
--suggestions-file suggested_alts.json
Available options:
--model(required) - LLM model to use (e.g.,gemini-2.5-flash,gpt-4o-mini,claude-3-5-sonnet)--max-chars- Maximum characters for alt text (default: 300)--timeout- LLM timeout in seconds (default: 120)--estimate-only- Only show cost estimate without generating--process-existing- Also process assets that already have captions
Cost estimation:
alt-text-llm generate \
--root /path/to/markdown/files \
--model gemini-2.5-flash \
--estimate-only
3. Label and approve suggestions
Interactively review and approve the AI-generated suggestions:
alt-text-llm label \
--suggestions-file suggested_alts.json \
--output asset_captions.json
Interactive commands:
- Edit the suggested alt text (vim keybindings enabled)
- Press Enter to accept the suggestion as-is
- Submit
undooruto go back to the previous item - Images display in your terminal (requires
imgcat)
4. Apply approved captions
Apply the approved captions back to your markdown files:
alt-text-llm apply \
--captions-file asset_captions.json
Available options:
--captions-file- Path to the captions JSON file withfinal_altpopulated (default:asset_captions.json)--dry-run- Preview changes without modifying files
What it does:
- Reads approved captions from the captions file
- Locates corresponding images/videos in markdown files
- Updates alt text for all supported formats:
- Markdown images:
 - HTML img tags:
<img src="path" alt="alt"> - Wikilink images:
![[path|alt]]
- Markdown images:
- Preserves file formatting and handles special characters
Example workflow
# 1. Scan markdown files for missing alt text
alt-text-llm scan --root ./content
# 2. Estimate the cost
alt-text-llm generate \
--root ./content \
--model gemini-2.5-flash \
--estimate-only
# 3. Generate suggestions (if cost is acceptable)
alt-text-llm generate \
--root ./content \
--model gemini-2.5-flash
# 4. Review and approve suggestions
alt-text-llm label
# 5. Apply approved captions to markdown files
alt-text-llm apply
Configuration
LLM Integration
This tool uses the llm CLI tool to generate alt text. This provides access to many different AI models including:
- Gemini (Google) via the llm-gemini plugin
- Claude (Anthropic) via the llm-claude-3 plugin
- And many more via plugins
Setting up your model
For Gemini models (default):
llm install llm-gemini
llm keys set gemini # enter API key
llm -m gemini-flash-latest "Hello, world!"
For other models:
- Install the appropriate llm plugin (e.g.,
llm install llm-openai) - Configure your API key (e.g.,
llm keys set openai) - Use the model name with
--modelflag.
See the llm documentation for setup instructions and the plugin directory for available models.
Output files
asset_queue.json- Queue of assets needing alt text (fromscan)suggested_alts.json- AI-generated suggestions (fromgenerate)asset_captions.json- Approved final captions (fromlabel)
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file alt_text_llm-1.2.tar.gz.
File metadata
- Download URL: alt_text_llm-1.2.tar.gz
- Upload date:
- Size: 48.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2ad7ca4996b9ed54cf40457594ce6d9fe9b21361fd5a914f93f5ea27a39bfe3f
|
|
| MD5 |
4677b057e71326612cf9fdff0a4be40a
|
|
| BLAKE2b-256 |
c00ad28a00c0927125db0aab6725753a5f7fad686928460f93bd946bc53f9b2f
|
Provenance
The following attestation bundles were made for alt_text_llm-1.2.tar.gz:
Publisher:
publish.yml on alexander-turner/alt-text-llm
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
alt_text_llm-1.2.tar.gz -
Subject digest:
2ad7ca4996b9ed54cf40457594ce6d9fe9b21361fd5a914f93f5ea27a39bfe3f - Sigstore transparency entry: 841729200
- Sigstore integration time:
-
Permalink:
alexander-turner/alt-text-llm@8691cae8cf81e92ad4c3a4f167b53ab3296f5a84 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/alexander-turner
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8691cae8cf81e92ad4c3a4f167b53ab3296f5a84 -
Trigger Event:
push
-
Statement type:
File details
Details for the file alt_text_llm-1.2-py3-none-any.whl.
File metadata
- Download URL: alt_text_llm-1.2-py3-none-any.whl
- Upload date:
- Size: 26.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4cf543a313e195072b7b67eb351674617ca08eb2d0a7c6a113c20a6931a4296e
|
|
| MD5 |
de56d820230177563f382a974aa975b2
|
|
| BLAKE2b-256 |
d2471f7198d8949e8f68c2aadcd310832c0066bac8ebfb679c6edaa929eefbeb
|
Provenance
The following attestation bundles were made for alt_text_llm-1.2-py3-none-any.whl:
Publisher:
publish.yml on alexander-turner/alt-text-llm
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
alt_text_llm-1.2-py3-none-any.whl -
Subject digest:
4cf543a313e195072b7b67eb351674617ca08eb2d0a7c6a113c20a6931a4296e - Sigstore transparency entry: 841729201
- Sigstore integration time:
-
Permalink:
alexander-turner/alt-text-llm@8691cae8cf81e92ad4c3a4f167b53ab3296f5a84 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/alexander-turner
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8691cae8cf81e92ad4c3a4f167b53ab3296f5a84 -
Trigger Event:
push
-
Statement type: