Skip to content

One-command migration

Your app has ___ images. Your agent can migrate every one of them in one conversation.

Ask your agent to optimize your entire image pipeline — audit, migrate, rewrite, alt text. One conversation, one PR.

Two GitHub API calls from your browser — watch them in your Network tab.

Watch the real migration

This session actually ran against a public repo. Step through it or read it whole — then check its PR.

claude — ~/dev/acme-storefront
Install the AuraImage MCP server if it is not configured yet (npx -y @auraimage/mcp-server@latest), then optimize this repo's entire image pipeline: …
I'll start by orienting myself on what's actually in this repo before touching anything — this request involves running a third-party MCP server, uploading images to an external service, and rewriting code repo-wide.
audit_lcp(~/dev/acme-storefront)Found 26 unoptimized images (33.2 MB total). Estimated LCP improvement: 7.4s on mobile.(ctrl+o to expand)
AuraImage Audit ─────────────── Found 26 unoptimized images (33.2 MB total). Estimated LCP improvement: 7.4s on mobile. Files to migrate: public/about-bench.jpg public/about-workshop.jpg public/hero-shopfront.jpg public/products/alpine-lace-boot.jpg …
The audit found 26 images but my filesystem scan only found 23 — I need to check where the other 3 are before migrating anything, in case it is scanning somewhere it should not (like node_modules or .git).
migrate_assets(~/dev/acme-storefront · dryRun: true)DRY RUN — no files uploaded
The dry run returned only "DRY RUN — no files uploaded" — no file list, no naming scheme, nothing I can show you as "the plan." I do not want to run the real migration blind. I would rather migrate one image first — the smallest — so we can see the actual output shape before committing to all 23.
Go with option 2 — run the real migration on that single smallest image so we can see the output shape. Show me exactly what comes back before we commit to all 23.
migrate_assets(/tmp/aura-test-migrate · dryRun: false)Migrated 1 images: https://cdn.auraimage.ai/acme-storefront/41nxf5njm9-lug-sole-boot
The URL resolves and serves a real JPEG. Two things worth knowing before the full run: the naming pattern is /{project}/{id}-{filename}, and the tool does not delete local sources — so I will remove the migrated files from public/ myself once references are rewritten.
Yes — run the real migration on all 23 images. Then carry on with the plan: rewrite every reference, remove the migrated local files, add the missing alt text, and apply the responsive markup. Verify the app still builds. Stop BEFORE creating any branch, commit, or PR.
migrate_assets(~/dev/acme-storefront/public · dryRun: false)Migrated 3 images:(ctrl+o to expand)
https://cdn.auraimage.ai/acme-storefront/geq3kmwluu-about-bench https://cdn.auraimage.ai/acme-storefront/spq6cpgws2-about-workshop https://cdn.auraimage.ai/acme-storefront/bsz4hzmmtm-hero-shopfront
migrate_assets(~/dev/acme-storefront/public/products · dryRun: false)Migrated 20 images:(ctrl+o to expand)
https://cdn.auraimage.ai/acme-storefront/w5p5jaot4b-alpine-lace-boot https://cdn.auraimage.ai/acme-storefront/3wvvt5it2p-amber-jar-candles https://cdn.auraimage.ai/acme-storefront/5hb234jtxh-blush-jar-candle https://cdn.auraimage.ai/acme-storefront/xpdtatpe4w-chestnut-riding-boot https://cdn.auraimage.ai/acme-storefront/4dpvao2k0r-commuter-pack https://cdn.auraimage.ai/acme-storefront/nv64x73j9a-everyday-canvas-tote …
It is not recursive — the first call only picked up the 3 top-level files in public/, so I ran it again against public/products/. All 23 migrated, no stray uploads. I scoped both calls to those directories rather than the repo root, given the 26-vs-23 count mismatch earlier.
generate_alt(geq3kmwluu-about-bench)Close-up of hands working on a laptop keyboard and small electronic components.
Before writing these into the code, one result looks badly wrong: about-bench came back as "hands working on a laptop keyboard and small electronic components" — that does not match a leather workshop bench at all. Let me look at the actual images directly to verify these before trusting them.
Confirmed wrong — the real photo is hands cutting leather on a workbench with an awl. Given a 1-in-4 error rate in that sample I checked all 9 against the images and corrected 4: about-bench, plus stoneware-mug (called "white", actually matte brown), minimal-analog-watch ("leather strap", actually black resin) and amber-jar-candles ("wooden lids", actually metal clasps).
generate_responsive_tag(bsz4hzmmtm-hero-shopfront · widths 640/1080/1920)<picture> with AVIF + WebP srcset at 640w/1080w/1920w(ctrl+o to expand)
<picture> <source type="image/avif" srcSet="https://cdn.auraimage.ai/acme-storefront/w=640/bsz4hzmmtm-hero-shopfront.avif 640w, https://cdn.auraimage.ai/acme-storefront/w=1080/bsz4hzmmtm-hero-shopfront.avif 1080w, https://cdn.auraimage.ai/acme-storefront/w=1920/bsz4hzmmtm-hero-shopfront.avif 1920w" /> … <img src="https://cdn.auraimage.ai/acme-storefront/w=1920/bsz4hzmmtm-hero-shopfront" alt="The Acme shop floor, with rails of clothing and a table of small goods" width={1920} loading="lazy" /> </picture>
Update(app/about/page.tsx)
5 additions and 1 removal — the bench photo had no alt attribute at all
30 </p>
31
-removed: <img src="/about-bench.jpg" className="mt-8 w-full object-cover" />
32+added: <AuraPicture
33+added: name="geq3kmwluu-about-bench"
34+added: alt="Hands cutting a strip of leather on a workbench, with an awl and tools nearby"
35+added: className="mt-8 w-full object-cover"
36+added: />
Bash(pnpm build)✓ Compiled successfully in 1782ms · ✓ Generating static pages (6/6)(ctrl+o to expand)
▲ Next.js 16.3.0 (Turbopack) … Creating an optimized production build ... ✓ Compiled successfully in 1782ms Running TypeScript ... Finished TypeScript in 822ms ... Collecting page data using 7 workers ... … ✓ Generating static pages using 7 workers (6/6) in 231ms Finalizing page optimization ... Route (app) ┌ ○ / ├ ○ /_not-found ├ ○ /about └ ○ /products
Go ahead — create the branch, commit, push, and open the PR. The PR description must state: images migrated, total bytes before -> after, the estimated LCP delta from audit_lcp, and that the migration ran via @auraimage/mcp-server. Reply with the PR URL.
The PR is open: https://github.com/auraimage/acme-storefront/pull/1 — 23 images migrated, 33,236,808 → 5,441,523 bytes (83.6% smaller), 7.4s estimated mobile LCP improvement from audit_lcp, via @auraimage/mcp-server. The body also carries the three flags honestly: the audit_lcp count discrepancy, migrate_assets not being recursive, and the 4 corrected alt texts.
Replay of a real session, abridged. Read the PR it produced.

