open source is social v-it.org
0
fork

Configure Feed

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

complete vit branding across CLI and repo

Extend brand mark/prefix to remaining commands (adopt, follow, remix,
vet, vouch). Add SVG assets to docs/brand/ and docs/badge/ for hosting
on v-it.org. Add vit-enabled and social-open-source badges to README.
Generate .vit/README.md from brand template on init.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

+134 -21
+4 -1
README.md
··· 1 - # vit manifesto 1 + [![v̇it](https://v-it.org/badge/vit-enabled.svg)](https://v-it.org) 2 + [![open source is social](https://v-it.org/badge/social-open-source.svg)](https://v-it.org) 3 + 4 + # v̇it manifesto 2 5 3 6 vit is a **social system for personalized software** where the unit of exchange is not pull requests, not screenshots, not diffs, not even git. 4 7
+21
docs/badge/social-open-source.svg
··· 1 + <svg xmlns="http://www.w3.org/2000/svg" width="156" height="20" role="img" aria-label="open source: social"> 2 + <title>open source: social</title> 3 + <linearGradient id="s" x2="0" y2="100%"> 4 + <stop offset="0" stop-color="#bbb" stop-opacity=".1"/> 5 + <stop offset="1" stop-opacity=".1"/> 6 + </linearGradient> 7 + <clipPath id="r"> 8 + <rect width="156" height="20" rx="3" fill="#fff"/> 9 + </clipPath> 10 + <g clip-path="url(#r)"> 11 + <rect width="88" height="20" fill="#555"/> 12 + <rect x="88" width="68" height="20" fill="#06D6A0"/> 13 + <rect width="156" height="20" fill="url(#s)"/> 14 + </g> 15 + <g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="11"> 16 + <text aria-hidden="true" x="44" y="15" fill="#010101" fill-opacity=".3">open source</text> 17 + <text x="44" y="14">open source</text> 18 + <text aria-hidden="true" x="121" y="15" fill="#010101" fill-opacity=".3">social</text> 19 + <text x="121" y="14">social</text> 20 + </g> 21 + </svg>
+14
docs/badge/vit-enabled-flat.svg
··· 1 + <svg xmlns="http://www.w3.org/2000/svg" width="108" height="20" role="img" aria-label="vit: enabled"> 2 + <title>vit: enabled</title> 3 + <clipPath id="r"> 4 + <rect width="108" height="20" rx="3" fill="#fff"/> 5 + </clipPath> 6 + <g clip-path="url(#r)"> 7 + <rect width="38" height="20" fill="#333"/> 8 + <rect x="38" width="70" height="20" fill="#06D6A0"/> 9 + </g> 10 + <g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="11"> 11 + <text x="19" y="14">vit</text> 12 + <text x="72" y="14">enabled</text> 13 + </g> 14 + </svg>
+21
docs/badge/vit-enabled.svg
··· 1 + <svg xmlns="http://www.w3.org/2000/svg" width="108" height="20" role="img" aria-label="vit: enabled"> 2 + <title>vit: enabled</title> 3 + <linearGradient id="s" x2="0" y2="100%"> 4 + <stop offset="0" stop-color="#bbb" stop-opacity=".1"/> 5 + <stop offset="1" stop-opacity=".1"/> 6 + </linearGradient> 7 + <clipPath id="r"> 8 + <rect width="108" height="20" rx="3" fill="#fff"/> 9 + </clipPath> 10 + <g clip-path="url(#r)"> 11 + <rect width="38" height="20" fill="#555"/> 12 + <rect x="38" width="70" height="20" fill="#06D6A0"/> 13 + <rect width="108" height="20" fill="url(#s)"/> 14 + </g> 15 + <g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="11"> 16 + <text aria-hidden="true" x="19" y="15" fill="#010101" fill-opacity=".3">vit</text> 17 + <text x="19" y="14">vit</text> 18 + <text aria-hidden="true" x="72" y="15" fill="#010101" fill-opacity=".3">enabled</text> 19 + <text x="72" y="14">enabled</text> 20 + </g> 21 + </svg>
+12
docs/badge/vit-icon-only.svg
··· 1 + <svg xmlns="http://www.w3.org/2000/svg" width="28" height="20" role="img" aria-label="vit"> 2 + <title>vit</title> 3 + <clipPath id="r"> 4 + <rect width="28" height="20" rx="3" fill="#fff"/> 5 + </clipPath> 6 + <g clip-path="url(#r)"> 7 + <rect width="28" height="20" fill="#06D6A0"/> 8 + </g> 9 + <!-- vit mark scaled to badge --> 10 + <circle cx="14" cy="5" r="1.8" fill="#fff"/> 11 + <path d="M7 7.5 L14 16.5 L21 7.5" stroke="#fff" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" fill="none"/> 12 + </svg>
+5
docs/brand/vit-mark-dark.svg
··· 1 + <svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"> 2 + <!-- vit mark for dark backgrounds --> 3 + <circle cx="16" cy="5.5" r="3" fill="#34D399"/> 4 + <path d="M5.5 10 L16 26 L26.5 10" stroke="#34D399" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/> 5 + </svg>
+5
docs/brand/vit-mark-white.svg
··· 1 + <svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"> 2 + <!-- vit mark in white — for use on colored/dark backgrounds --> 3 + <circle cx="16" cy="5.5" r="3" fill="#ffffff"/> 4 + <path d="M5.5 10 L16 26 L26.5 10" stroke="#ffffff" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/> 5 + </svg>
+5
docs/brand/vit-mark.svg
··· 1 + <svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"> 2 + <!-- vit mark: a "v" with a social dot — alive, connected, approachable --> 3 + <circle cx="16" cy="5.5" r="3" fill="#06D6A0"/> 4 + <path d="M5.5 10 L16 26 L26.5 10" stroke="#06D6A0" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/> 5 + </svg>
+15
docs/brand/vit-wordmark.svg
··· 1 + <svg viewBox="0 0 56 34" xmlns="http://www.w3.org/2000/svg"> 2 + <!-- vit wordmark: all letters drawn with the same rounded stroke --> 3 + 4 + <!-- v (the mark) --> 5 + <circle cx="16" cy="6" r="3" fill="#06D6A0"/> 6 + <path d="M5.5 11 L16 27 L26.5 11" stroke="#06D6A0" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/> 7 + 8 + <!-- i — dot + vertical stroke, same style as the mark --> 9 + <circle cx="33.5" cy="6" r="3" fill="#06D6A0"/> 10 + <line x1="33.5" y1="12.5" x2="33.5" y2="27" stroke="#06D6A0" stroke-width="3.5" stroke-linecap="round"/> 11 + 12 + <!-- t — taller stem + crossbar --> 13 + <line x1="45" y1="7" x2="45" y2="27" stroke="#06D6A0" stroke-width="3.5" stroke-linecap="round"/> 14 + <line x1="39" y1="12.5" x2="51" y2="12.5" stroke="#06D6A0" stroke-width="3.5" stroke-linecap="round"/> 15 + </svg>
+5 -4
src/cmd/adopt.js
··· 7 7 import { parseGitUrl, toBeacon, beaconToHttps } from '../lib/beacon.js'; 8 8 import { requireNotAgent } from '../lib/agent.js'; 9 9 import { which } from '../lib/compat.js'; 10 + import { mark, brand } from '../lib/brand.js'; 10 11 11 12 export default function register(program) { 12 13 program ··· 19 20 try { 20 21 const gate = requireNotAgent(); 21 22 if (!gate.ok) { 22 - console.error('vit adopt must be run by a human. run it in your own terminal.'); 23 + console.error(`${brand} adopt must be run by a human. run it in your own terminal.`); 23 24 process.exitCode = 1; 24 25 return; 25 26 } ··· 78 79 } 79 80 80 81 // success output 81 - console.log(`beacon: ${beaconUri}`); 82 - console.log(`directory: ${dirName}`); 82 + console.log(`${mark} beacon: ${beaconUri}`); 83 + console.log(`${mark} directory: ${dirName}`); 83 84 console.log(`run: cd ${dirName}`); 84 85 console.log(''); 85 - console.log("next: start your agent and ask it to run 'vit init'"); 86 + console.log(`next: start your agent and ask it to run '${brand} init'`); 86 87 } catch (err) { 87 88 console.error(err instanceof Error ? err.message : String(err)); 88 89 process.exitCode = 1;
+3 -2
src/cmd/follow.js
··· 4 4 import { requireDid } from '../lib/config.js'; 5 5 import { restoreAgent } from '../lib/oauth.js'; 6 6 import { readFollowing, writeFollowing } from '../lib/vit-dir.js'; 7 + import { mark } from '../lib/brand.js'; 7 8 8 9 export default function register(program) { 9 10 program ··· 37 38 38 39 list.push({ handle, did: targetDid, followedAt: new Date().toISOString() }); 39 40 writeFollowing(list); 40 - console.log(`following ${handle} (${targetDid})`); 41 + console.log(`${mark} following ${handle} (${targetDid})`); 41 42 } catch (err) { 42 43 console.error(err instanceof Error ? err.message : String(err)); 43 44 process.exitCode = 1; ··· 64 65 65 66 writeFollowing(filtered); 66 67 if (verbose) console.log(`[verbose] removed ${handle} from following list`); 67 - console.log(`unfollowed ${handle}`); 68 + console.log(`${mark} unfollowed ${handle}`); 68 69 } catch (err) { 69 70 console.error(err instanceof Error ? err.message : String(err)); 70 71 process.exitCode = 1;
+5 -4
src/cmd/remix.js
··· 7 7 import { readProjectConfig, readFollowing, readLog } from '../lib/vit-dir.js'; 8 8 import { requireAgent } from '../lib/agent.js'; 9 9 import { resolveRef, REF_PATTERN } from '../lib/cap-ref.js'; 10 + import { brand } from '../lib/brand.js'; 10 11 11 12 export default function register(program) { 12 13 program ··· 19 20 try { 20 21 const gate = requireAgent(); 21 22 if (!gate.ok) { 22 - console.error('vit remix should be run by a coding agent (e.g. claude code, gemini cli).'); 23 - console.error("open your agent and ask it to run 'vit remix' for you."); 23 + console.error(`${brand} remix should be run by a coding agent (e.g. claude code, gemini cli).`); 24 + console.error(`open your agent and ask it to run '${brand} remix' for you.`); 24 25 process.exitCode = 1; 25 26 return; 26 27 } ··· 40 41 const projectConfig = readProjectConfig(); 41 42 const beacon = projectConfig.beacon; 42 43 if (!beacon) { 43 - console.error("no beacon set. run 'vit init' in a project directory first."); 44 + console.error(`no beacon set. run '${brand} init' in a project directory first.`); 44 45 process.exitCode = 1; 45 46 return; 46 47 } ··· 103 104 const description = record.description || ''; 104 105 const text = record.text || ''; 105 106 106 - console.log(`# remix: ${title}`); 107 + console.log(`# ${brand} remix: ${title}`); 107 108 console.log(''); 108 109 console.log(`ref: ${ref}`); 109 110 console.log(`author: ${author}`);
+5 -4
src/cmd/vet.js
··· 7 7 import { appendLog, readProjectConfig, readFollowing } from '../lib/vit-dir.js'; 8 8 import { requireNotAgent } from '../lib/agent.js'; 9 9 import { resolveRef, REF_PATTERN } from '../lib/cap-ref.js'; 10 + import { mark, brand } from '../lib/brand.js'; 10 11 11 12 export default function register(program) { 12 13 program ··· 20 21 try { 21 22 const gate = requireNotAgent(); 22 23 if (!gate.ok) { 23 - console.error('vit vet must be run by a human. run it in your own terminal.'); 24 + console.error(`${brand} vet must be run by a human. run it in your own terminal.`); 24 25 console.error(''); 25 26 console.error('cap vetting requires human review for safety.'); 26 27 console.error('ask your user to run this command in their terminal:'); ··· 51 52 const projectConfig = readProjectConfig(); 52 53 const beacon = projectConfig.beacon; 53 54 if (!beacon) { 54 - console.error("no beacon set. run 'vit init' in a project directory first."); 55 + console.error(`no beacon set. run '${brand} init' in a project directory first.`); 55 56 process.exitCode = 1; 56 57 return; 57 58 } ··· 103 104 uri: match.uri, 104 105 trustedAt: new Date().toISOString(), 105 106 }); 106 - console.log(`trusted: ${ref}`); 107 + console.log(`${mark} trusted: ${ref}`); 107 108 return; 108 109 } 109 110 ··· 112 113 const description = record.description || ''; 113 114 const text = record.text || ''; 114 115 115 - console.log('=== Cap Review ==='); 116 + console.log(`=== ${brand} cap review ===`); 116 117 console.log('Review this cap carefully before trusting it.'); 117 118 console.log(''); 118 119 console.log(` Ref: ${ref}`);
+3 -2
src/cmd/vouch.js
··· 6 6 import { restoreAgent } from '../lib/oauth.js'; 7 7 import { appendLog, readProjectConfig, readFollowing, readLog } from '../lib/vit-dir.js'; 8 8 import { resolveRef, REF_PATTERN } from '../lib/cap-ref.js'; 9 + import { mark, brand } from '../lib/brand.js'; 9 10 10 11 export default function register(program) { 11 12 program ··· 31 32 const projectConfig = readProjectConfig(); 32 33 const beacon = projectConfig.beacon; 33 34 if (!beacon) { 34 - console.error("no beacon set. run 'vit init' in a project directory first."); 35 + console.error(`no beacon set. run '${brand} init' in a project directory first.`); 35 36 process.exitCode = 1; 36 37 return; 37 38 } ··· 117 118 } 118 119 if (verbose) console.log('[verbose] logged to vouched.jsonl'); 119 120 120 - console.log(`vouched: ${ref} (${match.uri})`); 121 + console.log(`${mark} vouched: ${ref} (${match.uri})`); 121 122 } catch (err) { 122 123 console.error(err instanceof Error ? err.message : String(err)); 123 124 process.exitCode = 1;
+11 -4
test/init.test.js
··· 23 23 test('writes beacon from HTTPS URL', () => { 24 24 const result = run('init --beacon https://github.com/solpbc/vit.git', tmpDir, { CLAUDECODE: '1' }); 25 25 expect(result.exitCode).toBe(0); 26 - expect(result.stdout).toBe('beacon: vit:github.com/solpbc/vit'); 26 + expect(result.stdout).toContain('beacon: vit:github.com/solpbc/vit'); 27 27 28 28 const content = readFileSync(join(tmpDir, '.vit', 'config.json'), 'utf-8'); 29 29 expect(JSON.parse(content).beacon).toBe('vit:github.com/solpbc/vit'); ··· 32 32 test('writes beacon from SSH URL', () => { 33 33 const result = run('init --beacon git@github.com:solpbc/vit.git', tmpDir, { CLAUDECODE: '1' }); 34 34 expect(result.exitCode).toBe(0); 35 - expect(result.stdout).toBe('beacon: vit:github.com/solpbc/vit'); 35 + expect(result.stdout).toContain('beacon: vit:github.com/solpbc/vit'); 36 36 37 37 const content = readFileSync(join(tmpDir, '.vit', 'config.json'), 'utf-8'); 38 38 expect(JSON.parse(content).beacon).toBe('vit:github.com/solpbc/vit'); ··· 44 44 expect(existsSync(join(tmpDir, '.vit'))).toBe(true); 45 45 }); 46 46 47 + test('generates .vit/README.md on init', () => { 48 + run('init --beacon https://github.com/solpbc/vit.git', tmpDir, { CLAUDECODE: '1' }); 49 + const readme = readFileSync(join(tmpDir, '.vit', 'README.md'), 'utf-8'); 50 + expect(readme).toContain('social open source network'); 51 + expect(readme).toContain('v-it.org'); 52 + }); 53 + 47 54 test('overwrites existing beacon silently', () => { 48 55 run('init --beacon https://github.com/old/repo.git', tmpDir, { CLAUDECODE: '1' }); 49 56 run('init --beacon https://github.com/solpbc/vit.git', tmpDir, { CLAUDECODE: '1' }); ··· 59 66 60 67 const result = run('init --beacon .', tmpDir, { CLAUDECODE: '1' }); 61 68 expect(result.exitCode).toBe(0); 62 - expect(result.stdout).toBe('beacon: vit:github.com/solpbc/vit'); 69 + expect(result.stdout).toContain('beacon: vit:github.com/solpbc/vit'); 63 70 }); 64 71 65 72 test('errors when --beacon . has no git remote', () => { ··· 150 157 151 158 const result = run('init --beacon .', tmpDir, { CLAUDECODE: '1' }); 152 159 expect(result.exitCode).toBe(0); 153 - expect(result.stdout).toBe('beacon: vit:github.com/solpbc/vit'); 160 + expect(result.stdout).toContain('beacon: vit:github.com/solpbc/vit'); 154 161 }); 155 162 156 163 test('shows guidance for already initialized repo', () => {