From ai-skills
This skill should be used when the user wants to write their end-of-day / evening "build-in-public" update for a given Linear project — 3-4 impact-focused bullets plus a Next line synthesized from the project's Linear activity and the repo's git/PR shipping evidence, ready to paste into the pod thread. Invoke as /build-in-public with a Linear project ID. Triggers on "build-in-public post", "evening update", "what did I ship today", "end-of-day update", or any variant of "what did I do today" for a work update — even without the word "skill". Default to drafting; never post anywhere automatically.
How this skill is triggered — by the user, by Claude, or both
Slash command
/ai-skills:build-in-public <linear-project-id><linear-project-id>This skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Turn a day's raw work into a short, high-signal evening update that reads as *impact and direction*, not activity. It is NOT a demo and NOT a status report — its currency is **progress + decisions + what got unblocked**, which is exactly what foundation/groundwork days produce.
Turn a day's raw work into a short, high-signal evening update that reads as impact and direction, not activity. It is NOT a demo and NOT a status report — its currency is progress + decisions + what got unblocked, which is exactly what foundation/groundwork days produce.
The reader is a PM / project owner, not a teammate dev. They do NOT know what a BOF-438 is, what a "walking skeleton" is, or which file a schema lives in. Write in features and business outcomes: name the feature ("Host submission form"), say what it unlocks for the product, and keep ticket IDs as trailing links only — never as the subject of a sentence. If a bullet can't be understood by someone who has never opened the repo, it's written wrong. Terse is good; jargon is not.
The update is scoped to one Linear project, passed as $ARGUMENTS. If no project ID is given, ask for it before gathering anything — it is the scope anchor and there is no sensible default.
Pull the raw material first. Don't ask the user to type it out if the tools can find it. Linear is the primary source (the project scopes the work); git/PRs are the shipping evidence; devsql is enrichment + a heads-down backstop.
Resolve the project ID → name first. linear issue query filters by --project name, not ID, while $ARGUMENTS is a project ID. Look up the name (and team) once:
linear project view "$ARGUMENTS" --json | jq -r '{name, team: .teams.nodes[0].key}'
Linear — issues in that project that moved today (use the resolved name):
linear issue query --project "<name>" --assignee "@me" \
--updated-after "$(date +%F)" --all-states --limit 50 --json
Split the results into shipped (state type completed, or state name matching /review/i) vs in-flight (started). See the linear-cli skill for any further CLI mechanics — don't re-document them here.
Linear is the scope authority. git/PRs are evidence only when they map to a Linear issue in this project. A repo holds work for many projects; today's commits and PRs may belong to a different one entirely. Before any PR/commit becomes a bullet, confirm its issue is in the project's linear issue query result above. If it isn't — drop it, don't narrate it. Likewise, a CLOSED PR is not "in-flight": don't invent a story to reconcile it. When in doubt about whether a day produced shippable code at all, ask the user one line ("code today, or spec/planning?") rather than assembling a plausible-looking shipping narrative from loose git activity. Fabrication is the worst failure mode here.
git / PRs — shipping evidence from the current repo:
# PRs authored today (opened, updated, or merged)
gh pr list --author "@me" --state all --search "updated:>=$(date +%F)"
# Commits today (current branch/repo only — no --all)
git log --author="$(git config user.email)" --since="00:00" --oneline
devsql — what was actually worked on and decided today (this repo): local Claude Code/Codex history joined with git. Use it to recover decisions and their rationale (the "because Z" in rule 4) and to substantiate a heads-down day (rule 7) when git+Linear are thin — NOT to list activity.
# Today's session topics for this repo
devsql "SELECT s.title, s.git_branch, s.user_message_count
FROM sessions s
WHERE s.cwd = '$(pwd)'
AND date(s.last_timestamp) = date('now','localtime')
ORDER BY s.last_timestamp DESC"
For prompt-level detail (the actual decisions debated), query history.display filtered to today. See the devsql-querying skill for schema and query mechanics (note cwd can be a worktree path, and title may be empty on in-progress sessions — fall back to git_branch). devsql reads local history only and may be absent — treat it as optional. It is the weakest of the three signals: never let a raw prompt become a bullet, and never let it inflate the post toward activity-over-impact.
If a source isn't reachable (no linear/gh/devsql, auth fails, project ID invalid), fall back to asking the user to paste their issues/PRs — never fabricate activity.
Apply these rules, in priority order. They exist because a daily that just lists tasks ("worked on X, worked on Y") signals effort, not impact — and on a foundation day it makes real work look like nothing.
#1234) or issue (BOF-430) link. A link the reader can open > a sentence describing it.Rule 1 is a principle the model reads then ignores, generating in the chronological order it gathered (engine → mail → "oh and the shared path"). This step is the forcing function. Do it explicitly before writing a single bullet:
Once the bullets are written, pass the draft through the humanizer skill to strip AI tells (inflated/promotional words, vague attributions, filler phrases, signposting) and apply the user's personal STYLE.md if present.
The Output format below overrides humanizer — this post's conventions are intentional, not slop. Humanizer must NOT touch:
→ arrows — they are structure (foundation → unlock, decision X → Y), not dash overuse.🛠️, ⏭️, #1234, BOF-430 all stay.So: keep the shape, remove the tells. If humanizer is unavailable, ship the draft as-is — it's a polish pass, not a gate.
ALWAYS produce exactly this shape, as a fenced markdown block ready to paste:
🛠️ <name> — <date>
- <foundation or highest-impact item, with link and what it unlocks>
- <consumer / feature item, with link and status>
- <other item or honest heads-down line, with link/ETA>
- ⏭️ Next: <in-flight continuation>. Then <new item, with link>; + <smaller item, with link>.
Use $(date +%d/%m) for the date. Keep bullets to one line each where possible. Use the user's real ticket/PR links in markdown form.
This is not a decorative checklist — it is a gate. Before emitting, run every item. If any item fails, rewrite the post and re-run the whole list. Emit nothing until all pass.
Output the block in chat for the user to review and paste. Never post to Slack (or anywhere) automatically. Only if the user explicitly asks, create a Slack draft (a draft, not a send) so they review it in their client. Always list any assumptions made about the "why" as a short note under the draft.
Raw work (input):
Update (output):
🛠️ Alex — 18/06
- Laid the shared auth adapter: single provider abstraction replacing the per-IdP branches → unblocks multi-tenant SSO + future IdPs. PR WIP #211.
- SSO config UI wired onto the adapter (#214, in review).
- Root-caused the cron timeouts: connection pool, not the query. Fix merged (#209).
- ⏭️ Next: finish the SSO UI. Then new workstream — SCIM provisioning (PROJ-88).
Note the transform: the adapter (foundation) becomes the headline, the UI becomes proof it pays off, "fixed/worked on" become movement, and every line links out. No visual was needed for any of it.
npx claudepluginhub benjaming/ai-skills --plugin ai-skillsCreates bite-sized, testable implementation plans from specs or requirements, with file structure and task decomposition. Activates before coding multi-step tasks.