@opendirectory.dev/skills 0.1.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/.claude/skills/claude-md-generator/.env.example +7 -0
- package/.claude/skills/claude-md-generator/README.md +78 -0
- package/.claude/skills/claude-md-generator/SKILL.md +248 -0
- package/.claude/skills/claude-md-generator/evals/evals.json +35 -0
- package/.claude/skills/claude-md-generator/references/section-guide.md +175 -0
- package/dist/e2e.test.d.ts +1 -0
- package/dist/e2e.test.js +62 -0
- package/dist/fs-adapters.d.ts +4 -0
- package/dist/fs-adapters.js +101 -0
- package/dist/fs-adapters.test.d.ts +1 -0
- package/dist/fs-adapters.test.js +108 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +211 -0
- package/dist/transformers.d.ts +6 -0
- package/dist/transformers.js +2 -0
- package/package.json +25 -0
- package/registry.json +226 -0
- package/skills/blog-cover-image-cli/.github/workflows/publish.yml +19 -0
- package/skills/blog-cover-image-cli/LICENSE +15 -0
- package/skills/blog-cover-image-cli/README.md +126 -0
- package/skills/blog-cover-image-cli/SKILL.md +7 -0
- package/skills/blog-cover-image-cli/agent-skill/blog-cover-generator/README.md +30 -0
- package/skills/blog-cover-image-cli/agent-skill/blog-cover-generator/SKILL.md +72 -0
- package/skills/blog-cover-image-cli/bin/cli.js +226 -0
- package/skills/blog-cover-image-cli/examples/100x_UX_Research_AI_Agent.png +0 -0
- package/skills/blog-cover-image-cli/examples/Firecrawl-supabase-bolt.png +0 -0
- package/skills/blog-cover-image-cli/examples/Git-City_Case_study_Cover_Image.jpg +0 -0
- package/skills/blog-cover-image-cli/examples/THE DISTRIBUTION LAYER (2).png +0 -0
- package/skills/blog-cover-image-cli/examples/canva-perplexity-duolingo-cover-image.png +0 -0
- package/skills/blog-cover-image-cli/examples/gamma-mistral-veed.png +0 -0
- package/skills/blog-cover-image-cli/examples/server-survival-case-study-cover-image(1).png +0 -0
- package/skills/blog-cover-image-cli/examples/viral-meme-automation.png +0 -0
- package/skills/blog-cover-image-cli/index.js +2 -0
- package/skills/blog-cover-image-cli/package-lock.json +2238 -0
- package/skills/blog-cover-image-cli/package.json +37 -0
- package/skills/blog-cover-image-cli/src/geminiGenerator.js +126 -0
- package/skills/blog-cover-image-cli/src/imageValidator.js +54 -0
- package/skills/blog-cover-image-cli/src/logoFetcher.js +86 -0
- package/skills/claude-md-generator/.env.example +7 -0
- package/skills/claude-md-generator/README.md +78 -0
- package/skills/claude-md-generator/SKILL.md +254 -0
- package/skills/claude-md-generator/evals/evals.json +35 -0
- package/skills/claude-md-generator/references/section-guide.md +175 -0
- package/skills/cook-the-blog/README.md +86 -0
- package/skills/cook-the-blog/SKILL.md +130 -0
- package/skills/dependency-update-bot/.env.example +13 -0
- package/skills/dependency-update-bot/README.md +101 -0
- package/skills/dependency-update-bot/SKILL.md +376 -0
- package/skills/dependency-update-bot/evals/evals.json +45 -0
- package/skills/dependency-update-bot/references/changelog-patterns.md +201 -0
- package/skills/docs-from-code/.env.example +13 -0
- package/skills/docs-from-code/README.md +97 -0
- package/skills/docs-from-code/SKILL.md +160 -0
- package/skills/docs-from-code/evals/evals.json +29 -0
- package/skills/docs-from-code/references/extraction-guide.md +174 -0
- package/skills/docs-from-code/references/output-template.md +135 -0
- package/skills/docs-from-code/scripts/extract_py.py +238 -0
- package/skills/docs-from-code/scripts/extract_ts.ts +284 -0
- package/skills/docs-from-code/scripts/package.json +18 -0
- package/skills/explain-this-pr/README.md +74 -0
- package/skills/explain-this-pr/SKILL.md +130 -0
- package/skills/explain-this-pr/evals/evals.json +35 -0
- package/skills/google-trends-api-skills/README.md +78 -0
- package/skills/google-trends-api-skills/SKILL.md +7 -0
- package/skills/google-trends-api-skills/google-trends-api/SKILL.md +163 -0
- package/skills/google-trends-api-skills/google-trends-api/references/api-responses.md +188 -0
- package/skills/google-trends-api-skills/google-trends-api/scripts/discover_keywords.py +344 -0
- package/skills/google-trends-api-skills/seo-keyword-research/SKILL.md +205 -0
- package/skills/google-trends-api-skills/seo-keyword-research/references/keyword-placement-guide.md +89 -0
- package/skills/google-trends-api-skills/seo-keyword-research/references/tech-blog-examples.md +207 -0
- package/skills/google-trends-api-skills/seo-keyword-research/scripts/blog_seo_research.py +373 -0
- package/skills/hackernews-intel/.env.example +33 -0
- package/skills/hackernews-intel/README.md +161 -0
- package/skills/hackernews-intel/SKILL.md +156 -0
- package/skills/hackernews-intel/evals/evals.json +35 -0
- package/skills/hackernews-intel/package.json +15 -0
- package/skills/hackernews-intel/scripts/monitor-hn.js +258 -0
- package/skills/kill-the-standup/.env.example +22 -0
- package/skills/kill-the-standup/README.md +84 -0
- package/skills/kill-the-standup/SKILL.md +169 -0
- package/skills/kill-the-standup/evals/evals.json +35 -0
- package/skills/kill-the-standup/references/standup-format.md +102 -0
- package/skills/linkedin-post-generator/.env.example +14 -0
- package/skills/linkedin-post-generator/README.md +107 -0
- package/skills/linkedin-post-generator/SKILL.md +228 -0
- package/skills/linkedin-post-generator/evals/evals.json +35 -0
- package/skills/linkedin-post-generator/references/linkedin-format.md +216 -0
- package/skills/linkedin-post-generator/references/output-template.md +154 -0
- package/skills/llms-txt-generator/.env.example +18 -0
- package/skills/llms-txt-generator/README.md +142 -0
- package/skills/llms-txt-generator/SKILL.md +176 -0
- package/skills/llms-txt-generator/evals/evals.json +35 -0
- package/skills/llms-txt-generator/references/llms-txt-spec.md +88 -0
- package/skills/llms-txt-generator/references/output-template.md +76 -0
- package/skills/llms-txt-generator/test-output/genzcareer.in/llms.txt +31 -0
- package/skills/luma-attendees-scraper/README.md +170 -0
- package/skills/luma-attendees-scraper/SKILL.md +7 -0
- package/skills/luma-attendees-scraper/luma_attendees_export.js +223 -0
- package/skills/meeting-brief-generator/.env.example +21 -0
- package/skills/meeting-brief-generator/README.md +90 -0
- package/skills/meeting-brief-generator/SKILL.md +275 -0
- package/skills/meeting-brief-generator/evals/evals.json +35 -0
- package/skills/meeting-brief-generator/references/brief-format.md +114 -0
- package/skills/meeting-brief-generator/references/output-template.md +150 -0
- package/skills/meta-ads-skill/README.md +100 -0
- package/skills/meta-ads-skill/SKILL.md +7 -0
- package/skills/meta-ads-skill/meta-ads-skill/SKILL.md +41 -0
- package/skills/meta-ads-skill/meta-ads-skill/references/report_templates.md +47 -0
- package/skills/meta-ads-skill/meta-ads-skill/references/workflows.md +51 -0
- package/skills/meta-ads-skill/meta-ads-skill/scripts/auth_check.py +22 -0
- package/skills/meta-ads-skill/meta-ads-skill/scripts/formatters.py +46 -0
- package/skills/newsletter-digest/.env.example +20 -0
- package/skills/newsletter-digest/README.md +147 -0
- package/skills/newsletter-digest/SKILL.md +221 -0
- package/skills/newsletter-digest/evals/evals.json +35 -0
- package/skills/newsletter-digest/feeds.json +7 -0
- package/skills/newsletter-digest/package.json +15 -0
- package/skills/newsletter-digest/references/digest-format.md +123 -0
- package/skills/newsletter-digest/references/output-template.md +136 -0
- package/skills/newsletter-digest/scripts/fetch-feeds.js +141 -0
- package/skills/newsletter-digest/scripts/ghost-publish.js +147 -0
- package/skills/noise2blog/.env.example +16 -0
- package/skills/noise2blog/README.md +107 -0
- package/skills/noise2blog/SKILL.md +229 -0
- package/skills/noise2blog/evals/evals.json +35 -0
- package/skills/noise2blog/references/blog-format.md +188 -0
- package/skills/noise2blog/references/output-template.md +184 -0
- package/skills/outreach-sequence-builder/.env.example +12 -0
- package/skills/outreach-sequence-builder/README.md +108 -0
- package/skills/outreach-sequence-builder/SKILL.md +248 -0
- package/skills/outreach-sequence-builder/evals/evals.json +36 -0
- package/skills/outreach-sequence-builder/references/output-template.md +171 -0
- package/skills/outreach-sequence-builder/references/sequence-format.md +167 -0
- package/skills/outreach-sequence-builder/references/signal-playbook.md +117 -0
- package/skills/position-me/README.md +71 -0
- package/skills/position-me/SKILL.md +7 -0
- package/skills/position-me/position-me/SKILL.md +50 -0
- package/skills/position-me/position-me/references/EVALUATION_SOP.md +40 -0
- package/skills/position-me/position-me/references/REPORT_TEMPLATE.md +58 -0
- package/skills/position-me/position-me/scripts/extract_links.py +49 -0
- package/skills/pr-description-writer/README.md +81 -0
- package/skills/pr-description-writer/SKILL.md +141 -0
- package/skills/pr-description-writer/evals/evals.json +35 -0
- package/skills/pr-description-writer/references/pr-format-guide.md +145 -0
- package/skills/producthunt-launch-kit/.env.example +7 -0
- package/skills/producthunt-launch-kit/README.md +95 -0
- package/skills/producthunt-launch-kit/SKILL.md +380 -0
- package/skills/producthunt-launch-kit/evals/evals.json +35 -0
- package/skills/producthunt-launch-kit/references/copy-rules.md +124 -0
- package/skills/reddit-icp-monitor/.env.example +16 -0
- package/skills/reddit-icp-monitor/README.md +117 -0
- package/skills/reddit-icp-monitor/SKILL.md +271 -0
- package/skills/reddit-icp-monitor/evals/evals.json +40 -0
- package/skills/reddit-icp-monitor/references/icp-format.md +131 -0
- package/skills/reddit-icp-monitor/references/reply-rules.md +110 -0
- package/skills/reddit-post-engine/.env.example +13 -0
- package/skills/reddit-post-engine/README.md +103 -0
- package/skills/reddit-post-engine/SKILL.md +303 -0
- package/skills/reddit-post-engine/evals/evals.json +35 -0
- package/skills/reddit-post-engine/references/subreddit-playbook.md +156 -0
- package/skills/schema-markup-generator/.env.example +19 -0
- package/skills/schema-markup-generator/README.md +114 -0
- package/skills/schema-markup-generator/SKILL.md +192 -0
- package/skills/schema-markup-generator/evals/evals.json +35 -0
- package/skills/schema-markup-generator/references/json-ld-spec.md +263 -0
- package/skills/schema-markup-generator/references/output-template.md +556 -0
- package/skills/show-hn-writer/.env.example +14 -0
- package/skills/show-hn-writer/README.md +88 -0
- package/skills/show-hn-writer/SKILL.md +303 -0
- package/skills/show-hn-writer/evals/evals.json +35 -0
- package/skills/show-hn-writer/references/hn-rules.md +74 -0
- package/skills/show-hn-writer/references/title-formulas.md +93 -0
- package/skills/stargazer/README.md +79 -0
- package/skills/stargazer/SKILL.md +7 -0
- package/skills/stargazer/stargazer-skill/SKILL.md +58 -0
- package/skills/stargazer/stargazer-skill/assets/.env.example +18 -0
- package/skills/stargazer/stargazer-skill/scripts/convert_to_csv.py +63 -0
- package/skills/stargazer/stargazer-skill/scripts/count_emails.py +52 -0
- package/skills/stargazer/stargazer-skill/scripts/stargazer_deep_extractor.py +450 -0
- package/skills/tweet-thread-from-blog/.env.example +14 -0
- package/skills/tweet-thread-from-blog/README.md +109 -0
- package/skills/tweet-thread-from-blog/SKILL.md +177 -0
- package/skills/tweet-thread-from-blog/evals/evals.json +35 -0
- package/skills/tweet-thread-from-blog/references/output-template.md +193 -0
- package/skills/tweet-thread-from-blog/references/thread-format.md +107 -0
- package/skills/twitter-GTM-find-skill/README.md +43 -0
- package/skills/twitter-GTM-find-skill/SKILL.md +7 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/SKILL.md +37 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/references/icp-checklist.md +35 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/package.json +23 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/run_pipeline.sh +8 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/debug.ts +23 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/extractor.ts +79 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/icp-filter.ts +87 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/index.ts +94 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/scraper.ts +41 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/tsconfig.json +13 -0
- package/skills/yc-intent-radar-skill/README.md +39 -0
- package/skills/yc-intent-radar-skill/SKILL.md +7 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/SKILL.md +59 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/auth.js +29 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/db.js +62 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/export_radar_candidates.js +40 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/package-lock.json +1525 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/package.json +12 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/scraper.js +217 -0
- package/src/e2e.test.ts +35 -0
- package/src/fs-adapters.test.ts +91 -0
- package/src/fs-adapters.ts +65 -0
- package/src/index.ts +182 -0
- package/src/transformers.ts +6 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# kill-the-standup
|
|
2
|
+
|
|
3
|
+
<img width="1280" height="640" alt="kill-the-standup" src="https://github.com/user-attachments/assets/4fcf306d-7ef9-455a-b5f1-02532c292f65" />
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
Write your daily standup in seconds. The skill reads yesterday's Linear issues and GitHub commits, formats a done/doing/blockers update, and posts it to Slack.
|
|
7
|
+
|
|
8
|
+
## What It Does
|
|
9
|
+
|
|
10
|
+
- Fetches yesterday's Linear issues assigned to you (completed and in-progress)
|
|
11
|
+
- Fetches yesterday's GitHub commits from your configured repo
|
|
12
|
+
- Formats a three-section standup: Done, Doing, Blockers
|
|
13
|
+
- Posts to your Slack channel via Incoming Webhook
|
|
14
|
+
|
|
15
|
+
## Requirements
|
|
16
|
+
|
|
17
|
+
| Requirement | Purpose | How to Set Up |
|
|
18
|
+
|------------|---------|--------------|
|
|
19
|
+
| Linear API key | Fetching your issues | Linear, Settings, API, Personal API keys |
|
|
20
|
+
| Slack Incoming Webhook | Posting the standup | api.slack.com/apps, Your App, Incoming Webhooks |
|
|
21
|
+
| `gh` CLI (optional) | Fetching GitHub commits | https://cli.github.com, then run `gh auth login` |
|
|
22
|
+
|
|
23
|
+
No LLM API key needed. The agent reads your activity directly.
|
|
24
|
+
|
|
25
|
+
## Setup
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
cp .env.example .env
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Edit `.env` and fill in:
|
|
32
|
+
- `LINEAR_API_KEY` (required)
|
|
33
|
+
- `SLACK_WEBHOOK_URL` (required)
|
|
34
|
+
- `GITHUB_REPO` (optional, format: `owner/repo`)
|
|
35
|
+
- `GITHUB_USERNAME` (optional, defaults to your gh auth username)
|
|
36
|
+
|
|
37
|
+
## How to Use
|
|
38
|
+
|
|
39
|
+
Write and post standup:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
"Write my standup"
|
|
43
|
+
"Post my standup to Slack"
|
|
44
|
+
"Generate standup update"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Output only, no Slack post:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
"Write my standup but don't post it"
|
|
51
|
+
"What did I do yesterday?"
|
|
52
|
+
"Give me my standup text"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Output Format
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
Done
|
|
59
|
+
- [ENG-123] Fix session timeout bug
|
|
60
|
+
- fix: remove duplicate middleware registration
|
|
61
|
+
|
|
62
|
+
Doing
|
|
63
|
+
- [ENG-124] Migrate auth to OAuth2
|
|
64
|
+
|
|
65
|
+
Blockers
|
|
66
|
+
No blockers.
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Project Structure
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
kill-the-standup/
|
|
73
|
+
├── SKILL.md
|
|
74
|
+
├── README.md
|
|
75
|
+
├── .env.example
|
|
76
|
+
├── evals/
|
|
77
|
+
│ └── evals.json
|
|
78
|
+
└── references/
|
|
79
|
+
└── standup-format.md
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## License
|
|
83
|
+
|
|
84
|
+
MIT
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kill-the-standup
|
|
3
|
+
description: Reads yesterday's Linear issues and GitHub commits for the authenticated user, formats a standup update (done / doing / blockers), and posts it to Slack. Use when asked to write a standup, generate a standup update, post to the standup channel, summarize yesterday's work, or automate the daily standup. Trigger when a user says "write my standup", "post standup", "generate standup update", "what did I do yesterday", or "kill the standup".
|
|
4
|
+
compatibility: [claude-code, gemini-cli, github-copilot]
|
|
5
|
+
author: OpenDirectory
|
|
6
|
+
version: 1.0.0
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Kill the Standup
|
|
10
|
+
|
|
11
|
+
Read yesterday's Linear issues and GitHub commits. Format a standup update. Post it to Slack.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Step 1: Setup Check
|
|
16
|
+
|
|
17
|
+
Confirm required env vars are set:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
echo "LINEAR_API_KEY: ${LINEAR_API_KEY:+set}"
|
|
21
|
+
echo "SLACK_WEBHOOK_URL: ${SLACK_WEBHOOK_URL:+set}"
|
|
22
|
+
echo "GITHUB_REPO: ${GITHUB_REPO:-not set}"
|
|
23
|
+
echo "GITHUB_USERNAME: ${GITHUB_USERNAME:-not set}"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**If LINEAR_API_KEY is missing:**
|
|
27
|
+
Stop. Tell the user: "LINEAR_API_KEY is required. Get it from Linear → Settings → API → Personal API keys. Add it to your .env file."
|
|
28
|
+
|
|
29
|
+
**If SLACK_WEBHOOK_URL is missing:**
|
|
30
|
+
Stop. Tell the user: "SLACK_WEBHOOK_URL is required. Create an Incoming Webhook at api.slack.com/apps → Your App → Incoming Webhooks. Add it to your .env file."
|
|
31
|
+
|
|
32
|
+
**If GITHUB_REPO is missing:**
|
|
33
|
+
Continue. GitHub commits will be skipped. Note this to the user.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Step 2: Fetch Linear Activity
|
|
38
|
+
|
|
39
|
+
Compute yesterday's date in ISO 8601 format (e.g. `2026-04-09T00:00:00.000Z`).
|
|
40
|
+
|
|
41
|
+
**Get current user ID:**
|
|
42
|
+
```bash
|
|
43
|
+
curl -s -X POST https://api.linear.app/graphql \
|
|
44
|
+
-H "Authorization: Bearer $LINEAR_API_KEY" \
|
|
45
|
+
-H "Content-Type: application/json" \
|
|
46
|
+
-d '{"query": "query { viewer { id name email } }"}'
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Extract the `id` field from the response. Store as `LINEAR_USER_ID`.
|
|
50
|
+
|
|
51
|
+
**Fetch issues assigned to me, updated since yesterday:**
|
|
52
|
+
```bash
|
|
53
|
+
curl -s -X POST https://api.linear.app/graphql \
|
|
54
|
+
-H "Authorization: Bearer $LINEAR_API_KEY" \
|
|
55
|
+
-H "Content-Type: application/json" \
|
|
56
|
+
-d '{
|
|
57
|
+
"query": "query($since: DateTime!, $userId: ID!) { issues(first: 50, filter: { assignee: { id: { eq: $userId } } updatedAt: { gte: $since } }) { edges { node { identifier title state { name } url completedAt updatedAt createdAt } } } }",
|
|
58
|
+
"variables": {"since": "YESTERDAY_ISO", "userId": "LINEAR_USER_ID"}
|
|
59
|
+
}'
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Categorize issues:**
|
|
63
|
+
- `completedAt` is non-null → **Done**
|
|
64
|
+
- `state.name` is "In Progress", "Started", or "In Review" → **Doing**
|
|
65
|
+
- `state.name` is "Cancelled" → skip
|
|
66
|
+
- `state.name` is "Todo" or "Backlog" → skip (not worked on)
|
|
67
|
+
|
|
68
|
+
If zero issues: note "No Linear activity found for yesterday."
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Step 3: Fetch GitHub Commits
|
|
73
|
+
|
|
74
|
+
Skip this step silently if GITHUB_REPO is not set.
|
|
75
|
+
|
|
76
|
+
If GITHUB_REPO is set:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
gh api "repos/$GITHUB_REPO/commits?author=${GITHUB_USERNAME:-$(gh api user --jq .login)}&since=YESTERDAY_ISO&per_page=30" \
|
|
80
|
+
--jq '[.[] | {message: .commit.message, url: .html_url}]'
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**Process commits:**
|
|
84
|
+
- Extract the first line of each commit message (everything before the first newline)
|
|
85
|
+
- Skip merge commits: drop any message starting with "Merge"
|
|
86
|
+
- Deduplicate by message text
|
|
87
|
+
|
|
88
|
+
If GITHUB_REPO is set but returns zero commits: note "No commits found yesterday."
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Step 4: Format Standup
|
|
93
|
+
|
|
94
|
+
Read `references/standup-format.md` in full before writing.
|
|
95
|
+
|
|
96
|
+
Produce the standup in this exact structure:
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
**Done**
|
|
100
|
+
- [ENG-123] Title of completed issue
|
|
101
|
+
- fix: commit message here
|
|
102
|
+
|
|
103
|
+
**Doing**
|
|
104
|
+
- [ENG-124] Title of in-progress issue
|
|
105
|
+
|
|
106
|
+
**Blockers**
|
|
107
|
+
No blockers.
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Rules from standup-format.md:
|
|
111
|
+
- No first-person pronouns ("I", "we")
|
|
112
|
+
- Past tense for Done items, present continuous for Doing items
|
|
113
|
+
- Each Linear item uses the `[IDENTIFIER] Title` format
|
|
114
|
+
- Each GitHub commit uses the first line of the commit message
|
|
115
|
+
- If no Done items: write "Nothing completed." under Done
|
|
116
|
+
- If no Doing items: write "Nothing in progress." under Doing
|
|
117
|
+
- If no blockers: write "No blockers."
|
|
118
|
+
- Under 200 words total
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Step 5: Post to Slack or Output
|
|
123
|
+
|
|
124
|
+
Present the formatted standup to the user.
|
|
125
|
+
|
|
126
|
+
Ask: "Post this to Slack, or output only?"
|
|
127
|
+
|
|
128
|
+
**On confirmation to post:**
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
curl -s -X POST "$SLACK_WEBHOOK_URL" \
|
|
132
|
+
-H "Content-Type: application/json" \
|
|
133
|
+
-d '{
|
|
134
|
+
"blocks": [
|
|
135
|
+
{
|
|
136
|
+
"type": "section",
|
|
137
|
+
"text": {
|
|
138
|
+
"type": "mrkdwn",
|
|
139
|
+
"text": "*Standup — DATE_HERE*\n\n*Done*\nITEMS\n\n*Doing*\nITEMS\n\n*Blockers*\nITEMS"
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
]
|
|
143
|
+
}'
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Pass the body via a temp file or heredoc to avoid shell quoting issues with special characters in commit messages or issue titles:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
cat > /tmp/standup-payload.json << 'ENDJSON'
|
|
150
|
+
{
|
|
151
|
+
"blocks": [
|
|
152
|
+
{
|
|
153
|
+
"type": "section",
|
|
154
|
+
"text": {
|
|
155
|
+
"type": "mrkdwn",
|
|
156
|
+
"text": "STANDUP_CONTENT_HERE"
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
]
|
|
160
|
+
}
|
|
161
|
+
ENDJSON
|
|
162
|
+
curl -s -X POST "$SLACK_WEBHOOK_URL" -H "Content-Type: application/json" -d @/tmp/standup-payload.json
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
After posting: "Standup posted."
|
|
166
|
+
|
|
167
|
+
**On "output only":** Print the standup in a code block for copy-paste.
|
|
168
|
+
|
|
169
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill_name": "kill-the-standup",
|
|
3
|
+
"evals": [
|
|
4
|
+
{
|
|
5
|
+
"id": 1,
|
|
6
|
+
"prompt": "Write my standup",
|
|
7
|
+
"expected_output": "Agent checks for LINEAR_API_KEY and SLACK_WEBHOOK_URL — both present. GITHUB_REPO is set. Runs Linear viewer query to get user ID. Runs issues query filtered by assignee + updatedAt >= yesterday. Runs gh api repos/OWNER/REPO/commits filtered by author + since yesterday. Produces three-section standup: Done (completed Linear issues + commits), Doing (in-progress issues), Blockers (No blockers). Presents standup to user and asks: Post to Slack or output only?",
|
|
8
|
+
"files": []
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"id": 2,
|
|
12
|
+
"prompt": "Generate my standup — I haven't set GITHUB_REPO",
|
|
13
|
+
"expected_output": "Agent detects GITHUB_REPO is not set. Skips Step 3 silently. Fetches Linear issues only. Produces standup with Done and Doing from Linear, no GitHub commits section. Blockers: No blockers. Asks user to confirm before posting. Does not error or mention GitHub unless noting it was skipped.",
|
|
14
|
+
"files": []
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"id": 3,
|
|
18
|
+
"prompt": "Post my standup to Slack",
|
|
19
|
+
"expected_output": "Agent runs full workflow. If Linear returns zero issues for yesterday, notes 'No Linear activity found for yesterday' but still checks GitHub if GITHUB_REPO is set. Produces valid standup (may show 'Nothing completed.' and 'Nothing in progress.'). Presents to user, confirms, then POSTs JSON payload to SLACK_WEBHOOK_URL using a temp file to avoid shell quoting issues. Confirms 'Standup posted.' after successful curl response.",
|
|
20
|
+
"files": []
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"id": 4,
|
|
24
|
+
"prompt": "Write my standup — I didn't do anything yesterday",
|
|
25
|
+
"expected_output": "Agent fetches Linear and GitHub (if configured). Both return zero results. Produces minimal standup: Done section shows 'Nothing completed.', Doing section shows 'Nothing in progress.', Blockers shows 'No blockers.' Agent presents this to the user and asks if they want to add context or post as-is. Does not invent activity.",
|
|
26
|
+
"files": []
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"id": 5,
|
|
30
|
+
"prompt": "Post standup to Slack",
|
|
31
|
+
"expected_output": "Agent checks SLACK_WEBHOOK_URL — it is missing from environment. Agent stops immediately at Step 1. Tells the user: 'SLACK_WEBHOOK_URL is required. Create an Incoming Webhook at api.slack.com/apps → Your App → Incoming Webhooks. Add it to your .env file.' Does not proceed to fetch Linear or GitHub data.",
|
|
32
|
+
"files": []
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Standup Format Guide
|
|
2
|
+
|
|
3
|
+
## Structure
|
|
4
|
+
|
|
5
|
+
Always three sections, always in this order:
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
**Done**
|
|
9
|
+
- [ENG-123] Title of completed issue
|
|
10
|
+
- fix: commit message here
|
|
11
|
+
|
|
12
|
+
**Doing**
|
|
13
|
+
- [ENG-124] Title of in-progress issue
|
|
14
|
+
|
|
15
|
+
**Blockers**
|
|
16
|
+
No blockers.
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Section Rules
|
|
22
|
+
|
|
23
|
+
### Done
|
|
24
|
+
What was completed yesterday.
|
|
25
|
+
|
|
26
|
+
- One bullet per Linear issue with `completedAt` set
|
|
27
|
+
- One bullet per GitHub commit (first line of message, deduplicated, skip merges)
|
|
28
|
+
- Format for Linear items: `[IDENTIFIER] Title` — e.g. `[ENG-42] Fix session timeout bug`
|
|
29
|
+
- Format for commits: first line of commit message — e.g. `fix: remove duplicate auth check`
|
|
30
|
+
- Tense: past tense implied by the format (no verb prefix needed unless the commit message has one)
|
|
31
|
+
- If nothing was completed: write `Nothing completed.` as the only bullet
|
|
32
|
+
|
|
33
|
+
### Doing
|
|
34
|
+
What is in progress right now.
|
|
35
|
+
|
|
36
|
+
- One bullet per Linear issue with state In Progress, Started, or In Review
|
|
37
|
+
- Format: `[IDENTIFIER] Title` — same as Done
|
|
38
|
+
- Tense: present continuous implied — no need to add "working on" or "continuing"
|
|
39
|
+
- If nothing is in progress: write `Nothing in progress.` as the only bullet
|
|
40
|
+
|
|
41
|
+
### Blockers
|
|
42
|
+
What is blocked and why.
|
|
43
|
+
|
|
44
|
+
- Write `No blockers.` if nothing is blocked
|
|
45
|
+
- Only add a blocker entry if the user explicitly mentions one, or if an issue has been In Progress for more than 3 days without a state change (createdAt vs updatedAt gap > 3 days)
|
|
46
|
+
- Format: `[ENG-125] Waiting on design approval` — issue + reason
|
|
47
|
+
- Never invent blockers
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Writing Rules
|
|
52
|
+
|
|
53
|
+
- No first-person pronouns: no "I", "we", "my", "our"
|
|
54
|
+
- No filler phrases: no "today I will", "yesterday I", "as per the discussion", "going to"
|
|
55
|
+
- No markdown headers inside the standup body — use bold `**Section**` labels only
|
|
56
|
+
- Under 200 words total
|
|
57
|
+
- Bullet list only — no paragraphs, no sentences that span multiple lines
|
|
58
|
+
- Each bullet is one issue or one commit, nothing more
|
|
59
|
+
- No hashtags, no em dashes
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Examples
|
|
64
|
+
|
|
65
|
+
**Full standup (Linear + GitHub):**
|
|
66
|
+
```
|
|
67
|
+
**Done**
|
|
68
|
+
- [ENG-88] Add Redis caching for session lookups
|
|
69
|
+
- fix: remove duplicate middleware registration
|
|
70
|
+
- chore: bump Next.js to 14.2.0
|
|
71
|
+
|
|
72
|
+
**Doing**
|
|
73
|
+
- [ENG-91] Migrate auth to OAuth2
|
|
74
|
+
|
|
75
|
+
**Blockers**
|
|
76
|
+
No blockers.
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Linear only (no GitHub repo configured):**
|
|
80
|
+
```
|
|
81
|
+
**Done**
|
|
82
|
+
- [OPS-14] Set up staging deployment pipeline
|
|
83
|
+
|
|
84
|
+
**Doing**
|
|
85
|
+
- [OPS-15] Configure load balancer health checks
|
|
86
|
+
- [OPS-16] Document rollback procedure
|
|
87
|
+
|
|
88
|
+
**Blockers**
|
|
89
|
+
No blockers.
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**No activity:**
|
|
93
|
+
```
|
|
94
|
+
**Done**
|
|
95
|
+
Nothing completed.
|
|
96
|
+
|
|
97
|
+
**Doing**
|
|
98
|
+
Nothing in progress.
|
|
99
|
+
|
|
100
|
+
**Blockers**
|
|
101
|
+
No blockers.
|
|
102
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# linkedin-post-generator — Environment Variables
|
|
2
|
+
# =================================================
|
|
3
|
+
# The AI agent writes the post — no LLM API key needed.
|
|
4
|
+
# Composio is the only optional dependency, for direct LinkedIn posting.
|
|
5
|
+
|
|
6
|
+
# Required for direct posting via Composio.
|
|
7
|
+
# Without this key, the agent outputs the formatted post as text for manual copy-paste.
|
|
8
|
+
#
|
|
9
|
+
# Setup steps:
|
|
10
|
+
# 1. Get your API key at: https://app.composio.dev/settings
|
|
11
|
+
# 2. Connect your LinkedIn account at: https://app.composio.dev/app/linkedin
|
|
12
|
+
# 3. Complete the OAuth flow
|
|
13
|
+
# 4. The agent will call linkedin_create_linkedin_post when you confirm posting
|
|
14
|
+
COMPOSIO_API_KEY=your_composio_api_key_here
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# linkedin-post-generator
|
|
2
|
+
|
|
3
|
+
<img width="1376" height="768" alt="LinkedIn_post_generator" src="https://github.com/user-attachments/assets/dc71e06b-8b3c-486a-adbf-d56a7b22cdc1" />
|
|
4
|
+
|
|
5
|
+
Generate LinkedIn posts from any content: blog posts, articles, GitHub PRs, or a description of what you built. The agent reads your source material, applies LinkedIn's content patterns, and produces a post with the right hook, story arc, and formatting.
|
|
6
|
+
|
|
7
|
+
## Post Styles
|
|
8
|
+
|
|
9
|
+
| Style | Use When | Example Input |
|
|
10
|
+
|-------|----------|---------------|
|
|
11
|
+
| Founder/Ship | Personal story of building or shipping | "We merged our streaming SDK after 3 weeks" |
|
|
12
|
+
| Insight | Educational observation or lesson | Blog article, pattern you noticed, lesson learned |
|
|
13
|
+
| Product Launch | Announcing a new tool or feature | PR description, launch brief, feature going GA |
|
|
14
|
+
| Tutorial Summary | Distilling a long technical post | Tutorial URL, deep-dive article, step-by-step guide |
|
|
15
|
+
|
|
16
|
+
The agent auto-detects the right style. You override it by asking for a specific one.
|
|
17
|
+
|
|
18
|
+
## Requirements
|
|
19
|
+
|
|
20
|
+
No LLM API key needed. The agent writes the post.
|
|
21
|
+
|
|
22
|
+
Composio is optional. Add it to post directly to LinkedIn.
|
|
23
|
+
|
|
24
|
+
## Setup
|
|
25
|
+
|
|
26
|
+
### Composio (Optional)
|
|
27
|
+
|
|
28
|
+
Without Composio, the agent outputs formatted text for copy-paste. No configuration needed.
|
|
29
|
+
|
|
30
|
+
To enable direct posting:
|
|
31
|
+
1. Get your API key at https://app.composio.dev/settings
|
|
32
|
+
2. Connect your LinkedIn account at https://app.composio.dev/app/linkedin
|
|
33
|
+
3. Complete the OAuth flow
|
|
34
|
+
4. Add the key to your .env file:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
cp .env.example .env
|
|
38
|
+
# Edit .env and add your COMPOSIO_API_KEY
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## How to Use
|
|
42
|
+
|
|
43
|
+
From a URL:
|
|
44
|
+
```
|
|
45
|
+
"Turn this into a LinkedIn post: https://yourblog.com/my-post"
|
|
46
|
+
"Write a LinkedIn post about this article: [URL]"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
From pasted text:
|
|
50
|
+
```
|
|
51
|
+
"Here's a case study, turn it into a LinkedIn post: [paste text]"
|
|
52
|
+
"Convert this to a LinkedIn post: [paste article]"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
From a PR or shipped feature:
|
|
56
|
+
```
|
|
57
|
+
"Write a LinkedIn post about this PR we merged: [paste PR description]"
|
|
58
|
+
"Announce our new feature on LinkedIn: [describe the feature]"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
With a style override:
|
|
62
|
+
```
|
|
63
|
+
"Write a LinkedIn post in Tutorial Summary style about: [topic]"
|
|
64
|
+
"Use the Product Launch style for this: [description]"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
With direct posting:
|
|
68
|
+
```
|
|
69
|
+
"Post this to LinkedIn: [paste content]"
|
|
70
|
+
"Generate and post a LinkedIn update about [topic]"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Output
|
|
74
|
+
|
|
75
|
+
| Output | Description |
|
|
76
|
+
|--------|-------------|
|
|
77
|
+
| LinkedIn post | Formatted text, 900-1,300 characters, ready to publish |
|
|
78
|
+
| First comment | Text with source links. Post this immediately after publishing. |
|
|
79
|
+
| Hook alternatives | 2 additional hook lines in different formats |
|
|
80
|
+
| Posted confirmation | If Composio is configured and you confirm posting |
|
|
81
|
+
|
|
82
|
+
## How Posts Are Formatted
|
|
83
|
+
|
|
84
|
+
Four rules drive every post the agent writes:
|
|
85
|
+
|
|
86
|
+
- Hook first. The first line is all most people see. It works standalone.
|
|
87
|
+
- Short paragraphs. 1-3 lines, then a blank line. LinkedIn is mobile-first.
|
|
88
|
+
- Links in the first comment. URLs in the post body reduce LinkedIn's distribution.
|
|
89
|
+
- Question or CTA at the end. One or the other, not both.
|
|
90
|
+
|
|
91
|
+
## Project Structure
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
linkedin-post-generator/
|
|
95
|
+
├── SKILL.md
|
|
96
|
+
├── README.md
|
|
97
|
+
├── .env.example
|
|
98
|
+
├── evals/
|
|
99
|
+
│ └── evals.json
|
|
100
|
+
└── references/
|
|
101
|
+
├── linkedin-format.md
|
|
102
|
+
└── output-template.md
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## License
|
|
106
|
+
|
|
107
|
+
MIT
|