From 5fa1a537a7961a92068bf61cf7f07a091f53a24a Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Mon, 7 Sep 2026 14:56:15 +0530 Subject: [PATCH] feat: surface cache token usage in exec usage footer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit exec's usage footer reported total in/out tokens but omitted cache read/write, unlike --print's footer which shows them. Track CacheReadTokens/CacheWriteTokens in the streaming loop and include a 'cache N read · M write' segment in the footer when nonzero, so cost-conscious exec users see prompt-caching savings. Footer still writes to stderr and honors --quiet. stream-json output is unchanged. --- cmd/exec.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/cmd/exec.go b/cmd/exec.go index 142d3d93..3533097b 100644 --- a/cmd/exec.go +++ b/cmd/exec.go @@ -295,7 +295,7 @@ func runExec(_ *cobra.Command, args []string) error { // Collect response var response strings.Builder - var totalIn, totalOut, turns int + var totalIn, totalOut, turns, cacheRead, cacheWrite int var execErr string jsonEnc := json.NewEncoder(os.Stdout) @@ -316,6 +316,8 @@ func runExec(_ *cobra.Command, args []string) error { if ev.Usage != nil { totalIn += ev.Usage.PromptTokens totalOut += ev.Usage.CompletionTokens + cacheRead += ev.Usage.CacheReadTokens + cacheWrite += ev.Usage.CacheWriteTokens turns++ } case "error": @@ -400,11 +402,13 @@ func runExec(_ *cobra.Command, args []string) error { fmt.Println() } if !IsQuiet() { - fmt.Fprintf(os.Stderr, "%s\n", auditTint( - fmt.Sprintf("graycode: %d tokens in / %d out · %d turn(s) · %s · %s", - totalIn, totalOut, turns, time.Since(start).Round(time.Millisecond), effectiveModel), - textMuted, - )) + summary := fmt.Sprintf("graycode: %d tokens in / %d out · %d turn(s) · %s · %s", + totalIn, totalOut, turns, time.Since(start).Round(time.Millisecond), effectiveModel) + if cacheRead > 0 || cacheWrite > 0 { + summary = fmt.Sprintf("graycode: %d tokens in / %d out (cache %d read · %d write) · %d turn(s) · %s · %s", + totalIn, totalOut, cacheRead, cacheWrite, turns, time.Since(start).Round(time.Millisecond), effectiveModel) + } + fmt.Fprintf(os.Stderr, "%s\n", auditTint(summary, textMuted)) } if exitCode != 0 { return fmt.Errorf("exec failed: %s", execErr)