How to Use gogcli --json-transform and --results-only for Clean JSON Output
Use gogcli --json --results-only to strip envelope metadata and output only the primary data array, then combine it with --select=<fields> to project specific columns for script-friendly automation.
When automating workflows with steipete/gogcli, raw JSON output often includes wrapper objects containing pagination tokens and metadata. The --json-transform pipeline, controlled by the --results-only and --select flags, lets you extract clean, focused data directly from the command line without external tools like jq.
Understanding the JSON Transform Pipeline
The transformation system is implemented in internal/outfmt/outfmt.go and orchestrated through the command context. When you invoke gogcli with JSON formatting flags, the application:
- Parses global flags in
internal/cmd/root.go - Builds a
JSONTransformstruct and injects it into the context viaoutfmt.WithJSONTransform - Applies transformations during
outfmt.WriteJSONthroughapplyJSONTransform
How --results-only Strips the Envelope
The --results-only flag removes wrapper objects like nextPageToken and results, emitting only the primary payload.
In internal/cmd/root.go, the flag is defined as:
type RootFlags struct {
ResultsOnly bool `name:"results-only" help:"In JSON mode, emit only the primary result (drops envelope fields like nextPageToken)"`
// ...
}
The flag value is stored in a JSONTransform struct:
type JSONTransform struct {
ResultsOnly bool
Select []string
}
When outfmt.WriteJSON executes, it checks for the transform and calls unwrapPrimary to extract the core data:
if t.ResultsOnly {
anyV = unwrapPrimary(anyV)
}
The unwrapPrimary function searches for common envelope keys and returns the first non-metadata field, making it ideal for piping into jq or other JSON processors.
Projecting Fields with --select
The --select flag (aliased as --fields in some contexts) projects specific fields from the JSON output, supporting dot-path notation for nested objects.
Defined in internal/cmd/root.go:
Select string `name:"select" aliases:"pick,project" help:"In JSON mode, select comma-separated fields (best-effort; supports dot paths)"`
The transformation applies via selectFields and selectFieldsFromItem, which recursively walk arrays and objects to retain only requested paths.
Practical Usage Examples
Combine both flags for automation scripts that need clean, minimal JSON.
Extract only the primary array:
gogcli drive ls --json --results-only
Output becomes a raw array without the {"files": [...], "nextPageToken": "..."} wrapper.
Project specific columns:
gogcli drive ls --json --results-only --select=id,name,size
Result:
[
{ "id": "abc123", "name": "report.pdf", "size": 12345 },
{ "id": "def456", "name": "notes.txt", "size": 678 }
]
Using the --fields alias:
gogcli calendar events --json --fields=summary,start,end
Implementation Deep Dive
The transform pipeline relies on context propagation through the command tree. In internal/cmd/root.go, the PersistentPreRun hook initializes the transform:
ctx = outfmt.WithJSONTransform(ctx, outfmt.JSONTransform{
ResultsOnly: cli.ResultsOnly,
Select: splitCommaList(cli.Select),
})
This context is passed to all subcommands. When a command calls outfmt.WriteJSON(ctx, w, v), the function retrieves the transform via JSONTransformFromContext and applies it through applyJSONTransform.
The unwrapPrimary function in internal/outfmt/outfmt.go implements the envelope removal logic by checking for standard response keys like results, files, and threads, returning the first match to eliminate pagination metadata.
Summary
- Use
--results-onlyto strip envelope metadata and output only the primary data array fromgogcliJSON responses. - Use
--select=<fields>to project specific fields, supporting dot notation for nested objects. - Combine both flags for clean, script-friendly JSON output ideal for piping into
jqor other automation tools. - The transformation pipeline is implemented in
internal/outfmt/outfmt.goand activated via context ininternal/cmd/root.go.
Frequently Asked Questions
What is the difference between --results-only and --select?
--results-only removes the outer wrapper object (containing metadata like nextPageToken) and outputs only the primary data array or object. --select filters the fields within each object, keeping only the specified properties. Use --results-only for envelope removal and --select for field projection.
Can I use dot notation with --select?
Yes. The --select flag supports dot-path notation for nested fields. For example, --select=name,owner.displayName extracts the top-level name field and the displayName property nested within the owner object.
Where are these flags defined in the source code?
The flags are defined in the RootFlags struct in internal/cmd/root.go (lines 30-39). The transformation logic is implemented in internal/outfmt/outfmt.go, specifically in the applyJSONTransform, unwrapPrimary, and selectFields functions.
Is --fields the same as --select?
Yes, --fields is an alias for --select in most contexts. The root command defines --select with aliases including pick and project, and some subcommands rewrite --fields to use the global --select mechanism for consistent JSON field projection.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →