Skip to content

td serve has no way to run a TDQ query #202

Description

@madic-creates

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:

  1. 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

  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions