post-pr-to-slack
|
Install
mkdir -p .claude/skills/post-pr-to-slack && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/14726" && unzip -o skill.zip -d .claude/skills/post-pr-to-slack && rm skill.zipInstalls to .claude/skills/post-pr-to-slack
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Post a one-line PR announcement to a Slack channel, and mark it :merged: when the PR merges. Use whenever you open or meaningfully adjust a Sculptor PR.About this skill
Post PR to Slack
Announce Sculptor pull requests in the team's merges channel with a single
standalone line, then mark each announcement :merged: once its PR merges. This
file covers when to post and what the message should say; the Slack
mechanics (channel lookup, posting, reacting) live in
scripts/slack_pr.sh.
The skill is agent-agnostic — it depends only on latchkey, jq, gh, and
bash, not on any agent-specific tooling.
When to run
- When you open a PR for Sculptor. After
gh pr create --base mainsucceeds, post to#project-sculptor-merges. This is a standing instruction — just post; see Authorization. - When you meaningfully adjust an open PR — a force-push that changes the approach, a scope change, or a retitle. Reply in the existing thread; don't start a new top-level post. Skip trivial edits (typo fixes, rebases, minor doc tweaks). If unsure, ask the user.
- When a PR merges (you observe it, or the user says so). Add a
:merged:reaction to the original post. Do not post a separate "merged" message — the reaction is the convention.
Inputs
- Channel —
#project-sculptor-mergesfor Sculptor PRs unless the user says otherwise. - PR URL — infer from git when not given:
- current branch:
gh pr view --json url -q .url - a specific PR:
gh pr view <number> --json url -q .url
- current branch:
- One-line description — draft from the PR title/body (see
Drafting). If the PR already has a crisp one-liner
(its title, or a
## Summarybullet), reuse it verbatim so Slack and the PR stay in lockstep.
The only PR-host-specific step is fetching the URL with
gh. On a GitLab repo, swap inglab mr view --output json | jq -r .web_url; everything else is the same.
Setup
Point a variable at the helper script and confirm Slack is reachable, once per session:
SLACK=.claude/skills/post-pr-to-slack/scripts/slack_pr.sh
"$SLACK" check # prints "slack ok: team '…' as '…'", or says how to fix auth
If the check fails, run latchkey services info slack and follow its setup (a
browser login if supported, otherwise latchkey auth set). The script puts an
nvm-installed latchkey back on PATH itself; if check still reports it
missing, install it with npm install -g latchkey.
Steps — initial post
-
Read recent channel history to match the house style (terse vs. emoji-led, where the URL goes, capitalization), then draft the line per Drafting:
"$SLACK" history '#project-sculptor-merges' -
Post it and capture the message timestamp (
ts). The text is sent verbatim, so include the PR URL — Slack unfurls it into a preview:TEXT="Fix login crash when the token contains a colon $PR_URL" TS=$("$SLACK" post '#project-sculptor-merges' "$TEXT") echo "posted ts=$TS"slack_pr.shbuilds the JSON withjq, so backticks, quotes, or&in the text are safe. -
Report the channel and
tsback to the user, and remember thets— the merge-time:merged:step needs it.
Steps — adjusting an open PR
If a post for this PR already exists (use the ts you remembered, or find it),
reply in its thread — don't post a new top-level message for the same PR, which
splits the discussion:
TS=$("$SLACK" find-ts '#project-sculptor-merges' "$PR_URL")
"$SLACK" reply '#project-sculptor-merges' "$TS" "Revised approach: now …"
Steps — PR merged
TS=$("$SLACK" find-ts '#project-sculptor-merges' "$PR_URL")
"$SLACK" done '#project-sculptor-merges' "$TS"
find-ts matches the bare URL even when Slack has wrapped it in <…>. done is
idempotent — an already-present :merged: counts as success. Don't post anything
else; the reaction is the "merged" signal.
Drafting the one-liner
The audience is teammates and future reviewers skimming the channel. The line must convey the PR's one key outcome and read standalone — no thread, repo, or commit-history context required. Lead with a verb in the channel's imperative style ("Fix X", "Migrate Y", "Speed up Z"). Draft it directly; if your harness lets you delegate prose to a smaller/faster model, you may, but it's not required.
Check the draft against these guardrails:
- Outcome, not process. Describe what the PR achieves in the codebase as it now exists — not the bootstrap, onboarding, or workflow that produced it.
- Timeless. No "follow-up commit does Y", "next we'll…", or "still to come". Frame it as if every commit on the branch has already landed and is the new normal. A channel post is a record, not a roadmap or a per-commit changelog.
- One sentence, one outcome. No parenthetical hedging in a secondary change. If a second change is genuinely co-equal, that's a sign it should be its own PR.
- Plain, not hype. "Improve performance" — not "Massive perf win!" — unless the channel actually talks that way.
- Ends with the PR URL; no ticket IDs unless the channel uses them.
Authorization
The #project-sculptor-merges post-and-:merged: flow is pre-authorized for
Sculptor PRs — this skill living in the repo is the standing instruction.
Don't pause to ask "should I post this?" after gh pr create succeeds; just
post. Posting and reacting are still visible to others, so do ask before any
scope expansion: a different channel, @-mentioning people, a reaction other than
:merged:, or cross-posting to a non-Sculptor PR.
Notes
- Re-resolve the channel ID each invocation. Looking up by name tolerates renames; a cached ID can go stale across sessions.
- Track the
tsof your initial post in conversation memory so the merge-time reaction doesn't have to scan history. - Raw API / fallback. Every call routes through
latchkey curlagainst the Slack Web API; the exact endpoints and payloads are inscripts/slack_pr.shif you ever need to run them by hand.