@@ -16,6 +16,7 @@ import {
1616 escapeHtml ,
1717 getResourceIconSvg ,
1818 sanitizeUrl ,
19+ REPO_IDENTIFIER ,
1920} from "./utils" ;
2021import fm from "front-matter" ;
2122
@@ -498,6 +499,7 @@ export function setupModal(): void {
498499
499500 const closeBtn = document . getElementById ( "close-modal" ) ;
500501 const copyBtn = document . getElementById ( "copy-btn" ) ;
502+ const installCommandBtn = document . getElementById ( "install-command-btn" ) ;
501503 const downloadBtn = document . getElementById ( "download-btn" ) ;
502504 const shareBtn = document . getElementById ( "share-btn" ) ;
503505 const renderBtn = document . getElementById ( "render-btn" ) ;
@@ -535,6 +537,30 @@ export function setupModal(): void {
535537 }
536538 } ) ;
537539
540+ installCommandBtn ?. addEventListener ( "click" , async ( ) => {
541+ if ( currentFilePath && currentFileType === "skill" ) {
542+ const skill = await getSkillItemByFilePath ( currentFilePath ) ;
543+ if ( ! skill ) {
544+ showToast ( "Could not resolve skill ID." , "error" ) ;
545+ return ;
546+ }
547+ const command = `gh skill install ${ REPO_IDENTIFIER } ${ skill . id } ` ;
548+ const originalContent = installCommandBtn . innerHTML ;
549+ const success = await copyToClipboard ( command ) ;
550+ showToast (
551+ success ? "Install command copied!" : "Failed to copy" ,
552+ success ? "success" : "error"
553+ ) ;
554+ if ( success ) {
555+ installCommandBtn . innerHTML =
556+ '<svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor" aria-hidden="true"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.75.75 0 0 1 1.06-1.06L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0z"/></svg><span aria-hidden="true">Copied!</span>' ;
557+ setTimeout ( ( ) => {
558+ installCommandBtn . innerHTML = originalContent ;
559+ } , 2000 ) ;
560+ }
561+ }
562+ } ) ;
563+
538564 downloadBtn ?. addEventListener ( "click" , async ( ) => {
539565 if ( currentFilePath ) {
540566 if ( currentFileType === "skill" ) {
@@ -849,6 +875,7 @@ export async function openFileModal(
849875 "install-insiders"
850876 ) as HTMLAnchorElement | null ;
851877 const copyBtn = document . getElementById ( "copy-btn" ) ;
878+ const installCommandBtn = document . getElementById ( "install-command-btn" ) ;
852879 const downloadBtn = document . getElementById ( "download-btn" ) ;
853880 const closeBtn = document . getElementById ( "close-modal" ) ;
854881 if ( ! modal || ! title ) return ;
@@ -885,6 +912,10 @@ export async function openFileModal(
885912 if ( type === "plugin" ) {
886913 const modalContent = getModalContent ( ) ;
887914 if ( ! modalContent ) return ;
915+ if ( installCommandBtn ) {
916+ installCommandBtn . style . display = "none" ;
917+ installCommandBtn . classList . add ( "hidden" ) ;
918+ }
888919 hideSkillFileSwitcher ( ) ;
889920 await openPluginModal (
890921 filePath ,
@@ -906,6 +937,11 @@ export async function openFileModal(
906937 type === "skill" ? "Download skill as ZIP" : "Download file"
907938 ) ;
908939 }
940+ // Show copy install button only for skills
941+ if ( installCommandBtn ) {
942+ installCommandBtn . style . display = type === "skill" ? "inline-flex" : "none" ;
943+ installCommandBtn . classList . toggle ( "hidden" , type !== "skill" ) ;
944+ }
909945 renderPlainText ( "Loading..." ) ;
910946 hideSkillFileSwitcher ( ) ;
911947 updateViewButtons ( ) ;
0 commit comments