Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,25 @@ uipro uninstall --ai claude # Remove specific platform
uipro uninstall --global # Remove from global install
```

### CLI Troubleshooting

If you see `Invalid AI type: trae` or `Invalid AI type: droid`, your global CLI is usually outdated.

```bash
uipro --version
npm install -g uipro-cli@latest
```

If RooCode / Kiro generated `SKILL.md` appears to miss frontmatter metadata (`name`, `description`), upgrade and reinstall for those platforms:

```bash
npm install -g uipro-cli@latest
uipro uninstall --ai roocode
uipro uninstall --ai kiro
uipro init --ai roocode
uipro init --ai kiro
```

## Prerequisites

Python 3.x is required for the search script.
Expand Down
31 changes: 31 additions & 0 deletions cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,37 @@ uipro versions # List available versions
uipro update # Update to latest version
```

## Troubleshooting

### `Invalid AI type: trae` / `Invalid AI type: droid`

This usually means your global CLI is outdated.

```bash
# 1) Check installed version
uipro --version

# 2) Upgrade to latest
npm install -g uipro-cli@latest

# 3) Retry
uipro init --ai trae
# or
uipro init --ai droid
```

### RooCode / Kiro generated `SKILL.md` has missing frontmatter

If generated files seem to miss metadata fields (for example `name` / `description`), reinstall with the latest CLI and regenerate:

```bash
npm install -g uipro-cli@latest
uipro uninstall --ai roocode
uipro uninstall --ai kiro
uipro init --ai roocode
uipro init --ai kiro
```

## How It Works

By default, `uipro init` tries to download the latest release from GitHub to ensure you get the most up-to-date version. If the download fails (network error, rate limit), it automatically falls back to the bundled assets included in the CLI package.
Expand Down
1 change: 1 addition & 0 deletions cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"scripts": {
"build": "bun build src/index.ts --outdir dist --target node",
"dev": "bun run src/index.ts",
"verify:platform-configs": "node scripts/verify-platform-configs.mjs",
"prepublishOnly": "bun run build"
},
"keywords": [
Expand Down
44 changes: 44 additions & 0 deletions cli/scripts/verify-platform-configs.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { readFile } from 'node:fs/promises';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';

const __dirname = dirname(fileURLToPath(import.meta.url));
const cliRoot = join(__dirname, '..');

async function readJSON(path) {
const raw = await readFile(path, 'utf-8');
return JSON.parse(raw);
}

function assert(condition, message) {
if (!condition) {
throw new Error(message);
}
}

async function verifyAITypeCoverage() {
const typesPath = join(cliRoot, 'src', 'types', 'index.ts');
const content = await readFile(typesPath, 'utf-8');
assert(content.includes("'trae'"), "AI type 'trae' is missing in cli/src/types/index.ts");
assert(content.includes("'droid'"), "AI type 'droid' is missing in cli/src/types/index.ts");
}

async function verifyFrontmatter(platform) {
const configPath = join(cliRoot, 'assets', 'templates', 'platforms', `${platform}.json`);
const config = await readJSON(configPath);
assert(config.frontmatter && typeof config.frontmatter === 'object', `${platform} frontmatter is missing`);
assert(typeof config.frontmatter.name === 'string' && config.frontmatter.name.length > 0, `${platform} frontmatter.name is missing`);
assert(typeof config.frontmatter.description === 'string' && config.frontmatter.description.length > 0, `${platform} frontmatter.description is missing`);
}

async function main() {
await verifyAITypeCoverage();
await verifyFrontmatter('roocode');
await verifyFrontmatter('kiro');
console.log('Platform config verification passed (trae/droid + roocode/kiro frontmatter).');
}

main().catch((error) => {
console.error(error.message);
process.exit(1);
});
17 changes: 11 additions & 6 deletions cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ const pkg = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8')

const program = new Command();

function printInvalidAITypeError(input: string): void {
console.error(`Invalid AI type: ${input}`);
console.error(`Valid types: ${AI_TYPES.join(', ')}`);
console.error('Tip: your uipro-cli may be outdated. Run: uipro --version');
console.error('Then upgrade: npm install -g uipro-cli@latest');
console.error('After upgrading, retry: uipro init --ai <type>');
}

program
.name('uipro')
.description('CLI to install UI/UX Pro Max skill for AI coding assistants')
Expand All @@ -31,8 +39,7 @@ program
.option('-g, --global', 'Install globally to home directory (~/) instead of current project')
.action(async (options) => {
if (options.ai && !AI_TYPES.includes(options.ai)) {
console.error(`Invalid AI type: ${options.ai}`);
console.error(`Valid types: ${AI_TYPES.join(', ')}`);
printInvalidAITypeError(options.ai);
process.exit(1);
}
await initCommand({
Expand All @@ -54,8 +61,7 @@ program
.option('-a, --ai <type>', `AI assistant type (${AI_TYPES.join(', ')})`)
.action(async (options) => {
if (options.ai && !AI_TYPES.includes(options.ai)) {
console.error(`Invalid AI type: ${options.ai}`);
console.error(`Valid types: ${AI_TYPES.join(', ')}`);
printInvalidAITypeError(options.ai);
process.exit(1);
}
await updateCommand({
Expand All @@ -70,8 +76,7 @@ program
.option('-g, --global', 'Uninstall from home directory (~/) instead of current project')
.action(async (options) => {
if (options.ai && !AI_TYPES.includes(options.ai)) {
console.error(`Invalid AI type: ${options.ai}`);
console.error(`Valid types: ${AI_TYPES.join(', ')}`);
printInvalidAITypeError(options.ai);
process.exit(1);
}
await uninstallCommand({
Expand Down