Workspace tweaks for JOSM. All menu-driven features live under More tools → BetterWorkspace (each item is also a separate, shortcut-bindable, toolbar-registerable action — assign a key or add it to your toolbar via JOSM's own Preferences → Shortcuts / toolbar customization), in this order:
- Load a HOT Tasking Manager project's task grid as a data layer — including private and draft projects you have access to — via your personal TM API token.
- Toggle the visibility of the currently active layer - handy as keyboard shortcut
- Multi-validation prep — adding tasks into todolist (select all ways in the layer below the active one and add them to the todo plugin's list, for paging through task borders during validation) - also handy as keyboard shortcut
- Manage validation rules — additional validator checks that wouldn't be possible using only validator rules (landuse/place/highway QA), individually toggled on/off, split into fast "Regular" and heavier "Possibly slow" groups.
- Quick TMS — Quickly load TMS link as imagery layer without the need of storing it in your settings
- Load Esri Imagery Date Grid — loads Esri World Imagery's real per-tile acquisition dates for the current view as a data layer
- First time you run this feature it will create "BetterWorkspace: Esri Imagery Dates" map paint style. You can right click it in the Map Paint Styles window and change the colors in Style settings
- Secondary view-only map window that tracks the main view, with its own independent set of active layers.
- Batch download v2 — downloads OSM data into a new layer around every selected feature (or every feature in the active layer if none are selected), one at a time in the background with no popups stealing focus — see Batch download v2 below.
- Arrange the docked side panels, remembered across restarts.
Separately, it also adds a "Select objects" entry to the right-click menu of JOSM's built-in Authors panel (which otherwise only offers "Copy"), and a "Create filter from Key/Value" entry to the right-click menu of the Tags/Memberships panel, next to JOSM's own "Search Key/Value" — same key/value expression, but added as a new row in the Filters panel instead of running a search. If you also have the standard todo plugin (or a compatible fork) installed, marking an item done there keeps it visible in the list instead of removing it — see Keeping completed todo items visible below. It also automatically applies a HOT Tasking Manager project's imagery offset when you lock a task and open it in JOSM — see HOT Tasking Manager imagery offset below.
BetterWorkspace
├── Load HOT TM Task Grid...
├── Set HOT TM API Token...
├── Toggle active layer visibility
├── Multi-validation prep (add task borders to todo)
├── Manage validation rules...
├── ───────────────
├── Quick TMS...
├── Load Esri Imagery Date Grid...
├── Secondary Map View
├── ───────────────
├── Batch download v2
└── Arrange side panels...
This plugin talks to two external HTTP APIs - the HOT Tasking Manager API and Esri's World Imagery "Citations" service. Both are called only in direct response to a menu click: nothing in this plugin polls, auto-refreshes, retries in a loop, or runs on any kind of timer or schedule.
| HOT Tasking Manager | Esri World Imagery (Citations) | |
|---|---|---|
| Triggered by | Load HOT TM Task Grid... | Load Esri Imagery Date Grid... |
| Requests per click | 1 | 1 |
| Query scope | One project's task grid | Current map view only |
| Client-side size cap | n/a (a task grid is already small) | refused outright above 50 km across the view |
| Server-side cap | n/a | Esri caps every response at 100 features (maxRecordCount) regardless - detected via exceededTransferLimit and reported to the user rather than silently shown as an incomplete grid |
| Fields requested | n/a (task grid GeoJSON as-is) | only the 6 fields actually used, via outFields=... - never outFields=* |
| Timeouts | 15s connect / 30s read | 15s connect / 30s read |
| Identifies itself | User-Agent: BetterWorkspace-JOSMPlugin/<version> |
same |
The 50 km cap on the Esri query is doing two jobs at once: it keeps each request small, and it avoids the alternative failure mode of a large view silently coming back truncated at Esri's 100-feature limit and being misread as "no recent imagery here" - see Esri Imagery Date Grid below for the full reasoning.
Your HOT TM API token (see below) is the only credential this plugin ever sends anywhere, and it's only ever sent to the HOT Tasking Manager API itself, over HTTPS.
- Get your personal token from the TM website: tasks.hotosm.org → Settings → enable "Expert mode" → API Key card. Pasting the copied "Token xxx" text or just the token itself both work. It's stored via JOSM's own preferences, the same mechanism JOSM uses for its own OSM OAuth token.
- The token expires roughly 7 days after your last TM login — re-copy it periodically.
- Load HOT TM Task Grid... works for public projects too (no token needed), so it's a drop-in replacement for the Ctrl+L workflow either way, and remembers the last project ID you entered.
When a project manager sets an imagery offset for a TM project, only iD applies it automatically
today - JOSM users locking a task and opening it in JOSM don't get it (a stopgap until JOSM core's
/imagery remote-control command supports an offset param; see
hotosm/tasking-manager#6873). This plugin
closes that gap: when TM's "open in JOSM" sequence brings in the task's data and imagery, it applies
the project's configured offset via JOSM's own imagery-offset mechanism - the same thing as picking
a bookmark from an imagery layer's right-click Offset menu, just automatic. A short notification
confirms when it's applied. Projects with no offset configured are unaffected.
There are two ways to set the offset, checked in this order:
- Appended to the imagery URL itself, in TM's Imagery tab - add
#offset=east,north(in meters) to the very end of your custom TMS/WMS URL, e.g.https://example.com/{z}/{x}/{y}.png#offset=-12.34,9.87. This is inert for actual tile loading - a URL fragment is never sent to the tile server, only ever read client-side - so it doesn't affect the imagery itself. Use this for custom imagery projects. - TM's own "Additional iD URL parameters" field, in the project's Metadata tab - e.g.
disabled_features=buildings&offset=-10,5. This is the field TM already uses for iD; the plugin reads it via the TM API, which for a private project needs your personal HOT TM API token (see below) - and since that token expires roughly every 7 days, this option is friction for private projects specifically. Fine for public projects, or if you can't change the imagery URL, when using free public imagery like Bing or Esri.
Turn the whole feature off via the betterworkspace.tmimageryoffset.enabled preference (on by
default) in JOSM's own Preferences → Advanced Preferences.
TM hands a custom imagery URL to JOSM as the layer's title too, so by default the raw URL ends up as
the changeset source tag on upload. Add name=... to the URL fragment to use a readable name
instead, e.g. https://example.com/{z}/{x}/{y}.png#offset=-12.34,9.87&name=Drone imagery 2026 - or
without an offset, https://example.com/{z}/{x}/{y}.png#name=Drone imagery 2026. A second #
(...#offset=-12.34,9.87#name=Drone imagery 2026) works too. The name is used both as the layer's
title in the Layers panel and as the upload source tag. This works independently of the offset preference above.
Batch download v2 downloads OSM data into a new layer around every selected feature in the active layer, or every feature in it if none are selected. No dialog - it starts immediately, with no buffer and always into a fresh "Batch downloaded" layer. A standalone node that's already part of another selected way/relation is skipped, since downloading around it individually would just be redundant. With more than 100 features you'll get a heads-up that it may take a while before it starts.
Same idea as the separate josm-batch-downloader
plugin, with one difference: it runs quietly in the background. Each per-feature
download uses JOSM's NullProgressMonitor instead of leaving the monitor unset. An unset monitor
makes JOSM fall back to its own PleaseWaitProgressMonitor popup for every single download — with
one download per feature, that means the JOSM window keeps grabbing focus and coming to the front for
the whole run, making the rest of your computer unusable in the meantime (this is what
josm-batch-downloader does, and why). NullProgressMonitor has no UI at all, so only this action's
own status dialog is shown, and you can keep working in other windows while it downloads.
Its progress dialog has a Cancel button (also triggered by the window's close button or Esc) - aborts whichever download is currently in flight, disposes the dialog, and tells you how many features got downloaded before you stopped it. Whatever was downloaded up to that point stays in the new layer.
Quick TMS... previews a TMS layer without going through JOSM's own Preferences → Imagery → +TMS, which always writes the new entry into your persisted imagery list whether you wanted to keep it or not.
- By default the layer only lives in the current session — closing it or quitting JOSM just drops it, nothing touches your saved imagery list. Checking Pin to my imagery list before clicking Add Layer adds it to your list of imagery same as if you would go Preferences → Imagery → +TMS.
- The URL field requires a zoom placeholder (
{zoom}or{z}) plus both{x}and{y}— checked live as you type, with the "Add Layer" button disabled until it's satisfied. - Name is optional — leaving it blank uses the URL as the layer's name.
- A generic TMS URL has no known coverage area, so JOSM's own right-click Zoom to layer would otherwise zoom out to the whole world. Quick TMS captures your current map view as the new layer's bounds when you click Add Layer, so a later Zoom to layer returns you to roughly where you were looking instead — so add the layer while already looking at roughly the right place.
Load Esri Imagery Date Grid... queries Esri's own "Citations" footprint
layer (the same metadata source esri-imagery-date-finder
uses) for the current map view, and adds the footprints as a data layer - click any polygon to see its
real acquisition date (date, e.g. 2025-09-06) plus resolution, accuracy and source in the tags panel.
- Scoped to the current view and capped at 50 km across - Esri's own server already caps each query at 100 footprints, so a much larger area would silently come back incomplete rather than heavier to fetch. Zoom in and retry if asked.
- If a (still <50 km) view is dense enough to hit that 100-footprint cap anyway, you're warned that the grid is incomplete rather than shown a silently partial one.
- Each footprint's date is also drawn directly on the map (not just in the tags panel), via a small map paint style the plugin registers the first time this runs (Preferences → Map Paint Styles as "BetterWorkspace: Esri Imagery Dates"). It visualise attribute "date" for any object with attribute "SRC_RES" so should be safe to leave enabled permanently
- Text and outline color are both user-adjustable from Map Paint Styles window → right click → Style settings
(defaults: white
#FFFFFFtext, orange#FF9933outline)
A date only applies at the zoom level its footprint covers. World Imagery isn't one uniform
image - it's a resolution-stratified mosaic, so the same spot commonly has several overlapping
footprints with different dates, each only the actual visible imagery within its own zoom range
(e.g. a high-resolution capture that replaces an older, undated low-res basemap only once you're
zoomed in past a certain level - confirmed directly against Esri's service, which exposes this as
MinMapLevel/MaxMapLevel). This plugin tags that range as esri_zoom_min/esri_zoom_max
instead (replacing Esri's raw fields rather than duplicating them, so there's one place to look,
not two names for the same thing).
By default the on-map label is still just the plain date, e.g. 2025-12-20, to keep the map
uncluttered. Turn on Display zoom levels (Map Paint Styles window → right click this style →
Style settings) to show the zoom range alongside it instead, e.g. 2025-12-20 (z=12-19) - handy
when you suspect the imagery differs by zoom and want to check without opening the tags panel for
every footprint.
A second, view-only map window with its own checkbox list of layers, opened/closed via Secondary Map View. It stays in sync with the main view's position/zoom, but has its own independent set of which layers are shown — checking a box here never changes what's shown in the main Layers panel, and vice versa.
One exception: Toggle active layer visibility (see above) also flips that same layer's checkbox here, if this window is open, so that one shortcut affects both windows at once. Any other way of changing a layer's visibility (the main Layers panel, or a checkbox here) still only affects the one window it was changed in.
JOSM's bottom status bar gets an extra area field right after distance, so it reads latitude,
longitude, heading, angle, distance, area, name. It shows the area of the selected closed ways (or,
with only relations selected, multipolygons), and -- when there's nothing with an area. It's
calculated exactly like the measurement plugin's Selection Area, so both always show the same
number.
Multi-validation prep looks at the layer directly below the currently active one in the Layers panel, switches to it, selects all its ways, hands them to the todo plugin, then switches back. Works with the standard "todo" plugin or any compatible fork; if no matching todo dialog is found, it throws a warning instead of failing silently.
Normally, marking an item done in the todo plugin removes it from the list entirely. This plugin changes that so a marked-done item instead:
- stays in the list, at its original position, grayed out
- has the list automatically select and scroll to the next item, without circling back to the first (already-done) item once you mark the last one
- keeps the "done/total" count in the todo list's title accurate
You can turn this feature off by changing status of betterworkspace.todo.keepdone preference (on by default) in JOSM's own
Preferences → Advanced Preferences
Manage validation rules... opens a dialog to individually enable/disable extra validator checks this plugin adds, grouped into:
- Regular (fast, always cheap to run): Residential with multiple place nodes, Hamlet/village building count mismatch.
- Possibly slow (heavier geometry checks over many objects at once - may take noticeably longer on large downloads or slower machines; handy for third-pass validation, but not limited to it): Highway classification mismatch, Residential area without a highway, Overlapping landuse areas, Building overlapping residential landuse.
All of them are off by default - turn on whichever you want from the dialog, one checkbox each, applied immediately, no separate Apply step. Hover a rule for its full description.
This plugin was built with the help of Claude, Anthropic's AI chatbot, used throughout for design, implementation, and debugging.
| File | Purpose |
|---|---|
BetterWorkspacePlugin.java |
Entry point, builds the "More tools → BetterWorkspace" menu |
ArrangePanelsDialog.java / PanelReorderer.java |
Reorder the docked side panels; order remembered across restarts |
LoadTmTaskGridAction.java |
Loads a HOT TM project's task grid, including private/draft projects |
TmImageryOffsetSync.java |
Auto-applies a HOT TM project's imagery offset when its task is opened in JOSM |
SetTmApiTokenAction.java / TmApiToken.java |
Save/use your personal HOT TM API token |
ToggleActiveLayerAction.java |
Toggle the visibility of the currently active layer |
MultiValidationPrepAction.java / TodoBridge.java |
Select the layer-below's ways and hand them to the todo plugin |
TodoBehaviorSync.java |
Keeps marked-done todo items visible instead of removed - see Keeping completed todo items visible |
QuickTmsAction.java / QuickTmsDialog.java |
Preview a session-only TMS imagery layer |
LoadEsriImageryDatesAction.java |
Loads Esri World Imagery's real acquisition-date footprints for the current view |
ProgressDialog.java |
Shared "please wait" dialog used by both HTTP-loading actions above |
SecondaryMapViewAction.java / SecondaryMapViewFrame.java |
A second, view-only map window |
AuthorSelectHook.java |
Adds "Select objects" to the built-in Authors panel's right-click menu |
CreateFilterFromTagAction.java |
Adds "Create filter from Key/Value" to the built-in Tags/Memberships panel's right-click menu |
ManageValidationRulesAction.java / ValidationRulesDialog.java |
Dialog to toggle the validation rules below on/off |
validation/BwValidationConfig.java / BwTest.java |
Registry, on/off persistence, and shared base class for the validation rules |
validation/ResidentialMultiplePlaceNodes.java, HamletVillageTaggingMismatch.java, HighwayClassificationMismatch.java, ResidentialWithoutHighway.java, OverlappingLanduseAreas.java, BuildingOverlappingResidentialArea.java |
The validation rules themselves |
validation/BwResidentialArea.java / BwLanduseArea.java |
Shared geometry helpers (ring-stitching, point-in-polygon, hole-aware overlap) used by the rules above |