Skip to content

Commit 4eefef7

Browse files
committed
feat(cli): add npm registry support for vibe installation
MAJOR FEATURE: Users can now install vibes directly from npm! Before: - ❌ Only GitHub URLs worked - ❌ vdt install @vibe-devtools/basic → error After: - ✅ npm packages work: vdt install @vibe-devtools/basic - ✅ Version pinning: vdt install @vibe-devtools/basic@1.0.1 - ✅ npx workflow: npx vibe-devtools install @vibe-devtools/basic - ✅ Zero installation needed with npx Implementation: - Add npm-installer.ts (npm pack + tar extraction) - Parse npm package names correctly (@scope/pkg@version) - Validate vibe.json in extracted package - Cache management in ~/.vibes/cache/npm - Error handling for invalid packages Documentation: - Update CLI README with npx examples - Update monorepo README with both methods - Add comparison: global vs npx - Show quickstart for both approaches Impact: - 🚀 Much better UX - official packages via npm - ⚡ Faster onboarding with npx - 📦 Consistent with npm ecosystem - 🎯 Always get latest with npx This unlocks the full potential of the vibe-devtools ecosystem!
1 parent 26bd96a commit 4eefef7

5 files changed

Lines changed: 225 additions & 35 deletions

File tree

.changeset/add-npm-installer.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
"vibe-devtools": minor
3+
---
4+
5+
Add support for installing vibes directly from npm registry
6+
7+
- Implement npm-installer.ts for downloading and extracting npm packages
8+
- Support installation via package names: @vibe-devtools/basic
9+
- Support version pinning: @vibe-devtools/basic@1.0.1
10+
- Automatic extraction and validation of vibe.json
11+
- Update documentation with npx usage examples
12+
- Enable zero-installation workflow via npx vibe-devtools
13+
14+
This is a major usability improvement - users can now install official vibes directly from npm without needing GitHub URLs.
15+

README.md

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,35 +29,46 @@ Este é o **Vibe DevTools Ecosystem** — um monorepo completo que reúne **TUDO
2929

3030
## 🚀 Quick Start (2 Minutos para a Glória)
3131

32-
### 1️⃣ Instalar CLI
32+
### Método 1: Instalação Global (Recomendado)
3333

3434
```bash
35+
# 1️⃣ Instalar CLI globalmente
3536
npm install -g vibe-devtools
36-
```
37-
38-
### 2️⃣ Instalar Vibes Essenciais
3937

40-
```bash
41-
# Kit fundacional - makers, planners, constitution
38+
# 2️⃣ Instalar vibes essenciais
4239
vdt install @vibe-devtools/basic
43-
44-
# Pipelines de pesquisa acadêmica
4540
vdt install @vibe-devtools/research
41+
42+
# 3️⃣ Verificar instalação
43+
vdt list
44+
45+
# 4️⃣ Usar no Cursor/Claude/Gemini
46+
# /maker.command "criar componente React otimizado"
47+
# /research.deep.pipeline "TypeScript best practices 2025"
4648
```
4749

48-
### 3️⃣ Verificar Instalação
50+
**Vantagem**: Comando curto `vdt` sempre disponível.
51+
52+
### Método 2: Via npx (Zero Instalação)
4953

5054
```bash
51-
vdt list
55+
# Usar diretamente sem instalar CLI
56+
npx vibe-devtools install @vibe-devtools/basic
57+
npx vibe-devtools install @vibe-devtools/research
58+
npx vibe-devtools list
59+
60+
# Criar alias para facilitar
61+
alias vdt="npx vibe-devtools"
62+
vdt install @vibe-devtools/basic
5263
```
5364

54-
### 4️⃣ Usar no Cursor/Claude/Gemini
65+
**Vantagem**: Sempre usa versão latest, sem precisar atualizar.
5566

56-
```
57-
/maker.command "criar componente React otimizado"
58-
/research.deep.pipeline "TypeScript best practices 2025"
59-
/planner.project "Migrar para Next.js 15"
60-
```
67+
### 🔥 Qual Escolher?
68+
69+
- **Global**: Se vai usar frequentemente (recomendado)
70+
- **npx**: Se quer testar primeiro ou quer sempre latest
71+
- **Ambos**: Use npx para experimentar, depois instale global
6172

6273
**🎉 Pronto! Você já está no futuro do desenvolvimento!**
6374

@@ -114,13 +125,21 @@ Uma CLI moderna que transforma seu ambiente de desenvolvimento em uma **central
114125
### 💻 Comandos Principais
115126

116127
```bash
117-
# Instalação
128+
# Instalação (npm packages) ⭐ NOVO!
118129
vdt install @vibe-devtools/basic # Do npm
130+
npx vibe-devtools install @vibe-devtools/research # Via npx
131+
132+
# Instalação (GitHub)
119133
vdt install github:you/custom-vibe # Do GitHub
134+
npx vibe-devtools install github:you/vibe # Via npx
135+
136+
# Instalação (local)
120137
vdt install ./local-vibe # Local dev
138+
npx vibe-devtools install ./my-vibe # Via npx
121139

122140
# Gestão
123141
vdt list # Ver instalados
142+
npx vibe-devtools list # Via npx
124143
vdt uninstall basic # Remover
125144
vdt update basic # Atualizar (soon)
126145

@@ -129,6 +148,8 @@ vdt --version # Versão CLI
129148
vdt --help # Ajuda
130149
```
131150

151+
**💡 npx vs global**: Use `npx` para sempre ter latest, ou instale global para comando mais curto.
152+
132153
### 📚 Documentação
133154

