Skip to content

Commit 3d1a332

Browse files
committed
style: improve console output formatting across workflow engines and CLI
- Fix unstyled fmt.Printf calls in workflow engines to use console.FormatErrorMessage, console.FormatWarningMessage, and console.FormatVerboseMessage - Update CLI success messages to use console.FormatSuccessMessage - Add console package imports to workflow files that were missing them - Ensure consistent terminal styling across claude_engine, custom_engine, codex_engine, cache, network_proxy, and push_to_pull_request_branch - Maintain proper stderr output routing and TTY detection for color support 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 6a95e84 commit 3d1a332

7 files changed

Lines changed: 39 additions & 22 deletions

File tree

pkg/cli/commands.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -352,9 +352,9 @@ func addWorkflowsWithPR(workflows []string, number int, verbose bool, engineOver
352352
}
353353

354354
if len(workflows) == 1 {
355-
fmt.Printf("Successfully created PR for workflow: %s\n", workflows[0])
355+
fmt.Fprintln(os.Stderr, console.FormatSuccessMessage(fmt.Sprintf("Successfully created PR for workflow: %s", workflows[0])))
356356
} else {
357-
fmt.Printf("Successfully created PR for workflows: %s\n", strings.Join(workflows, ", "))
357+
fmt.Fprintln(os.Stderr, console.FormatSuccessMessage(fmt.Sprintf("Successfully created PR for workflows: %s", strings.Join(workflows, ", "))))
358358
}
359359
return nil
360360
}

pkg/workflow/cache.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package workflow
22

33
import (
44
"fmt"
5+
"os"
56
"strings"
67

8+
"github.com/githubnext/gh-aw/pkg/console"
79
"github.com/goccy/go-yaml"
810
)
911

@@ -87,7 +89,7 @@ func generateCacheSteps(builder *strings.Builder, data *WorkflowData, verbose bo
8789
var topLevel map[string]any
8890
if err := yaml.Unmarshal([]byte(data.Cache), &topLevel); err != nil {
8991
if verbose {
90-
fmt.Printf("Warning: Failed to parse cache configuration: %v\n", err)
92+
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Failed to parse cache configuration: %v", err)))
9193
}
9294
return
9395
}
@@ -96,7 +98,7 @@ func generateCacheSteps(builder *strings.Builder, data *WorkflowData, verbose bo
9698
cacheConfig, exists := topLevel["cache"]
9799
if !exists {
98100
if verbose {
99-
fmt.Printf("Warning: No cache key found in parsed configuration\n")
101+
fmt.Fprintln(os.Stderr, console.FormatWarningMessage("No cache key found in parsed configuration"))
100102
}
101103
return
102104
}

pkg/workflow/claude_engine.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@ package workflow
33
import (
44
"encoding/json"
55
"fmt"
6+
"os"
67
"slices"
78
"sort"
89
"strings"
910
"time"
11+
12+
"github.com/githubnext/gh-aw/pkg/console"
1013
)
1114

1215
// ClaudeEngine represents the Claude Code agentic engine
@@ -593,7 +596,7 @@ func (e *ClaudeEngine) RenderMCPConfig(yaml *strings.Builder, tools map[string]a
593596
if toolConfig, ok := tools[toolName].(map[string]any); ok {
594597
if hasMcp, _ := hasMCPConfig(toolConfig); hasMcp {
595598
if err := e.renderClaudeMCPConfig(yaml, toolName, toolConfig, isLast); err != nil {
596-
fmt.Printf("Error generating custom MCP configuration for %s: %v\n", toolName, err)
599+
fmt.Fprintln(os.Stderr, console.FormatErrorMessage(fmt.Sprintf("Error generating custom MCP configuration for %s: %v", toolName, err)))
597600
}
598601
}
599602
}
@@ -855,7 +858,7 @@ func (e *ClaudeEngine) parseClaudeJSONLog(logContent string, verbose bool) LogMe
855858
if err := json.Unmarshal([]byte(logContent), &logEntries); err != nil {
856859
// If that fails, try to parse as mixed format (debug logs + JSONL)
857860
if verbose {
858-
fmt.Printf("Failed to parse Claude log as JSON array, trying JSONL format: %v\n", err)
861+
fmt.Fprintln(os.Stderr, console.FormatVerboseMessage(fmt.Sprintf("Failed to parse Claude log as JSON array, trying JSONL format: %v", err)))
859862
}
860863

861864
logEntries = []map[string]any{}
@@ -914,7 +917,7 @@ func (e *ClaudeEngine) parseClaudeJSONLog(logContent string, verbose bool) LogMe
914917
if err := json.Unmarshal([]byte(trimmedLine), &jsonEntry); err != nil {
915918
// Skip invalid JSON lines (could be partial debug output)
916919
if verbose {
917-
fmt.Printf("Skipping invalid JSON line: %s\n", trimmedLine)
920+
fmt.Fprintln(os.Stderr, console.FormatVerboseMessage(fmt.Sprintf("Skipping invalid JSON line: %s", trimmedLine)))
918921
}
919922
continue
920923
}
@@ -924,13 +927,13 @@ func (e *ClaudeEngine) parseClaudeJSONLog(logContent string, verbose bool) LogMe
924927

925928
if len(logEntries) == 0 {
926929
if verbose {
927-
fmt.Printf("No valid JSON entries found in Claude log\n")
930+
fmt.Fprintln(os.Stderr, console.FormatVerboseMessage("No valid JSON entries found in Claude log"))
928931
}
929932
return metrics
930933
}
931934

932935
if verbose {
933-
fmt.Printf("Extracted %d JSON entries from mixed format Claude log\n", len(logEntries))
936+
fmt.Fprintln(os.Stderr, console.FormatVerboseMessage(fmt.Sprintf("Extracted %d JSON entries from mixed format Claude log", len(logEntries))))
934937
}
935938
}
936939

@@ -982,8 +985,8 @@ func (e *ClaudeEngine) parseClaudeJSONLog(logContent string, verbose bool) LogMe
982985
}
983986

984987
if verbose {
985-
fmt.Printf("Extracted from Claude result payload: tokens=%d, cost=%.4f, turns=%d\n",
986-
metrics.TokenUsage, metrics.EstimatedCost, metrics.Turns)
988+
fmt.Fprintln(os.Stderr, console.FormatVerboseMessage(fmt.Sprintf("Extracted from Claude result payload: tokens=%d, cost=%.4f, turns=%d",
989+
metrics.TokenUsage, metrics.EstimatedCost, metrics.Turns)))
987990
}
988991
break
989992
} else if typeStr == "assistant" {
@@ -1027,8 +1030,8 @@ func (e *ClaudeEngine) parseClaudeJSONLog(logContent string, verbose bool) LogMe
10271030
for _, seq := range metrics.ToolSequences {
10281031
totalTools += len(seq)
10291032
}
1030-
fmt.Printf("Claude parser extracted %d tool sequences with %d total tool calls\n",
1031-
len(metrics.ToolSequences), totalTools)
1033+
fmt.Fprintln(os.Stderr, console.FormatVerboseMessage(fmt.Sprintf("Claude parser extracted %d tool sequences with %d total tool calls",
1034+
len(metrics.ToolSequences), totalTools)))
10321035
}
10331036

10341037
// Convert tool call map to slice

pkg/workflow/codex_engine.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ package workflow
22

33
import (
44
"fmt"
5+
"os"
56
"regexp"
67
"sort"
78
"strconv"
89
"strings"
910
"time"
11+
12+
"github.com/githubnext/gh-aw/pkg/console"
1013
)
1114

1215
// convertToIdentifier converts a workflow name to a valid identifier format
@@ -250,7 +253,7 @@ func (e *CodexEngine) RenderMCPConfig(yaml *strings.Builder, tools map[string]an
250253
if toolConfig, ok := expandedTools[toolName].(map[string]any); ok {
251254
if hasMcp, _ := hasMCPConfig(toolConfig); hasMcp {
252255
if err := e.renderCodexMCPConfig(yaml, toolName, toolConfig); err != nil {
253-
fmt.Printf("Error generating custom MCP configuration for %s: %v\n", toolName, err)
256+
fmt.Fprintln(os.Stderr, console.FormatErrorMessage(fmt.Sprintf("Error generating custom MCP configuration for %s: %v", toolName, err)))
254257
}
255258
}
256259
}

pkg/workflow/custom_engine.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ package workflow
22

33
import (
44
"fmt"
5+
"os"
56
"strings"
7+
8+
"github.com/githubnext/gh-aw/pkg/console"
69
)
710

811
// CustomEngine represents a custom agentic engine that executes user-defined GitHub Actions steps
@@ -167,7 +170,7 @@ func (e *CustomEngine) RenderMCPConfig(yaml *strings.Builder, tools map[string]a
167170
if toolConfig, ok := tools[toolName].(map[string]any); ok {
168171
if hasMcp, _ := hasMCPConfig(toolConfig); hasMcp {
169172
if err := e.renderCustomMCPConfig(yaml, toolName, toolConfig, isLast); err != nil {
170-
fmt.Printf("Error generating custom MCP configuration for %s: %v\n", toolName, err)
173+
fmt.Fprintln(os.Stderr, console.FormatErrorMessage(fmt.Sprintf("Error generating custom MCP configuration for %s: %v", toolName, err)))
171174
}
172175
}
173176
}
@@ -300,7 +303,7 @@ func (e *CustomEngine) ParseLogMetrics(logContent string, verbose bool) LogMetri
300303
if claudeMetrics.Turns > 0 || claudeMetrics.TokenUsage > 0 || claudeMetrics.EstimatedCost > 0 {
301304
// Found structured data, use Claude parsing
302305
if verbose {
303-
fmt.Println("Custom engine: Using Claude-style parsing for logs")
306+
fmt.Fprintln(os.Stderr, console.FormatVerboseMessage("Custom engine: Using Claude-style parsing for logs"))
304307
}
305308
return claudeMetrics
306309
}
@@ -313,15 +316,15 @@ func (e *CustomEngine) ParseLogMetrics(logContent string, verbose bool) LogMetri
313316
if codexMetrics.Turns > 0 || codexMetrics.TokenUsage > 0 {
314317
// Found some data, use Codex parsing
315318
if verbose {
316-
fmt.Println("Custom engine: Using Codex-style parsing for logs")
319+
fmt.Fprintln(os.Stderr, console.FormatVerboseMessage("Custom engine: Using Codex-style parsing for logs"))
317320
}
318321
return codexMetrics
319322
}
320323
}
321324

322325
// Fall back to basic parsing if neither Claude nor Codex approaches work
323326
if verbose {
324-
fmt.Println("Custom engine: Using basic fallback parsing for logs")
327+
fmt.Fprintln(os.Stderr, console.FormatVerboseMessage("Custom engine: Using basic fallback parsing for logs"))
325328
}
326329

327330
lines := strings.Split(logContent, "\n")

pkg/workflow/network_proxy.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ package workflow
33
import (
44
_ "embed"
55
"fmt"
6+
"os"
67
"strings"
8+
9+
"github.com/githubnext/gh-aw/pkg/console"
710
)
811

912
//go:embed config/squid.conf
@@ -56,14 +59,14 @@ func (c *Compiler) generateInlineProxyConfig(yaml *strings.Builder, toolName str
5659
mcpConfig, err := getMCPConfig(toolConfig, toolName)
5760
if err != nil {
5861
if c.verbose {
59-
fmt.Printf("Error getting MCP config for %s: %v\n", toolName, err)
62+
fmt.Fprintln(os.Stderr, console.FormatVerboseMessage(fmt.Sprintf("Error getting MCP config for %s: %v", toolName, err)))
6063
}
6164
return
6265
}
6366

6467
if mcpConfig.Container == "" {
6568
if c.verbose {
66-
fmt.Printf("Proxy-enabled tool '%s' missing container configuration\n", toolName)
69+
fmt.Fprintln(os.Stderr, console.FormatVerboseMessage(fmt.Sprintf("Proxy-enabled tool '%s' missing container configuration", toolName)))
6770
}
6871
return
6972
}
@@ -76,7 +79,7 @@ func (c *Compiler) generateInlineProxyConfig(yaml *strings.Builder, toolName str
7679
}
7780

7881
if c.verbose {
79-
fmt.Printf("Generating inline proxy configuration for tool '%s'\n", toolName)
82+
fmt.Fprintln(os.Stderr, console.FormatVerboseMessage(fmt.Sprintf("Generating inline proxy configuration for tool '%s'", toolName)))
8083
}
8184

8285
// Generate squid.conf inline

pkg/workflow/push_to_pull_request_branch.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ package workflow
22

33
import (
44
"fmt"
5+
"os"
6+
7+
"github.com/githubnext/gh-aw/pkg/console"
58
)
69

710
// PushToPullRequestBranchConfig holds configuration for pushing changes to a specific branch from agent output
@@ -157,7 +160,7 @@ func (c *Compiler) parsePushToPullRequestBranchConfig(outputMap map[string]any)
157160
default:
158161
// Invalid value, use default and log warning
159162
if c.verbose {
160-
fmt.Printf("Warning: invalid if-no-changes value '%s', using default 'warn'\n", ifNoChangesStr)
163+
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("invalid if-no-changes value '%s', using default 'warn'", ifNoChangesStr)))
161164
}
162165
pushToBranchConfig.IfNoChanges = "warn"
163166
}

0 commit comments

Comments
 (0)