forkfeed-mcp 1.0.16 → 1.3.0

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.
@@ -6,143 +6,91 @@
6
6
  export const GUIDE_CONTENT = `
7
7
  # Forkfeed Content Guide - "The Fuck I Pushed"
8
8
 
9
- Turn GitHub commits into swipeable card content. One fork per repo, one feed per commit, 8 cards per feed (35-62 variants total).
9
+ Turn GitHub commits into swipeable card content. One fork per repo, one feed per commit, 8 cards per feed.
10
10
 
11
- **Important: process exactly ONE commit at a time, never multiple commits in a single run.**
11
+ **Process exactly ONE commit at a time, never multiple.**
12
12
 
13
13
  ## Quick start
14
14
 
15
- 1. Ask which single commit to process
16
- 2. Fetch commit data via git or gh CLI
17
- 3. Generate 8-card manifest JSON
18
- 4. Call forkfeed_push with the manifest
15
+ 1. Call **forkfeed_guide** and **forkfeed_commits()** in parallel
16
+ 2. Show commits table, ask which ONE to process
17
+ 3. Call **forkfeed_commits(sha)** to get diff, stats, and suggested scene images
18
+ 4. Generate simplified content JSON (see format below)
19
+ 5. Call **forkfeed_build** with the content (push defaults to true)
19
20
 
20
21
  ---
21
22
 
22
- ## Phase 1: Resolve repo and commit
23
+ ## Simplified content format (for forkfeed_build)
23
24
 
24
- Use the **current working directory** as the repo. Do not ask which repo.
25
+ The builder auto-detects repo info (owner, repo, GitHub URL), auto-assigns card backgrounds, and fetches existing feed IDs from the server. You only provide creative content.
25
26
 
26
- Process exactly one commit per run. If the user didn't specify, use the latest commit. If they ask for multiple commits, process only the first and tell them to run again for the next.
27
-
28
- Use **IT Scenes** images. Call **forkfeed_images** to get the full catalog (200 scene images + 30 backgrounds). Match images to content by tags and semantic similarity. Do not ask about image style.
29
-
30
- ---
31
-
32
- ## Phase 2: Fetch commit data
33
-
34
- ### GitHub repos
35
- \`\`\`bash
36
- # Verify access
37
- gh api repos/{owner}/{repo} --jq '.full_name'
38
-
39
- # Metadata
40
- gh api repos/{owner}/{repo}/commits/{sha} --jq '{sha: .sha, shortSha: (.sha[:7]), message: .commit.message, author: .commit.author.name, date: .commit.author.date, additions: .stats.additions, deletions: .stats.deletions, totalFiles: (.files | length)}'
41
-
42
- # Full diff
43
- gh api repos/{owner}/{repo}/commits/{sha} -H "Accept: application/vnd.github.v3.diff"
44
-
45
- # README for fork title/description
46
- gh api repos/{owner}/{repo} --jq '.description'
47
- \`\`\`
48
-
49
- ### Local repos
50
- \`\`\`bash
51
- git -C "{path}" log -1 --format='{"sha":"%H","shortSha":"%h","message":"%s","author":"%an","date":"%aI"}' {sha}
52
- git -C "{path}" diff --stat {sha}^..{sha}
53
- git -C "{path}" diff {sha}^..{sha}
54
- \`\`\`
55
-
56
- Skip merge commits (>1 parent) unless it's the only commit.
57
-
58
- ---
59
-
60
- ## Phase 3: Generate manifest
61
-
62
- ### ID conventions
63
- - Fork: \`tfip-{owner}-{repo}\` or \`tfip-local-{dirname}\`
64
- - Feed: \`tfip-{owner}-{repo}-{7char-sha}\`
65
- - Card: UUID v4 (generate inline, do not use any scripts or commands)
66
-
67
- All IDs must match \`/^[a-z0-9-]+$/\` (except card UUIDs).
68
-
69
- ### JSON structure
70
27
  \`\`\`json
71
28
  {
72
- "forks": [{
73
- "_id": "tfip-owner-repo",
74
- "title": "Project Name (from README)",
75
- "description": "What the project IS",
76
- "imageSrc": "same as card 0 cover image",
77
- "feedIds": ["tfip-owner-repo-abc1234"],
78
- "actionLabel": "View on GitHub",
79
- "actionUrl": "https://github.com/owner/repo"
80
- }],
81
- "feeds": [{
82
- "_id": "tfip-owner-repo-abc1234",
83
- "title": "Human-readable headline (max 60 chars)",
84
- "description": "Mon DD: one-line impact summary",
85
- "imageSrc": "same as card 0 cover image",
86
- "mode": "sequential",
87
- "scrollDirection": "vertical",
88
- "engagement": true
89
- }],
29
+ "sha": "7char-sha",
30
+ "feedTitle": "Max 60 chars headline",
31
+ "feedDescription": "Mon DD: one-line impact summary",
32
+ "forkTitle": "Project Name",
33
+ "forkDescription": "What the project IS",
90
34
  "cards": [
91
35
  {
92
- "_id": "uuid-v4",
93
- "feedId": "tfip-owner-repo-abc1234",
94
- "order": 0,
95
36
  "variants": [
96
- { "type": "FULL_IMAGE", "imageSrc": "url", "title": "Section name", "subtitle": "Hook text (max 200 chars)" },
97
- { "type": "CONTENT", "backgroundSrc": "url", "blocks": [...] }
37
+ { "blocks": [{ "img": "img47" }, { "title": "Section heading" }, { "text": "Paragraph content..." }] },
38
+ { "blocks": [{ "title": "Another section" }, { "text": "More content..." }] }
98
39
  ]
99
40
  }
100
41
  ]
101
42
  }
102
43
  \`\`\`
103
44
 
104
- ### The 8 cards (sections)
105
-
106
- Each card: variant[0] = FULL_IMAGE cover, variant[1+] = CONTENT details.
107
-
108
- | # | Section | Detail variants | Block pattern | Tone |
109
- |---|---------|----------------|---------------|------|
110
- | 0 | Explain like I'm 5 | 3-6 | IMAGE(wide) -> TITLE -> TEXT | Playful, zero jargon |
111
- | 1 | The roast | 3-6 | IMAGE(wide) -> TITLE -> TEXT, optional SUBTEXT | Maximum cheekiness, swearing ok |
112
- | 2 | Commit message, decoded | 2-4 | SOCIAL -> TITLE -> TEXT -> optional CODE | Escalating absurdity |
113
- | 3 | The LinkedIn post | 2-4 | SOCIAL -> TITLE -> TEXT -> SUBTEXT | Peak LinkedIn parody |
114
- | 4 | Statistics | 3-5 | IMAGE(wide) -> TITLE -> CODE | Deadpan data humor |
115
- | 5 | Learning moment | 3-8 | IMAGE(wide) -> TITLE -> TEXT -> optional CODE -> BUTTON(last) | Teach with personality |
116
- | 6 | Alternatives | 3-6 | IMAGE(wide) -> TITLE -> TEXT -> optional CODE | Constructive snark |
117
- | 7 | Quiz | 10-15 | TITLE -> QUIZ (no IMAGE) | Quiz show energy |
118
-
119
- ### Content block types
120
-
121
- \`\`\`typescript
122
- // CONTENT_IMAGE - inline image
123
- { type: "CONTENT_IMAGE", imageSrc: "url", sizing: "wide" }
124
-
125
- // CONTENT_TITLE - section heading (required in every detail variant, sentence case)
126
- { type: "CONTENT_TITLE", title: "Feature detection pattern" }
127
-
128
- // CONTENT_TEXT - paragraph (50-200 words, use \\n\\n for breaks)
129
- { type: "CONTENT_TEXT", text: "..." }
45
+ Only 5 fields + cards. Everything else is auto-populated.
46
+
47
+ ### Block types (inferred from fields)
48
+
49
+ | Write this | Becomes | Notes |
50
+ |------------|---------|-------|
51
+ | \`{ "img": "img47" }\` | CONTENT_IMAGE | sizing defaults to "wide". Options: automatic, wide, portrait, square, small_portrait |
52
+ | \`{ "img": "img47", "sizing": "square" }\` | CONTENT_IMAGE | With explicit sizing |
53
+ | \`{ "title": "Heading" }\` | CONTENT_TITLE | Required in every detail variant, sentence case |
54
+ | \`{ "text": "Paragraph..." }\` | CONTENT_TEXT | 50-200 words, use \\\\n\\\\n for breaks |
55
+ | \`{ "code": "const x = 1", "lang": "typescript" }\` | CONTENT_CODE | Real code from diff, 5-20 lines, strip +/- prefixes |
56
+ | \`{ "subtext": "Pro tip..." }\` | CONTENT_SUBTEXT | Aside or protip |
57
+ | \`{ "name": "Chad", "subtitle": "10x Engineer", "avatar": "img98", "source": "linkedin" }\` | CONTENT_SOCIAL | Cards 2-3 only. avatar can be image ID or URL. source: x, linkedin, threads, etc. |
58
+ | \`{ "question": "What does X do?", "options": [{"label": "A", "correct": false}, {"label": "B", "correct": true}], "explanation": "Because..." }\` | CONTENT_QUIZ | Card 7 only. 4 options recommended, min 2, one correct, always include explanation |
59
+ | \`{ "label": "Google it", "action": "url", "target": "https://google.com/search?q=topic" }\` | CONTENT_BUTTON | Card 5 only, MUST be last block in every detail variant |
60
+
61
+ ### What the builder does automatically
62
+ - Detects repo owner/name from git remote
63
+ - Generates fork/feed IDs from convention (tfip-{owner}-{repo}-{sha})
64
+ - Constructs GitHub action URL
65
+ - Fetches existing feed IDs from server (for incremental updates)
66
+ - Assigns 8 unique card backgrounds from preference table + commit tags
67
+ - Generates UUID v4 for each card ID
68
+ - Resolves short image IDs (img47, bg10) to full CDN URLs
69
+ - Adds FULL_IMAGE cover variant with fixed title/subtitle per card type
70
+ - Sets backgroundSrc, feedId, and order on each card
71
+ - Validates the assembled manifest before pushing
72
+
73
+ ### Optional overrides
74
+ - \`bgOverride\`: array of 8 background IDs to override auto-assignment
75
+ - \`coverOverride\`: array of 8 cover image IDs (defaults to backgrounds)
76
+ - \`cwd\`: working directory if not process.cwd()
130
77
 
131
- // CONTENT_CODE - code snippet (real from diff, 5-20 lines, strip +/- prefixes)
132
- { type: "CONTENT_CODE", code: "...", language: "typescript" }
133
-
134
- // CONTENT_SOCIAL - persona post (Cards 2-3 only, replaces IMAGE)
135
- { type: "CONTENT_SOCIAL", avatarSrc: "url", name: "Chad Gitpush", subtitle: "10x Engineer", source: "linkedin" }
78
+ ---
136
79
 
137
- // CONTENT_SUBTEXT - aside or protip
138
- { type: "CONTENT_SUBTEXT", text: "..." }
80
+ ## The 8 cards
139
81
 
140
- // CONTENT_QUIZ - quiz question (Card 7 only, exactly 4 options, one correct)
141
- { type: "CONTENT_QUIZ", question: "...", options: [{ label: "A", correct: false }, ...], explanation: "..." }
82
+ Each card = array of detail variants (cover is auto-generated). Provide 1+ variants per card.
142
83
 
143
- // CONTENT_BUTTON - action button (Card 5 only, MUST be last block)
144
- { type: "CONTENT_BUTTON", label: "Google it", action: "url", target: "https://www.google.com/search?q=topic+here" }
145
- \`\`\`
84
+ | # | Section | Detail variants | Block pattern | Tone |
85
+ |---|---------|----------------|---------------|------|
86
+ | 0 | Explain like I'm 5 | 3-6 | img -> title -> text | Playful, zero jargon |
87
+ | 1 | The roast | 3-6 | img -> title -> text, optional subtext | Maximum cheekiness, swearing ok |
88
+ | 2 | Commit message, decoded | 2-4 | social -> title -> text -> optional code | Escalating absurdity |
89
+ | 3 | The LinkedIn post | 2-4 | social -> title -> text -> subtext | Peak LinkedIn parody |
90
+ | 4 | Statistics | 3-5 | img -> title -> code | Deadpan data humor |
91
+ | 5 | Learning moment | 3-8 | img -> title -> text -> optional code -> button(last) | Teach with personality |
92
+ | 6 | Alternatives | 3-6 | img -> title -> text -> optional code | Constructive snark |
93
+ | 7 | Quiz | 10-15 | title -> quiz (no img blocks) | Quiz show energy |
146
94
 
147
95
  ### Card 2 personas (Decoded)
148
96
  - "What you meant" (source: "x" or "threads")
@@ -154,88 +102,29 @@ Each card: variant[0] = FULL_IMAGE cover, variant[1+] = CONTENT details.
154
102
  - Alexandra Middleware: "VP of Forward Thinking at TechCorp"
155
103
  - Dave 'Shipping' Johnson: "Just a humble engineer doing humble things"
156
104
 
157
- ### Key rules
158
- - All CONTENT variants in a card share the same backgroundSrc
159
- - 8 unique backgroundSrc values across the 8 cards
160
- - 8 unique FULL_IMAGE cover imageSrc values
105
+ ---
106
+
107
+ ## Key rules
108
+
109
+ - Exactly 8 cards in the cards array (one per section above)
110
+ - Use short image IDs from forkfeed_commits output (img47, not full URLs)
111
+ - 12-20 unique scene images (img*) across the feed, no duplicate within same card
161
112
  - Cards 0-5: code must be REAL from the diff (never fabricated)
162
113
  - Card 6: synthesized code IS allowed
163
- - Card 7: no code blocks, no CONTENT_IMAGE
164
- - Card 5: every detail variant MUST end with CONTENT_BUTTON
165
- - CONTENT_QUIZ: exactly 4 options, exactly one correct: true, explanation required
114
+ - Card 7: no img blocks, quiz blocks only (with title per variant)
115
+ - Card 5: every detail variant MUST end with a button block
116
+ - Cards 2-3: first block should be social (not img)
117
+ - CONTENT_QUIZ: 4 options recommended (min 2), exactly one correct, always include explanation
166
118
  - No em dashes, smart quotes, or non-ASCII characters
167
- - Top-level key MUST be "forks" (plural array)
168
-
169
- ### IT Scenes images
170
-
171
- Call **forkfeed_images** to get the full catalog. 200 scene images (img1-img200) for covers and inline images, 30 backgrounds (bg1-bg30) for card backgrounds.
172
-
173
- **Matching rules:**
174
- 1. Identify commit tags from the diff: deploy, git, disaster, debug, hype, victory, beginner, language, lifestyle, workplace, sarcastic, general
175
- 2. Filter images by tag overlap
176
- 3. Rank by semantic similarity to card content (title, text, code topics)
177
- 4. Assign best match, remove from pool (no duplicates)
178
-
179
- **Uniqueness rules:**
180
- - 8 unique scene images for FULL_IMAGE covers (one per card)
181
- - Detail CONTENT_IMAGE must differ from the card's cover
182
- - No two detail variants in the same card share a CONTENT_IMAGE
183
- - 8 unique bg* images for backgroundSrc (one per card)
184
- - Pick 16-25 unique images per feed
185
-
186
- **BG preferences per section:**
187
- - ELI5 (0): bg10, bg27 | Roast (1): bg11, bg1 | Decoded (2): bg20, bg11
188
- - LinkedIn (3): bg25, bg24 | Statistics (4): bg9, bg3 | Learning (5): match tech
189
- - Alternatives (6): bg25, bg30 | Quiz (7): bg18, bg5
190
-
191
- **Fork/feed imageSrc** = Card 0's FULL_IMAGE imageSrc
119
+ - Feed title max 60 chars
192
120
 
193
121
  ### Tone
194
- Casual, cheeky, technically accurate. Like your funniest friend reviewing your code.
195
- - Use "you" directly
196
- - Short paragraphs
197
- - Contractions
198
- - Swear occasionally for emphasis
199
- - Humor is the default
122
+ Casual, cheeky, technically accurate. Use "you," contractions, short paragraphs, occasional swearing. Humor is the default.
200
123
 
201
124
  ### Incremental updates
202
- Always call **forkfeed_status** before generating content. It lists published feeds by their externalFeedId (which contains the commit SHA, e.g. \`tfip-owner-repo-abc1234\`). When presenting commits to the user, cross-reference with status results: match the 7-char SHA in each feed ID against commit SHAs to show which commits already have feeds.
203
-
204
- - **New commit**: Generate only the new feed and cards. The fork's feedIds must include ALL existing feed IDs plus the new one. Missing old IDs causes them to be deleted.
205
- - **Existing commit**: Warn the user that this commit already has a feed. Only regenerate if they confirm. The old cards will be replaced.
206
- - **One commit per run**: Never process multiple commits at once. If the user wants more, they run the command again.
207
-
208
- ---
209
-
210
- ## Phase 4: Push
211
-
212
- Generate the entire manifest (forks, feeds, and all 8 cards with variants) in a single JSON output. Do NOT use any scripts, tools, agents, or commands to generate content, UUIDs, or JSON. Everything must be produced purely in your response.
213
-
214
- After generating the manifest JSON, call the **forkfeed_push** tool with it:
215
- \`\`\`
216
- forkfeed_push({ manifest: { forks: [...], feeds: [...], cards: [...] } })
217
- \`\`\`
218
-
219
- Content starts as **private**. The user can make it public from the forkfeed mobile app (requires admin approval).
220
-
221
- ---
125
+ **forkfeed_commits()** (list mode) shows which commits have published feeds. The builder auto-fetches existing feed IDs, so you don't need to track them.
222
126
 
223
- ## Validation checklist (verify before pushing)
224
-
225
- - [ ] Fork/feed IDs match /^[a-z0-9-]+$/
226
- - [ ] Card IDs are valid UUID v4
227
- - [ ] Every card.feedId matches an actual feed._id
228
- - [ ] Fork.feedIds match actual feed._id values
229
- - [ ] Top-level key is "forks" (plural array)
230
- - [ ] Card order values are sequential 0-7
231
- - [ ] Each card has >= 2 variants
232
- - [ ] variant[0] is FULL_IMAGE with imageSrc, title, subtitle
233
- - [ ] variant[1+] are CONTENT with backgroundSrc and blocks
234
- - [ ] FULL_IMAGE subtitle max 200 chars
235
- - [ ] Feed title max 60 chars
236
- - [ ] Feed mode: "sequential", scrollDirection: "vertical", engagement: true
237
- - [ ] CONTENT_QUIZ: exactly 4 options, one correct, explanation required
238
- - [ ] Card 5 detail variants end with CONTENT_BUTTON
239
- - [ ] 8 unique cover images, 8 unique backgrounds
240
- - [ ] No em dashes or smart quotes
127
+ - **New commit**: Just generate content. The builder handles feed ID preservation.
128
+ - **Existing commit**: Warn the user. Only regenerate if they confirm.
129
+ - **One commit per run**: Never process multiple commits at once.
241
130
  `.trim();