# What should go in the \<license\> tag?

**URL:** <https://discourse.openrobotics.org/t/what-should-go-in-the-license-tag/56952>\
**Category:** ROS General\
**Created:** [July 25, 2026, 9:37am UTC](https://discourse.openrobotics.org/t/what-should-go-in-the-license-tag/56952 "2026-07-25T09:37:44Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![peci1](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/peci1/32/10145_2.png) [@peci1](https://discourse.openrobotics.org/u/peci1)\
**Post date:** [July 25, 2026, 9:37am UTC](https://discourse.openrobotics.org/t/what-should-go-in-the-license-tag/56952/1 "2026-07-25T09:37:44Z")

</div>

I’ve always put just “BSD” in the package.xml of our projects, mostly because it is the exact value mentioned in [https://www.ros.org/reps/rep-0149.html#license-multiple-but-at-least-one](https://www.ros.org/reps/rep-0149.html#license-multiple-but-at-least-one) . However, this value is not SPDX.

What’s the current best practice? Should we start putting SPDX identifiers into the license tag? Would it deserve a small update of REP 149?

---

<div class="post-metadata">

**Author:** ![mjcarroll](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/mjcarroll/32/35469_2.png) [@mjcarroll](https://discourse.openrobotics.org/u/mjcarroll)\
**Post date:** [July 25, 2026, 2:28pm UTC](https://discourse.openrobotics.org/t/what-should-go-in-the-license-tag/56952/2 "2026-07-25T14:28:53Z")

</div>

I think it would be ideal to move to SPDX, just because it is explicit.

When I review, I’m not particularly strict on that, but it does seem like a good opportunity for a REP update and some more automation in the [GitHub - ros-infrastructure/rosdistro-reviewer: Automation for analyzing changes to the rosdep database and rosdistro index · GitHub](https://github.com/ros-infrastructure/rosdistro-reviewer)

---

<div class="post-metadata">

**Author:** ![rkent](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/rkent/32/22727_2.png) [@rkent](https://discourse.openrobotics.org/u/rkent)\
**Post date:** [July 27, 2026, 6:36pm UTC](https://discourse.openrobotics.org/t/what-should-go-in-the-license-tag/56952/3 "2026-07-27T18:36:08Z")

</div>

The \<license\> field in package.xml is used by both rosdoc2 and rosindex to display license information on documentation pages. I tried to understand what they actually use by examining the code. Caveat: did not actually test.

rosindex takes the text from the first of possibly multiple license tags, and displays that string as the “License” in the package summary:  
`license = REXML::XPath.first(manifest_doc, "/package/license/text()").to_s`

rosdoc2 uses catkin\_package, which will concatenate strings for possibly multiple tags. rosdoc2 will include the text of a file found in the root directory with the name license.\* (ignoring case). I could not find any use of the optional ‘file’ attribute of the license tag.

So “best practice” from the perspective of current implementations of these documentation generators would be to include the string that you actually want displayed as the license summary. Plenty of packages use “Apache License 2.0” as that string for example instead of “Apache-2.0” as recommended by REP 149

I’m not saying any of this is correct or official “best practice”, only what is actually implemented.

---

<div class="post-metadata">

**Author:** ![peci1](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/peci1/32/10145_2.png) [@peci1](https://discourse.openrobotics.org/u/peci1)\
**Post date:** [July 29, 2026, 12:18pm UTC](https://discourse.openrobotics.org/t/what-should-go-in-the-license-tag/56952/4 "2026-07-29T12:18:08Z")

</div>

Thanks for the details, @rkent . I tried listing rosindex and looking at the licenses, but it seems it’s not possible in the search results page. Only package details show the license. Do you know an easy way to get a listing of all packages with their licenses?

---

<div class="post-metadata">

**Author:** ![rkent](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/rkent/32/22727_2.png) [@rkent](https://discourse.openrobotics.org/u/rkent)\
**Post date:** [July 30, 2026, 4:27pm UTC](https://discourse.openrobotics.org/t/what-should-go-in-the-license-tag/56952/5 "2026-07-30T16:27:50Z")

</div>

The license field is not included in the database that rosindex uses for search and display, so at the moment there is no way to either display or search for the license field in rosindex tables.

It would not be difficult to add that. The issue though is two:

- there are already a lot of fields displayed in the index, and adding a new one would reduce the space available for other fields, like the description.
- the database is currently distributed as a single json file that covers all packages in a single ros distro, that is downloaded by the web app as needed. The size of this file is already quite large, and adding additional fields would make it even larger.

You could certainly file an issue in rosindex asking to add this. I’d be happy to do the coding, which as I said is fairly easy if you understand rosindex. Whether this is a good idea or not, I’m not sure. As currently managed, it wold largely be a decision that @tfoote would make.

---

<div class="post-metadata">

**Author:** ![peci1](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/peci1/32/10145_2.png) [@peci1](https://discourse.openrobotics.org/u/peci1)\
**Post date:** [July 30, 2026, 10:45pm UTC](https://discourse.openrobotics.org/t/what-should-go-in-the-license-tag/56952/6 "2026-07-30T22:45:26Z")

</div>

Okay, I went ahead and created the issue: [List licenses on the search results page · Issue #650 · ros-infrastructure/rosindex · GitHub](https://github.com/ros-infrastructure/rosindex/issues/650) .

I also found a very old issue on this topic [list of all packages known to ros index with their licenses · Issue #181 · ros-infrastructure/rosindex · GitHub](https://github.com/ros-infrastructure/rosindex/issues/181) . The issue contains a script that can at least create the CSV with licenses locally.

I ran it for a few distros and here are some trimmed histograms. I’ve put in bold known SPDX identifiers. Apparently, they are there, but the majority does not follow SPDX (including all core ROS 2!).

# Noetic

BSD: 1401  
Apache 2.0: 225  
**MIT: 164**  
license not found: 88  
Apache-2.0: 42  
**BSD-3-Clause: 27**  
Apache License 2.0: 27  
GPLv3: 26  
BSD-3: 25  
LGPLv3: 19  
LGPL: 19  
GPL: 16  
Apache 2: 13  
Proprietary: 11  
GPLv2: 10  
BSD 3-Clause: 8  
**GPL-3.0-or-later: 6**  
EPL: 6

# Humble

Apache License 2.0: 764  
BSD: 650  
**Apache-2.0: 191**  
**MIT: 182**  
Apache 2.0: 169  
**BSD-3-Clause: 141**  
GPLv3: 40  
Apache 2: 33  
Apache License, Version 2.0: 31  
license not found: 21  
BSD Clause 3: 12  
LGPLv3: 11  
BSD 3-clause: 10  
Apache2: 10  
**BSD-2-Clause: 8**  
Apache-2: 7  
LGPL: 4  
**GPL-3.0-or-later: 4**  
GPL-3.0: 4  
GPL: 4  
BSD 3-Clause: 4\*\*  
MIT License: 3  
LGPL-2.1-or-later: 3  
GPL-2.0-or-later: 3\*\*  
BSD-3: 3

# Jazzy

Apache License 2.0: 713  
BSD: 601  
**Apache-2.0: 257**  
**MIT: 218**  
Apache 2.0: 156  
**BSD-3-Clause: 148**  
Apache License, Version 2.0: 34  
Apache 2: 31  
GPLv3: 30  
LGPLv3: 9  
**BSD-2-Clause: 9**  
Apache2: 9  
license not found: 7  
**GPL-3.0-only: 7**  
Apache-2: 7  
**GPL-2.0-or-later: 5**  
zlib: 4  
**LGPL-2.1-or-later: 4**  
LGPL: 4  
GPL: 4  
Public Domain: 3  
MIT License: 3  
GPLv2: 3  
GPL-3.0: 3  
BSD-3: 3  
BSD-2: 3  
BSD 3-clause: 3  
BSD 3-Clause: 3  
ALv2: 3

# Lyrical

Apache License 2.0: 585  
BSD: 511  
**Apache-2.0: 161**  
**BSD-3-Clause: 123**  
**MIT: 120**  
Apache 2.0: 94  
Apache License, Version 2.0: 35  
GPLv3: 30  
license not found: 25  
LGPLv3: 9  
**BSD-2-Clause: 9**  
Apache2: 9  
Apache-2: 7  
**GPL-3.0-only: 5  
GPL-2.0-or-later: 4**  
GPL: 4  
**MPL-2.0: 3**  
MIT License: 3  
**LGPL-2.1-or-later: 3**  
LGPL: 3  
GPL-3.0: 3  
BSD-2: 3  
BSD 3-clause: 3  
BSD 3-Clause: 3  
Apache 2: 3  
ALv2: 3  
Public Domain: 2

# Rolling

Apache License 2.0: 579  
BSD: 479  
**MIT: 117**  
**BSD-3-Clause: 114**  
**Apache-2.0: 109**  
Apache 2.0: 95  
license not found: 40  
GPLv3: 30  
Apache License, Version 2.0: 13  
LGPLv3: 9  
**BSD-2-Clause: 9**  
Apache2: 9  
Apache-2: 7  
GPL-3.0-only: 5  
GPL-2.0-or-later: 4  
GPL: 4  
**MPL-2.0: 3**  
MIT License: 3  
**LGPL-2.1-or-later: 3**  
GPL-3.0: 3  
BSD-2: 3  
BSD 3-clause: 3  
BSD 3-Clause: 3  
Apache 2: 3  
ALv2: 3  
Public Domain: 2  
**MIT-0: 2**  
LGPL: 2  
GNU Lesser Public License 2.1: 2  
**CC-BY-3.0: 2**  
**BSL-1.0: 2**

# A few tables from Gemini

I haven’t checked these tables row-by-row, but a quick look says they’re consistent with the exact data from the tables above.

 ![Code_Generated_Image](https://us1.discourse-cdn.com/flex022/uploads/ros/original/3X/5/2/52180f059236ec09974e567b1b0373ad2a1d8072.png)

And percentage of total distro packages:

 ![Code_Generated_Image](https://us1.discourse-cdn.com/flex022/uploads/ros/original/3X/2/6/26b18eba798eb5ec5fe151673340c81320d50cff.png)

And with some normalization of the license names:

 ![Code_Generated_Image](https://us1.discourse-cdn.com/flex022/uploads/ros/original/3X/7/e/7e939a5b6df3734a12093d1b0123250a3f0bc2b3.png)

 ![Code_Generated_Image](https://us1.discourse-cdn.com/flex022/uploads/ros/original/3X/0/f/0f837ef100e98ca87884e0285dab49f1e0ff769e.png)

---

<div class="post-metadata">

**Author:** ![peci1](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/peci1/32/10145_2.png) [@peci1](https://discourse.openrobotics.org/u/peci1)\
**Post date:** [July 30, 2026, 11:07pm UTC](https://discourse.openrobotics.org/t/what-should-go-in-the-license-tag/56952/7 "2026-07-30T23:07:00Z")

</div>

The takeaway for me is that using SPDX strings is okay and wouldn’t break anything. The most common are, however, the non-SPDX license names. Except for “Apache License 2.0” (the text used in OSRA packages), the top 3 most prevalent names are those from REP 149. So I’d say the content of the REP has a great influence (or correlation) on what people put there.

---

<div class="post-metadata">

**Author:** ![gbiggs](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/gbiggs/32/30361_2.png) [@gbiggs](https://discourse.openrobotics.org/u/gbiggs)\
**Post date:** [July 31, 2026, 12:49am UTC](https://discourse.openrobotics.org/t/what-should-go-in-the-license-tag/56952/8 "2026-07-31T00:49:29Z")

</div>

> [@rkent](#):
>
> - there are already a lot of fields displayed in the index, and adding a new one would reduce the space available for other fields, like the description.

This sounds like a good place to allow which columns are displayed to be dynamically configured.

> [@rkent](#):
>
> - the database is currently distributed as a single json file that covers all packages in a single ros distro, that is downloaded by the web app as needed. The size of this file is already quite large, and adding additional fields would make it even larger.

This sounds painful. Do you know why it’s implemented this way rather than pulling pages from the server as needed?

---

<div class="post-metadata">

**Author:** ![smac](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/smac/32/6763_2.png) [@smac](https://discourse.openrobotics.org/u/smac)\
**Post date:** [July 31, 2026, 6:28pm UTC](https://discourse.openrobotics.org/t/what-should-go-in-the-license-tag/56952/9 "2026-07-31T18:28:25Z")

</div>

> [@peci1](#):
>
> I ran it for a few distros and here are some trimmed histograms. I’ve put in bold known SPDX identifiers. Apparently, they are there, but the majority does not follow SPDX (including all core ROS 2!).

This would be one true exception where I would be OK with the use of AI to spam repos to update these to the correct strings. Easy bulk task with no harm but saves alot of human time (and scripting time to do the same)

---

<div class="post-metadata">

**Author:** ![rkent](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/rkent/32/22727_2.png) [@rkent](https://discourse.openrobotics.org/u/rkent)\
**Post date:** [July 31, 2026, 6:42pm UTC](https://discourse.openrobotics.org/t/what-should-go-in-the-license-tag/56952/10 "2026-07-31T18:42:14Z")

</div>

> [@gbiggs](#):
>
> This sounds like a good place to allow which columns are displayed to be dynamically configured.

Possible, but an additional complication to the UI. Even ignoring the effort to implement this, I am skeptical that the additional UI complexity is warranted. I’ll probably try an implementation showing the license field, and shrinking some other fields.

> [@gbiggs](#):
>
> This sounds painful. Do you know why it’s implemented this way rather than pulling pages from the server as needed?

I implemented this, so yes I know why it is done this way. I am a generalist hack, that is not a web designer, so I really don’t know if downloading 10MB files in the background is considered foolish behavior or not. The largest files (indexes needed for search) are about 12MB per repo, around 3MB of data after compression. Github web pages has an limit of 25 MB per file, so we have room there. At least on my system (fiber internet, fast laptop) that takes a few hundred milliseconds, usually done in the background, and is cached locally between sessions. So you really have to work hard to see any latency from this. The upside is that search and scrolling is really fast. So it seems to work, and I convinced myself it was not foolish to do this, even though I was initially skeptical. But I am still cautious.

Another side to this is that “pulling pages from the server” IIUC means server-side rendering, for example of search results. That cannot be done using Github pages, so would require a change in the infrastructure beyond a rosindex PR.

---

<div class="post-metadata">

**Author:** ![gbiggs](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/gbiggs/32/30361_2.png) [@gbiggs](https://discourse.openrobotics.org/u/gbiggs)\
**Post date:** [August 2, 2026, 11:35pm UTC](https://discourse.openrobotics.org/t/what-should-go-in-the-license-tag/56952/11 "2026-08-02T23:35:57Z")

</div>

> [@rkent](#):
>
> I really don’t know if downloading 10MB files in the background is considered foolish behavior or not. The largest files (indexes needed for search) are about 12MB per repo, around 3MB of data after compression. Github web pages has an limit of 25 MB per file, so we have room there. At least on my system (fiber internet, fast laptop) that takes a few hundred milliseconds, usually done in the background, and is cached locally between sessions. So you really have to work hard to see any latency from this. The upside is that search and scrolling is really fast. So it seems to work, and I convinced myself it was not foolish to do this, even though I was initially skeptical. But I am still cautious.

That’s a lot less data than I was imagining, and like you thought, probably worth it to get the fast search. I guess the “best” way would be to download piece-meal and cache, but that’s a lot more effort.

---

<div class="post-metadata">

**Author:** ![ct2034](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/ct2034/32/1421_2.png) [@ct2034](https://discourse.openrobotics.org/u/ct2034)\
**Post date:** [September 7, 2026, 7:06am UTC](https://discourse.openrobotics.org/t/what-should-go-in-the-license-tag/56952/12 "2026-09-07T07:06:23Z")

</div>

Hi all  
I am very happy that this discussion comes up again. I think it is very problematic that a lot of packages don’t have a proper license declaration. And I think, we should aim for all license tags using valid SPDX keys.

But we / my colleague Ralph made a lot of additional suggestions: [https://github.com/ros-infrastructure/rep/pull/347](https://github.com/ros-infrastructure/rep/pull/347)

I made a linter that checks for the SPDX-compatibility (amongst many other things):

> **[GitHub - boschresearch/ros\_license\_toolkit: Checks ROS packages for correct license...](https://github.com/boschresearch/ros_license_toolkit)**
>
> Checks ROS packages for correct license declaration

Please also see my ROSCon talk: [Licensing of ROS Packages Changes to package.xml and new tool support](https://vimeo.com/879001224/d6461b638a)

---

<div class="post-metadata">

**Author:** ![peci1](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/peci1/32/10145_2.png) [@peci1](https://discourse.openrobotics.org/u/peci1)\
**Post date:** [September 8, 2026, 6:38pm UTC](https://discourse.openrobotics.org/t/what-should-go-in-the-license-tag/56952/13 "2026-09-08T18:38:21Z")

</div>

It would be great to get this initiative moving again! Unfortunately, the rep repo is now archived, so the discussion cannot continue there.

Thanks for the toolkit. Do you also plan to turn it into a ROS package so that it could be used as a test\_depend ?

---

<div class="post-metadata">

**Author:** ![mjcarroll](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/mjcarroll/32/35469_2.png) [@mjcarroll](https://discourse.openrobotics.org/u/mjcarroll)\
**Post date:** [September 8, 2026, 6:50pm UTC](https://discourse.openrobotics.org/t/what-should-go-in-the-license-tag/56952/14 "2026-09-08T18:50:59Z")

</div>

Yep, lets do it!

I have a backburner project to audit the ros2.repos contents at least and bring those into alignment/best practices.

---

<div class="post-metadata">

**Author:** ![Katherine\_Scott](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/katherine_scott/32/4434_2.png) [@Katherine\_Scott](https://discourse.openrobotics.org/u/Katherine_Scott)\
**Post date:** [September 8, 2026, 7:03pm UTC](https://discourse.openrobotics.org/t/what-should-go-in-the-license-tag/56952/15 "2026-09-08T19:03:48Z")

</div>

> [@ct2034](#):
>
> And I think, we should aim for all license tags using valid SPDX keys.

> I have a backburner project to audit the ros2.repos contents at least and bring those into alignment/best practices.

@mjcarroll is this something we could get Bob to do?

Thinking about the M-turtle release, perhaps we should start thinking about a more structured way of running AI-delegated tasks across a subset of the packages in ROS Index and automatically issuing PRs to the maintainers. Looking down the road, we’re not too far out from being able to cut a release and automatically upgrade packages. Obviously there are token costs associated with something like this, but having the capability could come in handy at times (e.g. the ongoing build farm issues).
