Summary
td serve exposes no endpoint or parameter for running a TDQ query. Tested against v0.57.0.
I maintain td-gui, a local web UI that talks only to td serve. Its issue list can filter on status, type and priority and run a full-text search=, which is exactly what the API offers. It cannot express tdq queries like type = bug AND priority <= P1, even though td parses that happily on the command line, and even though td serve already evaluates TDQ server-side for a board's saved query.
What I would like
I have no preference:
GET /v1/issues?q=<tdq>, or
- a dedicated
GET /v1/query?q=<tdq>
Two additional properties that I think are important:
-
A malformed query should fail with an error message, with the parse error in the normal error envelope. td query already produces an excellent message (parse error at line 1, column 9: expected value (expected identifier, string, number, date, or special value, got EOF)); surfacing that over HTTP would let a GUI show td's own wording
-
The response should use the same issue JSON as /v1/issues, not the CLI's. If the endpoint reused td query -o json, clients would end up with two slightly different versions of the same object. One issue, td query -o json on the left and GET /v1/issues/{id} on the right:
"labels": ["search", "tdq"],
+ "available_transitions": ["start", "review", "block", "close"],
+ "parent_id": null,
- "created_at": "2026-08-18T16:43:50.384145961+02:00",
+ "created_at": "2026-08-18T16:43:50+02:00",
- "implementer_session": "",
+ "implementer_session": null,
Four differences:
- Empty fields are left out instead of being sent as null.
parent_id is present on issues that have a parent and missing on those that do not, so a client has to treat every field as optional
- An empty session id is
"" in one and null in the other. Same meaning, two values to check for
- Timestamps differ in precision, so the same issue fetched from the two places does not compare equal. Anything that caches by value, or watches
updated_at to decide whether a row changed, sees changes that did not happen
available_transitions is missing altogether, since it is computed rather than stored. A UI that renders exactly the transitions td reports would show an issue with no available actions at all
Workaround in the meantime
td-gui will shell out to td query <expr> -o ids -n 0 and join the returned ids against the issue list it already caches. It works, but it means the GUI spawns a process for something the server it is already talking to could answer, so I would rather delete it.
Summary
td serveexposes no endpoint or parameter for running a TDQ query. Tested against v0.57.0.I maintain td-gui, a local web UI that talks only to
td serve. Its issue list can filter on status, type and priority and run a full-textsearch=, which is exactly what the API offers. It cannot express tdq queries liketype = bug AND priority <= P1, even though td parses that happily on the command line, and even thoughtd servealready evaluates TDQ server-side for a board's savedquery.What I would like
I have no preference:
GET /v1/issues?q=<tdq>, orGET /v1/query?q=<tdq>Two additional properties that I think are important:
A malformed query should fail with an error message, with the parse error in the normal error envelope.
td queryalready produces an excellent message (parse error at line 1, column 9: expected value (expected identifier, string, number, date, or special value, got EOF)); surfacing that over HTTP would let a GUI show td's own wordingThe response should use the same issue JSON as
/v1/issues, not the CLI's. If the endpoint reusedtd query -o json, clients would end up with two slightly different versions of the same object. One issue,td query -o jsonon the left andGET /v1/issues/{id}on the right:Four differences:
parent_idis present on issues that have a parent and missing on those that do not, so a client has to treat every field as optional""in one andnullin the other. Same meaning, two values to check forupdated_atto decide whether a row changed, sees changes that did not happenavailable_transitionsis missing altogether, since it is computed rather than stored. A UI that renders exactly the transitions td reports would show an issue with no available actions at allWorkaround in the meantime
td-gui will shell out to
td query <expr> -o ids -n 0and join the returned ids against the issue list it already caches. It works, but it means the GUI spawns a process for something the server it is already talking to could answer, so I would rather delete it.