forkfeed-mcp 1.0.16 → 1.2.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.
- package/dist/guide-content.js +86 -181
- package/dist/image-catalog.d.ts +232 -230
- package/dist/image-catalog.js +238 -230
- package/dist/index.js +492 -112
- package/package.json +1 -1
package/dist/guide-content.js
CHANGED
|
@@ -6,143 +6,88 @@
|
|
|
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
|
|
9
|
+
Turn GitHub commits into swipeable card content. One fork per repo, one feed per commit, 8 cards per feed.
|
|
10
10
|
|
|
11
|
-
**
|
|
11
|
+
**Process exactly ONE commit at a time, never multiple.**
|
|
12
12
|
|
|
13
13
|
## Quick start
|
|
14
14
|
|
|
15
|
-
1.
|
|
16
|
-
2.
|
|
17
|
-
3.
|
|
18
|
-
4.
|
|
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 pre-filtered 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
|
-
##
|
|
23
|
+
## Simplified content format (for forkfeed_build)
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
The builder handles UUIDs, full image URLs, cover variants, type wrappers, feedId/order, and fork/feed boilerplate. 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
|
-
"
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
-
|
|
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
|
+
"owner": "owner-or-local",
|
|
30
|
+
"repo": "repo-name",
|
|
31
|
+
"sha": "7char",
|
|
32
|
+
"feedTitle": "Max 60 chars headline",
|
|
33
|
+
"feedDescription": "Mon DD: one-line impact summary",
|
|
34
|
+
"forkTitle": "Project Name",
|
|
35
|
+
"forkDescription": "What the project IS",
|
|
36
|
+
"actionUrl": "https://github.com/owner/repo",
|
|
37
|
+
"existingFeedIds": [],
|
|
38
|
+
"images": {
|
|
39
|
+
"bg": ["bg10", "bg11", "bg20", "bg25", "bg9", "bg12", "bg30", "bg18"]
|
|
40
|
+
},
|
|
90
41
|
"cards": [
|
|
91
42
|
{
|
|
92
|
-
"_id": "uuid-v4",
|
|
93
|
-
"feedId": "tfip-owner-repo-abc1234",
|
|
94
|
-
"order": 0,
|
|
95
43
|
"variants": [
|
|
96
|
-
{ "
|
|
97
|
-
{ "
|
|
44
|
+
{ "blocks": [{ "img": "img47", "sizing": "wide" }, { "title": "Section heading" }, { "text": "Paragraph content..." }] },
|
|
45
|
+
{ "blocks": [{ "title": "Another section" }, { "text": "More content..." }] }
|
|
98
46
|
]
|
|
99
47
|
}
|
|
100
48
|
]
|
|
101
49
|
}
|
|
102
50
|
\`\`\`
|
|
103
51
|
|
|
104
|
-
###
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
|
109
|
-
|
|
110
|
-
|
|
|
111
|
-
|
|
|
112
|
-
|
|
|
113
|
-
|
|
|
114
|
-
|
|
|
115
|
-
|
|
|
116
|
-
|
|
|
117
|
-
|
|
52
|
+
### Block types (inferred from fields)
|
|
53
|
+
|
|
54
|
+
| Write this | Becomes | Notes |
|
|
55
|
+
|------------|---------|-------|
|
|
56
|
+
| \`{ "img": "img47" }\` | CONTENT_IMAGE | sizing defaults to "wide". Options: automatic, wide, portrait, square, small_portrait |
|
|
57
|
+
| \`{ "img": "img47", "sizing": "square" }\` | CONTENT_IMAGE | With explicit sizing |
|
|
58
|
+
| \`{ "title": "Heading" }\` | CONTENT_TITLE | Required in every detail variant, sentence case |
|
|
59
|
+
| \`{ "text": "Paragraph..." }\` | CONTENT_TEXT | 50-200 words, use \\\\n\\\\n for breaks |
|
|
60
|
+
| \`{ "code": "const x = 1", "lang": "typescript" }\` | CONTENT_CODE | Real code from diff, 5-20 lines, strip +/- prefixes |
|
|
61
|
+
| \`{ "subtext": "Pro tip..." }\` | CONTENT_SUBTEXT | Aside or protip |
|
|
62
|
+
| \`{ "name": "Chad", "subtitle": "10x Engineer", "avatar": "img98", "source": "linkedin" }\` | CONTENT_SOCIAL | Cards 2-3 only. source: x, linkedin, threads, etc. |
|
|
63
|
+
| \`{ "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 |
|
|
64
|
+
| \`{ "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 |
|
|
65
|
+
|
|
66
|
+
### What the builder does automatically
|
|
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 on all CONTENT variants from images.bg[cardIndex]
|
|
71
|
+
- Sets feedId and order on each card
|
|
72
|
+
- Builds fork and feed objects with correct IDs and metadata
|
|
73
|
+
- Validates the assembled manifest before pushing
|
|
118
74
|
|
|
119
|
-
|
|
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: "..." }
|
|
130
|
-
|
|
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" }
|
|
75
|
+
---
|
|
136
76
|
|
|
137
|
-
|
|
138
|
-
{ type: "CONTENT_SUBTEXT", text: "..." }
|
|
77
|
+
## The 8 cards
|
|
139
78
|
|
|
140
|
-
|
|
141
|
-
{ type: "CONTENT_QUIZ", question: "...", options: [{ label: "A", correct: false }, ...], explanation: "..." }
|
|
79
|
+
Each card = array of detail variants (cover is auto-generated). Provide 1+ variants per card.
|
|
142
80
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
81
|
+
| # | Section | Detail variants | Block pattern | Tone |
|
|
82
|
+
|---|---------|----------------|---------------|------|
|
|
83
|
+
| 0 | Explain like I'm 5 | 3-6 | img -> title -> text | Playful, zero jargon |
|
|
84
|
+
| 1 | The roast | 3-6 | img -> title -> text, optional subtext | Maximum cheekiness, swearing ok |
|
|
85
|
+
| 2 | Commit message, decoded | 2-4 | social -> title -> text -> optional code | Escalating absurdity |
|
|
86
|
+
| 3 | The LinkedIn post | 2-4 | social -> title -> text -> subtext | Peak LinkedIn parody |
|
|
87
|
+
| 4 | Statistics | 3-5 | img -> title -> code | Deadpan data humor |
|
|
88
|
+
| 5 | Learning moment | 3-8 | img -> title -> text -> optional code -> button(last) | Teach with personality |
|
|
89
|
+
| 6 | Alternatives | 3-6 | img -> title -> text -> optional code | Constructive snark |
|
|
90
|
+
| 7 | Quiz | 10-15 | title -> quiz (no img blocks) | Quiz show energy |
|
|
146
91
|
|
|
147
92
|
### Card 2 personas (Decoded)
|
|
148
93
|
- "What you meant" (source: "x" or "threads")
|
|
@@ -154,88 +99,48 @@ Each card: variant[0] = FULL_IMAGE cover, variant[1+] = CONTENT details.
|
|
|
154
99
|
- Alexandra Middleware: "VP of Forward Thinking at TechCorp"
|
|
155
100
|
- Dave 'Shipping' Johnson: "Just a humble engineer doing humble things"
|
|
156
101
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Key rules
|
|
105
|
+
|
|
106
|
+
- Exactly 8 cards in the cards array (one per section above)
|
|
107
|
+
- images.bg must have 8 unique background IDs
|
|
108
|
+
- 12-20 unique scene images (img*) across the feed, no duplicate within same card
|
|
161
109
|
- Cards 0-5: code must be REAL from the diff (never fabricated)
|
|
162
110
|
- Card 6: synthesized code IS allowed
|
|
163
|
-
- Card 7: no
|
|
164
|
-
- Card 5: every detail variant MUST end with
|
|
165
|
-
-
|
|
111
|
+
- Card 7: no img blocks, quiz blocks only (with title per variant)
|
|
112
|
+
- Card 5: every detail variant MUST end with a button block
|
|
113
|
+
- Cards 2-3: first block should be social (not img)
|
|
114
|
+
- CONTENT_QUIZ: 4 options recommended (min 2), exactly one correct, always include explanation
|
|
166
115
|
- No em dashes, smart quotes, or non-ASCII characters
|
|
167
|
-
-
|
|
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.
|
|
116
|
+
- Feed title max 60 chars
|
|
172
117
|
|
|
173
|
-
|
|
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)
|
|
118
|
+
### Images
|
|
178
119
|
|
|
179
|
-
**
|
|
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
|
|
120
|
+
Images are pre-filtered by **forkfeed_commits(sha)**. Pick from the suggested list.
|
|
185
121
|
|
|
186
|
-
**BG preferences
|
|
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
|
|
122
|
+
**BG preferences:** ELI5: bg10/bg27 | Roast: bg11/bg1 | Decoded: bg20/bg11 | LinkedIn: bg25/bg24 | Stats: bg9/bg3 | Learning: match tech | Alts: bg25/bg30 | Quiz: bg18/bg5
|
|
192
123
|
|
|
193
124
|
### Tone
|
|
194
|
-
Casual, cheeky, technically accurate.
|
|
195
|
-
- Use "you" directly
|
|
196
|
-
- Short paragraphs
|
|
197
|
-
- Contractions
|
|
198
|
-
- Swear occasionally for emphasis
|
|
199
|
-
- Humor is the default
|
|
125
|
+
Casual, cheeky, technically accurate. Use "you," contractions, short paragraphs, occasional swearing. Humor is the default.
|
|
200
126
|
|
|
201
127
|
### Incremental updates
|
|
202
|
-
|
|
128
|
+
**forkfeed_commits()** (list mode) shows which commits have published feeds and lists existing feed IDs.
|
|
203
129
|
|
|
204
|
-
- **New commit**:
|
|
205
|
-
- **Existing commit**: Warn the user
|
|
206
|
-
- **One commit per run**: Never process multiple commits at once.
|
|
130
|
+
- **New commit**: Include ALL existing feed IDs in existingFeedIds. Missing old IDs causes deletion.
|
|
131
|
+
- **Existing commit**: Warn the user. Only regenerate if they confirm.
|
|
132
|
+
- **One commit per run**: Never process multiple commits at once.
|
|
207
133
|
|
|
208
134
|
---
|
|
209
135
|
|
|
210
|
-
##
|
|
136
|
+
## Advanced: direct push with full manifest (forkfeed_push)
|
|
211
137
|
|
|
212
|
-
|
|
138
|
+
If you need full control, you can build the manifest manually and use forkfeed_push directly. The full manifest requires:
|
|
139
|
+
- Fork/feed objects with all fields (mode, scrollDirection, engagement, etc.)
|
|
140
|
+
- FULL_IMAGE cover variant[0] per card with fixed titles/subtitles
|
|
141
|
+
- CONTENT variants with type field, full image URLs, backgroundSrc
|
|
142
|
+
- UUID v4 card IDs, feedId and order on each card
|
|
213
143
|
|
|
214
|
-
|
|
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
|
-
---
|
|
222
|
-
|
|
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
|
|
144
|
+
ID conventions: Fork: \`tfip-{owner}-{repo}\`, Feed: \`tfip-{owner}-{repo}-{7char-sha}\`, Card: UUID v4
|
|
145
|
+
All IDs must match \`/^[a-z0-9-]+$/\` (except card UUIDs).
|
|
241
146
|
`.trim();
|