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