From 7e1aac8d23364fed6caf747b8219545e1ae1fc41 Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Mon, 7 Sep 2026 10:35:57 +0530 Subject: [PATCH] feat: theme auto-skill report and animate cloud graph sync - Colorize the --auto-skill report (Detected label, error/check icons, installed summary) via theme.Tint, honoring NO_COLOR/TTY. - Wrap cloud graph sync's graph-build and upload steps in a CLIProgress spinner for animated progress feedback. --- cmd/cloud_graph.go | 7 +++++++ internal/plugin/auto_skill.go | 9 +++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/cmd/cloud_graph.go b/cmd/cloud_graph.go index 1d7d839d..5cc2eee9 100644 --- a/cmd/cloud_graph.go +++ b/cmd/cloud_graph.go @@ -30,6 +30,9 @@ facts are immutable after acceptance. This is explicit and opt-in; local execution never depends on cloud synchronization.`, Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { + prog := NewCLIProgress("Graph sync", []string{"Building execution graph", "Uploading to Graycode Cloud"}) + defer prog.Abort() + prog.StartStep(0) var export executiongraph.Export var err error if strings.TrimSpace(missionDir) != "" { @@ -56,6 +59,8 @@ execution never depends on cloud synchronization.`, if err != nil { return fmt.Errorf("prepare graph for Graycode Cloud: %w", err) } + prog.CompleteStep(0) + prog.StartStep(1) result, err := client.SyncGraph(cmd.Context(), cloud.GraphSyncRequest{ SyncID: prepared.SyncID, ProjectID: cfg.ProjectID, @@ -64,6 +69,8 @@ execution never depends on cloud synchronization.`, if err != nil { return err } + prog.CompleteStep(1) + prog.Done() status := "accepted" if result.Duplicate { status = "already synchronized" diff --git a/internal/plugin/auto_skill.go b/internal/plugin/auto_skill.go index 2690d935..b5f442f8 100644 --- a/internal/plugin/auto_skill.go +++ b/internal/plugin/auto_skill.go @@ -6,6 +6,7 @@ import ( "path/filepath" "strings" + "github.com/GrayCodeAI/graycode-cli/internal/theme" "github.com/GrayCodeAI/graycode-cli/internal/ui/icons" ) @@ -168,22 +169,22 @@ func RunAutoSkill(dir string) (string, error) { } var b strings.Builder - _, _ = fmt.Fprintf(&b, "Detected: %s\n", strings.Join(sigNames, ", ")) + _, _ = fmt.Fprintf(&b, "%s %s\n", theme.Tint("Detected:", theme.ReportMuted), strings.Join(sigNames, ", ")) installed := 0 for _, skill := range recommended { msg, err := rc.Install(skill.Repo, skill.Name, "user") if err != nil { - _, _ = fmt.Fprintf(&b, " "+icons.CloseThick()+" %s — %v\n", skill.Name, err) + _, _ = fmt.Fprintf(&b, " "+icons.CloseThick()+" %s — %s\n", skill.Name, theme.Tint(err.Error(), theme.ReportError)) continue } _ = msg - _, _ = fmt.Fprintf(&b, " "+icons.CheckBold()+" %s — %s\n", skill.Name, skill.Description) + _, _ = fmt.Fprintf(&b, " %s %s — %s\n", theme.Tint(icons.CheckBold(), theme.ReportSuccess), skill.Name, skill.Description) installed++ } if installed > 0 { - _, _ = fmt.Fprintf(&b, "\nInstalled %d skill(s) to Graycode user state", installed) + _, _ = fmt.Fprintf(&b, "\n%s", theme.Tint(fmt.Sprintf("Installed %d skill(s) to Graycode user state", installed), theme.ReportSuccess)) } return b.String(), nil }