From bed27dbffb692a006a22ae592c6b5ed452221df9 Mon Sep 17 00:00:00 2001 From: 1Code <1code@21st.dev> Date: Tue, 27 Jan 2026 02:45:04 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=96=20Bump=20version=20to=200.0.30=20a?= =?UTF-8?q?nd=20add=20Octolens=20analyze=20command?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add new 'analyze' command to CLI that integrates with Octolens analyzemyrepo service: - Analyze any GitHub repository for insights - Auto-detect current repository from git remote - Support --open flag to open analysis in browser - Cross-platform browser opening support Co-Authored-By: Claude Opus 4.5 --- README.md | 17 +++++++++ package-lock.json | 5 ++- package.json | 2 +- src/cli.ts | 97 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8244e52..1a83ed6 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ Adds MagicMCP configuration to AI IDEs (Cursor, Windsurf, Cline, etc.) ## Usage +### Install MCP Configuration + ```bash npx @21st-dev/cli@latest install --api-key ``` @@ -12,6 +14,21 @@ You can obtain your API key at [21st.dev Magic Console](https://21st.dev/magic/c Supported IDEs: cursor, windsurf, cline, claude, witsy, enconvo +### Analyze GitHub Repository (Octolens) + +Analyze any GitHub repository using [Octolens analyzemyrepo](https://analyzemyrepo.com): + +```bash +# Analyze a specific repository +npx @21st-dev/cli@latest analyze facebook/react + +# Analyze current repository (auto-detected from git remote) +npx @21st-dev/cli@latest analyze + +# Open analysis in browser +npx @21st-dev/cli@latest analyze --open +``` + ## Manual Installation Add to your IDE's MCP config: diff --git a/package-lock.json b/package-lock.json index 9aa094f..381bfa1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@21st-dev/cli", - "version": "0.0.29", + "version": "0.0.30", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@21st-dev/cli", - "version": "0.0.29", + "version": "0.0.30", "license": "ISC", "dependencies": { "chalk": "^5.3.0", @@ -338,6 +338,7 @@ "integrity": "sha512-U58sbKhDrthHlxHRJw7ZLiLDZGmAUOZUbpw0S6nL27sYUdhvgBLCRu/keSd6qcTsfArd1sRFCCBxzWATGr/0UA==", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~6.19.2" } diff --git a/package.json b/package.json index 940787e..5035b51 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@21st-dev/cli", - "version": "0.0.29", + "version": "0.0.30", "type": "module", "description": "MCP configuration installer by 21st.dev", "main": "dist/index.js", diff --git a/src/cli.ts b/src/cli.ts index db8c9c7..4a5895e 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -245,6 +245,103 @@ program } ); +program + .command("analyze") + .description( + "Analyze a GitHub repository using Octolens analyzemyrepo service" + ) + .argument( + "[repository]", + "GitHub repository in format owner/repo (e.g., facebook/react). Defaults to current repository." + ) + .option("--open", "Open the analysis in browser") + .action(async (repository: string | undefined, options: { open?: boolean }) => { + const OCTOLENS_BASE_URL = "https://analyzemyrepo.com"; + + let repoToAnalyze = repository; + + // If no repository provided, try to detect from git remote + if (!repoToAnalyze) { + try { + const gitRemote = execSync("git remote get-url origin", { + encoding: "utf-8", + stdio: ["pipe", "pipe", "pipe"], + }).trim(); + + // Parse GitHub URL formats: + // https://github.com/owner/repo.git + // git@github.com:owner/repo.git + const httpsMatch = gitRemote.match(/github\.com\/([^\/]+)\/([^\/\.]+)/); + const sshMatch = gitRemote.match(/github\.com:([^\/]+)\/([^\/\.]+)/); + + if (httpsMatch) { + repoToAnalyze = `${httpsMatch[1]}/${httpsMatch[2]}`; + } else if (sshMatch) { + repoToAnalyze = `${sshMatch[1]}/${sshMatch[2]}`; + } + + if (repoToAnalyze) { + console.log(chalk.blue(`Detected repository: ${repoToAnalyze}`)); + } + } catch { + // Not in a git repo or no remote configured + } + } + + if (!repoToAnalyze) { + console.error( + chalk.red( + "Could not detect repository. Please provide a repository in format owner/repo (e.g., facebook/react)" + ) + ); + process.exit(1); + } + + // Validate repository format + if (!repoToAnalyze.match(/^[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+$/)) { + console.error( + chalk.red( + `Invalid repository format: "${repoToAnalyze}". Expected format: owner/repo` + ) + ); + process.exit(1); + } + + const analysisUrl = `${OCTOLENS_BASE_URL}/analyze/${repoToAnalyze}`; + + console.log(chalk.green(`\nšŸ” Octolens Repository Analysis`)); + console.log(chalk.cyan(`Repository: ${repoToAnalyze}`)); + console.log(chalk.cyan(`Analysis URL: ${analysisUrl}\n`)); + + if (options.open) { + console.log(chalk.blue("Opening in browser...")); + try { + // Cross-platform open command + const openCommand = + process.platform === "darwin" + ? "open" + : process.platform === "win32" + ? "start" + : "xdg-open"; + + execSync(`${openCommand} "${analysisUrl}"`, { + stdio: "ignore", + }); + console.log(chalk.green("Browser opened successfully!")); + } catch { + console.log( + chalk.yellow( + `Could not open browser automatically. Please visit the URL above.` + ) + ); + } + } else { + console.log( + chalk.gray("Tip: Use --open flag to open the analysis in your browser") + ); + } + }); + program .command("remove") .description(