@@ -601,18 +601,21 @@ server.registerTool(
601601// Repository Sync Tools
602602// =============================================================================
603603
604- import {
605- pullFromGitHub ,
604+ import {
605+ pullFromGitHub ,
606606 pushToGitHub ,
607- listLocalStaged ,
608- browseRepo ,
607+ listLocalStaged ,
608+ browseRepo ,
609609 applyItem ,
610610 applyAll ,
611611 listRepoItems ,
612612 listPulledRepos ,
613613 promoteItem ,
614614 demoteItem ,
615- listBothScopes
615+ listBothScopes ,
616+ linkSkillToCommand ,
617+ linkSubagentToCommand ,
618+ linkAll
616619} from "../src/repo-sync.js" ;
617620
618621server . registerTool (
@@ -882,9 +885,9 @@ server.registerTool(
882885 async ( ) => {
883886 try {
884887 const { project, user } = await listBothScopes ( ) ;
885-
888+
886889 let text = "👁 Comparing Scopes\n\n" ;
887-
890+
888891 text += "📁 User (~/.claude):\n" ;
889892 if ( user . length === 0 ) {
890893 text += " (empty)\n" ;
@@ -894,7 +897,7 @@ server.registerTool(
894897 text += ` ${ icon } ${ item . name } \n` ;
895898 }
896899 }
897-
900+
898901 text += "\n📁 Project (.claude):\n" ;
899902 if ( project . length === 0 ) {
900903 text += " (empty)\n" ;
@@ -904,7 +907,7 @@ server.registerTool(
904907 text += ` ${ icon } ${ item . name } \n` ;
905908 }
906909 }
907-
910+
908911 text += "\nUse promote_setting or demote_setting to move items between scopes." ;
909912 return { content : [ { type : "text" , text } ] } ;
910913 } catch ( error ) {
@@ -913,6 +916,113 @@ server.registerTool(
913916 }
914917) ;
915918
919+ // =============================================================================
920+ // Link Tools - Connect skills/subagents to slash commands
921+ // =============================================================================
922+
923+ server . registerTool (
924+ "link_skill_to_command" ,
925+ {
926+ description : "Link a skill to a slash command for explicit invocation" ,
927+ inputSchema : {
928+ skillName : z . string ( ) . describe ( "Name of the skill to link" ) ,
929+ commandName : z . string ( ) . optional ( ) . describe ( "Custom command name (defaults to skill name)" ) ,
930+ scope : z . enum ( [ "user" , "project" ] ) . optional ( ) . describe ( "Scope: user (~/.claude) or project (.claude). Default: user" ) ,
931+ } ,
932+ } ,
933+ async ( { skillName, commandName, scope = "user" } ) => {
934+ try {
935+ const result = await linkSkillToCommand ( skillName , { scope, commandName } ) ;
936+ return {
937+ content : [ {
938+ type : "text" ,
939+ text : `✅ Linked skill "${ result . skill } " to command "/${ result . command } "\n\nPath: ${ result . path } \n\nYou can now use /${ result . command } to explicitly invoke this skill.`
940+ } ]
941+ } ;
942+ } catch ( error ) {
943+ return {
944+ content : [ { type : "text" , text : `❌ Error: ${ error . message } ` } ] ,
945+ isError : true
946+ } ;
947+ }
948+ }
949+ ) ;
950+
951+ server . registerTool (
952+ "link_subagent_to_command" ,
953+ {
954+ description : "Link a subagent to a slash command for explicit invocation" ,
955+ inputSchema : {
956+ agentName : z . string ( ) . describe ( "Name of the subagent to link" ) ,
957+ commandName : z . string ( ) . optional ( ) . describe ( "Custom command name (defaults to agent name)" ) ,
958+ scope : z . enum ( [ "user" , "project" ] ) . optional ( ) . describe ( "Scope: user (~/.claude) or project (.claude). Default: user" ) ,
959+ } ,
960+ } ,
961+ async ( { agentName, commandName, scope = "user" } ) => {
962+ try {
963+ const result = await linkSubagentToCommand ( agentName , { scope, commandName } ) ;
964+ return {
965+ content : [ {
966+ type : "text" ,
967+ text : `✅ Linked subagent "${ result . agent } " to command "/${ result . command } "\n\nPath: ${ result . path } \n\nYou can now use /${ result . command } to explicitly invoke this subagent.`
968+ } ]
969+ } ;
970+ } catch ( error ) {
971+ return {
972+ content : [ { type : "text" , text : `❌ Error: ${ error . message } ` } ] ,
973+ isError : true
974+ } ;
975+ }
976+ }
977+ ) ;
978+
979+ server . registerTool (
980+ "link_all_to_commands" ,
981+ {
982+ description : "Link all skills and subagents to slash commands" ,
983+ inputSchema : {
984+ scope : z . enum ( [ "user" , "project" ] ) . optional ( ) . describe ( "Scope: user (~/.claude) or project (.claude). Default: user" ) ,
985+ skillsOnly : z . boolean ( ) . optional ( ) . describe ( "Only link skills" ) ,
986+ agentsOnly : z . boolean ( ) . optional ( ) . describe ( "Only link subagents" ) ,
987+ } ,
988+ } ,
989+ async ( { scope = "user" , skillsOnly, agentsOnly } ) => {
990+ try {
991+ const results = await linkAll ( { scope, skillsOnly, agentsOnly } ) ;
992+
993+ let message = "✅ Linked all items to slash commands\n\n" ;
994+
995+ if ( results . skills . length > 0 ) {
996+ message += "**Skills:**\n" ;
997+ results . skills . forEach ( r => {
998+ message += `- ${ r . skill } → /${ r . command } \n` ;
999+ } ) ;
1000+ message += "\n" ;
1001+ }
1002+
1003+ if ( results . agents . length > 0 ) {
1004+ message += "**Subagents:**\n" ;
1005+ results . agents . forEach ( r => {
1006+ message += `- ${ r . agent } → /${ r . command } \n` ;
1007+ } ) ;
1008+ }
1009+
1010+ if ( results . skills . length === 0 && results . agents . length === 0 ) {
1011+ message += "No skills or subagents found to link." ;
1012+ }
1013+
1014+ return {
1015+ content : [ { type : "text" , text : message } ]
1016+ } ;
1017+ } catch ( error ) {
1018+ return {
1019+ content : [ { type : "text" , text : `❌ Error: ${ error . message } ` } ] ,
1020+ isError : true
1021+ } ;
1022+ }
1023+ }
1024+ ) ;
1025+
9161026// =============================================================================
9171027// Resource Registration
9181028// =============================================================================
0 commit comments