# cli: standardize on printJSON for indented JSON output

`9346b6f`·

Soph·2w ago·9 files·+26 added/-66 removed

Package cli had five copies of encode-with-SetIndent — printJSON, writeJSON, and three per-report wrappers. Keep printJSON (already the most used, in corecmd/status) and route the token/attribution reports and test fixtures through it. Encode-failure wording unifies to "encode output".

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

## Sessions

351ee2316125View transcript

## Changes

9

- cmd/entire/cli

- Mattribution.go+3/-13
  - Mcheckpoint_tokens.go+1/-11
  - Mgrant_wiring_test.go+1/-1
  - Mlist_pagination_test.go+2/-2
  - Mrepo_clone_test.go+1/-1
  - Mrepo_mirror_test.go+6/-6
  - Mresolveref_test.go+10/-10
  - Msession_tokens.go+1/-11
  - Mtokens_profile.go+1/-11

```
3 unmodified lines

4
5
6
7
7
8
9
224 unmodified lines

234
235
236
238
237
238
239
240
24 unmodified lines

265
266
267
269
268
269
270
271
20 unmodified lines

292
293
294
296
295
296
297
298
1126 unmodified lines

1425
1426
1427
1429
1430
1431
1432
1433
1434
1435
1436
1437

3 unmodified lines

"bufio"
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
224 unmodified lines

}

if opts.JSON {
		return writeJSON(w, result)
		return printJSON(w, result)
	}
	renderAttributionBlame(w, result, opts.LineFlag, opts.Long)
	return nil
24 unmodified lines

if !hasLine {
		if opts.JSON {
			return writeJSON(w, result)
			return printJSON(w, result)
		}
		renderAttributionFileWhy(w, result)
		return nil
20 unmodified lines

Line:        *selected,
		Checkpoints: checkpointContextsForLines([]attributionLine{*selected}, result.Checkpoints),
	}
	return writeJSON(w, payload)
	return printJSON(w, payload)
	}
	renderAttributionLineWhy(w, result.File, *selected)
	return nil
1126 unmodified lines

func isZeroCommit(sha string) bool {
	return sha == "" || strings.Trim(sha, "0") == ""
}

func writeJSON(w io.Writer, value any) error {
	encoder := json.NewEncoder(w)
	encoder.SetIndent("", "  ")
	if err := encoder.Encode(value); err != nil {
		return fmt.Errorf("encode json: %w", err)
	}
	return nil
}
```

Mcmd/entire/cli/attribution.go+3/-13

```
1 unmodified line

2
3
4
5
5
6
7
116 unmodified lines

124
125
126
128
127
128
129
130
414 unmodified lines

545
546
547
549
550
551
552
553
554
555
556
557
548
549
550

1 unmodified line

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
116 unmodified lines

}

if jsonOutput {
		return writeCheckpointTokensJSON(cmd.OutOrStdout(), report)
		return printJSON(cmd.OutOrStdout(), report)
	}
	if agentBrief {
		writeCheckpointTokensAgentBrief(cmd.OutOrStdout(), report)
414 unmodified lines

return "Total tokens include cache/context replay; use the cache/context replay delta below before treating total direction as work saved or added."
}

func writeCheckpointTokensJSON(w io.Writer, report checkpointTokensReport) error {
	enc := json.NewEncoder(w)
	enc.SetIndent("", "  ")
	if err := enc.Encode(report); err != nil {
		return fmt.Errorf("failed to encode checkpoint token report: %w", err)
	}
	return nil
}

func writeCheckpointTokensText(w io.Writer, report checkpointTokensReport) {
	fmt.Fprintln(w, "Checkpoint tokens")
	fmt.Fprintln(w)
```

Mcmd/entire/cli/checkpoint_tokens.go+1/-11

