DSH Plugins Marketplace

DSH Plugins

Plugins

/

Tools & Capabilities

/

lightroom-py

d

lightroom-py

Manifest valid★ 3

Adobe Lightroom Classic as native dsh tools through the lightroom-py MCP server: read the catalog, apply develop settings and presets, export JPEG/TIFF/PSD/DNG, and write ratings, labels, keywords and

hasBundlePatch

lightroom-py

Drive Adobe Lightroom Classic from Python and Claude. First open agent driver with verified programmatic mask creation (35.4% pixel-diff confirmed) and the AI mask compute path documented elsewhere as impossible.

Python 3.10+ License: MIT LR Classic 15.3 verified Tests

62 bridge handlers · 80 CLI verbs · 101 tests · 7+ real-LR validation sessions documented in CHANGELOG.md. Unofficial, MIT, not affiliated with Adobe.


Install — 3 user actions

pip install lightroom-py            # 1. install
lightroom setup                     # 2. one-command: plugin + LaunchAgent + skill
                                    # 3. In LR: Plug-in Manager → enable
                                    #    "lightroom-py bridge"  (~10 sec, one-time)

lightroom setup installs the LR plugin into ~/Library/Application Support/Adobe/Lightroom/Modules/, generates a bridge token at ~/.lightroom/profiles/default/bridge.json, registers a macOS LaunchAgent that auto-starts the bridge server on login (no terminal), and installs the Claude agent skill. The token auto-loads into LR's plugin — no manual paste.

Verify with lightroom doctor.

Install variants + macOS TCC gotcha + Windows notes

Variants

NeedCommand
Default (CLI + Python lib)pip install lightroom-py
With Claude Desktop MCP serverpip install "lightroom-py[mcp]"
With ExifTool fast-path for XMPpip install "lightroom-py[exiftool]"
Everything (mcp + exiftool + dev)pip install "lightroom-py[all]"

macOS TCC-protected venvs

LaunchAgents on macOS can't read files under ~/Documents, ~/Desktop, ~/Downloads, ~/Pictures, ~/Movies, ~/Music without Full Disk Access. Install your venv outside those dirs:

python3 -m venv ~/.lightroom/venv
~/.lightroom/venv/bin/pip install lightroom-py
~/.lightroom/venv/bin/lightroom setup

lightroom setup and bridge install-service detect protected paths and refuse with workaround instructions before silently failing.

Windows

Manual bridge start (no LaunchAgent equivalent yet):

pip install lightroom-py
lightroom bridge install
lightroom bridge start         # leave running
# Then in LR: Plug-in Manager → enable

What you can do

SurfaceVerbs
Catalogcatalog open / info / stats — counts of photos / folders / keywords / collections
Photosphotos list / count / find-by-path — filter by rating, camera, lens, keyword, date, color label, file format, ISO, aperture, focal length, GPS; SQLite read fast-path (50k+ catalogs return instantly)
Selection + navselect, select-all/none/inverse/extend, next, previous
Flags + ratingsflag-pick/reject/clear, rate-up/rate-down, color-cycle
Metadataadd-keywords (hierarchical "People|Family|Mom"), rate, color, set-iptc (caption/title/headline/copyright/creator/city/state/country)
XMPmetadata write-xmp / read-xmp + ExifTool fast-path
Develop — globalsapply-preset, apply-settings, paste-settings --subset, get-settings, copy, reset, live set
Develop — typedcrop, hsl, color-grade, transform, lens-correction, calibration, detail, effects
Develop — tone curvecurve get/set/preset/linear/s-curve — RGB + per-channel
Develop — snapshotssnapshot create/list — safety checkpoints before agent edits
Develop — process versionprocess-version get/set
Develop — targeted resetsreset-crop / -masking / -spot / -redeye / -transforms
Masks — read + clearmask list / clear (unified MaskGroupBasedCorrections schema, LR 15.3+)
Masks — create ⭐mask create-radial (verified end-to-end) + create-linear (best-effort) with 20+ Local* adjustments per mask
AI mask compute ⭐apply-preset --folder "Adaptive: Subject" + library export → LR's "AI Updates Required" dialog → one click → mask renders (verified 20.91% pixel-diff)
Collectionslist / create / add / remove / delete / get-photos — regular + smart
Librarylist-folders, export (JPEG/TIFF/PSD/DNG with watermark, output sharpening, resize, DPI, filename templates, minimize-metadata), make-virtual-copy, stack
Edit-Inexport to disk, run for full roundtrip (export → external tool → reimport as stack)
Dev toolsbridge reload (hot-reload Lua handlers without LR restart), bridge eval (arbitrary Lua), bridge tail-log
Service mgmt (macOS)bridge install-service / uninstall-service / service-status

What's NOT implementable (Adobe SDK gaps, documented)

SurfaceWhy
AI Denoise computeLR exposes no public trigger for Enhance → Denoise…. Stage settings, user clicks Enhance.
Brush mask creationMask/Paint schema (Dabs: stroke array) not yet probed. Use radial as workaround for v0.6.
Spot removal createNot exposed in LR 15.3.
Photo deletioncat:trashPhotos doesn't exist in 15.3.
Virtual copy deleteOnly creation works.
Lightroom Cloud (LR CC)Partner-API gated; we target LR Classic.

Command cheatsheet

Full reference: docs/cli-reference.md. The 20 most common patterns:

# === Setup + health ===
lightroom setup                                              # one-shot: plugin + service + skill
lightroom doctor                                             # diagnose install + bridge state
lightroom bridge ping                                        # round-trip test

# === Catalog + cull ===
lightroom catalog open ~/Pictures/Lightroom/MyCatalog.lrcat
lightroom photos list --rating ">=4" --iso ">=400" --since 2026-01-01 --json
lightroom photos count --keyword wedding
lightroom photos select-all
lightroom photos flag-pick --selection
lightroom photos rate-up --selection                         # cycle +1 star

# === Metadata ===
lightroom metadata add-keywords "wedding,bride,People|Family|Mom" --selection
lightroom metadata rate 5 --selection
lightroom metadata set-iptc -f caption="Sunset" -f city="Paris" --selection

# === Global develop ===
lightroom develop list-presets
lightroom develop apply-preset "Pop" --folder "Adaptive: Subject" --selection
lightroom develop apply-settings '{"Exposure2012":0.5,"Contrast2012":20}' --selection
lightroom develop hsl --saturation orange=10 --luminance blue=15 --selection
lightroom develop color-grade --shadow-hue 215 --shadow-sat 20 \
                              --highlight-hue 30 --highlight-sat 25 --selection
lightroom develop curve preset "Medium Contrast" --selection

# === ⭐ Geometry mask creation (v0.6, verified) ===
lightroom develop mask create-radial --left 0.05 --right 0.5 \
    --top 0.4 --bottom 0.95 --exposure 1.0 \
    --name "subject-brighten" --selection
lightroom develop mask create-radial --top 0.15 --bottom 0.85 \
    --left 0.15 --right 0.85 --invert --exposure -1.0 --feather 70 --selection
    # ↑ vignette-style darkening (invert = effect OUTSIDE the ellipse)

# === Safety + experimentation ===
lightroom develop snapshot create "Pre-agent-edit" --selection
lightroom develop mask list --selection                      # see what masks are on the photo
lightroom develop mask clear --kind all --selection          # wipe all masks
lightroom develop reset --selection                          # full reset

# === Production export ===
lightroom library export ~/Desktop/finals --selection --format JPEG \
    --quality 88 --resize-long-edge 1920 --sharpening standard --dpi 96

# === External tool roundtrip ===
lightroom edit-in run "magick {input} -auto-level {output}" --selection

Three ways to use

1. CLI

lightroom photos list --rating ">=4" --iso ">=400" --json
lightroom develop apply-preset "Pop" --folder "Adaptive: Subject" --selection
lightroom develop mask create-radial --left 0.05 --right 0.5 --top 0.4 --bottom 0.95 \
    --exposure 1.0 --selection                          # ⭐ verified renders
lightroom library export ~/finals --selection --format JPEG \
    --resize-long-edge 1920 --sharpening standard --dpi 96

2. Python API

import asyncio
from lightroom import LightroomClient

async def main():
    async with LightroomClient.connect() as lr:
        await lr.catalog.open("~/Pictures/Lightroom/MyCatalog.lrcat")
        keepers = await lr.photos.list(rating_gte=4, iso_gte=400, since="2026-01-01")
        for p in keepers:
            await lr.develop.apply_preset("Pop", folder="Adaptive: Subject", photo_uuids=[p.uuid])
            await lr.develop.mask_create_radial(
                left=0.05, right=0.5, top=0.4, bottom=0.95,
                exposure=1.0, photo_uuids=[p.uuid],
            )

asyncio.run(main())

Full async sub-client reference: docs/python-api.md.

3. Claude / agent skill

The package ships a canonical SKILL.md installable via lightroom skill install (also done automatically by lightroom setup). It activates on /lightroom or intent like "cull these photos", "apply my warm preset to the selection", "export the 5-star photos as JPEGs".

For Claude Desktop's MCP integration: pip install "lightroom-py[mcp]" + point Claude Desktop's config at the bundled lightroom-mcp binary. See docs/mcp.md.

4. DeepSeek Harness (dsh)

This repository is also a DeepSeek Harness plugin bundle (package.json + cordis.patch.yml at the root — pure configuration, no build step):

pip install "lightroom-py[mcp]"                        # the MCP server (0.6.1+; on 0.6.0 add "mcp<2")
dsh plugin add github:drshy-org/lightroom-py           # the bundle; tools appear as mcp__lightroom_py__*

All 15 MCP tools become native dsh tools; the agent skill is shipped as dsh/skills/lightroom/SKILL.md. Details and the skill-discovery note: dsh/README.md. Any other MCP client (Codex CLI, Cursor, Gemini CLI, OpenCode) works the same way — point it at the lightroom-mcp binary.


Why this exists

LR Classic is the most locked-down RAW editor for automation: no AppleScript, no COM, no UXP. The Lua plugin SDK is the only door, and LrSocket / LrHttp are outbound-only — a plugin physically cannot host a server. lightroom-py is the missing Python-side counterpart: a tiny .lrplugin polls a local Python HTTP server, and Python (or Claude via the bundled agent skill / MCP server) drives Lightroom by enqueueing commands.

Claude Desktop / Code / CLI ──HTTP──▶  lightroom-py (Python aiohttp)
                                              ▲
                                              │ poll / respond
                                              │
                              .lrplugin ──────┘  (Lua, runs inside LR)

Configuration

VariableDefaultPurpose
LIGHTROOM_HOME~/.lightroomConfig root
LIGHTROOM_PROFILEdefaultPer-agent isolation

The bridge server reads host / port / token from $LIGHTROOM_HOME/profiles/$LIGHTROOM_PROFILE/bridge.json — auto-generated on first lightroom setup. bridge.json is the single source of truth; the LR plugin reads it directly.


Troubleshooting

SymptomFix
doctor says "Bridge plugin not installed"lightroom setup
doctor says "loaded but not currently running" + last_exit=256macOS TCC blocked the venv. Reinstall outside ~/Documents/.
bridge ping times outlightroom bridge install --force && lightroom bridge reload. For Lua changes outside Handlers.lua: Cmd+Q LR + relaunch.
Plugin disabled after a Lua errorLR auto-disables on plugin init crash. File → Plug-in Manager → re-enable.
Yielding is not allowed within a C or metamethod callUse LrTasks.pcall instead of bare pcall. See CHANGELOG v0.1.2 / v0.3.1 / v0.4.1.
AI mask preset applied but export looks unchangedClick Export on the "AI Updates Required" modal with the "Update affected photos" box checked.

For the developer log: lightroom bridge tail-log -n 50.


Development

git clone https://github.com/drshy-org/lightroom-py.git
cd lightroom-py
python -m venv .venv && source .venv/bin/activate
pip install -e ".[all]"
pre-commit install
ruff format . && ruff check . && mypy && pytest

See CONTRIBUTING.md for the ranked backlog, architecture details, the LR sandbox gotchas list, and the hot-reload dev loop.


Roadmap

VersionStatus
v0.1–v0.3Scaffold, bridge protocol, SQLite read, metadata writes, Collections/Library/Edit-In, MCP server, hot-reload tooling
v0.4Feature catch-up: tone curve, snapshots, process version, paste-settings, mask read/clear, AI staging
v0.4.2Install simplification — setup, LaunchAgent, token auto-load, TCC defensive check
v0.5Typed Develop wrappers, EXIF query layer, production exports
v0.6 (current)Geometry mask CREATION (radial verified). Unified MaskGroupBasedCorrections mask_list rewrite.
v0.7Brush mask schema probe + create, linear mask empirical verification, Windows LaunchAgent, .mcpb Claude Desktop bundle
Out of scopeLR Cloud, AppleScript (LR doesn't expose), photo deletion + virtual-copy delete + AI compute trigger (SDK gaps)

Contact

Built by drshy — drshy.xyz. Issues + PRs at github.com/drshy-org/lightroom-py. If lightroom-py saves you time, a star ⭐ is appreciated.

Citation

If you use lightroom-py in research, blog posts, papers, or talks, please cite it. GitHub auto-detects CITATION.cff and shows a "Cite this repository" button on the right sidebar.

Plain-text / APA:

drshy. (2026). lightroom-py: A Python and Claude agent driver for Adobe Lightroom Classic (v0.6.0) [Software]. Retrieved from https://github.com/drshy-org/lightroom-py — http://www.drshy.xyz

BibTeX:

@software{drshy_lightroom_py_2026,
  author       = {drshy},
  title        = {{lightroom-py}: {A} {Python} and {Claude} agent driver for {Adobe} {Lightroom} {Classic}},
  url          = {https://github.com/drshy-org/lightroom-py},
  version      = {0.6.0},
  date         = {2026-05-10},
  note         = {Author homepage: \url{http://www.drshy.xyz}}
}

If your work uses one of the specific empirical results from this project (the verified geometry mask creation pixel-diff, the AI mask compute path, the LR Classic 15.3 sandbox gotchas catalog), please link to the relevant CHANGELOG.md version entry so readers can find the original evidence.

License

MIT — see LICENSE. Use freely; no warranty; not affiliated with Adobe.

Comments

Loading…

Similar plugins

dsh-plugin-codegraph-project

A CodeGraph tool scoped to the session's own indexed project, resolved from its workspace directory. One MCP server is launched through npx per project root and shared by every session working there;

Tools & CapabilitiesManifest valid

★ 0

dsh plugin --profile web add dsh-plugin-codegraph-project

by LuminariSoftwares

Your MCP servers for ~300 tokens instead of ~28,000. MCP server + native DeepSeek Harness bundle.

Security & AuditTools & CapabilitiesModels & ProvidersManifest valid

★ 2

↓ 523/wk

MIT

Python

Oct 24, 2026

dsh plugin --profile web add dsh-tool-guardian

by BruceZhang1993

DeepSeek Harness plugin: bridges the computer-use-linux MCP server into DSH as native mcp__cul__* tools — AT-SPI accessibility trees, screenshots, window targeting, and Wayland/X11 input for Linux des

Manifest valid

★ 0

MIT

JavaScript

Oct 10, 2026

dsh plugin --profile web add @brucezhang1993/dsh-computer-use-linux

by Andrietteprotective835

Shrink massive MCP catalogs to two tools, letting DeepSeek Harness search and call 1,000+ remote APIs efficiently.

Manifest valid

★ 0

MIT

TypeScript

Oct 13, 2026

dsh plugin --profile web add dsh-mcp-lens

by daimingxing

Per-project CodeGraph MCP tools: each session queries the repo it is actually working in

Tools & CapabilitiesDevelopment & InfrastructureManifest valid

★ 1

MIT

JavaScript

Oct 26, 2026

dsh plugin --profile web add dsh-codegraph-project

by xiamubumu

Composes tools, skills and MCP servers into switchable per-session sets, shrinking the resident tool surface and the system prompt on demand.

Tools & CapabilitiesManifest valid

★ 0

MIT

JavaScript

Oct 15, 2026

dsh plugin --profile web add dsh-capability-composer