@hypersocial/cli-games 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +2799 -296
- package/dist/cli.js.map +1 -1
- package/dist/{create-NVLKKJX6.js → create-CIK3AD2D.js} +3 -1
- package/dist/{create-NVLKKJX6.js.map → create-CIK3AD2D.js.map} +1 -1
- package/dist/index.js +2798 -307
- package/dist/index.js.map +1 -1
- package/dist/update-check-PNB4U4P7.js +130 -0
- package/dist/update-check-PNB4U4P7.js.map +1 -0
- package/package.json +1 -1
|
@@ -354,6 +354,8 @@ async function showDevMenu(repoRoot) {
|
|
|
354
354
|
async function vibeCommand(args) {
|
|
355
355
|
const name = args.filter((a) => !a.startsWith("--"))[0];
|
|
356
356
|
p.intro("cli-games");
|
|
357
|
+
const { checkForUpdateInteractive } = await import("./update-check-PNB4U4P7.js");
|
|
358
|
+
await checkForUpdateInteractive();
|
|
357
359
|
const repoRoot = await findOrSetupRepo();
|
|
358
360
|
if (!repoRoot) {
|
|
359
361
|
p.cancel("Cancelled.");
|
|
@@ -413,4 +415,4 @@ export {
|
|
|
413
415
|
removeCommand,
|
|
414
416
|
vibeCommand
|
|
415
417
|
};
|
|
416
|
-
//# sourceMappingURL=create-
|
|
418
|
+
//# sourceMappingURL=create-CIK3AD2D.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/create.ts"],"sourcesContent":["/**\n * `cli-games vibe` — developer hub for cli-games\n *\n * Interactive TUI for creating, vibe coding, playing, removing games,\n * and submitting PRs — all powered by clack prompts and Claude Code.\n */\n\nimport { readFileSync, writeFileSync, mkdirSync, existsSync, rmSync } from 'fs';\nimport { resolve, relative } from 'path';\nimport { execSync, spawn } from 'child_process';\nimport * as p from '@clack/prompts';\n\n// ---------------------------------------------------------------------------\n// Name utilities\n// ---------------------------------------------------------------------------\n\nfunction toKebab(name: string): string {\n return name.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');\n}\n\nfunction toPascal(kebab: string): string {\n return kebab.split('-').map(s => s.charAt(0).toUpperCase() + s.slice(1)).join('');\n}\n\nfunction toTitle(kebab: string): string {\n return kebab.split('-').map(s => s.charAt(0).toUpperCase() + s.slice(1)).join(' ');\n}\n\n// ---------------------------------------------------------------------------\n// Repo detection\n// ---------------------------------------------------------------------------\n\nfunction isCliGamesRepo(dir: string): boolean {\n return existsSync(resolve(dir, '.git')) &&\n existsSync(resolve(dir, 'src/games')) &&\n existsSync(resolve(dir, 'src/games/index.ts'));\n}\n\nfunction findRepoRoot(from: string): string | null {\n let dir = resolve(from);\n const root = resolve('/');\n while (dir !== root) {\n if (isCliGamesRepo(dir)) return dir;\n dir = resolve(dir, '..');\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Game registry parsing\n// ---------------------------------------------------------------------------\n\ninterface RegisteredGame {\n id: string;\n name: string;\n description: string;\n}\n\nfunction parseRegisteredGames(indexContent: string): RegisteredGame[] {\n const games: RegisteredGame[] = [];\n const regex = /\\{\\s*id:\\s*'([^']+)',\\s*name:\\s*'([^']+)',\\s*description:\\s*'([^']+)'/g;\n let match;\n while ((match = regex.exec(indexContent)) !== null) {\n games.push({ id: match[1], name: match[2], description: match[3] });\n }\n return games;\n}\n\nfunction getGames(repoRoot: string): RegisteredGame[] {\n const indexPath = resolve(repoRoot, 'src/games/index.ts');\n return parseRegisteredGames(readFileSync(indexPath, 'utf-8'));\n}\n\nfunction getUserGames(repoRoot: string): RegisteredGame[] {\n const allGames = getGames(repoRoot);\n\n // Games tracked in git are built-in; untracked ones are the user's\n let trackedFiles: string;\n try {\n trackedFiles = execSync('git ls-files src/games/', { cwd: repoRoot, encoding: 'utf-8' });\n } catch {\n return allGames;\n }\n\n const trackedDirs = new Set<string>();\n for (const line of trackedFiles.split('\\n')) {\n const match = line.match(/^src\\/games\\/([^/]+)\\//);\n if (match) trackedDirs.add(match[1]);\n }\n\n return allGames.filter(g => !trackedDirs.has(g.id));\n}\n\n// ---------------------------------------------------------------------------\n// Interactive repo setup\n// ---------------------------------------------------------------------------\n\nasync function findOrSetupRepo(): Promise<string | null> {\n const cwd = process.cwd();\n const found = findRepoRoot(cwd);\n if (found) return found;\n\n const setup = await p.select({\n message: 'You\\'re not inside the cli-games repository. How would you like to set up?',\n options: [\n { value: 'clone', label: 'Clone cli-games here', hint: `→ ${cwd}/cli-games` },\n { value: 'path', label: 'I already have it cloned', hint: 'enter path' },\n { value: 'cancel', label: 'Cancel' },\n ],\n });\n\n if (p.isCancel(setup) || setup === 'cancel') return null;\n\n if (setup === 'path') {\n const inputPath = await p.text({\n message: 'Path to your cli-games clone:',\n validate: (value) => {\n if (!value) return 'Path is required';\n if (!isCliGamesRepo(resolve(value))) {\n return 'Not a cli-games repo (missing src/games/index.ts or .git)';\n }\n },\n });\n if (p.isCancel(inputPath)) return null;\n return resolve(inputPath);\n }\n\n const targetDir = resolve(cwd, 'cli-games');\n if (existsSync(targetDir)) {\n if (isCliGamesRepo(targetDir)) {\n p.log.info('cli-games/ already exists here, using it.');\n return targetDir;\n }\n p.log.error(`${targetDir} exists but doesn't look like cli-games.`);\n return null;\n }\n\n const s = p.spinner();\n s.start('Cloning hypersocialinc/cli-games...');\n try {\n execSync('git clone https://github.com/hypersocialinc/cli-games.git', {\n cwd,\n stdio: 'ignore',\n });\n s.stop('Cloned cli-games.');\n } catch {\n s.stop('Clone failed.');\n p.log.error('Check your internet connection and git setup.');\n return null;\n }\n\n s.start('Installing dependencies...');\n try {\n execSync('npm install', { cwd: targetDir, stdio: 'ignore' });\n s.stop('Dependencies installed.');\n } catch {\n s.stop('npm install failed.');\n p.log.warn('You may need to run npm install manually.');\n }\n\n return targetDir;\n}\n\n// ---------------------------------------------------------------------------\n// Index manipulation\n// ---------------------------------------------------------------------------\n\nfunction addToIndex(indexPath: string, kebab: string, title: string, description: string, runFn: string) {\n let index = readFileSync(indexPath, 'utf-8');\n\n const importRegex = /^import \\{ run\\w+ \\} from '.\\/[^']+';$/gm;\n let lastImport: RegExpExecArray | null = null;\n let m: RegExpExecArray | null;\n while ((m = importRegex.exec(index)) !== null) lastImport = m;\n\n if (lastImport) {\n const pos = lastImport.index + lastImport[0].length;\n index = index.slice(0, pos) + `\\nimport { ${runFn} } from './${kebab}';` + index.slice(pos);\n }\n\n const entryRegex = /run: run\\w+ \\},?\\s*$/gm;\n let lastEntry: RegExpExecArray | null = null;\n while ((m = entryRegex.exec(index)) !== null) lastEntry = m;\n\n if (lastEntry) {\n const lineEnd = index.indexOf('\\n', lastEntry.index);\n const entry = `\\n { id: '${kebab}', name: '${title}', description: '${description}', run: ${runFn} },`;\n index = index.slice(0, lineEnd) + entry + index.slice(lineEnd);\n }\n\n const exportRegex = /^\\s+run\\w+(?:Game|Test),?$/gm;\n let lastExport: RegExpExecArray | null = null;\n while ((m = exportRegex.exec(index)) !== null) lastExport = m;\n\n if (lastExport) {\n const lineEnd = index.indexOf('\\n', lastExport.index);\n index = index.slice(0, lineEnd) + `\\n ${runFn},` + index.slice(lineEnd);\n }\n\n writeFileSync(indexPath, index);\n}\n\nfunction removeFromIndex(indexPath: string, kebab: string) {\n let index = readFileSync(indexPath, 'utf-8');\n\n index = index.replace(new RegExp(`^import \\\\{ run\\\\w+ \\\\} from '\\\\.\\\\/${kebab}';\\\\n`, 'gm'), '');\n index = index.replace(new RegExp(`^\\\\s*\\\\{[^}]*id:\\\\s*'${kebab}'[^}]*\\\\},?\\\\n`, 'gm'), '');\n\n const pascal = toPascal(kebab);\n const runFn = `run${pascal}Game`;\n index = index.replace(new RegExp(`^\\\\s+${runFn},?\\\\n`, 'gm'), '');\n\n writeFileSync(indexPath, index);\n}\n\n// ---------------------------------------------------------------------------\n// Launch Claude Code\n// ---------------------------------------------------------------------------\n\nfunction launchClaude(repoRoot: string, prompt: string): Promise<void> {\n p.log.info('Launching Claude Code...');\n\n const child = spawn('claude', [prompt], {\n cwd: repoRoot,\n stdio: 'inherit',\n });\n\n return new Promise((res) => {\n child.on('close', () => res());\n child.on('error', () => {\n p.log.error('Could not launch Claude Code. Is it installed? Run: npm install -g @anthropic-ai/claude-code');\n res();\n });\n });\n}\n\n// ---------------------------------------------------------------------------\n// Actions\n// ---------------------------------------------------------------------------\n\nasync function doCreate(repoRoot: string, initialName?: string) {\n let kebab: string;\n if (initialName) {\n kebab = toKebab(initialName);\n } else {\n const nameInput = await p.text({\n message: 'What\\'s your game called?',\n placeholder: 'space-dodge',\n validate: (value) => {\n if (!value) return 'Name is required';\n const k = toKebab(value);\n if (!/^[a-z][a-z0-9-]*$/.test(k) || k.length < 2) {\n return 'Use lowercase letters, numbers, and hyphens (e.g. space-dodge)';\n }\n if (existsSync(resolve(repoRoot, 'src/games', k))) {\n return `Game \"${k}\" already exists`;\n }\n },\n });\n if (p.isCancel(nameInput)) return;\n kebab = toKebab(nameInput);\n }\n\n if (!/^[a-z][a-z0-9-]*$/.test(kebab) || kebab.length < 2) {\n p.log.error(`Invalid game name: \"${kebab}\"`);\n return;\n }\n\n const gamesDir = resolve(repoRoot, 'src/games');\n const gameDir = resolve(gamesDir, kebab);\n\n if (existsSync(gameDir)) {\n p.log.error(`Game \"${kebab}\" already exists at src/games/${kebab}/`);\n return;\n }\n\n const descInput = await p.text({\n message: 'Describe your game in a few words:',\n placeholder: 'A terminal game',\n defaultValue: 'A terminal game',\n });\n if (p.isCancel(descInput)) return;\n const description = descInput || 'A terminal game';\n\n const pascal = toPascal(kebab);\n const title = toTitle(kebab);\n const runFn = `run${pascal}Game`;\n\n // Install skill if needed\n const skillPath = resolve(repoRoot, '.claude/skills/game-dev');\n if (!existsSync(skillPath)) {\n const s = p.spinner();\n s.start('Installing game-dev skill for Claude Code...');\n try {\n execSync('npx skills add hypersocialinc/cli-games -a claude-code -s game-dev -y', {\n cwd: repoRoot,\n stdio: 'ignore',\n });\n s.stop('Installed game-dev skill.');\n } catch {\n s.stop('Could not install game-dev skill.');\n }\n }\n\n // Read and fill template\n const templatePath = resolve(repoRoot, '.claude/skills/game-dev/templates/game-scaffold.ts');\n if (!existsSync(templatePath)) {\n p.cancel(`Template not found at ${templatePath}`);\n return;\n }\n\n let template = readFileSync(templatePath, 'utf-8');\n template = template.replace(/\\{GameName\\}/g, pascal);\n template = template.replace(/\\{GAME_NAME\\}/g, title);\n template = template.replace(/\\{GAME_DESCRIPTION\\}/g, description);\n template = template.replace(/\\{TITLE_LINE_1\\}/g, title.toUpperCase());\n template = template.replace(/\\{TITLE_LINE_2\\}/g, '═'.repeat(title.length));\n template = template.replace(/\\{CONTROLS_HINT\\}/g, 'Arrow keys to move, Space to act');\n\n mkdirSync(gameDir, { recursive: true });\n writeFileSync(resolve(gameDir, 'index.ts'), template);\n p.log.success(`Created src/games/${kebab}/index.ts`);\n\n addToIndex(resolve(gamesDir, 'index.ts'), kebab, title, description, runFn);\n p.log.success('Registered in src/games/index.ts');\n\n // Offer to launch Claude Code\n const vibeNow = await p.confirm({\n message: 'Launch Claude Code to start vibe coding?',\n });\n if (!p.isCancel(vibeNow) && vibeNow) {\n await launchClaude(repoRoot, `Build out the ${kebab} game. It should be: ${description}. Use the game-dev skill — check src/games/${kebab}/index.ts for the scaffold.`);\n } else {\n const needsCd = resolve(repoRoot) !== resolve(process.cwd());\n const rel = relative(process.cwd(), repoRoot);\n const cdPath = rel.startsWith('..') ? resolve(repoRoot) : rel;\n\n const steps = [\n ...(needsCd ? [`cd ${cdPath}`] : []),\n 'Open Claude Code in this directory',\n `Tell Claude: \"Build out the ${kebab} game — make it a [your idea]\"`,\n `Test with: npx cli-games ${kebab}`,\n 'Submit a PR when ready!',\n ];\n\n p.note(steps.map((s, i) => `${i + 1}. ${s}`).join('\\n'), 'Next steps');\n }\n}\n\n// ---------------------------------------------------------------------------\n// Game actions — second-level menu after picking a game\n// ---------------------------------------------------------------------------\n\nasync function playGame(repoRoot: string, gameId: string) {\n const s = p.spinner();\n s.start('Building...');\n try {\n execSync('npm run build', { cwd: repoRoot, stdio: 'ignore' });\n s.stop('Build complete.');\n } catch {\n s.stop('Build failed.');\n p.log.error('Fix build errors and try again.');\n return;\n }\n\n p.log.info(`Launching ${gameId}... (press Q to quit back here)`);\n\n const cliPath = resolve(repoRoot, 'dist/cli.js');\n const child = spawn('node', [cliPath, gameId], {\n cwd: repoRoot,\n stdio: 'inherit',\n });\n\n await new Promise<void>((res) => {\n child.on('close', () => res());\n });\n}\n\nasync function vibeCodeGame(repoRoot: string, gameId: string) {\n const idea = await p.text({\n message: 'What do you want Claude to do?',\n placeholder: `Make ${gameId} a fast-paced bullet-hell dodger`,\n });\n if (p.isCancel(idea) || !idea) return;\n\n await launchClaude(repoRoot, `${idea}. Work on src/games/${gameId}/index.ts. Use the game-dev skill for patterns and conventions.`);\n}\n\nasync function removeGame(repoRoot: string, gameId: string) {\n const gamesDir = resolve(repoRoot, 'src/games');\n const game = getGames(repoRoot).find(g => g.id === gameId)!;\n const gameDir = resolve(gamesDir, gameId);\n\n const confirmed = await p.confirm({\n message: `Remove ${game.name}? This deletes src/games/${gameId}/ and unregisters it.`,\n });\n if (p.isCancel(confirmed) || !confirmed) return;\n\n if (existsSync(gameDir)) {\n rmSync(gameDir, { recursive: true });\n p.log.success(`Deleted src/games/${gameId}/`);\n }\n\n removeFromIndex(resolve(gamesDir, 'index.ts'), gameId);\n p.log.success('Unregistered from src/games/index.ts');\n}\n\nasync function submitPR(repoRoot: string, gameId: string) {\n const game = getGames(repoRoot).find(g => g.id === gameId)!;\n await launchClaude(repoRoot, `Help me submit a PR for the ${game.name} game. Check git status, create a branch if needed, commit the changes in src/games/${gameId}/ and src/games/index.ts, and open a PR.`);\n}\n\nasync function showGameActions(repoRoot: string, gameId: string) {\n const game = getGames(repoRoot).find(g => g.id === gameId)!;\n\n const action = await p.select({\n message: `${game.name} — ${game.description}`,\n options: [\n { value: 'play', label: 'Play', hint: 'build & launch' },\n { value: 'vibe', label: 'Vibe code', hint: 'launch Claude Code' },\n { value: 'pr', label: 'Submit a PR', hint: 'launch Claude Code' },\n { value: 'remove', label: 'Remove', hint: 'delete + unregister' },\n { value: 'back', label: 'Back' },\n ],\n });\n\n if (p.isCancel(action) || action === 'back') return;\n\n if (action === 'play') await playGame(repoRoot, gameId);\n if (action === 'vibe') await vibeCodeGame(repoRoot, gameId);\n if (action === 'pr') await submitPR(repoRoot, gameId);\n if (action === 'remove') await removeGame(repoRoot, gameId);\n}\n\n// ---------------------------------------------------------------------------\n// Dev menu — top level\n// ---------------------------------------------------------------------------\n\nasync function showDevMenu(repoRoot: string) {\n const userGames = getUserGames(repoRoot);\n\n type MenuOption = { value: string; label: string; hint?: string };\n const options: MenuOption[] = [\n { value: 'create', label: 'Create a new game' },\n ];\n\n if (userGames.length > 0) {\n options.push({ value: 'games', label: 'Your games', hint: `${userGames.length} game${userGames.length === 1 ? '' : 's'}` });\n }\n\n options.push({ value: 'exit', label: 'Exit' });\n\n const action = await p.select({ message: 'What would you like to do?', options });\n\n if (p.isCancel(action) || action === 'exit') return;\n\n if (action === 'create') {\n await doCreate(repoRoot);\n return;\n }\n\n if (action === 'games') {\n const selected = await p.select({\n message: 'Pick a game:',\n options: userGames.map(g => ({\n value: g.id,\n label: g.name,\n hint: g.description,\n })),\n });\n if (p.isCancel(selected)) return;\n\n await showGameActions(repoRoot, selected);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Entry points — called from cli.ts\n// ---------------------------------------------------------------------------\n\nexport async function vibeCommand(args: string[]) {\n const name = args.filter(a => !a.startsWith('--'))[0];\n\n p.intro('cli-games');\n\n const repoRoot = await findOrSetupRepo();\n if (!repoRoot) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n\n if (name) {\n // cli-games vibe <name> — if game exists, show actions; if not, create it\n const kebab = toKebab(name);\n const games = getGames(repoRoot);\n const existing = games.find(g => g.id === kebab);\n if (existing) {\n await showGameActions(repoRoot, kebab);\n } else {\n await doCreate(repoRoot, name);\n }\n } else {\n await showDevMenu(repoRoot);\n }\n\n p.outro('Happy building!');\n}\n\nexport async function removeCommand(args: string[]) {\n const name = args.filter(a => !a.startsWith('--'))[0];\n\n p.intro('cli-games');\n\n const repoRoot = await findOrSetupRepo();\n if (!repoRoot) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n\n if (name) {\n const kebab = toKebab(name);\n const games = getGames(repoRoot);\n if (!games.find(g => g.id === kebab)) {\n p.log.error(`Game \"${kebab}\" not found.`);\n } else {\n await removeGame(repoRoot, kebab);\n }\n } else {\n // No name — show game picker\n const games = getGames(repoRoot);\n if (games.length === 0) {\n p.log.warn('No games found.');\n } else {\n const selected = await p.select({\n message: 'Which game do you want to remove?',\n options: games.map(g => ({\n value: g.id,\n label: g.name,\n hint: g.description,\n })),\n });\n if (!p.isCancel(selected)) {\n await removeGame(repoRoot, selected);\n }\n }\n }\n\n p.outro('Done.');\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/create.ts"],"sourcesContent":["/**\n * `cli-games vibe` — developer hub for cli-games\n *\n * Interactive TUI for creating, vibe coding, playing, removing games,\n * and submitting PRs — all powered by clack prompts and Claude Code.\n */\n\nimport { readFileSync, writeFileSync, mkdirSync, existsSync, rmSync } from 'fs';\nimport { resolve, relative } from 'path';\nimport { execSync, spawn } from 'child_process';\nimport * as p from '@clack/prompts';\n\n// ---------------------------------------------------------------------------\n// Name utilities\n// ---------------------------------------------------------------------------\n\nfunction toKebab(name: string): string {\n return name.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');\n}\n\nfunction toPascal(kebab: string): string {\n return kebab.split('-').map(s => s.charAt(0).toUpperCase() + s.slice(1)).join('');\n}\n\nfunction toTitle(kebab: string): string {\n return kebab.split('-').map(s => s.charAt(0).toUpperCase() + s.slice(1)).join(' ');\n}\n\n// ---------------------------------------------------------------------------\n// Repo detection\n// ---------------------------------------------------------------------------\n\nfunction isCliGamesRepo(dir: string): boolean {\n return existsSync(resolve(dir, '.git')) &&\n existsSync(resolve(dir, 'src/games')) &&\n existsSync(resolve(dir, 'src/games/index.ts'));\n}\n\nfunction findRepoRoot(from: string): string | null {\n let dir = resolve(from);\n const root = resolve('/');\n while (dir !== root) {\n if (isCliGamesRepo(dir)) return dir;\n dir = resolve(dir, '..');\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Game registry parsing\n// ---------------------------------------------------------------------------\n\ninterface RegisteredGame {\n id: string;\n name: string;\n description: string;\n}\n\nfunction parseRegisteredGames(indexContent: string): RegisteredGame[] {\n const games: RegisteredGame[] = [];\n const regex = /\\{\\s*id:\\s*'([^']+)',\\s*name:\\s*'([^']+)',\\s*description:\\s*'([^']+)'/g;\n let match;\n while ((match = regex.exec(indexContent)) !== null) {\n games.push({ id: match[1], name: match[2], description: match[3] });\n }\n return games;\n}\n\nfunction getGames(repoRoot: string): RegisteredGame[] {\n const indexPath = resolve(repoRoot, 'src/games/index.ts');\n return parseRegisteredGames(readFileSync(indexPath, 'utf-8'));\n}\n\nfunction getUserGames(repoRoot: string): RegisteredGame[] {\n const allGames = getGames(repoRoot);\n\n // Games tracked in git are built-in; untracked ones are the user's\n let trackedFiles: string;\n try {\n trackedFiles = execSync('git ls-files src/games/', { cwd: repoRoot, encoding: 'utf-8' });\n } catch {\n return allGames;\n }\n\n const trackedDirs = new Set<string>();\n for (const line of trackedFiles.split('\\n')) {\n const match = line.match(/^src\\/games\\/([^/]+)\\//);\n if (match) trackedDirs.add(match[1]);\n }\n\n return allGames.filter(g => !trackedDirs.has(g.id));\n}\n\n// ---------------------------------------------------------------------------\n// Interactive repo setup\n// ---------------------------------------------------------------------------\n\nasync function findOrSetupRepo(): Promise<string | null> {\n const cwd = process.cwd();\n const found = findRepoRoot(cwd);\n if (found) return found;\n\n const setup = await p.select({\n message: 'You\\'re not inside the cli-games repository. How would you like to set up?',\n options: [\n { value: 'clone', label: 'Clone cli-games here', hint: `→ ${cwd}/cli-games` },\n { value: 'path', label: 'I already have it cloned', hint: 'enter path' },\n { value: 'cancel', label: 'Cancel' },\n ],\n });\n\n if (p.isCancel(setup) || setup === 'cancel') return null;\n\n if (setup === 'path') {\n const inputPath = await p.text({\n message: 'Path to your cli-games clone:',\n validate: (value) => {\n if (!value) return 'Path is required';\n if (!isCliGamesRepo(resolve(value))) {\n return 'Not a cli-games repo (missing src/games/index.ts or .git)';\n }\n },\n });\n if (p.isCancel(inputPath)) return null;\n return resolve(inputPath);\n }\n\n const targetDir = resolve(cwd, 'cli-games');\n if (existsSync(targetDir)) {\n if (isCliGamesRepo(targetDir)) {\n p.log.info('cli-games/ already exists here, using it.');\n return targetDir;\n }\n p.log.error(`${targetDir} exists but doesn't look like cli-games.`);\n return null;\n }\n\n const s = p.spinner();\n s.start('Cloning hypersocialinc/cli-games...');\n try {\n execSync('git clone https://github.com/hypersocialinc/cli-games.git', {\n cwd,\n stdio: 'ignore',\n });\n s.stop('Cloned cli-games.');\n } catch {\n s.stop('Clone failed.');\n p.log.error('Check your internet connection and git setup.');\n return null;\n }\n\n s.start('Installing dependencies...');\n try {\n execSync('npm install', { cwd: targetDir, stdio: 'ignore' });\n s.stop('Dependencies installed.');\n } catch {\n s.stop('npm install failed.');\n p.log.warn('You may need to run npm install manually.');\n }\n\n return targetDir;\n}\n\n// ---------------------------------------------------------------------------\n// Index manipulation\n// ---------------------------------------------------------------------------\n\nfunction addToIndex(indexPath: string, kebab: string, title: string, description: string, runFn: string) {\n let index = readFileSync(indexPath, 'utf-8');\n\n const importRegex = /^import \\{ run\\w+ \\} from '.\\/[^']+';$/gm;\n let lastImport: RegExpExecArray | null = null;\n let m: RegExpExecArray | null;\n while ((m = importRegex.exec(index)) !== null) lastImport = m;\n\n if (lastImport) {\n const pos = lastImport.index + lastImport[0].length;\n index = index.slice(0, pos) + `\\nimport { ${runFn} } from './${kebab}';` + index.slice(pos);\n }\n\n const entryRegex = /run: run\\w+ \\},?\\s*$/gm;\n let lastEntry: RegExpExecArray | null = null;\n while ((m = entryRegex.exec(index)) !== null) lastEntry = m;\n\n if (lastEntry) {\n const lineEnd = index.indexOf('\\n', lastEntry.index);\n const entry = `\\n { id: '${kebab}', name: '${title}', description: '${description}', run: ${runFn} },`;\n index = index.slice(0, lineEnd) + entry + index.slice(lineEnd);\n }\n\n const exportRegex = /^\\s+run\\w+(?:Game|Test),?$/gm;\n let lastExport: RegExpExecArray | null = null;\n while ((m = exportRegex.exec(index)) !== null) lastExport = m;\n\n if (lastExport) {\n const lineEnd = index.indexOf('\\n', lastExport.index);\n index = index.slice(0, lineEnd) + `\\n ${runFn},` + index.slice(lineEnd);\n }\n\n writeFileSync(indexPath, index);\n}\n\nfunction removeFromIndex(indexPath: string, kebab: string) {\n let index = readFileSync(indexPath, 'utf-8');\n\n index = index.replace(new RegExp(`^import \\\\{ run\\\\w+ \\\\} from '\\\\.\\\\/${kebab}';\\\\n`, 'gm'), '');\n index = index.replace(new RegExp(`^\\\\s*\\\\{[^}]*id:\\\\s*'${kebab}'[^}]*\\\\},?\\\\n`, 'gm'), '');\n\n const pascal = toPascal(kebab);\n const runFn = `run${pascal}Game`;\n index = index.replace(new RegExp(`^\\\\s+${runFn},?\\\\n`, 'gm'), '');\n\n writeFileSync(indexPath, index);\n}\n\n// ---------------------------------------------------------------------------\n// Launch Claude Code\n// ---------------------------------------------------------------------------\n\nfunction launchClaude(repoRoot: string, prompt: string): Promise<void> {\n p.log.info('Launching Claude Code...');\n\n const child = spawn('claude', [prompt], {\n cwd: repoRoot,\n stdio: 'inherit',\n });\n\n return new Promise((res) => {\n child.on('close', () => res());\n child.on('error', () => {\n p.log.error('Could not launch Claude Code. Is it installed? Run: npm install -g @anthropic-ai/claude-code');\n res();\n });\n });\n}\n\n// ---------------------------------------------------------------------------\n// Actions\n// ---------------------------------------------------------------------------\n\nasync function doCreate(repoRoot: string, initialName?: string) {\n let kebab: string;\n if (initialName) {\n kebab = toKebab(initialName);\n } else {\n const nameInput = await p.text({\n message: 'What\\'s your game called?',\n placeholder: 'space-dodge',\n validate: (value) => {\n if (!value) return 'Name is required';\n const k = toKebab(value);\n if (!/^[a-z][a-z0-9-]*$/.test(k) || k.length < 2) {\n return 'Use lowercase letters, numbers, and hyphens (e.g. space-dodge)';\n }\n if (existsSync(resolve(repoRoot, 'src/games', k))) {\n return `Game \"${k}\" already exists`;\n }\n },\n });\n if (p.isCancel(nameInput)) return;\n kebab = toKebab(nameInput);\n }\n\n if (!/^[a-z][a-z0-9-]*$/.test(kebab) || kebab.length < 2) {\n p.log.error(`Invalid game name: \"${kebab}\"`);\n return;\n }\n\n const gamesDir = resolve(repoRoot, 'src/games');\n const gameDir = resolve(gamesDir, kebab);\n\n if (existsSync(gameDir)) {\n p.log.error(`Game \"${kebab}\" already exists at src/games/${kebab}/`);\n return;\n }\n\n const descInput = await p.text({\n message: 'Describe your game in a few words:',\n placeholder: 'A terminal game',\n defaultValue: 'A terminal game',\n });\n if (p.isCancel(descInput)) return;\n const description = descInput || 'A terminal game';\n\n const pascal = toPascal(kebab);\n const title = toTitle(kebab);\n const runFn = `run${pascal}Game`;\n\n // Install skill if needed\n const skillPath = resolve(repoRoot, '.claude/skills/game-dev');\n if (!existsSync(skillPath)) {\n const s = p.spinner();\n s.start('Installing game-dev skill for Claude Code...');\n try {\n execSync('npx skills add hypersocialinc/cli-games -a claude-code -s game-dev -y', {\n cwd: repoRoot,\n stdio: 'ignore',\n });\n s.stop('Installed game-dev skill.');\n } catch {\n s.stop('Could not install game-dev skill.');\n }\n }\n\n // Read and fill template\n const templatePath = resolve(repoRoot, '.claude/skills/game-dev/templates/game-scaffold.ts');\n if (!existsSync(templatePath)) {\n p.cancel(`Template not found at ${templatePath}`);\n return;\n }\n\n let template = readFileSync(templatePath, 'utf-8');\n template = template.replace(/\\{GameName\\}/g, pascal);\n template = template.replace(/\\{GAME_NAME\\}/g, title);\n template = template.replace(/\\{GAME_DESCRIPTION\\}/g, description);\n template = template.replace(/\\{TITLE_LINE_1\\}/g, title.toUpperCase());\n template = template.replace(/\\{TITLE_LINE_2\\}/g, '═'.repeat(title.length));\n template = template.replace(/\\{CONTROLS_HINT\\}/g, 'Arrow keys to move, Space to act');\n\n mkdirSync(gameDir, { recursive: true });\n writeFileSync(resolve(gameDir, 'index.ts'), template);\n p.log.success(`Created src/games/${kebab}/index.ts`);\n\n addToIndex(resolve(gamesDir, 'index.ts'), kebab, title, description, runFn);\n p.log.success('Registered in src/games/index.ts');\n\n // Offer to launch Claude Code\n const vibeNow = await p.confirm({\n message: 'Launch Claude Code to start vibe coding?',\n });\n if (!p.isCancel(vibeNow) && vibeNow) {\n await launchClaude(repoRoot, `Build out the ${kebab} game. It should be: ${description}. Use the game-dev skill — check src/games/${kebab}/index.ts for the scaffold.`);\n } else {\n const needsCd = resolve(repoRoot) !== resolve(process.cwd());\n const rel = relative(process.cwd(), repoRoot);\n const cdPath = rel.startsWith('..') ? resolve(repoRoot) : rel;\n\n const steps = [\n ...(needsCd ? [`cd ${cdPath}`] : []),\n 'Open Claude Code in this directory',\n `Tell Claude: \"Build out the ${kebab} game — make it a [your idea]\"`,\n `Test with: npx cli-games ${kebab}`,\n 'Submit a PR when ready!',\n ];\n\n p.note(steps.map((s, i) => `${i + 1}. ${s}`).join('\\n'), 'Next steps');\n }\n}\n\n// ---------------------------------------------------------------------------\n// Game actions — second-level menu after picking a game\n// ---------------------------------------------------------------------------\n\nasync function playGame(repoRoot: string, gameId: string) {\n const s = p.spinner();\n s.start('Building...');\n try {\n execSync('npm run build', { cwd: repoRoot, stdio: 'ignore' });\n s.stop('Build complete.');\n } catch {\n s.stop('Build failed.');\n p.log.error('Fix build errors and try again.');\n return;\n }\n\n p.log.info(`Launching ${gameId}... (press Q to quit back here)`);\n\n const cliPath = resolve(repoRoot, 'dist/cli.js');\n const child = spawn('node', [cliPath, gameId], {\n cwd: repoRoot,\n stdio: 'inherit',\n });\n\n await new Promise<void>((res) => {\n child.on('close', () => res());\n });\n}\n\nasync function vibeCodeGame(repoRoot: string, gameId: string) {\n const idea = await p.text({\n message: 'What do you want Claude to do?',\n placeholder: `Make ${gameId} a fast-paced bullet-hell dodger`,\n });\n if (p.isCancel(idea) || !idea) return;\n\n await launchClaude(repoRoot, `${idea}. Work on src/games/${gameId}/index.ts. Use the game-dev skill for patterns and conventions.`);\n}\n\nasync function removeGame(repoRoot: string, gameId: string) {\n const gamesDir = resolve(repoRoot, 'src/games');\n const game = getGames(repoRoot).find(g => g.id === gameId)!;\n const gameDir = resolve(gamesDir, gameId);\n\n const confirmed = await p.confirm({\n message: `Remove ${game.name}? This deletes src/games/${gameId}/ and unregisters it.`,\n });\n if (p.isCancel(confirmed) || !confirmed) return;\n\n if (existsSync(gameDir)) {\n rmSync(gameDir, { recursive: true });\n p.log.success(`Deleted src/games/${gameId}/`);\n }\n\n removeFromIndex(resolve(gamesDir, 'index.ts'), gameId);\n p.log.success('Unregistered from src/games/index.ts');\n}\n\nasync function submitPR(repoRoot: string, gameId: string) {\n const game = getGames(repoRoot).find(g => g.id === gameId)!;\n await launchClaude(repoRoot, `Help me submit a PR for the ${game.name} game. Check git status, create a branch if needed, commit the changes in src/games/${gameId}/ and src/games/index.ts, and open a PR.`);\n}\n\nasync function showGameActions(repoRoot: string, gameId: string) {\n const game = getGames(repoRoot).find(g => g.id === gameId)!;\n\n const action = await p.select({\n message: `${game.name} — ${game.description}`,\n options: [\n { value: 'play', label: 'Play', hint: 'build & launch' },\n { value: 'vibe', label: 'Vibe code', hint: 'launch Claude Code' },\n { value: 'pr', label: 'Submit a PR', hint: 'launch Claude Code' },\n { value: 'remove', label: 'Remove', hint: 'delete + unregister' },\n { value: 'back', label: 'Back' },\n ],\n });\n\n if (p.isCancel(action) || action === 'back') return;\n\n if (action === 'play') await playGame(repoRoot, gameId);\n if (action === 'vibe') await vibeCodeGame(repoRoot, gameId);\n if (action === 'pr') await submitPR(repoRoot, gameId);\n if (action === 'remove') await removeGame(repoRoot, gameId);\n}\n\n// ---------------------------------------------------------------------------\n// Dev menu — top level\n// ---------------------------------------------------------------------------\n\nasync function showDevMenu(repoRoot: string) {\n const userGames = getUserGames(repoRoot);\n\n type MenuOption = { value: string; label: string; hint?: string };\n const options: MenuOption[] = [\n { value: 'create', label: 'Create a new game' },\n ];\n\n if (userGames.length > 0) {\n options.push({ value: 'games', label: 'Your games', hint: `${userGames.length} game${userGames.length === 1 ? '' : 's'}` });\n }\n\n options.push({ value: 'exit', label: 'Exit' });\n\n const action = await p.select({ message: 'What would you like to do?', options });\n\n if (p.isCancel(action) || action === 'exit') return;\n\n if (action === 'create') {\n await doCreate(repoRoot);\n return;\n }\n\n if (action === 'games') {\n const selected = await p.select({\n message: 'Pick a game:',\n options: userGames.map(g => ({\n value: g.id,\n label: g.name,\n hint: g.description,\n })),\n });\n if (p.isCancel(selected)) return;\n\n await showGameActions(repoRoot, selected);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Entry points — called from cli.ts\n// ---------------------------------------------------------------------------\n\nexport async function vibeCommand(args: string[]) {\n const name = args.filter(a => !a.startsWith('--'))[0];\n\n p.intro('cli-games');\n\n // Interactive update check — offer to update if outdated\n const { checkForUpdateInteractive } = await import('./update-check');\n await checkForUpdateInteractive();\n\n const repoRoot = await findOrSetupRepo();\n if (!repoRoot) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n\n if (name) {\n // cli-games vibe <name> — if game exists, show actions; if not, create it\n const kebab = toKebab(name);\n const games = getGames(repoRoot);\n const existing = games.find(g => g.id === kebab);\n if (existing) {\n await showGameActions(repoRoot, kebab);\n } else {\n await doCreate(repoRoot, name);\n }\n } else {\n await showDevMenu(repoRoot);\n }\n\n p.outro('Happy building!');\n}\n\nexport async function removeCommand(args: string[]) {\n const name = args.filter(a => !a.startsWith('--'))[0];\n\n p.intro('cli-games');\n\n const repoRoot = await findOrSetupRepo();\n if (!repoRoot) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n\n if (name) {\n const kebab = toKebab(name);\n const games = getGames(repoRoot);\n if (!games.find(g => g.id === kebab)) {\n p.log.error(`Game \"${kebab}\" not found.`);\n } else {\n await removeGame(repoRoot, kebab);\n }\n } else {\n // No name — show game picker\n const games = getGames(repoRoot);\n if (games.length === 0) {\n p.log.warn('No games found.');\n } else {\n const selected = await p.select({\n message: 'Which game do you want to remove?',\n options: games.map(g => ({\n value: g.id,\n label: g.name,\n hint: g.description,\n })),\n });\n if (!p.isCancel(selected)) {\n await removeGame(repoRoot, selected);\n }\n }\n }\n\n p.outro('Done.');\n}\n"],"mappings":"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","names":[]}
|