```
29 unmodified lines

30
31
32
33
33
34
35
36

29 unmodified lines

return func(w http.ResponseWriter, r *http.Request) {
		if r.Method == http.MethodGet && strings.Contains(r.URL.Path, "/identity/handles/") {
			w.Header().Set("Content-Type", "application/json")
			if err := writeJSON(w, &coreapi.ResolvedIdentity{
			if err := printJSON(w, &coreapi.ResolvedIdentity{
				AccountId:      wiringGranteeULID,
				Provider:       providerGitHub,
				Handle:         "alice",
```

Mcmd/entire/cli/grant_wiring_test.go+1/-1

```
34 unmodified lines

35
36
37
38
38
39
40
41
47 unmodified lines

89
90
91
92
92
93
94
95

34 unmodified lines

default:
			t.Errorf("unexpected cursor %q", cursor)
		}
		if err := writeJSON(w, &body); err != nil {
		if err := printJSON(w, &body); err != nil {
			t.Errorf("encode orgs: %v", err)
		}
		}))
47 unmodified lines

default:
			t.Errorf("unexpected pageToken %q", token)
		if err := writeJSON(w, &body); err != nil {
		if err := printJSON(w, &body); err != nil {
			t.Errorf("encode mirrors: %v", err)
		}
		}))
```

Mcmd/entire/cli/list_pagination_test.go+2/-2

```
200 unmodified lines

201
202
203
204
204
205
206
207

200 unmodified lines

{Owner: "entirehq", Repo: "entire-api", ClusterHost: "aws-eu-west-1.entire.io"},
		{Owner: "entirehq", Repo: "entire-cli", ClusterHost: "aws-us-east-2.entire.io"},
		}}
		if err := writeJSON(w, body); err != nil {
		if err := printJSON(w, body); err != nil {
			t.Errorf("encode response: %v", err)
		}
		}))
```

Mcmd/entire/cli/repo_clone_test.go+1/-1

```
141 unmodified lines

142
143
144
145
145
146
147
148
149
150
151
151
152
153
154
172 unmodified lines

327
328
329
330
330
331
332
333
334
334
335
336
337
248 unmodified lines

586
587
588
589
589
590
591
592
17 unmodified lines

610
611
612
613
613
614
615
616

141 unmodified lines

return
		}
		w.WriteHeader(http.StatusCreated)
		if err := writeJSON(w, created); err != nil {
		if err := printJSON(w, created); err != nil {
			t.Errorf("encode created response: %v", err)
		}
		}
		case r.Method == http.MethodGet && strings.HasPrefix(r.URL.Path, "/api/v1/mirrors/"):
			m := &coreapi.Mirror{}
			m.Status = coreapi.NewOptMirrorStatus(coreapi.MirrorStatusReady)
			if err := writeJSON(w, m); err != nil {
			if err := printJSON(w, m); err != nil {
				t.Errorf("encode mirror response: %v", err)
			}
		}
		default:
172 unmodified lines

w.Header().Set("Content-Type", "application/json")
		switch r.URL.Path {
		case "/api/v1/mirrors/available":
			if err := writeJSON(w, &coreapi.ListAvailableMirrorsOutputBody{Available: available}); err != nil {
			if err := printJSON(w, &coreapi.ListAvailableMirrorsOutputBody{Available: available}); err != nil {
				t.Errorf("encode available response: %v", err)
			}
		case mirrorsAPIPath:
			if err := writeJSON(w, &coreapi.ListMirrorsOutputBody{Mirrors: mirrors}); err != nil {
			if err := printJSON(w, &coreapi.ListMirrorsOutputBody{Mirrors: mirrors}); err != nil {
				t.Errorf("encode mirrors response: %v", err)
			}
		default:
248 unmodified lines

c, _ := resolveTestClient(t, func(w http.ResponseWriter, r *http.Request) {
			q := r.URL.Query()
			gotCluster, gotProvider, gotOwner = q.Get("cluster"), q.Get("provider"), q.Get("owner")
			if err := writeJSON(w, &coreapi.ListMirrorsOutputBody{Mirrors: []coreapi.Mirror{
			if err := printJSON(w, &coreapi.ListMirrorsOutputBody{Mirrors: []coreapi.Mirror{
				{MirrorId: otherULID, Owner: "entirehq", Repo: "other", ClusterHost: "aws-eu-central-1.entire.io"},
				{MirrorId: mirrorULID, Owner: "entirehq", Repo: "entire-api", ClusterHost: "aws-eu-central-1.entire.io"},
			}}); err != nil {
					t.Errorf("encode mirrors: %v", err)
			}
			}))
17 unmodified lines

t.Run("no matching repo is a friendly error", func(t *testing.T) {
	t.Parallel()
	c, _ := resolveTestClient(t, func(w http.ResponseWriter, _ *http.Request) {
		if err := writeJSON(w, &coreapi.ListMirrorsOutputBody{Mirrors: []coreapi.Mirror{
			if err := printJSON(w, &coreapi.ListMirrorsOutputBody{Mirrors: []coreapi.Mirror{
				{MirrorId: otherULID, Owner: "entirehq", Repo: "other", ClusterHost: "aws-eu-central-1.entire.io"},
			}}); err != nil {
					t.Errorf("encode mirrors: %v", err)
			}
		}))

Mcmd/entire/cli/repo_mirror_test.go+6/-6

```
68 unmodified lines

