(
manifestPath: string,
options: { cowork?: boolean },
)
| 93 | |
| 94 | // plugin validate |
| 95 | export async function pluginValidateHandler( |
| 96 | manifestPath: string, |
| 97 | options: { cowork?: boolean }, |
| 98 | ): Promise<void> { |
| 99 | if (options.cowork) setUseCoworkPlugins(true) |
| 100 | try { |
| 101 | const result = await validateManifest(manifestPath) |
| 102 | |
| 103 | console.log(`Validating ${result.fileType} manifest: ${result.filePath}\n`) |
| 104 | printValidationResult(result) |
| 105 | |
| 106 | // If this is a plugin manifest located inside a .claude-plugin directory, |
| 107 | // also validate the plugin's content files (skills, agents, commands, |
| 108 | // hooks). Works whether the user passed a directory or the plugin.json |
| 109 | // path directly. |
| 110 | let contentResults: ValidationResult[] = [] |
| 111 | if (result.fileType === 'plugin') { |
| 112 | const manifestDir = dirname(result.filePath) |
| 113 | if (basename(manifestDir) === '.claude-plugin') { |
| 114 | contentResults = await validatePluginContents(dirname(manifestDir)) |
| 115 | for (const r of contentResults) { |
| 116 | console.log(`Validating ${r.fileType}: ${r.filePath}\n`) |
| 117 | printValidationResult(r) |
| 118 | } |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | const allSuccess = result.success && contentResults.every(r => r.success) |
| 123 | const hasWarnings = |
| 124 | result.warnings.length > 0 || |
| 125 | contentResults.some(r => r.warnings.length > 0) |
| 126 | |
| 127 | if (allSuccess) { |
| 128 | cliOk( |
| 129 | hasWarnings |
| 130 | ? `${figures.tick} Validation passed with warnings` |
| 131 | : `${figures.tick} Validation passed`, |
| 132 | ) |
| 133 | } else { |
| 134 | console.log(`${figures.cross} Validation failed`) |
| 135 | process.exit(1) |
| 136 | } |
| 137 | } catch (error) { |
| 138 | logError(error) |
| 139 | console.error( |
| 140 | `${figures.cross} Unexpected error during validation: ${errorMessage(error)}`, |
| 141 | ) |
| 142 | process.exit(2) |
| 143 | } |
| 144 | } |
| 145 | |
| 146 | // plugin list (lines 5217–5416) |
| 147 | export async function pluginListHandler(options: { |
no test coverage detected