@@ -717,3 +717,89 @@ TODO: Add step-by-step instructions for the agent.
717717 assert .Contains (t , out , "claude-code" )
718718 assert .Contains (t , out , "2025-01-15" )
719719}
720+
721+ // --- skill tags ---
722+
723+ func TestSkillCreate_WithTags (t * testing.T ) {
724+ cc := testRegistry (t )
725+
726+ _ , err := runCmd (t , cc , "skill" , "create" , "tagged-skill" ,
727+ "--description" , "A tagged skill" ,
728+ "--tags" , "devops,testing" ,
729+ "--json" )
730+ require .NoError (t , err )
731+
732+ out , err := runCmd (t , cc , "skill" , "show" , "tagged-skill" , "--json" )
733+ require .NoError (t , err )
734+
735+ var result output.SkillResult
736+ require .NoError (t , json .Unmarshal ([]byte (out ), & result ))
737+ assert .Equal (t , []string {"devops" , "testing" }, result .Tags )
738+ }
739+
740+ func TestSkillCreate_WithTags_Show (t * testing.T ) {
741+ cc := testRegistry (t )
742+
743+ _ , err := runCmd (t , cc , "skill" , "create" , "tagged-text" ,
744+ "--description" , "A tagged skill" ,
745+ "--tags" , "ci,deploy" )
746+ require .NoError (t , err )
747+
748+ out , err := runCmd (t , cc , "skill" , "show" , "tagged-text" )
749+ require .NoError (t , err )
750+ assert .Contains (t , out , "Tags:" )
751+ assert .Contains (t , out , "ci" )
752+ assert .Contains (t , out , "deploy" )
753+ }
754+
755+ func TestSkillList_FilterByTag (t * testing.T ) {
756+ cc := testRegistry (t )
757+
758+ _ , err := runCmd (t , cc , "skill" , "create" , "tool-a" ,
759+ "--description" , "Tool A" , "--tags" , "devops" )
760+ require .NoError (t , err )
761+
762+ _ , err = runCmd (t , cc , "skill" , "create" , "tool-b" ,
763+ "--description" , "Tool B" , "--tags" , "testing" )
764+ require .NoError (t , err )
765+
766+ _ , err = runCmd (t , cc , "skill" , "create" , "tool-c" ,
767+ "--description" , "Tool C" , "--tags" , "devops,testing" )
768+ require .NoError (t , err )
769+
770+ // Filter by devops — should get tool-a and tool-c
771+ out , err := runCmd (t , cc , "skill" , "list" , "--tag" , "devops" , "--json" )
772+ require .NoError (t , err )
773+
774+ var result output.SkillListResult
775+ require .NoError (t , json .Unmarshal ([]byte (out ), & result ))
776+ assert .Equal (t , 2 , result .Count )
777+
778+ names := map [string ]bool {}
779+ for _ , s := range result .Skills {
780+ names [s .Name ] = true
781+ }
782+ assert .True (t , names ["tool-a" ])
783+ assert .True (t , names ["tool-c" ])
784+ }
785+
786+ func TestSkillSearch_FilterByTag (t * testing.T ) {
787+ cc := testRegistry (t )
788+
789+ _ , err := runCmd (t , cc , "skill" , "create" , "code-lint" ,
790+ "--description" , "Lint code" , "--tags" , "code-quality" )
791+ require .NoError (t , err )
792+
793+ _ , err = runCmd (t , cc , "skill" , "create" , "code-format" ,
794+ "--description" , "Format code" , "--tags" , "formatting" )
795+ require .NoError (t , err )
796+
797+ // Search "code" but filter by code-quality — should get only code-lint
798+ out , err := runCmd (t , cc , "skill" , "search" , "code" , "--tag" , "code-quality" , "--json" )
799+ require .NoError (t , err )
800+
801+ var result output.SkillSearchResult
802+ require .NoError (t , json .Unmarshal ([]byte (out ), & result ))
803+ assert .Equal (t , 1 , result .Count )
804+ assert .Equal (t , "code-lint" , result .Results [0 ].Name )
805+ }
0 commit comments