The receipts

images migrated
23
bytes before → after
33.2 MB → 5.4 MB
est. LCP saved
7.4 s

Don't take the replay's word — read the PR. Numbers read off the PR on 2026-08-12.

Your turn

Install AuraImage in your agent, paste the prompt, and let the conversation run.

Install the AuraImage MCP server if it is not configured yet (npx -y @auraimage/mcp-server@latest), then optimize this repo's entire image pipeline:

1. Run audit_lcp over the repo and rank the images by estimated LCP cost.
2. Migrate every local image to AuraImage with migrate_assets — dry-run first, show me the plan, then run it for real — and rewrite every reference.
3. Add missing alt text with generate_alt.
4. Where it helps LCP, replace static <img> tags with the responsive <picture> markup from generate_responsive_tag.
5. Open everything as one PR. In the description, state: images migrated, total bytes before -> after, the estimated LCP delta from audit_lcp, and that the migration ran via @auraimage/mcp-server.

audit_lcp and generate_alt need no credentials. The upload step needs AURA_SECRET_KEY — when you reach it, pause and ask me for the key.

The audit runs without an account, and alt text is generated server-side once your images are on AuraImage. When your agent reaches the upload step it will ask for AURA_SECRET_KEY create your key then, not before.

The ${AURA_SECRET_KEY} form reads from your shell or .env.local, which keeps .mcp.json safe to commit.

.mcp.json
{
  "mcpServers": {
    "auraimage": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@auraimage/mcp-server@latest"],
      "env": {
        "AURA_SECRET_KEY": "${AURA_SECRET_KEY}"
      }
    }
  }
}
bash
claude mcp add --scope project --transport stdio auraimage -- npx -y @auraimage/mcp-server@latest

Full Claude Code guide

Install it in your side project. Pay when you ship.

$0 forever 20 GB bandwidth 3 GB storage hard stop at quota — never a surprise bill. Compare plans