← back to Cli Printing Press
feat(cli): add smart-default output format to generator templates (#60)
283ab9bfeaadaa44a20b8affe68453b870682de7 · 2026-03-29 18:45:35 -0700 · Trevin Chow
Generated CLIs now auto-detect terminal vs pipe to choose output format:
- Terminal (human typing): renders tables via printAutoTable
- Pipe (agent/script): outputs JSON (existing behavior)
- --json/--agent/--csv/--compact: always machine format
This works because Claude Code, Codex, and scripts capture stdout as a
pipe, so isTerminal() returns false automatically. Humans in interactive
terminals get readable tables without needing --human-friendly.
Adds wantsHumanTable() helper and formatCompact() for large numbers.
Only applies to GET/HEAD endpoints with array responses.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Files touched
M internal/generator/templates/command_endpoint.go.tmplM internal/generator/templates/helpers.go.tmpl
Diff
commit 283ab9bfeaadaa44a20b8affe68453b870682de7
Author: Trevin Chow <trevin@trevinchow.com>
Date: Sun Mar 29 18:45:35 2026 -0700
feat(cli): add smart-default output format to generator templates (#60)
Generated CLIs now auto-detect terminal vs pipe to choose output format:
- Terminal (human typing): renders tables via printAutoTable
- Pipe (agent/script): outputs JSON (existing behavior)
- --json/--agent/--csv/--compact: always machine format
This works because Claude Code, Codex, and scripts capture stdout as a
pipe, so isTerminal() returns false automatically. Humans in interactive
terminals get readable tables without needing --human-friendly.
Adds wantsHumanTable() helper and formatCompact() for large numbers.
Only applies to GET/HEAD endpoints with array responses.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---
.../generator/templates/command_endpoint.go.tmpl | 14 +++++++++++
internal/generator/templates/helpers.go.tmpl | 29 ++++++++++++++++++++++
2 files changed, 43 insertions(+)
diff --git a/internal/generator/templates/command_endpoint.go.tmpl b/internal/generator/templates/command_endpoint.go.tmpl
index 59f198c1..c51fb786 100644
--- a/internal/generator/templates/command_endpoint.go.tmpl
+++ b/internal/generator/templates/command_endpoint.go.tmpl
@@ -191,6 +191,20 @@ func new{{camel .FuncPrefix}}{{camel .EndpointName}}Cmd(flags *rootFlags) *cobra
}
return printOutput(cmd.OutOrStdout(), json.RawMessage(envelopeJSON), true)
}
+{{- end}}
+{{- if or (eq .Endpoint.Method "GET") (eq .Endpoint.Method "HEAD")}}
+ if wantsHumanTable(cmd.OutOrStdout(), flags) {
+ var items []map[string]any
+ if json.Unmarshal(data, &items) == nil && len(items) > 0 {
+ if err := printAutoTable(cmd.OutOrStdout(), items); err != nil {
+ return err
+ }
+ if len(items) >= 25 {
+ fmt.Fprintf(os.Stderr, "\nShowing %d results. To narrow: add --limit, --json --select, or filter flags.\n", len(items))
+ }
+ return nil
+ }
+ }
{{- end}}
return printOutputWithFlags(cmd.OutOrStdout(), data, flags)
},
diff --git a/internal/generator/templates/helpers.go.tmpl b/internal/generator/templates/helpers.go.tmpl
index 87720dfc..0413e589 100644
--- a/internal/generator/templates/helpers.go.tmpl
+++ b/internal/generator/templates/helpers.go.tmpl
@@ -519,6 +519,35 @@ func suggestFlag(unknown string, cmd *cobra.Command) string {
return best
}
+// wantsHumanTable returns true when output should be a human-friendly table.
+// Smart default: terminal=table, pipe=JSON.
+// - Human in terminal: isTerminal()=true → table
+// - Claude Code/Codex bash tool: stdout piped → JSON
+// - --json/--csv/--compact/--agent: machine format → JSON
+func wantsHumanTable(w io.Writer, flags *rootFlags) bool {
+ if flags.asJSON || flags.csv || flags.compact || flags.quiet || flags.plain {
+ return false
+ }
+ if flags.selectFields != "" {
+ return false
+ }
+ return isTerminal(w)
+}
+
+// formatCompact formats large numbers compactly (e.g., 1.2M, 728K).
+func formatCompact(n int64) string {
+ switch {
+ case n >= 1_000_000:
+ return fmt.Sprintf("%.1fM", float64(n)/1_000_000)
+ case n >= 10_000:
+ return fmt.Sprintf("%.0fK", float64(n)/1_000)
+ case n >= 1_000:
+ return fmt.Sprintf("%.1fK", float64(n)/1_000)
+ default:
+ return fmt.Sprintf("%d", n)
+ }
+}
+
func printAutoTable(w io.Writer, items []map[string]any) error {
if len(items) == 0 {
return nil
← f27c735e docs(cli): add "Why These CLIs Win" section to README (#59)
·
back to Cli Printing Press
·
feat(cli): add spec_source, auth_required, client_pattern to f5716d90 →