diff --git a/src/cmd/beacon.js b/src/cmd/beacon.js index bac00c7..fa4dfe5 100644 --- a/src/cmd/beacon.js +++ b/src/cmd/beacon.js @@ -52,7 +52,8 @@ export default function register(program) { if (beacon) { console.log(`${mark} beacon: lit ${beacon}`); } else { - console.log(`${mark} beacon: unlit`); + console.log(`${mark} beacon: unlit — this repo hasn't initialized vit yet.`); + console.log("the maintainer can light the beacon by running 'vit init' inside the repo."); } } catch (err) { console.error(err instanceof Error ? err.message : String(err)); diff --git a/src/cmd/config.js b/src/cmd/config.js index a7641fa..18ca93b 100644 --- a/src/cmd/config.js +++ b/src/cmd/config.js @@ -23,7 +23,12 @@ export default function register(program) { // Default to list when no action given if (!action || action === 'list') { const config = loadConfig(); - for (const [k, v] of getScalars(config)) { + const scalars = [...getScalars(config)]; + if (scalars.length === 0) { + console.log("no configuration set. run 'vit login ' to get started."); + return; + } + for (const [k, v] of scalars) { console.log(`${k}=${v}`); } return; diff --git a/src/cmd/doctor.js b/src/cmd/doctor.js index 98ff6ba..520f7f5 100644 --- a/src/cmd/doctor.js +++ b/src/cmd/doctor.js @@ -88,7 +88,7 @@ export default function register(program) { if (projConfig.beacon) { if (!opts.json) console.log(`${mark} beacon: ${projConfig.beacon}`); } else { - if (!opts.json) console.log(`${mark} beacon: not set`); + if (!opts.json) console.log(`${mark} beacon: not set (run vit init)`); } const skillPath = join(process.cwd(), '.claude', 'skills', 'using-vit', 'SKILL.md'); diff --git a/src/cmd/explore.js b/src/cmd/explore.js index 02f3c69..c86ea6d 100644 --- a/src/cmd/explore.js +++ b/src/cmd/explore.js @@ -255,6 +255,8 @@ export default function register(program) { console.log(`${brand} explore caps`); if (!data.caps?.length) { console.log('no caps found.'); + console.log('the network is just getting started. ship a cap or skill to be one of the first.'); + console.log("try 'vit scan' for real-time discovery — the explore index may still be catching up."); return; } @@ -310,6 +312,7 @@ export default function register(program) { console.log(`${brand} explore skills`); if (!data.skills?.length) { console.log('no skills found.'); + console.log('the network is just getting started. ship a cap or skill to be one of the first.'); return; } @@ -357,6 +360,7 @@ export default function register(program) { console.log(`${brand} explore beacons`); if (!data.beacons?.length) { console.log('no beacons found.'); + console.log('the network is just getting started. ship a cap or skill to be one of the first.'); return; } diff --git a/src/cmd/follow.js b/src/cmd/follow.js index 137a724..e5cf37e 100644 --- a/src/cmd/follow.js +++ b/src/cmd/follow.js @@ -117,10 +117,13 @@ export default function register(program) { const list = readFollowing(); if (list.length === 0) { if (opts.json) { - jsonOk({ following: [] }); + jsonOk({ following: [], hint: "run 'vit follow ' to add accounts" }); return; } - console.log('no followings'); + console.log('not following anyone yet.'); + console.log(''); + console.log("run 'vit follow ' to start seeing what people are shipping."); + console.log("try 'vit scan' to discover active publishers on the network."); return; } if (opts.json) { diff --git a/src/cmd/learn.js b/src/cmd/learn.js index 34915d1..f0f157c 100644 --- a/src/cmd/learn.js +++ b/src/cmd/learn.js @@ -78,7 +78,7 @@ export default function register(program) { return; } console.error(`skill '${ref}' is not yet vetted. user-wide install requires vetting.`); - console.error(`ask the user to vet it first:`); + console.error(`tell your operator to vet it first:`); console.error(''); console.error(` vit vet ${ref}`); console.error(''); @@ -98,7 +98,7 @@ export default function register(program) { return; } console.error(`skill '${ref}' is not yet vetted.`); - console.error(`ask the user to vet it first:`); + console.error(`tell your operator to vet it first:`); console.error(''); console.error(` vit vet ${ref}`); console.error(''); @@ -158,6 +158,10 @@ export default function register(program) { return; } console.error(`no skill found with ref '${ref}' from followed accounts.`); + console.error(''); + console.error('hint: skills appear from accounts you follow and your own.'); + console.error(` vit following check who you're following`); + console.error(` vit explore skills browse skills network-wide`); process.exitCode = 1; return; } diff --git a/src/cmd/remix.js b/src/cmd/remix.js index 565f534..091fea5 100644 --- a/src/cmd/remix.js +++ b/src/cmd/remix.js @@ -74,10 +74,10 @@ export default function register(program) { const trustGate = shouldBypassVet(); if (!trustGate.bypass) { if (opts.json) { - jsonError(`cap '${ref}' is not trusted`, `ask user to run 'vit vet ${ref} --trust'`); + jsonError(`cap '${ref}' is not trusted`, `tell your operator to run 'vit vet ${ref} --trust'`); return; } - console.error(`cap '${ref}' is not trusted. ask the user to vet it first:`); + console.error(`cap '${ref}' is not trusted. tell your operator to vet it first:`); console.error(''); console.error(` vit vet ${ref}`); console.error(''); @@ -129,6 +129,10 @@ export default function register(program) { return; } console.error(`no cap found with ref '${ref}' for this beacon.`); + console.error(''); + console.error('hint: caps only appear from accounts you follow and your own.'); + console.error(` vit following check who you're following`); + console.error(` vit explore cap ${ref} search the network-wide index`); process.exitCode = 1; return; } diff --git a/src/cmd/scan.js b/src/cmd/scan.js index 4a699e6..adec05b 100644 --- a/src/cmd/scan.js +++ b/src/cmd/scan.js @@ -162,6 +162,8 @@ export default function register(program) { return; } console.log(`no ${scanType} publishers found in this time window.`); + console.log('the network is young — be an early publisher.'); + console.log("ship a cap with 'vit ship' or a skill with 'vit ship --skill' to get things started."); return; } diff --git a/src/cmd/ship.js b/src/cmd/ship.js index 25d48ab..54caebe 100644 --- a/src/cmd/ship.js +++ b/src/cmd/ship.js @@ -200,7 +200,7 @@ async function shipSkill(opts) { jsonError('session expired or invalid', "run 'vit login '"); return; } - console.error(`session expired or invalid. tell your user to run '${name} login '.`); + console.error(`session expired or invalid. tell your operator to run '${name} login '.`); process.exitCode = 1; return; } @@ -416,7 +416,7 @@ async function shipCap(opts) { jsonError('session expired or invalid', "run 'vit login '"); return; } - console.error(`session expired or invalid. tell your user to run '${name} login '.`); + console.error(`session expired or invalid. tell your operator to run '${name} login '.`); process.exitCode = 1; return; } diff --git a/src/cmd/skim.js b/src/cmd/skim.js index 40a6794..0b00c5a 100644 --- a/src/cmd/skim.js +++ b/src/cmd/skim.js @@ -135,15 +135,41 @@ export default function register(program) { const capped = allItems.slice(0, limit); if (opts.json) { - console.log(JSON.stringify(capped, null, 2)); + if (capped.length === 0) { + const following = readFollowing(); + let hint; + if (skillsOnly) { + hint = "no skills found — try 'vit explore skills' or ship your own with 'vit ship --skill'"; + } else if (following.length === 0) { + hint = "not following anyone — run 'vit follow '"; + } else { + hint = "no matching caps — try 'vit explore caps' or 'vit ship'"; + } + console.log(JSON.stringify({ ok: true, items: [], hint }, null, 2)); + } else { + console.log(JSON.stringify(capped, null, 2)); + } } else { if (capped.length === 0) { if (skillsOnly) { - console.log('no skills found.'); - } else if (opts.caps) { - console.log('no caps found for this beacon.'); + console.log('no skills found from followed accounts.'); + console.log(''); + console.log("try 'vit explore skills' to discover skills network-wide, or ship your own with 'vit ship --skill'."); } else { - console.log('no caps or skills found.'); + const following = readFollowing(); + if (following.length === 0) { + console.log("no caps or skills found. you're not following anyone yet and haven't shipped any caps for this beacon."); + console.log(''); + console.log('next steps:'); + console.log(' vit scan discover active publishers on the network'); + console.log(' vit follow start following someone to see their caps'); + console.log(' vit ship publish a cap to seed the network'); + } else { + console.log('no caps found for this beacon from your followed accounts.'); + console.log(''); + console.log("the network grows when people ship. publish a cap with 'vit ship' to get things started for this project."); + console.log("try 'vit explore caps' for network-wide discovery."); + } } } for (const rec of capped) { @@ -172,8 +198,10 @@ export default function register(program) { console.log(); } } - console.log('---'); - console.log(`hint: tell your user to run '${name} vet ' in another terminal for any item they want to review.`); + if (capped.length > 0) { + console.log('---'); + console.log(`hint: tell your operator to run '${name} vet ' in another terminal for any item they want to review.`); + } } } catch (err) { console.error(err instanceof Error ? err.message : String(err)); diff --git a/src/cmd/vet.js b/src/cmd/vet.js index 9f61562..d9f9357 100644 --- a/src/cmd/vet.js +++ b/src/cmd/vet.js @@ -179,7 +179,7 @@ export default function register(program) { console.log(' caps and skills in this project.'); console.log(''); console.log(' any agent running in this project can remix caps and learn skills'); - console.log(' without human review. only do this if you trust the agent\'s judgment'); + console.log(' without operator review. only do this if you trust the agent\'s judgment'); console.log(' and the network sources you follow.'); console.log(''); console.log(' to proceed, confirm: vit vet --dangerous-accept --confirm'); @@ -230,10 +230,10 @@ export default function register(program) { // Sandboxed sub-agent pattern — allow it } else { if (opts.json) { - jsonError('vit vet is for human review', 'use --trust --confirm to bypass'); + jsonError('vit vet is for operator review', 'use --trust --confirm to bypass'); return; } - console.error('vit vet is for human review. agents should not vet directly.'); + console.error('vit vet is for operator review. agents should not vet directly.'); console.error(''); console.error('if you are a sandboxed sub-agent specifically tasked with vetting,'); console.error('you can bypass this gate:'); @@ -305,6 +305,10 @@ export default function register(program) { return; } console.error(`no cap found with ref '${ref}' for this beacon.`); + console.error(''); + console.error('hint: caps only appear from accounts you follow and your own.'); + console.error(` vit following check who you're following`); + console.error(` vit explore cap ${ref} search the network-wide index`); process.exitCode = 1; return; } @@ -448,6 +452,10 @@ export default function register(program) { return; } console.error(`no skill found with ref '${ref}' from followed accounts.`); + console.error(''); + console.error('hint: skills appear from accounts you follow and your own.'); + console.error(` vit following check who you're following`); + console.error(` vit explore skills browse skills network-wide`); process.exitCode = 1; return; } diff --git a/src/cmd/vouch.js b/src/cmd/vouch.js index 7de5a12..8e77c2b 100644 --- a/src/cmd/vouch.js +++ b/src/cmd/vouch.js @@ -111,6 +111,10 @@ export default function register(program) { return; } console.error(`no skill found with ref '${ref}' from followed accounts.`); + console.error(''); + console.error('hint: skills appear from accounts you follow and your own.'); + console.error(` vit following check who you're following`); + console.error(` vit explore skills browse skills network-wide`); process.exitCode = 1; return; } @@ -219,11 +223,16 @@ export default function register(program) { return; } console.error(`no cap found with ref '${ref}' for this beacon.`); + console.error(''); + console.error('hint: caps only appear from accounts you follow and your own.'); + console.error(` vit following check who you're following`); + console.error(` vit explore cap ${ref} search the network-wide index`); process.exitCode = 1; return; } const now = new Date().toISOString(); + const projBeacon = [...beaconSet][0]; const vouchRecord = { $type: VOUCH_COLLECTION, subject: { @@ -232,7 +241,7 @@ export default function register(program) { }, createdAt: now, ref, - beacon, + beacon: projBeacon, }; if (verbose) vlog(`[verbose] creating vouch for ${match.uri}`); const rkey = TID.nextStr(); @@ -250,7 +259,7 @@ export default function register(program) { uri: match.uri, cid: match.cid, vouchUri: res.data.uri, - beacon, + beacon: projBeacon, ts: now, }); } catch (logErr) { diff --git a/test/follow.test.js b/test/follow.test.js index 563df94..0011a9c 100644 --- a/test/follow.test.js +++ b/test/follow.test.js @@ -90,6 +90,6 @@ describe('vit following', () => { test('shows message when no followings', () => { const result = run('following', tmpDir); expect(result.exitCode).toBe(0); - expect(result.stdout).toContain('no followings'); + expect(result.stdout).toContain('not following anyone yet'); }); }); diff --git a/test/vet-skill.test.js b/test/vet-skill.test.js index b2e327f..df544f6 100644 --- a/test/vet-skill.test.js +++ b/test/vet-skill.test.js @@ -16,7 +16,7 @@ describe('vit vet (skill refs)', () => { test('rejects when run inside a coding agent (skill ref)', () => { const result = run('vet skill-agent-test', undefined, { CLAUDECODE: '1' }); expect(result.exitCode).toBe(1); - expect(result.stderr).toContain('vit vet is for human review'); + expect(result.stderr).toContain('vit vet is for operator review'); expect(result.stderr).toContain('vit vet skill-agent-test'); expect(result.stderr).toContain('--trust --confirm'); }); diff --git a/test/vet.test.js b/test/vet.test.js index 877a490..daee524 100644 --- a/test/vet.test.js +++ b/test/vet.test.js @@ -94,7 +94,7 @@ describe('vit vet', () => { test('agent without flags: error with sandboxed sub-agent hint', () => { const result = run('vet fast-cache-invalidation', undefined, agentEnv); expect(result.exitCode).toBe(1); - expect(result.stderr).toContain('vit vet is for human review'); + expect(result.stderr).toContain('vit vet is for operator review'); expect(result.stderr).toContain('--trust --confirm'); expect(result.stderr).toContain('sandboxed sub-agent'); }); @@ -102,14 +102,14 @@ describe('vit vet', () => { test('agent with --trust but no --confirm: error', () => { const result = run('vet fast-cache-invalidation --trust', undefined, agentEnv); expect(result.exitCode).toBe(1); - expect(result.stderr).toContain('vit vet is for human review'); + expect(result.stderr).toContain('vit vet is for operator review'); expect(result.stderr).toContain('--trust --confirm'); }); test('agent with --confirm but no --trust: error', () => { const result = run('vet fast-cache-invalidation --confirm', undefined, agentEnv); expect(result.exitCode).toBe(1); - expect(result.stderr).toContain('vit vet is for human review'); + expect(result.stderr).toContain('vit vet is for operator review'); }); test('agent with --trust --confirm: passes agent gate (fails at DID)', () => { @@ -118,7 +118,7 @@ describe('vit vet', () => { mkdirSync(configHome, { recursive: true }); const result = run('vet fast-cache-invalidation --trust --confirm', undefined, { ...agentEnv, XDG_CONFIG_HOME: configHome }); // Should NOT contain the agent gate error - expect(result.stderr).not.toContain('vit vet is for human review'); + expect(result.stderr).not.toContain('vit vet is for operator review'); rmSync(configHome, { recursive: true, force: true }); }); @@ -127,7 +127,7 @@ describe('vit vet', () => { mkdirSync(configHome, { recursive: true }); const result = run('vet fast-cache-invalidation --trust --confirm', undefined, { ...noAgentEnv, XDG_CONFIG_HOME: configHome }); // Should NOT contain the agent gate error - expect(result.stderr).not.toContain('vit vet is for human review'); + expect(result.stderr).not.toContain('vit vet is for operator review'); rmSync(configHome, { recursive: true, force: true }); }); }); @@ -186,7 +186,7 @@ describe('vit vet', () => { mkdirSync(configHome, { recursive: true }); const result = run('vet fast-cache-invalidation --sandbox claude', undefined, { ...agentEnv, XDG_CONFIG_HOME: configHome }); // Should NOT contain the agent gate error - expect(result.stderr).not.toContain('vit vet is for human review'); + expect(result.stderr).not.toContain('vit vet is for operator review'); rmSync(configHome, { recursive: true, force: true }); });