open source is social v-it.org
0
fork

Configure Feed

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

Add preflight checks and shipping guide to vit ship

Ship now validates DID, beacon, and session internally with actionable
errors, so agents don't need to run vit doctor first. Success output
is clean text (shipped: ref + uri:) with full JSON behind --verbose.
Skill doc gets a step-by-step shipping guide for when users say "ship it".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+58 -25
+1
.vit/caps.jsonl
··· 1 1 {"ts":"2026-02-12T03:56:05.612Z","did":"did:plc:gnmc53xy3rhbyepipqv2b3rl","rkey":"3men3vw76522p","collection":"org.v-it.cap","pds":"https://bsky.social","uri":"at://did:plc:gnmc53xy3rhbyepipqv2b3rl/org.v-it.cap/3men3vw76522p","cid":"bafyreidlziwnl33r6j45ayedaxr2x2745crbnoe6hgao5olikjeynahytu"} 2 2 {"ts":"2026-03-09T13:33:55.478Z","did":"did:plc:gnmc53xy3rhbyepipqv2b3rl","rkey":"3mgmxu7cptc2j","ref":"network-explorer-launch","collection":"org.v-it.cap","pds":"https://bsky.social","uri":"at://did:plc:gnmc53xy3rhbyepipqv2b3rl/org.v-it.cap/3mgmxu7cptc2j","cid":"bafyreicocgzx6ges4nzdybnyowmudqnaiqrxd7hnrzf44c5kn7i65kvfhu"} 3 3 {"ts":"2026-03-09T13:53:08.868Z","did":"did:plc:gnmc53xy3rhbyepipqv2b3rl","rkey":"3mgmywlbrx22k","ref":"clean-vouch-lexicon","collection":"org.v-it.cap","pds":"https://bsky.social","uri":"at://did:plc:gnmc53xy3rhbyepipqv2b3rl/org.v-it.cap/3mgmywlbrx22k","cid":"bafyreifnaurvivxrnuihv74si4yf4og4z25pchy6tfa3ckcn7abmdhdncy"} 4 + {"ts":"2026-03-24T21:47:34.202Z","did":"did:plc:gnmc53xy3rhbyepipqv2b3rl","rkey":"3mhtkgpstnc2l","ref":"skim-handle-attribution","collection":"org.v-it.cap","pds":"https://bsky.social","uri":"at://did:plc:gnmc53xy3rhbyepipqv2b3rl/org.v-it.cap/3mhtkgpstnc2l","cid":"bafyreiglrfvrpgkzktlsiv3tlqlo5xneoikorjr47af4lb4hv2yyqhmnam"}
+21 -2
skills/vit/SKILL.md
··· 94 94 - Usage: `vit ship --title <title> --description <description> --ref <ref> [--recap <ref>] <<'EOF' ... EOF` 95 95 - Key flags: required `--title <title>`, `--description <description>`, `--ref <ref>`; optional `--recap <ref>`, `--did <did>`, `-v, --verbose` 96 96 - Input: cap body is required via stdin (pipe or heredoc). 97 - - Gate: agent-only (`requireAgent()`). 98 - - Output: JSON object on success. 97 + - Gate: agent-only (`requireAgent()`). Ship runs its own preflight checks (DID, beacon, session) — no need to run `vit doctor` first. 98 + - Output: `shipped: <ref>` and `uri:` on success. Use `--verbose` for full JSON. 99 99 - Common errors: not running in an agent context, missing stdin body, no DID, invalid ref, recap ref not found, session expired. 100 + 101 + #### Shipping guide 102 + 103 + When the user says "ship it", "vit ship", or asks you to publish a cap for work you've done: 104 + 105 + 1. **Identify what to ship** — summarize the feature or fix you just completed. A cap describes a self-contained capability, not a commit message. 106 + 2. **Craft the fields:** 107 + - `--title`: concise noun phrase (2-5 words), e.g. "Skim Handle Attribution" 108 + - `--description`: one sentence explaining the value, e.g. "vit skim shows which handle published each cap" 109 + - `--ref`: three lowercase words with dashes, memorable slug for discovery, e.g. "skim-handle-attribution" 110 + - `--recap <ref>`: only if this cap derives from another cap (e.g. after `vit remix`) 111 + - **body (stdin)**: a short paragraph explaining what the cap does and how it works — written for another developer or agent who might adopt it 112 + 3. **Run the command:** 113 + ``` 114 + vit ship --title "..." --description "..." --ref "..." <<'EOF' 115 + ... body ... 116 + EOF 117 + ``` 118 + 4. Ship will validate prerequisites (DID, beacon, session) and give actionable errors if anything is missing. 100 119 101 120 ### `vit beacon <target>` 102 121 - Description: Probe a remote repo and report whether its beacon is lit.
+36 -23
src/cmd/ship.js
··· 27 27 if (!gate.ok) { 28 28 console.error(`${name} ship should be run by a coding agent (e.g. claude code, gemini cli).`); 29 29 console.error(`open your agent and ask it to run '${name} ship' for you.`); 30 + console.error(`refer to the using-vit skill (skills/vit/SKILL.md) for a shipping guide.`); 30 31 process.exitCode = 1; 31 32 return; 32 33 } 33 34 34 35 const { verbose } = opts; 36 + 37 + // preflight: DID 35 38 const did = requireDid(opts); 36 39 if (!did) return; 37 40 if (verbose) console.log(`[verbose] DID: ${did}`); 41 + 42 + // preflight: beacon 43 + const projectConfig = readProjectConfig(); 44 + if (!projectConfig.beacon) { 45 + console.error(`no beacon set. run '${name} init' in a project directory first.`); 46 + process.exitCode = 1; 47 + return; 48 + } 49 + if (verbose) console.log(`[verbose] beacon: ${projectConfig.beacon}`); 38 50 39 51 let text; 40 52 try { ··· 72 84 73 85 const now = new Date().toISOString(); 74 86 75 - const { agent, session } = await restoreAgent(did); 87 + // preflight: session 88 + let agent, session; 89 + try { 90 + ({ agent, session } = await restoreAgent(did)); 91 + } catch { 92 + console.error(`session expired or invalid. tell your user to run '${name} login <handle>'.`); 93 + process.exitCode = 1; 94 + return; 95 + } 76 96 if (verbose) console.log(`[verbose] Session restored, PDS: ${session.serverMetadata?.issuer}`); 77 97 78 98 if (opts.recap && !recapUri) { ··· 120 140 ref: opts.ref, 121 141 createdAt: now, 122 142 }; 123 - const projectConfig = readProjectConfig(); 124 143 if (projectConfig.beacon) record.beacon = projectConfig.beacon; 125 144 if (opts.recap) record.recap = { uri: recapUri, ref: opts.recap }; 126 - if (verbose && projectConfig.beacon) console.log(`[verbose] Beacon: ${projectConfig.beacon}`); 127 145 const rkey = TID.nextStr(); 128 146 if (verbose) console.log(`[verbose] Record built, rkey: ${rkey}`); 129 147 const putArgs = { ··· 150 168 console.error('warning: failed to write caps.jsonl:', logErr.message); 151 169 } 152 170 if (verbose) console.log(`[verbose] Log written to caps.jsonl`); 153 - console.log( 154 - JSON.stringify({ 155 - ts: now, 156 - pds: session.serverMetadata?.issuer, 157 - xrpc: 'com.atproto.repo.putRecord', 158 - request: putArgs, 159 - response: putRes.data, 160 - }), 161 - ); 171 + console.log(`shipped: ${opts.ref}`); 172 + console.log(`uri: ${putRes.data.uri}`); 173 + if (verbose) { 174 + console.log( 175 + JSON.stringify({ 176 + ts: now, 177 + pds: session.serverMetadata?.issuer, 178 + xrpc: 'com.atproto.repo.putRecord', 179 + request: putArgs, 180 + response: putRes.data, 181 + }), 182 + ); 183 + } 162 184 } catch (err) { 163 185 console.error(err instanceof Error ? err.message : String(err)); 164 186 process.exitCode = 1; ··· 167 189 .addHelpText('after', ` 168 190 Authoring guidance (for coding agents): 169 191 192 + Refer to the using-vit skill (skills/vit/SKILL.md) for a complete shipping guide. 193 + 170 194 Fields: 171 195 --title Short name for the cap (2-5 words) 172 196 --description One sentence explaining what this cap does ··· 174 198 --recap <ref> Optional. Ref of the cap this derives from (links back to original) 175 199 body (stdin) Full cap content, piped or via heredoc 176 200 177 - What makes a good cap: 178 - - Title is a concise noun phrase: "Fast LRU Cache", "JWT Auth Middleware" 179 - - Description explains the value: "Thread-safe LRU cache with O(1) eviction" 180 - - Body contains the complete, self-contained capability text 181 - - Ref is a memorable three-word slug for discovery 182 - 183 - When to use --recap: 184 - Use --recap when this cap is derived from another cap (e.g. after vit remix). 185 - It creates a link back to the original, like a quote-post. 186 - 187 201 Example: 188 202 vit ship --title "Fast LRU Cache" \\ 189 203 --description "Thread-safe LRU cache with O(1) eviction" \\ 190 204 --ref "fast-lru-cache" \\ 191 - --recap "original-cache-ref" \\ 192 205 <<'EOF' 193 206 ... full cap body text ... 194 207 EOF`);