134155
**README Completo**: [apps/cli/README.md](./apps/cli/README.md)
@@ -1008,6 +1029,8 @@ MIT © 2025 [Ono Sendae](https://github.com/onosendae)
10081029
10091030
## 🎉 Quickstart Absoluto
10101031
1032+
### Com Instalação Global
1033+
10111034
```bash
10121035
# 30 segundos para mudar sua vida
10131036

@@ -1029,6 +1052,24 @@ vdt list
10291052
# 🚀 Welcome to the future!
10301053
```
10311054
1055+
### SEM Instalação (npx) ⭐ MAIS RÁPIDO
1056+
1057+
```bash
1058+
# 20 segundos para mudar sua vida (zero instalação!)
1059+
1060+
npx vibe-devtools install @vibe-devtools/basic
1061+
npx vibe-devtools install @vibe-devtools/research
1062+
npx vibe-devtools list
1063+
1064+
# Usar no Cursor
1065+
# /maker.command
1066+
# /research.simple.pipeline
1067+
1068+
# 🚀 Welcome to the future - via npx!
1069+
```
1070+
1071+
**🔥 Diferença**: npx não instala CLI, sempre usa latest automaticamente!
1072+
10321073
---
10331074
10341075
## 💭 Citação Final

apps/cli/README.md

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -95,28 +95,35 @@ vdt install @vibe-devtools/basic
9595

9696
## 🚀 Quick Start
9797

98-
### 1. Instalar CLI
98+
### Opção A: Instalação Global (Recomendado)
9999

100100
```bash
101+
# 1. Instalar CLI globalmente
101102
npm install -g vibe-devtools
102-
```
103-
104-
### 2. Instalar Seu Primeiro Vibe
105103

106-
```bash
107-
# Kit fundacional - makers, planners, governance
104+
# 2. Usar comando curto (vdt)
108105
vdt install @vibe-devtools/basic
109-
110-
# Pipelines de pesquisa acadêmica
111106
vdt install @vibe-devtools/research
107+
vdt list
112108
```
113109

114-
### 3. Ver o Que Você Tem
110+
**Vantagem**: Comando curto `vdt` sempre disponível.
111+
112+
### Opção B: Via npx (Sem Instalar)
115113

116114
```bash
117-
vdt list
115+
# Usar diretamente sem instalar
116+
npx vibe-devtools install @vibe-devtools/basic
117+
npx vibe-devtools install @vibe-devtools/research
118+
npx vibe-devtools list
119+
120+
# Ou criar alias para facilitar
121+
alias vdt="npx vibe-devtools"
122+
vdt install @vibe-devtools/basic
118123
```
119124

125+
**Vantagem**: Sempre usa a versão mais recente, sem precisar atualizar.
126+
120127
```
121128
📦 Vibes Instalados
122129
@@ -411,19 +418,25 @@ vdt install @yourcompany/dev-standards
411418
### Instalação
412419

413420
```bash
414-
# Do npm (oficial)
421+
# Do npm (oficial) ⭐ NOVO!
415422
vdt install @vibe-devtools/basic
423+
npx vibe-devtools install @vibe-devtools/research
416424

417425
# Do GitHub
418426
vdt install github:onosendae/my-vibe
427+
npx vibe-devtools install github:onosendae/my-vibe
419428

420429
# Local (desenvolvimento)
421430
vdt install ./my-vibe
431+
npx vibe-devtools install ./my-vibe
422432

423433
# Com versão específica
424434
vdt install @vibe-devtools/basic@1.0.0
435+
npx vibe-devtools install @vibe-devtools/basic@1.0.1
425436
```
426437

438+
**💡 Dica**: `npx` sempre baixa a versão mais recente do CLI!
439+
427440
### Listagem
428441

429442
```bash
@@ -631,9 +644,9 @@ MIT © 2025 [Ono Sendae](https://github.com/onosendae)
631644

632645
## 🎁 Bonus: Quickstart Total
633646

634-
```bash
635-
# 1 minuto para estar produtivo
647+
### Via Instalação Global (1 minuto)
636648

649+
```bash
637650
# Instalar CLI
638651
npm i -g vibe-devtools
639652

@@ -650,4 +663,20 @@ vdt list
650663
# 🎉 Pronto! Bem-vindo ao futuro do desenvolvimento!
651664
```
652665

666+
### Via npx (SEM Instalar - 30 segundos)
667+
668+
```bash
669+
# Usar diretamente (sempre versão latest)
670+
npx vibe-devtools install @vibe-devtools/basic
671+
npx vibe-devtools install @vibe-devtools/research
672+
npx vibe-devtools list
673+
674+
# Usar no Cursor
675+
# /maker.command "criar meu primeiro command"
676+
677+
# 🎉 Ainda mais rápido! Zero instalação!
678+
```
679+
680+
**🔥 Pro tip**: Combine os dois! Use `npx` para experimentar, depois instale globalmente se gostar.
681+
653682
**Divirta-se criando! 🚀✨**

apps/cli/src/commands/install.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import path from 'node:path';
44
import chalk from 'chalk';
55
import ora from 'ora';
66
import { installFromGitHub, type VibeManifest } from '../installers/github-installer.js';
7+
import { installFromNpm } from '../installers/npm-installer.js';
78
import { createSymlink, getVibesHome, getVibePackageDir } from '../utils/symlink-manager.js';
89
import { AdapterRegistry, AgentDetector, type VibePackage, type TargetPaths } from '../adapters/index.js';
910

@@ -116,11 +117,6 @@ export async function installCommand(
116117

117118
const sourceType = detectSource(source);
118119

119-
if (sourceType !== 'github' && sourceType !== 'local') {
120-
spinner.fail(chalk.red('npm and local sources not yet implemented. Use GitHub URL.'));
121-
return;
122-
}
123-
124120
spinner.text = 'Downloading vibe...';
125121

126122
let manifest: VibeManifest;
@@ -130,6 +126,10 @@ export async function installCommand(
130126
const result = await installFromGitHub(source);
131127
manifest = result.manifest;
132128
installedPath = result.installedPath;
129+
} else if (sourceType === 'npm') {
130+
const result = await installFromNpm(source);
131+
manifest = result.manifest;
132+
installedPath = result.installedPath;
133133
} else {
134134
const absolutePath = path.resolve(source);
135135
const vibeJsonPath = path.join(absolutePath, 'vibe.json');
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import fs from 'node:fs/promises';
2+
import { existsSync } from 'node:fs';
3+
import path from 'node:path';
4+
import { exec } from 'node:child_process';
5+
import { promisify } from 'node:util';
6+
import { getVibesHome, getVibePackageDir } from '../utils/symlink-manager.js';
7+
8+
const execAsync = promisify(exec);
9+
10+
export interface VibeManifest {
11+
name: string;
12+
version: string;
13+
description?: string;
14+
symlinks?: Record<string, string>;
15+
agentTargets?: Record<string, any>;
16+
dependencies?: Record<string, string>;
17+
[key: string]: unknown;
18+
}
19+
20+
export interface InstallResult {
21+
manifest: VibeManifest;
22+
installedPath: string;
23+
}
24+
25+
function parseNpmSource(source: string): { packageName: string; version?: string } {
26+
const parts = source.split('@');
27+
28+
if (source.startsWith('@')) {
29+
if (parts.length === 3) {
30+
return {
31+
packageName: `@${parts[1]}`,
32+
version: parts[2]
33+
};
34+
}
35+
return {
36+
packageName: `@${parts[1]}`,
37+
version: undefined
38+
};
39+
}
40+
41+
return {
42+
packageName: parts[0],
43+
version: parts[1]
44+
};
45+
}
46+
47+
export async function installFromNpm(source: string): Promise<InstallResult> {
48+
const { packageName, version } = parseNpmSource(source);
49+
const packageSpec = version ? `${packageName}@${version}` : packageName;
50+
51+
const cacheDir = path.join(getVibesHome(), 'cache', 'npm');
52+
await fs.mkdir(cacheDir, { recursive: true });
53+
54+
const tempDir = path.join(cacheDir, `temp-${Date.now()}`);
55+
await fs.mkdir(tempDir, { recursive: true });
56+
57+
try {
58+
const { stdout } = await execAsync(
59+
`npm pack ${packageSpec} --json`,
60+
{ cwd: tempDir }
61+
);
62+
63+
const packResult = JSON.parse(stdout);
64+
const tarballFilename = packResult[0].filename;
65+
66+
const extractDir = path.join(tempDir, 'extracted');
67+
await fs.mkdir(extractDir, { recursive: true });
68+
69+
await execAsync(
70+
`tar -xzf ${tarballFilename} -C extracted`,
71+
{ cwd: tempDir }
72+
);
73+
74+
const packageDir = path.join(extractDir, 'package');
75+
const vibeJsonPath = path.join(packageDir, 'vibe.json');
76+
77+
if (!existsSync(vibeJsonPath)) {
78+
throw new Error(`Package ${packageName} is not a valid vibe (missing vibe.json)`);
79+
}
80+
81+
const vibeJsonContent = await fs.readFile(vibeJsonPath, 'utf-8');
82+
const manifest = JSON.parse(vibeJsonContent) as VibeManifest;
83+
84+
const installedPath = getVibePackageDir(manifest.name, manifest.version);
85+
86+
if (existsSync(installedPath)) {
87+
await fs.rm(installedPath, { recursive: true, force: true });
88+
}
89+
90+
await fs.mkdir(path.dirname(installedPath), { recursive: true });
91+
await fs.cp(packageDir, installedPath, { recursive: true });
92+
93+
await fs.rm(tempDir, { recursive: true, force: true });
94+
95+
return {
96+
manifest,
97+
installedPath
98+
};
99+
100+
} catch (error) {
101+
await fs.rm(tempDir, { recursive: true, force: true }).catch(() => {});
102+
throw new Error(`Failed to install from npm: ${(error as Error).message}`);
103+
}
104+
}
105+

0 commit comments

Comments
 (0)