Skip to content

feat(output): add --fields to limit JSON listings to named keys - #451

Merged
ryanlewis merged 2 commits into
mainfrom
feat/json-fields
Oct 10, 2026
Merged

ryanlewis merged 2 commits into
mainfrom
feat/json-fields

Conversation

@ryanlewis

Copy link
Copy Markdown
Owner

Adds --fields to limit -j output to the named keys of each row, like gh --json title,url. Without it, a 94-task anytime listing is 90,150 bytes, and agents that cap output with head -c 6000 see about 6% of it.

things anytime -a "Personal Projects" -j --fields uuid,title,projectTitle,deadline,tags

On a copy of a real database this prints 15,736 bytes instead of 90,150. On logbook it prints 129,822 bytes instead of 778,483 (with uuid,title,deadline).

Where it works

  • Every task listing: today, inbox, upcoming, anytime, someday, repeating, logbook, trash, deadlines, and list with filters.
  • search, which shares the listing code path.
  • things projects.

things show does not take it and always prints the full record. areas and tags rows are short, so they were left out.

Decisions

  • Names are the JSON keys exactly as printed, camelCase and case-sensitive, with no aliases. The todo's example project is rejected, and the error lists projectTitle among the valid names. Task listings take the task keys and projects takes the project keys. Both lists are read from the model's json tags, so a new field becomes selectable without a second list.
  • Order follows the order the user gave.
  • A requested key the full record would omit on a row (an empty omitempty value) is omitted here too. Values are cut from the marshalled record, not re-encoded, so asking for every key prints the full record byte for byte. Tests and a binary comparison against main on a copied database check this.
  • Spaces around names are trimmed and repeats dropped; the first occurrence keeps its position.
  • An unknown name fails before the database is opened, with a new error token unknown field carrying kind, unknown (the names not recognised) and valid (every accepted name).
  • An empty list (--fields "" or ,) fails with the generic error token.
  • --fields without --json fails with "needs --json". Plain output is unchanged.
  • The projection lives in internal/output/fields.go and works on the marshalled rows generically.

Docs

  • docs/content/commands.md: new section on choosing fields.
  • docs/content/agents.md: the new error token.
  • README.md: an entry in the output section and the new token.
  • internal/skill/SKILL.md: a bullet and the command synopses.

--fields on the task listings, search and projects prints only the named
JSON keys of each row, in the order given. Names are the keys as printed,
read off the model's json tags; an unknown name fails with an
"unknown field" error listing the valid ones. It needs --json, and show
keeps the full record.
@ryanlewis
ryanlewis merged commit 2106d2e into main Oct 10, 2026
10 checks passed
@ryanlewis
ryanlewis deleted the feat/json-fields branch October 10, 2026 14:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant