@@ -845,6 +845,12 @@ func run(args []string) error {
845845 color := ! resolved .NoColor && render .ColorEnabled ()
846846 rend := render .New (os .Stderr , color ).WithModel (modelLabel )
847847
848+ // Wire skill verbosity to the renderer so skill lifecycle
849+ // notifications (save, suggest, delete) respect the config.
850+ if resolved .Skills .Learn {
851+ rend .WithSkillVerbose (resolved .Skills .Verbose )
852+ }
853+
848854 // Resolve skills config pointer (only when learn mode is enabled)
849855 var skillsCfg * skills.SkillsConfig
850856 if resolved .Skills .Learn {
@@ -1331,7 +1337,7 @@ func runLearnLoop(messages []llm.Message, task string, sm *skills.SkillManager,
13311337 // Filter out previously-skipped suggestions
13321338 filtered , skipped := skills .FilterSkipped (suggestions , userDir ,
13331339 skillsCfg .Curation .SkipThreshold , skillsCfg .Curation .SkipResetDays )
1334- if skipped > 0 {
1340+ if skipped > 0 && skillsCfg . Verbose {
13351341 fmt .Fprintf (os .Stderr , " (%d suggestion(s) previously skipped, suppressed)\n " , skipped )
13361342 }
13371343 if len (filtered ) == 0 {
@@ -1342,23 +1348,28 @@ func runLearnLoop(messages []llm.Message, task string, sm *skills.SkillManager,
13421348 if skillsCfg .AutoSave .Enabled {
13431349 if ! skillsCfg .AutoSave .RequireLLM || skillsCfg .LLMLearn {
13441350 result := skills .AutoSaveSuggestions (filtered , userDir , skillsCfg )
1345- for _ , name := range result .Saved {
1346- heuristic := result .Heuristics [name ]
1347- if heuristic != "" {
1348- fmt .Fprintf (os .Stderr , " ✓ Auto-saved skill %q (%s)\n " , name , heuristic )
1349- } else {
1350- fmt .Fprintf (os .Stderr , " ✓ Auto-saved skill %q\n " , name )
1351+ if skillsCfg .Verbose {
1352+ for _ , name := range result .Saved {
1353+ heuristic := result .Heuristics [name ]
1354+ if heuristic != "" {
1355+ fmt .Fprintf (os .Stderr , " ✓ Auto-saved skill %q (%s)\n " , name , heuristic )
1356+ } else {
1357+ fmt .Fprintf (os .Stderr , " ✓ Auto-saved skill %q\n " , name )
1358+ }
1359+ }
1360+ if result .Skipped > 0 {
1361+ fmt .Fprintf (os .Stderr , " (%d previously skipped, suppressed)\n " , result .Skipped )
13511362 }
1363+ for _ , name := range result .Failed {
1364+ fmt .Fprintf (os .Stderr , " ⚠ Quality gate failed for %q (use --no-auto-save to review manually)\n " , name )
1365+ }
1366+ }
1367+ // Fire notifier events even when silent so WebUI/Telegram get them
1368+ for _ , name := range result .Saved {
13521369 sm .Notifier .Notify (skills.SkillEvent {
13531370 Type : "saved" , SkillName : name , Timestamp : time .Now ().UTC (),
13541371 })
13551372 }
1356- if result .Skipped > 0 {
1357- fmt .Fprintf (os .Stderr , " (%d previously skipped, suppressed)\n " , result .Skipped )
1358- }
1359- for _ , name := range result .Failed {
1360- fmt .Fprintf (os .Stderr , " ⚠ Quality gate failed for %q (use --no-auto-save to review manually)\n " , name )
1361- }
13621373 if len (result .Saved ) > 0 {
13631374 sm .Reload ()
13641375 // Run micro-curation after auto-save
@@ -1369,6 +1380,9 @@ func runLearnLoop(messages []llm.Message, task string, sm *skills.SkillManager,
13691380 }
13701381
13711382 // Interactive fallback: show preview and prompt
1383+ if ! skillsCfg .Verbose {
1384+ return // silently skip interactive prompt in non-verbose mode
1385+ }
13721386 fmt .Fprintf (os .Stderr , "\n 🔍 Learning: detected %d skill pattern(s)\n " , len (filtered ))
13731387 for _ , s := range filtered {
13741388 fmt .Fprint (os .Stderr , skills .FormatSuggestionWithPreview (s , true , 400 ))
@@ -1407,7 +1421,7 @@ func runAutoCurate(userDir string, sm *skills.SkillManager, cfg skills.SkillsCon
14071421 }
14081422 }
14091423 msg := skills .RunAutoCurate (userDir , newSkills , allSkills , cfg , llmClient )
1410- if msg != "" {
1424+ if msg != "" && cfg . Verbose {
14111425 fmt .Fprint (os .Stderr , msg )
14121426 }
14131427}
0 commit comments