open source is social v-it.org
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

add skill installation to setup and skill check to doctor

setup now runs `npx skills add` to install the using-vit skill for
Claude Code after tool checks pass. Gracefully skips if npx is missing
or the install fails. doctor reports whether the skill is installed via
a fast filesystem check (no network, no subprocess).

+64
+4
.gitignore
··· 5 5 6 6 # Environment 7 7 .env 8 + 9 + # Skills 10 + .agents/ 11 + .claude/skills/
+9
src/cmd/doctor.js
··· 3 3 4 4 import { loadConfig } from '../lib/config.js'; 5 5 import { readProjectConfig } from '../lib/vit-dir.js'; 6 + import { existsSync } from 'node:fs'; 7 + import { join } from 'node:path'; 6 8 7 9 export default function register(program) { 8 10 program ··· 23 25 console.log(`beacon: ${projConfig.beacon}`); 24 26 } else { 25 27 console.log('beacon: not set'); 28 + } 29 + 30 + const skillPath = join(process.cwd(), '.claude', 'skills', 'using-vit', 'SKILL.md'); 31 + if (existsSync(skillPath)) { 32 + console.log('skill: ok (using-vit)'); 33 + } else { 34 + console.log('skill: not installed (run vit setup)'); 26 35 } 27 36 } catch (err) { 28 37 console.error(err instanceof Error ? err.message : String(err));
+24
src/cmd/setup.js
··· 28 28 return; 29 29 } 30 30 31 + // skill installation 32 + const npxPath = Bun.which('npx'); 33 + if (npxPath) { 34 + try { 35 + const result = Bun.spawnSync( 36 + ['npx', 'skills', 'add', 'https://github.com/solpbc/vit/tree/main/skills/vit', '-a', 'claude-code', '-y'], 37 + { 38 + stdout: 'pipe', 39 + stderr: 'pipe', 40 + } 41 + ); 42 + if (result.exitCode === 0) { 43 + console.log('skill: installed (using-vit)'); 44 + } else { 45 + const errText = result.stderr.toString().trim(); 46 + console.log(`skill: failed (${errText || 'unknown error'})`); 47 + } 48 + } catch { 49 + console.log('skill: failed (could not run npx skills)'); 50 + } 51 + } else { 52 + console.log('skill: skipped (npx not found)'); 53 + } 54 + 31 55 const config = loadConfig(); 32 56 if (config.did) { 33 57 console.log(`login: ${config.did}`);
+22
test/doctor.test.js
··· 1 + // SPDX-License-Identifier: AGPL-3.0-only 2 + // Copyright (c) 2026 sol pbc 3 + 4 + import { describe, test, expect } from 'bun:test'; 5 + import { run } from './helpers.js'; 6 + 7 + describe('vit doctor', () => { 8 + test('reports setup status', () => { 9 + const result = run('doctor'); 10 + expect(result.stdout).toMatch(/setup:/); 11 + }); 12 + 13 + test('reports beacon status', () => { 14 + const result = run('doctor'); 15 + expect(result.stdout).toMatch(/beacon:/); 16 + }); 17 + 18 + test('reports skill status', () => { 19 + const result = run('doctor'); 20 + expect(result.stdout).toMatch(/skill:/); 21 + }); 22 + });
+5
test/setup.test.js
··· 21 21 const result = run('setup', undefined, { CLAUDECODE: '', GEMINI_CLI: '', CODEX_CI: '' }); 22 22 expect(result.stdout).toMatch(/login:/); 23 23 }); 24 + 25 + test('reports skill installation status', () => { 26 + const result = run('setup', undefined, { CLAUDECODE: '', GEMINI_CLI: '', CODEX_CI: '' }); 27 + expect(result.stdout).toMatch(/skill:/); 28 + }); 24 29 });