69
70
71
72
72
73
74
75
15 unmodified lines

91
92
93
94
94
95
96
97
31 unmodified lines

129
130
131
132
132
133
134
135
15 unmodified lines

151
152
153
154
154
155
156
157
51 unmodified lines

209
210
211
212
212
213
214
215
17 unmodified lines

233
234
235
236
236
237
238
239
28 unmodified lines

268
269
270
271
271
272
273
274
12 unmodified lines

287
288
289
290
290
291
292
293
23 unmodified lines

317
318
319
320
320
321
322
323
44 unmodified lines

368
369
370
371
371
372
373
374

68 unmodified lines

var gotName string
	c, calls := resolveTestClient(t, func(w http.ResponseWriter, r *http.Request) {
		gotName = r.URL.Query().Get("name")
		if err := writeJSON(w, &coreapi.ListOrgsOutputBody{Org: coreapi.NewOptOrg(coreapi.Org{ID: ulidOrgGlobex, Name: "globex"})}); err != nil {
			if err := printJSON(w, &coreapi.ListOrgsOutputBody{Org: coreapi.NewOptOrg(coreapi.Org{ID: ulidOrgGlobex, Name: "globex"})}); err != nil {
				t.Errorf("encode org: %v", err)
			}
		})
15 unmodified lines

t.Run("unknown name is a friendly error", func(t *testing.T) {
	t.Parallel()
	c, _ := resolveTestClient(t, func(w http.ResponseWriter, _ *http.Request) {
		if err := writeJSON(w, &coreapi.ListOrgsOutputBody{}); err != nil {
			if err := printJSON(w, &coreapi.ListOrgsOutputBody{}); err != nil {
				t.Errorf("encode empty: %v", err)
			}
		})
31 unmodified lines

var gotName string
	c, calls := resolveTestClient(t, func(w http.ResponseWriter, r *http.Request) {
		gotName = r.URL.Query().Get("name")
		if err := writeJSON(w, &coreapi.ListProjectsOutputBody{Project: matched}); err != nil {
			if err := printJSON(w, &coreapi.ListProjectsOutputBody{Project: matched}); err != nil {
				t.Errorf("encode project: %v", err)
			}
		})
15 unmodified lines

t.Run("unknown name is a friendly error", func(t *testing.T) {
	t.Parallel()
	c, _ := resolveTestClient(t, func(w http.ResponseWriter, _ *http.Request) {
		if err := writeJSON(w, &coreapi.ListProjectsOutputBody{}); err != nil {
			if err := printJSON(w, &coreapi.ListProjectsOutputBody{}); err != nil {
				t.Errorf("encode empty: %v", err)
			}
		})
51 unmodified lines

// which is only populated for an unfiltered page. Reading `repos`
		// here was the COR-699 bug, so the fixture must mirror the real
		// server's singular field to keep that regression covered.
		if err := writeJSON(w, &coreapi.ListProjectReposOutputBody{Repo: coreapi.NewOptRepo(coreapi.Repo{ID: ulidRepoWeb, Name: "web"})}); err != nil {
			if err := printJSON(w, &coreapi.ListProjectReposOutputBody{Repo: coreapi.NewOptRepo(coreapi.Repo{ID: ulidRepoWeb, Name: "web"})}); err != nil {
				t.Errorf("encode repo: %v", err)
			}
		})
17 unmodified lines

t.Run("unknown name is a friendly error", func(t *testing.T) {
	t.Parallel()
	c, _ := resolveTestClient(t, func(w http.ResponseWriter, _ *http.Request) {
		if err := writeJSON(w, &coreapi.ListProjectReposOutputBody{}); err != nil {
			if err := printJSON(w, &coreapi.ListProjectReposOutputBody{}); err != nil {
				t.Errorf("encode empty: %v", err)
			}
		})
28 unmodified lines

t.Run("handle resolves via exactly one call", func(t *testing.T) {
	t.Parallel()
	c, calls := resolveTestClient(t, func(w http.ResponseWriter, _ *http.Request) {
		if err := writeJSON(w, &coreapi.ResolvedIdentity{AccountId: ulidResolvedAcct, Provider: "github", Handle: "alice"}); err != nil {
			if err := printJSON(w, &coreapi.ResolvedIdentity{AccountId: ulidResolvedAcct, Provider: "github", Handle: "alice"}); err != nil {
				t.Errorf("encode identity: %v", err)
			}
		})
12 unmodified lines

t.Run("empty resolved account id is an error", func(t *testing.T) {
	t.Parallel()
	c, _ := resolveTestClient(t, func(w http.ResponseWriter, _ *http.Request) {
		if err := writeJSON(w, &coreapi.ResolvedIdentity{AccountId: "", Provider: "github", Handle: "alice"}); err != nil {
			if err := printJSON(w, &coreapi.ResolvedIdentity{AccountId: "", Provider: "github", Handle: "alice"}); err != nil {
				t.Errorf("encode identity: %v", err)
			}
		})
23 unmodified lines

t.Run("handle resolves to the provider user id in one call", func(t *testing.T) {
	t.Parallel()
	c, calls := resolveTestClient(t, func(w http.ResponseWriter, _ *http.Request) {
		if err := writeJSON(w, &coreapi.ResolvedIdentity{AccountId: ulidResolvedAcct, Provider: providerGitHub, Handle: "alice", ProviderUserId: "12345"}); err != nil {
			if err := printJSON(w, &coreapi.ResolvedIdentity{AccountId: ulidResolvedAcct, Provider: providerGitHub, Handle: "alice", ProviderUserId: "12345"}); err != nil {
				t.Errorf("encode identity: %v", err)
			}
		})
44 unmodified lines

t.Run("empty provider user id is an error", func(t *testing.T) {
	t.Parallel()
	c, _ := resolveTestClient(t, func(w http.ResponseWriter, _ *http.Request) {
		if err := writeJSON(w, &coreapi.ResolvedIdentity{AccountId: ulidResolvedAcct, Provider: providerGitHub, Handle: "alice", ProviderUserId: ""}); err != nil {
			if err := printJSON(w, &coreapi.ResolvedIdentity{AccountId: ulidResolvedAcct, Provider: providerGitHub, Handle: "alice", ProviderUserId: ""}); err != nil {
				t.Errorf("encode identity: %v", err)
			}
		})
