LRBridge is a local Windows bridge for controlling Adobe Lightroom Classic from external control surfaces, browser controls, Bitfocus Companion, Stream Deck-style devices, Loupedeck / Razer Stream Controller setups, scripts, and other HTTP-capable automation tools.
It is designed for:
- Lightroom Classic users who want physical or browser-based controls.
- Bitfocus Companion users who want Lightroom slider and action control.
- Stream Deck and Loupedeck users who want HTTP-based Lightroom control.
- Users who want to control Lightroom from a tablet, touchscreen monitor, old phone, or LAN browser.
- Developers and AI coding agents that need a clear project map before making forks, patches, or Companion modules.
LRBridge is focused on reliable Lightroom slider and action control through a local HTTP bridge. The Web Controller supports polling-based feedback for visible sliders. LRBridge exposes a Lightroom context API so external tools can detect active module changes, selected photo changes, and Develop value changes.
Feedback and context updates are useful, but they are polling-based. They are not true native realtime Lightroom events.
Search keywords: Adobe Lightroom Classic controller, Lightroom HTTP API, Lightroom bridge, Bitfocus Companion Lightroom control, Generic HTTP Requests, Stream Deck Lightroom control, Loupedeck Lightroom knobs, Razer Stream Controller Lightroom, photo editing control surface, Lightroom slider control, Lightroom automation, Lightroom context API, Lightroom selected photo detection, Lightroom module detection, Electron, Node.js, Lua Lightroom plugin.
When LRBridge is running:
- Web Controller: http://127.0.0.1:17892/
- Human help page: http://127.0.0.1:17892/help
- Bitfocus Companion HTTP Builder: http://127.0.0.1:17892/bitfocus-companion-cheatsheet
- LRBridge API: http://127.0.0.1:17891/
- Raw API help: http://127.0.0.1:17891/help
- Lightroom context API: http://127.0.0.1:17891/context
Project links:
- LRBridge releases: https://github.com/ninoleto/LRBridge/releases
- Native Companion module: https://github.com/ninoleto/companion-module-ninoleto-lrbridge
- Support LRBridge development on Ko-fi: https://ko-fi.com/ninoleto
LRBridge lets Lightroom Classic users control Develop sliders and actions from the Web Controller, Bitfocus Companion, Stream Deck HTTP/request plugins, PowerShell, curl, scripts, and other HTTP-capable tools.
Original use case:
Loupedeck Live / Razer Stream Controller
↓
Bitfocus Companion
↓
LRBridge app
↓
LRBridge Lightroom plugin
↓
Lightroom Classic
LRBridge was originally built so Loupedeck Live hardware could be used with Lightroom Classic through Bitfocus Companion, without depending on the official Loupedeck / Logitech software for slider control.
It is also useful when you want a tablet, touchscreen monitor, old phone, browser shortcut, Stream Deck HTTP setup, or automation script to send simple commands to Lightroom Classic.
The Web Controller includes polling-based feedback for visible sliders. This means it can show current Lightroom slider values, but small delays are normal.
The Lightroom context API lets external tools detect when Lightroom changes selected photo, active module, or Develop values, so controllers can refresh their visible feedback instead of showing stale slider values.
LRBridge connects external controllers to Adobe Lightroom Classic.
Command path:
Web Controller / HTTP client / Bitfocus Companion
↓
LRBridge app
↓
LRBridge local HTTP API
↓
Command queue
↓
LRBridge Lightroom plugin polling
↓
Lightroom SDK / LrDevelopController
↓
Lightroom Classic Develop UI
Web Controller feedback path:
Web Controller asks for visible slider values
↓
LRBridge feedback queue
↓
LRBridge Lightroom plugin feedback polling
↓
Lightroom SDK / LrDevelopController.getValue()
↓
LRBridge feedback state
↓
Web Controller value display
Lightroom context path:
Lightroom Classic changes module, photo, or Develop values
↓
LRBridge Lightroom plugin context heartbeat
↓
LRBridge app context state
↓
/context and /status expose context counters
↓
Companion module / browser controller / script refreshes feedback
Feedback and context detection are polling-based. They are designed to be useful and lightweight, not perfect realtime feedback.
Current public package:
v0.5.2
Stability and hardening checkpoint for the Windows portable release, preserving the existing Lightroom context API and visible slider feedback
A Windows portable ZIP package is available from GitHub Releases. The package includes the LRBridge Windows app, Web Controller, Lightroom Classic plugin, configuration files, Companion HTTP Builder, README documentation, and development context documentation.
Stable enough for normal use:
- LRBridge Electron app.
- Windows portable ZIP package.
- Local HTTP API.
- Web Controller.
- Lightroom Classic plugin polling.
- Slider adjustments.
- Slider reset for an individual slider.
- Lightroom Develop actions.
- Command queue.
- Repeated slider adjustment coalescing.
- Configurable polling interval.
- Smoke test.
- Human Web Controller Help page.
- Companion Generic HTTP support.
- Polling-based Web Controller feedback for visible sliders.
- Lightroom context API for detecting active module, selected photo changes, and Develop value changes.
- Auto Tone and Auto White Balance cooldown in the Web Controller after slider changes.
Advanced or use with care:
/reset-groupand/reset-allexist as HTTP endpoints, but can overload Lightroom if abused./get/set/last-result- WebSocket command input
Companion integration:
- Generic HTTP Requests works now.
- Native LRBridge Companion module is available as a separate project:
https://github.com/ninoleto/companion-module-ninoleto-lrbridge - The native module may need manual installation until it is included in official Companion builds.
- The native module can use
/statusor/contextto detect when Lightroom changes photo, module, or Develop values.
Important design decision:
LRBridge v0.x stays HTTP-first and Lightroom-plugin controlled.
Do not build normal workflows on /get, /set, or /last-result.
Use /context or context fields in /status for refresh detection.
LRBridge/
app/
controller.html Web Controller UI
controller-help.html Human help page for Web Controller
index.html Electron app window
main.js Electron main process and Web Controller proxy server
preload.js Electron preload bridge
renderer.js Electron renderer logic
tray.png Tray/app icon
config/
settings.txt Polling interval configuration
sliders.json Slider metadata registry
docs/
COMPANION_HTTP_CHEATSHEET.md
lightroom/
LRBridge.lrplugin/
AutoStartPolling.lua Silent polling startup
FeedbackPolling.lua Side-channel feedback and context polling
Commands.lua Executes parsed commands
Driver.lua Lightroom SDK control layer
Info.lua Lightroom plugin manifest
Parser.lua Minimal JSON command parser
PluginInit.lua Plugin initialization
Query.lua Slider feedback/readback helpers
Settings.lua Reads config/settings.txt
StartPolling.lua Manual polling command
Test.lua Plugin test command
server/
commands.js Command validation, queue, results
context.js Lightroom context state for /context and /status
lightroomWake.js Windows Lightroom wake helper
sliders.js Slider registry helper
tests/
http-smoke.js Main HTTP API smoke test
bridge.js Core LRBridge HTTP/WebSocket server
package.json Node/Electron scripts and dependencies
start-bridge.bat Windows helper script
README.md This file
For normal packaged use:
- Windows PC.
- Adobe Lightroom Classic.
- Lightroom Classic plugin support.
- A writable folder for the portable LRBridge package.
For development from source:
- Windows PC.
- Adobe Lightroom Classic.
- Node.js.
- npm.
- Git.
- Lightroom Classic plugin support.
Optional:
- Bitfocus Companion.
- Browser or tablet/phone for Web Controller.
- Stream Deck-style device with HTTP request support.
- Loupedeck / Razer Stream Controller through Bitfocus Companion.
Known development environment:
Windows 11
Node.js
Electron
Lightroom Classic
Local ports 17890, 17891, 17892
LRBridge uses three local ports:
17891 LRBridge HTTP API
17890 LRBridge WebSocket command input, experimental
17892 Web Controller browser UI
Default URLs:
LRBridge API:
http://127.0.0.1:17891/
Web Controller:
http://127.0.0.1:17892/
WebSocket:
ws://127.0.0.1:17890/
On a LAN, the Web Controller may also be available from another device at:
http://YOUR_PC_LAN_IP:17892/
Example:
http://192.168.1.11:17892/
Windows Firewall may ask for permission the first time LRBridge runs. Allow access if you want the Web Controller to be available from another device on the same LAN.
Ports 17890–17892 are trusted-network services. The HTTP API listens on port 17891, the WebSocket command server listens on port 17890, and the Web Controller listens on port 17892. In production, these services are reachable on available network interfaces, subject to Windows Firewall and routing; LRBridge does not bind only to localhost. The Web Controller proxies API requests from port 17892 to port 17891.
LRBridge currently has no built-in authentication or authorization. Any device that can reach these ports can potentially control Lightroom or read bridge information. Many state-changing commands use GET URLs. CORS is not authentication and does not prevent links, images, forms, redirects, or WebSocket clients from sending requests. HTTPS/TLS alone also does not authenticate LRBridge commands.
Treat LRBridge as a trusted-network-only service. Public exposure is unsupported and unsafe:
- Do not forward ports 17890, 17891, or 17892 through your router.
- Do not expose them through Caddy or another reverse proxy, a public cloud tunnel, or Tailscale Funnel.
- Avoid guest Wi-Fi, shared office networks, event networks, hotel Wi-Fi, and other partially trusted networks.
- Normal home-LAN use assumes that every device able to reach LRBridge is trusted.
If remote LAN access is needed, configure Windows Firewall to permit LRBridge only on the Private profile. Ideally, scope access to the Companion computer's IP address or to a trusted subnet. If using Tailscale, apply restrictive ACLs or grants so only intended devices can connect, and do not use Funnel. A firewall or Tailscale policy limits who can reach LRBridge; it does not add LRBridge authentication.
Information endpoints can disclose bridge or Lightroom state. Selected-photo information returned by /status or /context may sometimes contain a local file path. /diagnostics/queue exposes aggregate queue information, but not queued command arguments.
This is the recommended option for normal users.
- Download the latest Windows portable ZIP from:
https://github.com/ninoleto/LRBridge/releases
- Extract the ZIP to a writable folder.
Recommended locations:
Documents\LRBridge
Desktop\LRBridge
Avoid extracting to:
C:\Program Files
- Run:
LRBridge.exe
- Open the Web Controller:
http://127.0.0.1:17892/
- Add the included Lightroom plugin in Lightroom Classic:
lightroom\LRBridge.lrplugin
Install dependencies:
cd D:\Projects\LRBridge
npm installStart the full LRBridge Electron app:
npm startStart only the backend server:
npm run serverRun the smoke test while the backend server or app is already running:
npm testExpected result:
Smoke test passed.
Important:
Normal packaged users should run LRBridge.exe.
Developers can use npm start or npm run server.
In Lightroom Classic:
File → Plug-in Manager
Add this plugin folder from the extracted portable package:
LRBridge\lightroom\LRBridge.lrplugin
Development example:
D:\Projects\LRBridge\lightroom\LRBridge.lrplugin
Then start polling:
Library → Plug-in Extras → Start LRBridge Polling
If polling is already running, Lightroom should show:
Polling is already running.
Polling interval is stored in:
config/settings.txt
Example:
poll_interval_ms=100
The Electron app can edit this value. Lightroom reloads the polling setting automatically.
Important:
Make sure Lightroom is loading the plugin from the same LRBridge folder that is currently running.
If you test development builds, remove old LRBridge plugin paths from Plug-in Manager before adding the new one.
Open the Web Controller:
http://127.0.0.1:17892/
The Web Controller provides:
- grouped Lightroom sliders
-5-1Reset+1+5- drag strips
- Lightroom action buttons
- crop/healing/red-eye/masking tool tabs
- human help page
- visible slider feedback values
The Help button opens:
http://127.0.0.1:17892/help
Raw API help is still available through:
http://127.0.0.1:17892/api/help
and directly from the LRBridge API:
http://127.0.0.1:17891/help
The Web Controller can show Lightroom slider feedback values below supported sliders.
Feedback behavior:
The browser asks for values only for sliders currently visible on screen.
Lightroom reads those values through the LRBridge Lightroom plugin.
LRBridge sends changed values back to the browser.
This keeps feedback lighter than reading every known slider all the time.
Important:
Feedback is polling-based.
It is not true native realtime feedback.
Small delays are normal, especially while moving sliders quickly.
Lightroom Classic can ignore Auto Tone and Auto White Balance commands for a short time after Develop sliders are changed.
This is a Lightroom timing limitation. After slider movement, Lightroom may need about 2 seconds before it reliably accepts Auto Tone or Auto White Balance commands again.
Practical Web Controller fix:
If the user changes a Develop slider, Auto Tone and Auto White Balance buttons are disabled for about 2.2 seconds.
During cooldown, the Web Controller shows a short wait state before the buttons become available again.
This avoids sending Auto Tone or Auto White Balance while Lightroom is still internally processing recent slider changes.
This is a Web Controller usability workaround, not a backend API change.
The LRBridge API runs on:
http://127.0.0.1:17891/
All current stable commands are HTTP GET requests.
This is intentional for easy testing, browser use, curl use, Companion Generic HTTP, Stream Deck HTTP plugins, and future Companion plugin development.
The generic /command endpoint and the existing WebSocket JSON path accept six selection command families. A successful response means the command was validated and queued in strict FIFO order; it does not confirm that Lightroom executed it. These commands act on Lightroom Classic's current selection and do not switch modules.
Navigate the selection with direction set to next, previous, first, or last:
{ "command": "selection.navigate", "direction": "next" }http://127.0.0.1:17891/command?command=selection.navigate&direction=next
first and last are available in all modules in Lightroom Classic 13 or later. On older Lightroom Classic versions they may require the Library module; LRBridge does not switch modules automatically.
Set the flag with flag set to pick, reject, or none:
{ "command": "selection.flag", "flag": "pick" }http://127.0.0.1:17891/command?command=selection.flag&flag=pick
Set an integer rating from 0 through 5 inclusive:
{ "command": "selection.rating.set", "rating": 5 }http://127.0.0.1:17891/command?command=selection.rating.set&rating=5
Adjust the current rating with direction set to increase or decrease:
{ "command": "selection.rating.adjust", "direction": "increase" }http://127.0.0.1:17891/command?command=selection.rating.adjust&direction=increase
Set a color label with label set to red, yellow, green, blue, purple, or none:
{ "command": "selection.label.set", "label": "red" }http://127.0.0.1:17891/command?command=selection.label.set&label=red
The underlying metadata strings for these color names depend on Lightroom's active Color Label Set.
Toggle a color label with label set to red, yellow, green, blue, or purple:
{ "command": "selection.label.toggle", "label": "red" }http://127.0.0.1:17891/command?command=selection.label.toggle&label=red
none is not valid for toggle. Clear a label with selection.label.set and label: "none". All six families call the Lightroom SDK directly and have no keyboard-shortcut or AutoHotkey dependency.
GET /help
Example:
http://127.0.0.1:17891/help
Returns current endpoint information and usage notes.
GET /status
Example:
http://127.0.0.1:17891/status
Returns queue status, result status, supported sliders, and Lightroom context fields when available.
Context fields include:
activeModule
selectedPhotoKey
contextCounter
contextChangedAt
developCounter
developChangedAt
lastHeartbeatAt
These fields allow external tools, including the native Companion module, to detect when Lightroom changes module, selected photo, or Develop values.
GET /context
Example:
http://127.0.0.1:17891/context
Returns a lightweight Lightroom context object:
{
"ok": true,
"queueLength": 0,
"activeModule": "develop",
"selectedPhotoKey": "photo-path-or-id",
"contextCounter": 123,
"contextChangedAt": 1783387000000,
"developCounter": 45,
"developChangedAt": 1783387000500,
"lastHeartbeatAt": 1783387000500
}Field meanings:
activeModule
Current Lightroom module, for example library or develop.
selectedPhotoKey
Selected photo identifier. LRBridge prefers Lightroom photo UUID when available and falls back to photo path.
contextCounter
Increments when Lightroom active module or selected photo changes.
contextChangedAt
Unix timestamp in milliseconds for the last module/photo context change.
developCounter
Increments when Develop values change, including manual slider changes or resets inside Lightroom.
developChangedAt
Unix timestamp in milliseconds for the last Develop value change.
lastHeartbeatAt
Unix timestamp in milliseconds for the most recent context heartbeat received from the Lightroom plugin.
This endpoint is designed for Companion modules, browser controllers, scripts, and other external tools that need to know when slider feedback should be refreshed.
Important:
/context is polling-based.
It is not a native realtime Lightroom event stream.
Small delays are normal.
GET /sliders
Example:
http://127.0.0.1:17891/sliders
Returns slider metadata from:
config/sliders.json
AI agents should inspect this endpoint or config/sliders.json before adding UI controls or Companion actions.
GET /groups
Example:
http://127.0.0.1:17891/groups
Returns available slider groups.
GET /adjust?slider=Exposure&amount=1
GET /adjust?slider=Exposure&amount=-1
Example:
http://127.0.0.1:17891/adjust?slider=Exposure&amount=1
amount means number of Lightroom increment/decrement steps.
It is not always equal to exact slider UI points.
Typical behavior:
Exposure amount=1 roughly 0.1 Exposure
Contrast amount=1 usually 5 points
Highlights amount=1 usually 5 points
Shadows amount=1 usually 5 points
Whites amount=1 usually 5 points
Blacks amount=1 usually 5 points
Avoid very large amount values unless intentional.
GET /reset?slider=Exposure
Example:
http://127.0.0.1:17891/reset?slider=Exposure
This uses Lightroom's single-slider reset behavior through LrDevelopController.resetToDefault().
Prefer /reset over /set for returning sliders to default.
GET /reset-group?group=Basic
Example:
http://127.0.0.1:17891/reset-group?group=Basic
Queues reset commands for every slider in that group.
Use carefully.
GET /reset-all
Example:
http://127.0.0.1:17891/reset-all
Queues reset commands for all mapped sliders.
Use carefully.
GET /action?action=setAutoTone
GET /action?action=setAutoWhiteBalance
GET /action?action=selectCropTool
GET /action?action=resetCrop
Example:
http://127.0.0.1:17891/action?action=setAutoTone
Known actions are validated in:
server/commands.js
Executed by:
lightroom/LRBridge.lrplugin/Driver.lua
Note:
Auto Tone and Auto White Balance may need a short cooldown after slider changes.
The Web Controller handles this automatically.
Direct API clients should avoid sending these commands immediately after slider movement.
GET /get?slider=Exposure
GET /last-result
Important:
/get is experimental.
/last-result is a single temporary result slot.
/last-result clears after read.
Do not build Companion feedback or Web Controller feedback on this.
The Web Controller uses dedicated feedback endpoints instead of /get and /last-result.
Dedicated feedback endpoints used by LRBridge:
GET /feedback/request?slider=Exposure
GET /feedback/request-many?sliders=Exposure,Contrast
GET /feedback/request-all
GET /feedback/next
GET /feedback/result?id=...&slider=...&value=...
GET /feedback/value?slider=Exposure
GET /feedback/all
These endpoints are for LRBridge feedback polling and may change while the feedback system is still being refined.
GET /set?slider=Exposure&value=1&experimental=1
Important:
/set is experimental and unreliable in Lightroom Classic.
Use /adjust or /reset for normal control.
Without this flag, LRBridge rejects /set:
experimental=1
The current source of truth for supported sliders is:
config/sliders.json
Do not hardcode a separate list in new integrations unless there is a good reason.
Current UI groups include:
Basic
Color
Presence
Detail
Color Mixer / HSL
B&W Mixer
Effects
Calibration
Lens / Defringe
Transform
Tone Curve
Some Lightroom SDK mappings are known to be unreliable or unsolved.
Example:
LensProfileChromaticAberrationScale
This unsupported control is intentionally not shown in the Web Controller.
Bitfocus Companion can use LRBridge in two ways.
Use Companion's built-in HTTP request tools to map LRBridge commands to Companion buttons, pages, and supported hardware controllers.
This method works with tools already integrated in Companion and does not require the native LRBridge Companion module. The Builder page provides copy-ready commands for slider adjustment, slider reset, and Lightroom actions.
Recommended Companion base URL when Companion runs on the same Windows PC as LRBridge:
http://127.0.0.1:17891
For Companion running on another machine on the LAN:
http://YOUR_LRBRIDGE_PC_IP:17891
Recommended Companion actions:
/adjust?slider=Exposure&amount=1
/adjust?slider=Exposure&amount=-1
/reset?slider=Exposure
/action?action=setAutoTone
/action?action=setAutoWhiteBalance
For a full copy/paste list of Bitfocus Companion HTTP paths for every supported slider and action, see:
docs/COMPANION_HTTP_CHEATSHEET.md
When the Web Controller server is running, it is also available in the browser:
http://127.0.0.1:17892/bitfocus-companion-cheatsheet
Regenerate it after slider/action changes with:
npm run generate:cheatsheetNative Companion module repo:
https://github.com/ninoleto/companion-module-ninoleto-lrbridge
Use this path for a cleaner Companion setup with LRBridge sliders and actions available from Companion dropdown menus.
The native module is maintained as a separate project. It is not bundled inside the LRBridge portable ZIP.
If the module is not available in the official Companion build yet, use the GitHub repo for the current development version and setup instructions.
LRBridge exposes context fields through /status and /context. The native Companion module can use these fields to detect when Lightroom changes active module, selected photo, or Develop values, and then refresh Companion variables or slider feedback.
The native Bitfocus Companion module should not contain Lightroom logic.
Correct architecture:
Companion module
↓
HTTP requests
↓
LRBridge app
↓
LRBridge Lightroom plugin
↓
Lightroom Classic SDK
The Companion module should:
- configure LRBridge host/IP
- configure LRBridge port
- expose slider adjustment actions
- expose slider reset actions
- expose Lightroom action commands
- optionally load slider metadata from
/sliders - optionally load groups from
/groups - use LRBridge feedback endpoints if value feedback is added to the Companion module
- use
/contextor context fields in/statusto detect Lightroom module, photo, or Develop value changes
The Companion module should not:
- talk directly to Lightroom
- duplicate Lightroom SDK logic
- assume
/getis reliable - depend on
/last-result - include generic keyboard shortcut sending
Current module repo:
https://github.com/ninoleto/companion-module-ninoleto-lrbridge
Create a branch:
git switch main
git pull
git switch -c my-change-nameMake changes.
Run smoke test with LRBridge running:
npm testCommit:
git status --short
git add .
git commit -m "Describe change"Merge:
git switch main
git merge my-change-name
git push origin mainTag important checkpoints:
git tag v0.x.x-short-name
git push origin v0.x.x-short-nameAI agents should follow this process.
git status --short
git branch --show-current
git log --oneline -5Common files:
bridge.js
server/commands.js
server/context.js
server/sliders.js
config/sliders.json
app/controller.html
app/main.js
lightroom/LRBridge.lrplugin/Driver.lua
lightroom/LRBridge.lrplugin/Commands.lua
lightroom/LRBridge.lrplugin/FeedbackPolling.lua
lightroom/LRBridge.lrplugin/Parser.lua
lightroom/LRBridge.lrplugin/Query.lua
Do not assume:
/getis reliable./setis reliable./last-resultis a feedback system.- controller feedback is instant or event-based. It is polling-based.
/contextis a native realtime Lightroom event stream. It is polling-based.- WebSocket is preferred over HTTP.
- Lightroom SDK calls always behave immediately.
- Auto Tone or Auto White Balance can be sent immediately after slider changes.
- every item in
Driver.luashould automatically appear in the Web Controller.
Use one branch per logical change.
Examples:
web-controller-layout-fix
readme-human-ai
package-portable-windows
companion-plugin-initial-http
feedback-state-api
context-api
At minimum:
npm testFor UI changes:
npm startThen manually test:
Web Controller
Lightroom command execution
Lightroom context detection
Help page
affected slider/action
Good commit messages:
Add Lightroom context API
Add cooldown after Lightroom slider changes
Polish web controller help and remove unsupported lens control
Fix web controller startup and UI status handling
Bad commit messages:
fix
update
stuff
final
Follow these rules unless explicitly told otherwise:
- Preserve the working command path.
- Do not rewrite large files unnecessarily.
- Do not remove existing slider mappings without checking usage.
- Do not add feedback based on
/last-result. - Do not make
/seta normal production feature yet. - Keep Web Controller changes simple and browser-compatible.
- Keep Lightroom Lua code conservative.
- Prefer HTTP for Companion integration first.
- Document any known Lightroom SDK workaround.
- Use
/contextor context fields in/statusfor module/photo/develop-change refresh detection. - Always keep Git clean before and after a change.
Start packaged app:
LRBridge.exe
Start development app:
npm startStart development server only:
npm run serverRun smoke test:
npm testManual API tests:
curl.exe "http://127.0.0.1:17891/help"
curl.exe "http://127.0.0.1:17891/status"
curl.exe "http://127.0.0.1:17891/context"
curl.exe "http://127.0.0.1:17891/sliders"
curl.exe "http://127.0.0.1:17891/groups"
curl.exe "http://127.0.0.1:17891/adjust?slider=Exposure&amount=1"
curl.exe "http://127.0.0.1:17891/reset?slider=Exposure"
curl.exe "http://127.0.0.1:17891/reset-group?group=Basic"
curl.exe "http://127.0.0.1:17891/reset-all"Expected smoke test ending:
Smoke test passed.
Manual Lightroom context test:
curl.exe "http://127.0.0.1:17891/context"Then in Lightroom:
1. Switch Library → Develop.
2. Select another photo.
3. Move or reset a Develop slider manually.
Run /context again after each change.
Expected behavior:
activeModule changes when Lightroom switches module.
selectedPhotoKey changes when the selected photo changes.
contextCounter increments when module or selected photo changes.
developCounter increments when Develop values change.
lastHeartbeatAt updates while the Lightroom plugin is polling.
For packaged use, run:
LRBridge.exe
For development use:
npm startIf only the backend is needed during development:
npm run serverIf Electron or Node is stuck during development:
taskkill /IM electron.exe /F
taskkill /IM node.exe /F
npm startThe LRBridge HTTP API is not running.
Start the app or server first:
LRBridge.exe
or, for development:
npm startThen rerun:
npm testOpen manually:
http://127.0.0.1:17892/
Check:
- Lightroom Classic is running.
- A photo is selected.
- The LRBridge Lightroom plugin is installed.
- Polling has started from Plug-in Extras.
- The LRBridge app is running.
If Lightroom still does not react, switch Lightroom to Library, then back to Develop, and try the command again.
Lightroom Classic can sometimes get stuck internally after plugin reloads, crashes, or heavy SDK activity. Switching Library → Develop usually wakes the Develop controller again.
If that does not help:
1. Quit Lightroom Classic.
2. Quit LRBridge.
3. Start LRBridge again.
4. Start Lightroom Classic again.
5. Disable and enable the LRBridge plugin in Plug-in Manager.
6. Start LRBridge polling again if needed.
Make sure Lightroom is loading the correct plugin folder.
In Lightroom Classic:
File → Plug-in Manager
Remove old LRBridge plugin entries if needed.
Then add the plugin from the same LRBridge folder you are currently running:
LRBridge\lightroom\LRBridge.lrplugin
Development example:
D:\Projects\LRBridge\lightroom\LRBridge.lrplugin
This is especially important when testing portable ZIP builds and source builds on the same computer.
Check:
1. LRBridge app is running.
2. Lightroom Classic is running.
3. LRBridge plugin is loaded from the correct folder.
4. FeedbackPolling.lua is included in the plugin.
5. A real photo is selected in Lightroom.
6. Lightroom plugin polling is running.
Then test:
curl.exe "http://127.0.0.1:17891/context"If lastHeartbeatAt is null, the Lightroom plugin is not sending context heartbeats.
If activeModule changes but selectedPhotoKey is empty, select a real photo in Library or Develop and test again.
Lightroom can ignore Auto Tone and Auto White Balance shortly after slider changes.
The Web Controller has a cooldown workaround.
After changing sliders, wait until the Auto Tone and Auto White Balance buttons are enabled again.
Direct API clients should avoid sending these commands immediately after slider movement.
Expected.
Use:
/adjust
/reset
not /set.
Check these first:
1. LRBridge app is running.
2. Lightroom Classic is running.
3. LRBridge Lightroom plugin polling is running.
4. FeedbackPolling.lua is included in the plugin.
5. The Web Controller page was refreshed after starting LRBridge.
Feedback is polling-based, so a small delay is normal.
Do not use /get or /last-result as the source of truth for Web Controller or Companion feedback.
Current public package format:
Windows portable ZIP
Reason:
- no installer required
- no admin rights
- easier testing
- config can stay close to app
- easier to share with Lightroom/Companion users
- simpler rollback
Portable package layout:
LRBridge/
LRBridge.exe
config/
settings.txt
sliders.json
lightroom/
LRBridge.lrplugin/
app/
docs/
README.md
Possible future format:
LRBridge-installer-v1.0.0.exe
The installer is optional for the future. The portable ZIP is the current release format.
Useful known tags:
v0.4.31-auto-wb-cooldown
v0.4.32-readme-human-ai
v0.4.38-windows-portable-build
v0.4.41-rc2-feedback-docs
v0.5.0
v0.5.1
v0.5.2
Current public release:
v0.5.2
Stability and hardening checkpoint for the Windows portable release, preserving the existing Lightroom context API and visible slider feedback
Suggested next milestones:
v0.6.0-sdk-actions-and-controller
v0.7.0-companion-polish
v0.8.0-companion-feedback
- Lightroom plugin polling must be running.
- Web Controller feedback is polling-based, not true native realtime feedback.
- Lightroom context detection is polling-based, not a native realtime Lightroom event stream.
- Auto Tone and Auto White Balance need a short cooldown after slider movement because of Lightroom timing behavior.
- Lightroom may occasionally stop reacting after plugin reloads, crashes, or heavy SDK activity. Switching Library → Develop usually wakes the Develop controller again.
- Native Companion module lives in a separate GitHub repo and may need manual installation until it is included in official Companion builds.
/getis experimental./setis experimental.- Lightroom SDK calls can have timing quirks.
- Some Lightroom controls are not mapped.
- Some mapped Lightroom controls may be SDK-version dependent.
- Windows is the primary packaged and tested target.
- No macOS package is currently provided.
LRBridge should remain:
small
local
transparent
HTTP-first
Lightroom-controlled
Companion-friendly
easy to debug
easy to fork
The core should not become a heavy Lightroom replacement UI.
The goal is a reliable bridge:
external controller → Lightroom Classic
not a full duplicate of Lightroom's Develop panel.