Pitch: Package Registry Search

Introduction

SE-0292 introduced a package registry service for the Swift ecosystem. Its future directions section identified package search as a natural extension of the registry service. This pitch proposes adding a search endpoint to the package registry specification and a corresponding swift package search subcommand to Swift Package Manager, enabling users to discover packages in registries by name, author, and other criteria.

Motivation

Today, to use a package from a registry a user must already know its exact package identifier (in the form scope.name ). There is no standardized mechanism for discovering packages within a registry.

This is a gap when comparing SwiftPM to other package ecosystems. npm provides npm search, PyPI has pip search, Cargo has cargo search, and NuGet has dotnet package search. Package discovery is a fundamental part of the package management workflow, and adding this at the registry protocol level offers benefits to both SwiftPM users as well as 3rd party clients.

SE-0292 anticipated this need in its future directions:

The package registry API could be extended to add a search endpoint to allow users to search for packages by name, keywords, or other criteria. This endpoint could be used by clients like Swift Package Manager.

$ swift package search LinkedList
LinkedList (github.com/mona/LinkedList) - One thing links to another.

$ swift package search --author "Mona Lisa Octocat"
LinkedList (github.com/mona/LinkedList) - One thing links to another.
RegEx (github.com/mona/RegEx) - Expressions on the reg.

With SE-0391 having introduced the swift package-registry publish subcommand alongside a standardized metadata schema, registries now have enough structured metadata to power search. This pitch builds on that foundation.

Proposed Solution

We propose:

  1. A new GET /search endpoint in the registry service specification
  2. A new swift package search subcommand in Swift Package Manager
  3. A structured query syntax supporting free-text search, field-specific qualifiers, and logical operators
  4. A formalized GET /availability endpoint, extending it to advertise optional capabilities.

The search endpoint is additive and therefore optional . Registries are not required to implement it, and clients must handle registries that do not support search. A registry that does not support search responds with 404 Not Found to requests to /search . Registries that do support search advertise this capability through the /availability response so that clients can discover it without trial and error.

For registries that implement search the endpoint returns a paginated list of packages matching the query. Registries are free to use whatever backend technology is appropriate for their deployment (database queries, full-text search engines, etc.) as long as they conform to the API contract defined here.

Detailed Design

Registry Service Endpoint

Capability Advertisement

Because search is an optional endpoint, registries that support it need a way to advertise this capability to clients.

Swift Package Manager already performs a GET /availability request to check whether a registry is reachable before interacting with it. This endpoint is not currently part of any proposal or the registry specification, and exists only as an implementation detail in SwiftPM's RegistryClient . However, registries today implement this endpoint since without it Swift Package Manager marks the registry as not available and throws an error. Today the client checks the status code alone and discards the response body.

This pitch formalizes GET /availability and extends it to serve as a capability discovery mechanism. A registry SHOULD respond with a 200 OK status and a JSON body listing its supported capabilities:

GET /availability HTTP/1.1
Host: packages.example.com
Accept: application/vnd.swift.registry.v1+json
HTTP/1.1 200 OK
Content-Type: application/json
Content-Version: 1
{
  "capabilities": {
    "search": {}
  }
}

Capabilities Object:

The capabilities field is a JSON object where each key is a capability name and the value describes that capability. This response can be used to declare new package registry capabilities in the future. This pitch defines one capability:

Capability Value Description
search {} The registry supports the search endpoint

The capability object is an empty object whose presence indicates that the registry supports search. Future capabilities for other features may declare more fine grained capabilities in this object.

A client SHOULD cache the capabilities response for the duration of its session.

Backwards Compatibility:

Registries that do not return a JSON body (or return an empty body) in their /availability response continue to work as they do today. A 200 status code indicates the registry is available, and the absence of a capabilities object means no optional features are advertised. Clients MUST NOT require a response body from /availability .

A registry that responds with 404 or 501 to /availability is treated as not supporting availability checks, which is the existing behaviour.

7. Search Packages

A client MAY search for packages by sending a GET request to /search.

GET /search?q={query} HTTP/1.1
Host: packages.example.com
Accept: application/vnd.swift.registry.v1+json
Query Parameters
Parameter Type Required Default Description
q String No "" The search query string
limit Integer No 20 Maximum number of results to return (1-100)
offset Integer No 0 Number of results to skip for pagination

If q is empty or omitted, the server SHOULD return the top packages ranked by score (see Result Ordering), with a default limit of 20 .

Query Syntax

The query string supports both free-text search and structured qualifiers. Free text matches against the package name, scope, and description. Qualifiers filter results to packages matching specific metadata fields. Spaces delimit separate search terms.

Multi-word values (in both free text and qualifier values) MUST be enclosed in double quotes:

GET /search?q="openapi+generator" HTTP/1.1
GET /search?q=scope:apple+"openapi+generator" HTTP/1.1
GET /search?q=author:"Mona+Lisa+Octocat" HTTP/1.1

Free-text search:

GET /search?q=networking HTTP/1.1

Qualifier syntax:
Qualifiers take the form field:value and filter results to packages where the specified metadata field matches the value. Multiple qualifiers and free-text terms may be combined in a single query.

Qualifier Metadata Field Description
scope: scope Filter by package scope
name: name Filter by package name
description: description Filter by package description
author: author.name Filter by author name
license: licenseURL Filter by license URL
pkg: N/A Search for a specific package url (purl)

Qualifier values are case-insensitive. Registries SHOULD treat qualifier values as substring matches.

The pkg: qualifier allows for searching for a specific package via purl, otherwise known as 'package url'. For example, pkg: swift/mona/LinkedList@1.1.1 searches the mona scope for a package called LinkedList with a version specifier of 1.1.1 . The type of the purl url is always swift.

Combining qualifiers and free text:

GET /search?q=scope:apple+networking HTTP/1.1

This searches for packages in the apple scope whose name or description matches "networking".

Logical operators:

The query syntax for the search endpoint is based on AIP-160: Filtering, a standard for filtering collections in APIs. AIP-160 defines a string-based filter language that supports logical operators (AND , OR , NOT /- ), comparison operators (= , != , < , > , <= , >= ), a traversal operator (. ) for nested structures, a has operator (: ) for field presence and collection membership, bare literals that match broadly across fields, and wildcards (* ) in string equality.

The search API adopts a subset of AIP-160. Free-text terms act as AIP-160 bare literals, matching across the package name, scope, and description. Qualifiers use the has operator (: ) to filter on specific metadata fields. Multiple terms separated by spaces are combined with implicit AND . The following logical operators are supported:

Operator Syntax Description
AND scope:apple networking Both conditions must match (implicit)
OR scope:apple OR scope:vapor Either condition may match
NOT NOT scope:example Exclude packages matching the condition

As in AIP-160, OR has higher precedence than AND . For example:

GET /search?q=networking+scope:apple+OR+scope:vapor HTTP/1.1

Returns packages matching "networking" in either the apple or vapor scope. This is equivalent to networking AND (scope:apple OR scope:vapor) .

GET /search?q=networking+NOT+scope:example HTTP/1.1

Registries MAY support additional AIP-160 operators (such as comparison operators for filtering by version count or score) in the future. Any extensions beyond the subset defined here MUST be documented by the registry. For more information, see the the EBNF grammar.

Fuzzy matching:

A registry MAY support fuzzy matching to handle typos and approximate search terms. For example, a query like netwrking could match packages containing "networking". The degree of fuzziness is left to the registry implementation. Registries that do not support fuzzy matching perform exact substring matching as described above.

Result Ordering

Search results are ordered by a package score . When a query is provided, the server SHOULD use query relevance as the primary ranking signal and the package score to order results with equivalent relevance. When no query is provided (empty q ), the server SHOULD return packages ordered by score alone.

The scoring model is based on the system used by the Swift Package Index, but excludes entries that score a package based on repository metrics (stars, maintainers, etc...). A package's score is computed as the sum of points across the following categories:

Category Criteria Points
Active Package is not archived/deprecated 20
Releases 5–19 tagged releases 10
20+ tagged releases 20
License License compatible with App Store 10
License incompatible with App Store 3
Documentation Has generated documentation 15
README Has a README 15
Dependencies Fewer than 3 dependencies 5
3–4 dependencies 2
Tests Has test targets 5

The score is intentionally not normalized to a percentage so that adding new scoring categories in the future does not change the meaning of existing scores.

Response

A server SHOULD respond with a 200 OK status and a JSON object containing the search results.

HTTP/1.1 200 OK
Content-Type: application/json
Content-Version: 1
{
    "results": [
        {
            "identity": "mona.LinkedList",
            "summary": "One thing links to another.",
            "versions": ["1.1.1", "1.0.0", "0.9.0"],
            "latestVersion": "1.1.1",
            "author": "Mona Lisa Octocat",
            "licenseURL": "https://github.com/mona/LinkedList/blob/main/LICENSE",
            "url": "https://packages.example.com/mona/LinkedList"
        },
        {
            "identity": "mona.RegEx",
            "summary": "Expressions on the reg.",
            "versions": ["2.0.0", "1.5.0"],
            "latestVersion": "2.0.0",
            "author": "Mona Lisa Octocat",
            "licenseURL": "https://github.com/mona/RegEx/blob/main/LICENSE",
            "url": "https://packages.example.com/mona/RegEx"
        }
    ],
    "total": 42,
    "offset": 0,
    "limit": 20
}

Results Object:

Field Type Required Description
identity String Yes The package identifier in scope.name format
summary String No Short description of the package
versions [String] No Available versions, ordered by precedence
latestVersion String No Highest precedence release version
author String No Package author name
licenseURL String No URL of the package's license document
url String No URL to the package's releases on this registry

Pagination:

Field Type Required Description
total Integer Yes Total number of matching packages matching the query
offset Integer Yes Current offset
limit Integer Yes Limit applied to this response

The server SHOULD include Link headers for pagination when additional results are available:

Link: </search?q=networking&limit=20&offset=0>; rel="first",
</search?q=networking&limit=20&offset=20>; rel="next",
</search?q=networking&limit=20&offset=40>; rel="last"
Errors
Status Description
400 Bad Request Invalid query syntax or parameter values
404 Not Found Search is not supported by this registry
429 Too Many Requests Rate limit exceeded

Error responses use RFC 7807 problem details:

{
"detail": "search query too long"
}

A server that does not support search SHOULD respond to requests to /search with 404 Not Found . A client MUST handle the case where a registry does not implement the search endpoint.

Swift Package Manager Subcommand

swift package search

A new swift package search subcommand enables searching configured registries from the command line.

SYNOPSIS

swift package search [<query>] [--scope <scope>] [--author <author>]
[--license <license>]
[--limit <limit>] [--offset <offset>]
[--registry <url>] [--json]

OPTIONS

Option Description
Free-text search term
--scope Filter by package scope
--author Filter by author name
--license Filter by license URL substring
--limit Maximum results to return (default: 20)
--offset Skip N results for pagination (default: 0)
--registry Search a specific registry
--json Output results as JSON

If --registry is not specified, the client searches the default registry, or all configured registries if no default is set.

EXAMPLES

Search for packages by name:

$ swift package search LinkedList
mona.LinkedList - One thing links to another. (v1.1.1)

Search by author:

$ swift package search --author "Mona Lisa Octocat"
mona.LinkedList - One thing links to another. (v1.1.1)
mona.RegEx - Expressions on the reg. (v2.0.0)

Search with a scope filter:

$ swift package search networking --scope apple
apple.swift-nio - Event-driven network application framework. (v2.60.0)
apple.swift-http-types - HTTP type definitions. (v1.0.3)

Search across multiple scopes:

$ swift package search "networking scope:apple OR scope:vapor"
apple.swift-nio - Event-driven network application framework. (v2.60.0)
vapor.vapor - A server-side Swift HTTP framework. (v4.92.0)

JSON output:

$ swift package search LinkedList --json
{
    "results": [
        {
            "identity": "mona.LinkedList",
            "summary": "One thing links to another.",
            "latestVersion": "1.1.1"
        }
    ],
    "total": 1,
    "offset": 0,
    "limit": 20
}

The subcommand constructs a query string from the provided options and sends it to the registry's /search endpoint. Named options are translated to their corresponding qualifiers (e.g., --author "Mona" becomes author:Mona in the q parameter).

If the registry has previously advertised search support via its /availability response, the client sends the search request to the advertised URL. If the registry did not advertise search support (no capabilities object, or no search key), the client informs the user:

$ swift package search LinkedList --registry https://nosearch.example.com
error: registry at 'https://nosearch.example.com' does not support search

Searchable Metadata

The search endpoint leverages package metadata submitted during the swift package-registry publish flow defined in SE-0391. The following metadata fields are searchable:

Search Field Metadata Source
Package scope Package identifier
Package name Package identifier
Description metadata.description
Author metadata.author.name
License metadata.licenseURL

Registries MAY index additional metadata beyond what is defined here.

Security

Search results MUST respect the same access controls as other registry endpoints. If a client is not authorized to access a package, that package MUST NOT appear in search results.

Registries SHOULD implement rate limiting on the search endpoint to prevent abuse. When rate limited, the server responds with 429 Too Many Requests and a Retry-After header as specified in the registry service specification.

Search queries MUST be sanitized by the server to prevent injection attacks against the underlying search backend. Registries SHOULD impose reasonable limits on query string length.

Impact on Existing Packages

This is a purely additive change. The search endpoint is optional and existing registries are unaffected. A registry that does not implement /search simply returns 404 Not Found , and clients handle this gracefully by informing the user that the registry does not support search. No changes to existing endpoints or package formats are required.

Alternatives Considered

Query string vs. individual query parameters

An alternative design would use individual query parameters for each searchable field rather than embedding qualifiers in the q parameter:

GET /search?name=LinkedList&author=Mona&scope=mona

This approach is simpler to parse on the server but less flexible. The qualifier syntax field:value within a single q parameter follows the conventions established by GitHub, npm, and other search APIs. It allows users to construct queries naturally in both the CLI and API contexts, and is extensible without requiring API changes when new searchable fields are added.

Returning full release metadata in search results

Search results could include the complete release metadata (manifests, checksums, signing information) for each result. This was rejected because search results should be lightweight. Clients that need full metadata can fetch it from the existing GET /{scope}/{name}/{version} endpoint after discovering a package through search.

Future Directions

Result Sorting Options

Registries could support alternative sort orders beyond the default score-based ranking. A sort query parameter could be added:

GET /search?q=networking&sort=recent
GET /search?q=networking&sort=name

Package Collections Integration

Search results could be used to populate SE-0291 Package Collections, enabling users to curate collections based on search queries.

Suggested Packages

Registries could provide a suggestions endpoint for autocomplete-style search, returning results as the user types.

Platform and Swift Version Filtering

As the ecosystem evolves, filtering packages by supported platforms or Swift language version could be valuable:

GET /search?q=networking+platform:linux+swift:6.0

This would require packages to declare platform and Swift version support in a machine-readable way.

18 Likes

I like this proposal, though I've not really had a chance to use package registries as there aren't many out there. I've used similar functionality in homebrew, pip, and npm. It's handy, though not really critical as you can always do a web search.

Note that PyPI actually permanently disabled the pip search command due to request volume: Python Infrastructure Status - PyPI XMLRPC Search Disabled .


I am curious about the package score:

  1. What's the point of requiring a certain scoring model, rather than just publishing it as "one possible implementation" guidance? Seems like there's no interoperability benefit from using the same scoring model, since the score isn't returned in the JSON. E.g. if Swift Package Index or GitHub had a registry, why shouldn't they be able to use stars, maintainers, etc. in their scores?
  2. App Store license compatibility seems like a weird choice as part of the score. While many people use Swift for iOS apps, that’s really not the only use. And I’m not sure the spec should be playing license favorites. I think “has a license” makes sense as part of the score, but not much beyond that.

And then one note on the qualifiers: I couldn't find precise documentation on the licenseURL property (SE-0391 just says "URL of the package release's license document.") but I'm interpreting it to be the package's license page (e.g. swift-foundation/LICENSE.md at main · swiftlang/swift-foundation · GitHub for swift-foundation). I don't think that's very useful to filter on, since most packages will have a unique value. So I think the “license:” qualifier shouldn’t filter licenseURL. “license:” seems like it should surely be an optional capability which identifies common licenses by a short ID like “MIT” or “GPLv3” rather than the unique URL. Identifying licenses seems like a big ask for registries which aren't already doing that, so I probably wouldn't require it.


And finally: I think that the proposed swift package search command is of limited utility without the ability to get more information from the registry about the package (e.g. brew info or npm info). If I search for a package I usually need more information than the short description make a decision about which I want to use. I probably want to get the project's home page and/or repo URL at least.

2 Likes

Thanks for this great feedback. You've hit on a lot of good issues I think we need to address in the pitch, I'll try to go through them each in turn.

What's the point of requiring a certain scoring model

Swift is a bit unique in the package registry landscape because users can configure one or more registries either globally or per package. Having a consistent score across different registries means results can be sorted consistently on the client when aggregating results from different registries.

You did hit on an important omission in the pitch; the score should be included in the JSON to facilitate this. I also think we could soften the language so that its clear that scoring is not strictly required, but it if it is present it can act as the primary value for clients to sort on.

App Store license compatibility seems like a weird choice as part of the score

I lifted the scoring system pretty much verbatim from the one used by the Swift Package Index, however it looks like just last week they changed the scoring system to score based on whether the licence is a known OSS licence or not, instead of whether its app store compatible. This leads in to the next point...

I couldn't find precise documentation on the licenseURL property ... I don't think that's very useful to filter on...

This list of searchable metadata comes from the package-metadata.json that is provided when doing a swift package publish. licenseURL is in there but I agree its not useful to search on. Its also a larger ask for package registries to open up a package, parse the licence and try and determine the actual licence type.

A goal was for the /search endpoint to be able to be offered with just the information provided during a swift package publish; no introspection required on the server. I think I'll remove licenceURL from the list of searchable metadata and add a section to Future Directions that covers adding licence sniffing to Swift Package Manager and supplying the licence type as part of the package-metadata.json.

I think that the proposed swift package search command is of limited utility without the ability to get more information from the registry about the package (e.g. brew info or npm info).

You're right, but I think this should be a follow on pitch. I think today the information that we could provide in a swift package info command would pretty much mirror what comes back in a search record. We'd need to give some thought in to what a swift package info record would contain, and if that would require more additions to the metadata extracted during package publish.

2 Likes

This is a great pitch. I have never work with registries, so my please let me know if my comments are not application.

Since SwiftPM can configure multiple registries, it may be work indication how swift package search will "show" the package the query finds hits in multi configured registries.

if multiple registries are configured, should the output (text and json) contains registry information?

But maybe I'm missing a fundamental piece on how SwiftPM interacts with registries.

Thank you for your thoughtful responses!

Swift is a bit unique in the package registry landscape because users can configure one or more registries either globally or per package.

I'm not sure this is quite true - pip has --index-url & I'm pretty sure npm has a similar option. From a brief google of ecosystems I'm less familiar with: cargo, maven, and ruby's bundler all seem to have options. I think where we differ is not having a clear default registry that most people use.

Is it expected usage for people to have many registries enabled & be searching all of them? In that case, I'd expect swift package search to have a flag which enables search all of them even when a default registry is set.

Having a consistent score across different registries means results can be sorted consistently on the client when aggregating results from different registries.

If you're going to include it in the JSON for merging results, then I think it makes sense to specify how the score is calculated so that results from different registries can be compared.

If you're still interested in giving registries some flexibility, you could consider adding a "registry-determined" component to the score. Then e.g. one that uses GitHub could use stars for that component & someone else could use whatever they like. So if, say, the max value of the registry-determined component was 10, then registries could use 1-10 to indicate their ranking & registries without a custom ranking could use 5. But I don't think any of this is strictly necessary.

I think I'll remove licenceURL from the list of searchable metadata and add a section to Future Directions that covers adding licence sniffing to Swift Package Manager and supplying the licence type as part of the package-metadata.json.

:+1:

Its also a larger ask for package registries to open up a package, parse the licence and try and determine the actual licence type.

I agree with this; I wasn't suggesting that adding a license-type scope is in any way necessary. But it does ask the question: if we can't expect registries to categorize licenses, how can we expect them to include App Store-compatibility or OSS-compatibility in the score?

I think today the information that we could provide in a swift package info command would pretty much mirror what comes back in a search record. We'd need to give some thought in to what a swift package info record would contain, and if that would require more additions to the metadata extracted during package publish.

I think it's fine to defer this to another pitch. But I want to push back a little on the idea that we don't have anything useful to show. SE-0391 contains readmeURL, description, repositoryURLs, author.name, author.organization.name , and author.organization.url, all of which I think might be helpful info. In particular I just want some way to learn more about a particular package. I think listing recent package release versions (already in the spec) could also be helpful. A "project homepage URL" and "changelog" info for versions (which don't already exist) would certainly be helpful but I don't think necessary for an initial version.

1 Like

if multiple registries are configured, should the output (text and json) contains registry information?

I think it could be useful to have an optional property in the response that is computed by SwiftPM and shows the registry URL that package is coming from, if there are multiple registries configured.

Is it expected usage for people to have many registries enabled & be searching all of them

I envision there being a common pattern in registries.json like the following, where the default registry is public and a company has a private one serving their packages:

{
  "version": 1,
  "registries": {
    "[default]": {
      "url": "https://packages.example.com"
    },
    "initech": {
      "url": "https://registry.initech.com",
      "supportsAvailability": true
    }
  }
}

I think a search should search all of the configured registries by default. I propose a --registry flag to swift package search in the pitch that narrows the scope to the single supplied registry. To @bkhouri's point I do think if search results are aggregated over multiple registries then the results should show what registry a record belongs to.

In particular I just want some way to learn more about a particular package.

I agree this is valuable. All of the fields you mention could come by default since that information is already stored in package metadata. To make it more useful individual registries could augment the response with optional fields. I could envision a registry operating the way Swift Package Index does, pulling more metadata out of packages by actually building them and getting things like platform support, detailed information about the repo (stars, contributors, etc) and including it in this response. However now I'm bikeshedding a new pitch...

1 Like

Ah so I think that's my point of confusion. The proposal says this instead:

Which says to me "not all registries will be searched if a default is defined."

FWIW I think I agree that searching all registries by default makes sense.

This should be changed to:

If --registry is not specified the client searches all configured registries.

1 Like

Thanks for your work on this @plemarquand, this will be a huge step forward for package discovery.

I'd go further than @willft and suggest leaving scoring and search implementation details out of the spec entirely. Even at SPI, the score is a fairly inconsequential part of search ranking and only comes into play as a tiebreaker when two packages have an exact tie on query relevance.

Mandating a specific scoring model across registries doesn't buy us much, and it locks every registry into a model that one implementation happens to use today. Score can be useful for many other reasons, and I am a fan of exposing it to the public (for example, here: https://swiftpackageindex.com/swiftlang/swift-testing/information-for-package-maintainers#package-score), but it’s a tiny part of search.

I'd suggest the spec say nothing about how registries rank or match results. SPI’s implementation could be referenced as one possible implementation, but only as an example.

Some other more minor points:

  • This is probably out of scope, but the search endpoint risks being abused as a way to enumerate every package in a registry. This is exactly the pattern that led PyPI to permanently disable pip search. Rate limiting helps, but it might be worth considering a separate endpoint for clients that genuinely need to enumerate the registry (mirroring, indexing, etc.), so that search can be tuned for search and enumeration can be tuned, or gated, separately.
  • For all the reasons mentioned above about scoring, I think an empty q should return an empty set. If we want “discovery” APIs, they could be on different endpoints rather than tacking on some discovery into the search API.
  • Mixing the double quotes and + syntax in the search queries might need a little more thought. The pitch uses + as a term separator (URL-encoded space) outside quotes, but the examples "openapi+generator" and author:"Mona+Lisa+Octocat" also seem to use + as a space inside the quotes, where strictly it should be a literal + character. I could see this working as "openapi%20generator" (with quotes) or openapi+generator (without), but + probably shouldn't mean two different things depending on whether it's inside quotes.
3 Likes

Thanks for all the great feedback!

I'd go further than @willft and suggest leaving scoring and search implementation details out of the spec entirely

You raise a good point, I think omitting scoring from the pitch is OK and we can leave ordering.

I will make one point in favour of it, which is that it can help with typosquatting. Imagine I create a malicious package called vapour that is trying to trick all those developers out there that use the Queen's english. With a scoring system an exact search for vapour would still rank vapor higher, since it has a ton of stars/downloads/maintainers/whatever. While vapour gets extra points for being an exact match, it still gets beat out by the real one because it scores higher on all the other metrics.

However I think mandating the same scoring system across registries just so that results can be consistently aggregated when searching across multiple registries is probably too much complexity for too little benefit.

For all the reasons mentioned above about scoring, I think an empty q should return an empty set.

Valid, I agree.

it might be worth considering a separate endpoint for clients that genuinely need to enumerate the registry

I think this is out of scope for this Pitch, but is a good idea.

Mixing the double quotes and + syntax in the search queries might need a little more thought.

You're right, I'll clean this up for the Proposal. Using + as space is confusing.

1 Like

I only fill repositoryURLs as everything else is redundant and just bound to get out of sync.

1 Like