Skip to content

Add WP-CLI command for bulk alt text generation#436

Open
adamsilverstein wants to merge 6 commits intoWordPress:developfrom
adamsilverstein:feature/cli-alt-text-generate
Open

Add WP-CLI command for bulk alt text generation#436
adamsilverstein wants to merge 6 commits intoWordPress:developfrom
adamsilverstein:feature/cli-alt-text-generate

Conversation

@adamsilverstein
Copy link
Copy Markdown
Member

@adamsilverstein adamsilverstein commented Apr 16, 2026

Summary

  • Adds wp ai alt-text generate — the plugin's first WP-CLI command
  • Queries images missing alt text and processes them server-side in batches using the existing ai/alt-text-generation ability
  • Supports --batch-size, --dry-run, --force, --ids, and --delay flags
  • Includes progress bar, summary table, memory management for large libraries, and graceful error handling

Closes #435

Test plan

  • wp ai alt-text generate --dry-run lists images missing alt text without making changes
  • wp ai alt-text generate --batch-size=2 processes images with progress bar, verify alt text saved in DB
  • wp ai alt-text generate --ids=<id1>,<id2> --force regenerates for specific images even if they already have alt text
  • Running with alt-text experiment disabled shows a clear error message
  • Running without AI credentials configured shows a clear error message
  • --delay flag adds visible pause between API calls
  • Large batch runs don't exhaust memory (object cache cleared between batches)
Open WordPress Playground Preview

AI use

I used Claude code to write this PR with a series of prompts. I tested the command manually and reviewed the code.

Introduce `wp ai alt-text generate` to backfill alt text for existing
media library images using the ai/alt-text-generation ability. Supports
--batch-size, --dry-run, --force, --ids, and --delay flags. Processes
images server-side in batches with progress reporting and memory management.

Closes WordPress#435
@github-actions
Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: adamsilverstein <adamsilverstein@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 16, 2026

Codecov Report

❌ Patch coverage is 93.29268% with 11 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.56%. Comparing base (4c9699f) to head (d2ffbb5).

Files with missing lines Patch % Lines
includes/CLI/Alt_Text_Command.php 94.44% 9 Missing ⚠️
includes/Main.php 0.00% 2 Missing ⚠️
Additional details and impacted files
@@              Coverage Diff              @@
##             develop     #436      +/-   ##
=============================================
+ Coverage      67.72%   68.56%   +0.83%     
- Complexity       959      994      +35     
=============================================
  Files             60       61       +1     
  Lines           4836     5000     +164     
=============================================
+ Hits            3275     3428     +153     
- Misses          1561     1572      +11     
Flag Coverage Δ
unit 68.56% <93.29%> (+0.83%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@adamsilverstein adamsilverstein marked this pull request as draft April 16, 2026 13:55
Add php-stubs/wp-cli-stubs for PHPStan to recognize WP-CLI classes.
Add cli\progress\Bar ignore pattern since the WP-CLI progress bar
internals are not in the stubs package. Fix type annotations and add
unreachable returns after WP_CLI::error() for static analysis.

Add 10 integration tests covering: admin user setup, attachment ID
querying (with/without alt text, force flag, specific IDs, invalid IDs),
memory cleanup, summary output, and dry-run display.
Add WP-CLI stubs that allow testing the CLI command without requiring
a full WP-CLI install. This raises patch coverage above the codecov
threshold and exercises the main process_images() and generate() paths.

New tests cover:
- process_images generates and saves alt text
- process_images handles decorative images
- process_images skips existing alt text without --force
- process_images force flag overwrites existing alt text
- process_images handles WP_Error responses from the ability
- print_summary with zero results path
- ensure_admin_user error when no admin exists
- generate errors when ability is not registered
@jeffpaul jeffpaul added this to the 0.8.0 milestone Apr 16, 2026
adamsilverstein and others added 3 commits April 16, 2026 16:51
Cover the main entry point paths not previously tested:
- generate() with no matching images (early return)
- generate() errors without AI credentials
- generate() processes attachments end-to-end
- generate() --dry-run does not modify alt text

Register a real fake ability via wp_register_ability() using the WP
core test pattern of faking $wp_current_filter to satisfy
doing_action('wp_abilities_api_init') without triggering re-entrant
init calls from the registry singleton.
…xt-generate

# Conflicts:
#	composer.lock
#	phpstan.neon.dist
@adamsilverstein adamsilverstein marked this pull request as ready for review April 22, 2026 17:41
@jeffpaul jeffpaul mentioned this pull request Apr 22, 2026
27 tasks
@jeffpaul jeffpaul requested a review from dkotter April 22, 2026 19:48
Copy link
Copy Markdown
Collaborator

@dkotter dkotter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a few comments, open to discussion on those. Also looks like PHPStan is failing so that needs looked at

}

if ( ! has_valid_ai_credentials() ) {
WP_CLI::error( 'No valid AI credentials found. Configure a provider in Settings > AI.' );
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
WP_CLI::error( 'No valid AI credentials found. Configure a provider in Settings > AI.' );
WP_CLI::error( 'No valid AI credentials found. Configure a provider in Settings > Connectors.' );

'post_type' => 'attachment',
'post_mime_type' => 'image',
'post_status' => 'inherit',
'posts_per_page' => -1,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any concern here on sites with lots of attachments, thinking multiple thousands? Wonder if we should instead implement batch processing, where we only query for a set number at a time and then continue to iterate until we've processed them all?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a batch capability makes sense, I'll add that!

private function display_dry_run( array $attachment_ids ): void {
$items = array();
foreach ( $attachment_ids as $id ) {
$alt = get_post_meta( $id, '_wp_attachment_image_alt', true );
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems we default to only getting images without alt text set unless the $force argument is passed. Should we be using that argument here so the results we show are accurate to what would actually be processed?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right, good point!

return;
}

WP_CLI::log( sprintf( 'Found %d image(s) to process.', count( $attachment_ids ) ) );
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also wonder if we need some sort of "Are you sure?" protection here to prevent someone from accidentally running this to generate alt text on thousands of images (and thus rack up a nice API bill). You could argue that if someone has access to WP-CLI and they decide to run this, that's on them but also think it would be nice to use the confirm method to get user input first

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense, maybe with a flag you can pass to skip that.

@dkotter dkotter modified the milestones: 0.8.0, 0.9.0 Apr 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add WP-CLI command for bulk alt text generation

3 participants